From b62378dcb42f576539cb1da2b24b48eda9ac025a Mon Sep 17 00:00:00 2001 From: DHDAXCW Date: Fri, 19 Jul 2024 17:13:54 +0800 Subject: [PATCH] sync --- config/Config-kernel.in | 13 + doc/h68k.jpg | Bin 63089 -> 0 bytes doc/r1.jpg | Bin 51680 -> 0 bytes doc/star.png | Bin 167163 -> 0 bytes include/kernel-5.15 | 4 +- include/kernel-6.1 | 4 +- include/target.mk | 4 +- include/trusted-firmware-a.mk | 6 +- include/u-boot.mk | 35 +- package/base-files/files/bin/config_generate | 8 +- .../base-files/files/lib/upgrade/common.sh | 18 + package/base-files/files/lib/upgrade/stage2 | 3 +- package/firmware/ath11k-firmware/Makefile | 24 +- package/firmware/ath11k-wifi/Makefile | 94 - .../firmware/ath11k-wifi/board-2.bin.IPQ6018 | Bin 787208 -> 0 bytes .../board-edgecore-eap102.bin.IPQ8074 | Bin 131072 -> 0 bytes .../ath11k-wifi/board-gl-ax1800.bin.IPQ6018 | Bin 787208 -> 0 bytes .../ath11k-wifi/board-gl-axt1800.bin.IPQ6018 | Bin 787208 -> 0 bytes .../ath11k-wifi/qdss_trace_config.bin | 99 -- package/firmware/b43legacy-firmware/Makefile | 72 - package/firmware/cypress-firmware/Makefile | 285 ++- package/firmware/cypress-nvram/Makefile | 96 +- .../files/brcmfmac4339-sdio.AP6335.txt | 99 ++ package/firmware/intel-microcode/Makefile | 4 +- package/firmware/ipq-wifi/Makefile | 56 +- .../ipq-wifi/board-8dev_habanero-dvk.qca4019 | Bin 24324 -> 0 bytes .../ipq-wifi/board-aruba_ap-303.qca4019 | Bin 24316 -> 0 bytes .../ipq-wifi/board-asus_rt-acrh17.qca4019 | Bin 12164 -> 0 bytes .../board-avm_fritzrepeater-1200.qca4019 | Bin 24332 -> 0 bytes .../board-buffalo_wtr-m2133hp.qca4019 | Bin 24332 -> 0 bytes .../board-buffalo_wtr-m2133hp.qca9984 | Bin 12172 -> 0 bytes .../ipq-wifi/board-cellc_rtl30vw.qca4019 | Bin 24316 -> 0 bytes .../ipq-wifi/board-century_wr142ac.qca4019 | Bin 24308 -> 0 bytes .../board-devolo_magic-2-wifi-next.qca4019 | Bin 24340 -> 0 bytes .../ipq-wifi/board-dlink_dap2610.qca4019 | Bin 24316 -> 0 bytes .../ipq-wifi/board-edgecore_ecw5410.qca9984 | Bin 24324 -> 0 bytes .../ipq-wifi/board-edgecore_oap100.qca4019 | Bin 24324 -> 0 bytes .../ipq-wifi/board-engenius_eap2200.qca4019 | Bin 24324 -> 0 bytes .../ipq-wifi/board-engenius_eap2200.qca9888 | Bin 12172 -> 0 bytes .../ipq-wifi/board-engenius_emd1.qca4019 | Bin 24316 -> 0 bytes .../ipq-wifi/board-engenius_emr3500.qca4019 | Bin 24324 -> 0 bytes .../board-ezviz_cs-w3-wd1200g-eup.qca4019 | Bin 24340 -> 0 bytes .../ipq-wifi/board-glinet_gl-a1300.qca4019 | Bin 24308 -> 0 bytes .../ipq-wifi/board-glinet_gl-ap1300.qca4019 | Bin 48596 -> 0 bytes .../ipq-wifi/board-glinet_gl-s1300.qca4019 | Bin 24276 -> 0 bytes .../ipq-wifi/board-hiwifi_c526a.qca4019 | Bin 24300 -> 0 bytes .../ipq-wifi/board-linksys_ea8300.qca4019 | Bin 97236 -> 0 bytes .../ipq-wifi/board-linksys_ea8300.qca9888 | Bin 48628 -> 0 bytes .../ipq-wifi/board-linksys_mr8300-v0.qca4019 | Bin 97268 -> 0 bytes .../ipq-wifi/board-linksys_mr8300-v0.qca9888 | Bin 48644 -> 0 bytes .../ipq-wifi/board-luma_wrtq-329acn.qca4019 | Bin 24324 -> 0 bytes .../ipq-wifi/board-mikrotik_hap-ac2.qca4019 | Bin 24324 -> 0 bytes .../board-mikrotik_sxtsq-5-ac.qca4019 | Bin 12176 -> 0 bytes .../board-mobipromo_cm520-79f.qca4019 | Bin 24308 -> 0 bytes .../ipq-wifi/board-nec_wg2600hp3.qca9984 | Bin 24332 -> 0 bytes .../ipq-wifi/board-netgear_sxr80.ipq8074 | Bin 131176 -> 0 bytes .../ipq-wifi/board-p2w_r619ac.qca4019 | Bin 24300 -> 0 bytes .../ipq-wifi/board-plasmacloud_pa1200.qca4019 | Bin 24324 -> 0 bytes .../ipq-wifi/board-plasmacloud_pa2200.qca4019 | Bin 24324 -> 0 bytes .../ipq-wifi/board-plasmacloud_pa2200.qca9888 | Bin 12172 -> 0 bytes .../firmware/ipq-wifi/board-qnap_301w.ipq8074 | Bin 131172 -> 0 bytes .../ipq-wifi/board-qxwlan_e2600ac.qca4019 | Bin 36464 -> 0 bytes .../firmware/ipq-wifi/board-redmi_ax6.ipq8074 | Bin 131172 -> 0 bytes .../ipq-wifi/board-tplink_xtr10890.ipq8074 | Bin 131176 -> 0 bytes .../ipq-wifi/board-xiaomi_ax3600.ipq8074 | Bin 131176 -> 0 bytes .../ipq-wifi/board-xiaomi_ax3600.qca9889 | Bin 2260 -> 0 bytes .../ipq-wifi/board-xiaomi_ax9000.ipq8074 | Bin 131176 -> 0 bytes .../firmware/ipq-wifi/board-zte_mf263.qca4019 | Bin 24308 -> 0 bytes .../firmware/ipq-wifi/board-zte_mf269.ipq8074 | Bin 131172 -> 0 bytes .../src/board-jdcloud_ax1800pro.ipq6018 | Bin 0 -> 65644 bytes .../ipq-wifi/src/board-jdcloud_ax6600.ipq6018 | Bin 0 -> 65644 bytes .../ipq-wifi/src/board-qihoo_360v6.ipq6018 | Bin 0 -> 65620 bytes .../src/board-redmi_ax5-jdcloud.ipq6018 | Bin 0 -> 65644 bytes .../ipq-wifi/src/board-xiaomi_rm1800.ipq6018 | Bin 0 -> 65620 bytes .../src/board-zn_m2.ipq6018} | Bin 787208 -> 787208 bytes package/firmware/linux-firmware/Makefile | 4 +- package/firmware/linux-firmware/airoha.mk | 8 + .../ap6236/brcmfmac43430-sdio.bin | Bin .../ap6236/brcmfmac43430-sdio.txt | 0 .../brcmfmac4356-sdio.rongpin,king3399.bin | Bin 580258 -> 0 bytes .../brcmfmac4356-sdio.rongpin,king3399.txt | 125 -- package/firmware/linux-firmware/intel.mk | 15 + package/firmware/linux-firmware/marvell.mk | 3 +- package/firmware/linux-firmware/mellanox.mk | 9 + package/firmware/linux-firmware/realtek.mk | 41 +- package/firmware/photonicat-firmware/Makefile | 28 + .../photonicat-firmware/files/board.bin | Bin 0 -> 8124 bytes .../files/firmware-sdio-5.bin | Bin 0 -> 616352 bytes package/kernel/cryptodev-linux/Makefile | 2 +- .../0005-fix-build-for-linux-5.10.220+.patch | 11 + package/kernel/mac80211/Makefile | 41 +- package/kernel/mac80211/ath.mk | 73 +- package/kernel/mac80211/broadcom.mk | 14 +- .../files/lib/netifd/wireless/mac80211.sh | 1244 +++++++++++++ .../mac80211/files/lib/wifi/mac80211.sh | 191 ++ .../kernel/mac80211/files/mac80211.hotplug | 5 + package/kernel/mac80211/intel.mk | 2 +- .../patches/ath/400-ath_move_debug_code.patch | 4 +- .../patches/ath/402-ath_regd_optional.patch | 2 +- .../patches/ath/404-regd_no_assoc_hints.patch | 4 +- ...add_platform_eeprom_support_to_ath5k.patch | 2 +- .../ath10k/080-ath10k_thermal_config.patch | 4 +- ...isable-caldata-prefetch-for-sdio-bus.patch | 12 + ...21-ath10k_init_devices_synchronously.patch | 5 +- .../930-ath10k_add_tpt_led_trigger.patch | 4 +- ...olling-support-for-various-chipsets.patch} | 319 ++-- ...75-ath10k-use-tpt-trigger-by-default.patch | 8 +- ...-power-reduction-for-US-regulatory-d.patch | 8 +- ...h10k-Try-to-get-mac-address-from-dts.patch | 4 +- .../ath10k/985-ath10k-allow-vht-on-2g.patch | 10 + ...k-always-use-mac80211-loss-detection.patch | 2 +- .../ath10k/990-ath10k-small-buffers.patch | 10 +- ...-tx-queues-immediately-upon-firmware.patch | 78 + ...-ath11k-Don-t-exit-on-wakeup-failure.patch | 45 + ...-Fix-spelling-mistake-chnange-change.patch | 25 + ...-ath11k-suppress-add-interface-error.patch | 52 + ...support-to-configure-channel-dwell-t.patch | 102 ++ ...firmware-crash-on-vdev-delete-race-c.patch | 116 ++ ...monitor-vdev-creation-with-firmware-.patch | 40 + ...qmi_msg_handler-data-structure-initi.patch | 33 + ...hronize-ath11k_mac_he_gi_to_nl80211_.patch | 42 + ...-ath11k-Make-QMI-message-rules-const.patch | 341 ++++ ...ger-sta-disconnect-on-hardware-resta.patch | 119 ++ ...race-condition-with-struct-htt_ppdu_.patch | 103 ++ ...-ath11k-update-hw-params-for-IPQ5018.patch | 125 ++ ...update-ce-configurations-for-IPQ5018.patch | 246 +++ ...-remap-ce-register-space-for-IPQ5018.patch | 351 ++++ ...11k-update-hal-srng-regs-for-IPQ5018.patch | 130 ++ ...ath11k-initialize-hw_ops-for-IPQ5018.patch | 90 + ...new-hw-ops-for-IPQ5018-to-get-rx-des.patch | 84 + ...fi-ath11k-add-ipq5018-device-support.patch | 31 + ...scan-request-param-frame-size-warnin.patch | 161 ++ ...support-to-configure-FTM-responder-r.patch | 169 ++ ...-channel-177-into-5-GHz-channel-list.patch | 41 + ...ix-ce-memory-mapping-for-ahb-devices.patch | 114 ++ ...ext-passive-scan-flag-to-adjust-pass.patch | 73 + ...return-value-check-in-ath11k_ahb_pro.patch | 27 + ...platform_get_irq-to-get-the-interrup.patch | 50 + ...SAC-bug-on-peer-addition-with-sta-ba.patch | 53 + ...low-system-suspend-to-survive-ath11k.patch | 43 + ...fy-accessor-macros-to-match-index-si.patch | 61 + ...-MU-MIMO-params-from-hostapd-to-hard.patch | 300 ++++ ...-HE-MCS-mapper-to-a-separate-functio.patch | 67 + ...rate-rx-and-tx-mcs-maps-for-supporte.patch | 64 + ...tx-ack-signal-support-for-management.patch | 150 ++ ...proper-regulatory-reference-for-band.patch | 216 +++ ...support-to-parse-new-WMI-event-for-6.patch | 844 +++++++++ ...debug-prints-in-regulatory-WMI-event.patch | 567 ++++++ ...ace-fake-flex-array-with-flexible-ar.patch | 246 +++ ...deinitialization-of-firmware-resourc.patch | 79 + ...BUFFER_DONE-read-on-monitor-ring-rx-.patch | 130 ++ ...wifi-ath11k-Optimize-6-GHz-scan-time.patch | 101 ++ ...igure-the-FTM-responder-role-using-f.patch | 117 ++ ...rssi-station-dump-not-updated-in-QCN.patch | 158 ++ ...invalid-management-rx-frame-length-i.patch | 115 ++ ...-writing-to-unintended-memory-region.patch | 43 + ...-11d-scan-start-before-WMI_START_SCA.patch | 61 + ...1k-Remove-redundant-pci_clear_master.patch | 58 + ...ble-Spectral-scan-upon-removing-inte.patch | 36 + ...ath11k-enable-SAR-support-on-WCN6750.patch | 29 + ...pci-Add-more-MODULE_FIRMWARE-entries.patch | 36 + ...t-a-warning-when-crypto_alloc_shash-.patch | 34 + ...re-frags-from-uninitialized-peer-in-.patch | 104 ++ ...-undefined-behavior-with-__fls-in-dp.patch | 29 + ...double-free-of-peer-rx_tid-during-re.patch | 144 ++ ...wifi-ath11k-Prevent-REO-cmd-failures.patch | 43 + ...peer-mac-information-in-failure-case.patch | 74 + ...tx-status-reporting-in-encap-offload.patch | 119 ++ ...-incorrect-update-of-radiotap-fields.patch | 49 + ...SKB-corruption-in-REO-destination-ri.patch | 70 + ...emove-disabling-of-80-80-and-160-MHz.patch | 49 + ...registration-of-6Ghz-only-phy-withou.patch | 61 + ...ound-false-positive-stringop-overrea.patch | 84 + ...k-driver-settings-for-MBSSID-and-EMA.patch | 133 ++ ...ID-configuration-during-vdev-create-.patch | 215 +++ ...ame-MBSSID-fields-in-wmi_vdev_up_cmd.patch | 52 + ...ID-parameter-configuration-in-AP-mod.patch | 138 ++ ...efactor-vif-parameter-configurations.patch | 86 + ...76-wifi-ath11k-MBSSID-beacon-support.patch | 190 ++ .../0077-wifi-ath11k-EMA-beacon-support.patch | 156 ++ ...cate-the-func-ath11k_mac_bitrate_mas.patch | 75 + ...-HT-fixed-rate-in-WMI-peer-fixed-par.patch | 141 ++ ...support-default-regdb-while-searchin.patch | 127 ++ ...ve-unused-function-ath11k_tm_event_w.patch | 128 ++ ...ifi-ath11k-factory-test-mode-support.patch | 850 +++++++++ ...w-ath11k-to-boot-without-caldata-in-.patch | 47 + ...11k-Add-HTT-stats-for-PHY-reset-case.patch | 261 +++ ...ix-memory-leak-in-WMI-firmware-stats.patch | 51 + ...ath11k-Add-missing-check-for-ioremap.patch | 38 + ...dd-missing-ops-config-for-IPQ5018-in.patch | 30 + ...firmware-after-cold-boot-calibration.patch | 47 + ...missing-hw_ops-get_ring_selector-for.patch | 58 + ...ert-wifi-ath11k-Enable-threaded-NAPI.patch | 44 + ...-Split-coldboot-calibration-hw_param.patch | 180 ++ ...coldboot-calibration-support-for-QCN.patch | 176 ++ ...k-Remove-cal_done-check-during-probe.patch | 33 + ...-add-a-warning-message-for-MHI_CB_EE.patch | 34 + ...chip-id-board-name-while-searching-b.patch | 214 +++ ...fix-boot-failure-with-one-MSI-vector.patch | 103 ++ ...-ath11k-disable-coldboot-for-ipq6018.patch | 26 - ...i-ath11k-use-unique-QRTR-instance-ID.patch | 10 +- ...-add-support-DT-ieee80211-freq-limit.patch | 24 - ...k-control-thermal-support-via-symbol.patch | 16 +- ...ci-fix-compilation-in-5.16-and-older.patch | 29 + ...ble-coldboot-calibration-for-IPQ8074.patch | 26 + ...upport-setting-FW-memory-mode-via-DT.patch | 6 +- ...tersection-support-for-regulatory-ru.patch | 95 +- ...ble-coldboot-calibration-for-IPQ6018.patch | 13 + .../ath5k/440-ath5k_channel_bw_debugfs.patch | 2 +- ..._hw-issue-external-reset-for-QCA955x.patch | 8 +- .../ath9k/500-ath9k_eeprom_debugfs.patch | 61 +- .../ath9k/511-ath9k_reduce_rxbuf.patch | 2 +- .../ath9k/512-ath9k_channelbw_debugfs.patch | 190 +- .../patches/ath9k/530-ath9k_extra_leds.patch | 26 +- .../ath9k/531-ath9k_extra_platform_leds.patch | 12 + .../ath9k/542-ath9k_debugfs_diag.patch | 10 +- .../ath9k/543-ath9k_entropy_from_adc.patch | 16 +- .../ath9k/545-ath9k_ani_ws_detect.patch | 4 +- .../ath9k/548-ath9k_enable_gpio_chip.patch | 8 +- .../ath9k/549-ath9k_enable_gpio_buttons.patch | 15 +- .../ath9k/551-ath9k_ubnt_uap_plus_hsr.patch | 8 +- .../patches/ath9k/552-ath9k-ahb_of.patch | 65 +- .../ath9k/553-ath9k_of_gpio_mask.patch | 2 +- .../810-b43-gpio-mask-module-option.patch | 2 +- .../brcm/812-b43-add-antenna-control.patch | 18 +- .../814-b43-only-use-gpio-0-1-for-led.patch | 2 +- ...-register-wiphy-s-during-module_init.patch | 64 + ...und-bug-with-some-inconsistent-BSSes.patch | 2 +- ...62-brcmfmac-Disable-power-management.patch | 2 +- ...-in-driver-tables-with-country-codes.patch | 2 +- ...d-alternative-firmware-names-from-DT.patch | 187 ++ ...mfmac-disable-dump_survey-on-bcm2835.patch | 38 - .../patches/build/001-fix_build.patch | 23 +- .../build/004-fix-kconf-compiling.patch | 47 - .../patches/build/050-lib80211_option.patch | 34 + .../patches/build/060-no_local_ssb_bcma.patch | 10 +- .../patches/build/080-resv_start_op.patch | 24 + .../patches/build/099-netlink-range.patch | 91 + .../100-backports-drop-QRTR-and-MHI.patch | 6 +- .../build/110-backport_namepace_const.patch | 14 - .../build/110-backport_napi_build_skb.patch | 11 + .../build/120-headers_version_fix.patch | 25 - .../patches/build/130-iommu_backport.patch | 26 - .../build/200-iwlwifi_thermal_backport.patch | 26 - .../build/210-backport_genl_split_ops.patch | 32 - ...list-don-t-backport-list_count_nodes.patch | 26 - .../230-brcmfmac_usb_driver_backport.patch | 14 - .../build/990-add_kernel_6.6_support.patch | 113 ++ ...700-mwl8k-missing-pci-id-for-WNR854T.patch | 2 +- .../801-libertas-configure-sysfs-links.patch | 2 +- .../802-libertas-set-wireless-macaddr.patch | 2 +- ...940-mwl8k_init_devices_synchronously.patch | 4 +- ...ringified-name-of-command-in-error-l.patch | 6 +- ...option-to-pass-EEPROM-file-name-from.patch | 43 - ...i-rt2x00-Support-EEPROM-swap-binding.patch | 44 - ...port-loading-eeprom-from-NVMEM-cells.patch | 97 -- ...> 602-rt2x00-introduce-rt2x00eeprom.patch} | 186 +- .../603-rt2x00-of_load_eeprom_filename.patch | 31 + ...m-on-SoC-from-a-mtd-device-defines-.patch} | 52 +- ...isabling_bands_through_platform_data.patch | 2 +- ...07-rt2x00-add_platform_data_mac_addr.patch | 2 +- ...00-allow_disabling_bands_through_dts.patch | 2 +- ...c-loadable-via-OF-on-rt288x-305x-SoC.patch | 2 +- ...0-rt2x00-change-led-polarity-from-OF.patch | 2 +- .../611-rt2x00-add-AP+STA-support.patch | 2 +- ...t-support-for-external-LNA-on-MT7620.patch | 74 +- ...duce-accessors-for-CHIP_VER-register.patch | 22 +- ...-differentiate-based-on-SoC-CHIP_VER.patch | 108 +- .../110-mac80211_keep_keys_on_stop_ap.patch | 13 +- .../patches/subsys/130-disable_auto_vif.patch | 27 - .../mac80211/patches/subsys/210-ap_scan.patch | 2 +- ...domize-BA-session-dialog-token-alloc.patch | 10 +- ...crease-quantum-for-airtime-scheduler.patch | 12 +- ...d-internal-handler-for-wake_tx_queue.patch | 183 ++ ...dd-wake_tx_queue-callback-to-drivers.patch | 396 +++++ ...c80211-Drop-support-for-TX-push-path.patch | 683 ++++++++ ...ltek-remove-duplicated-wake_tx_queue.patch | 32 + ...ear-vif-drv_priv-after-calling-remov.patch | 29 - ...port-for-restricting-netdev-features.patch | 506 ++++++ ...x-and-simplify-unencrypted-drop-chec.patch | 87 + ...ve-A-MSDU-check-in-ieee80211_data_to.patch | 25 + ...ctor-out-bridge-tunnel-RFC1042-heade.patch | 76 + ...move-mesh-forwarding-congestion-chec.patch | 54 + ...x-receiving-A-MSDU-frames-on-mesh-in.patch | 762 ++++++++ ...d-a-workaround-for-receiving-non-sta.patch | 145 ++ ...x-race-in-mesh-sequence-number-assig.patch | 37 + ...wifi-mac80211-mesh-fast-xmit-support.patch | 850 +++++++++ ...race-period-for-DFS-available-after-.patch | 149 -- ...e-mesh-header-cache-to-speed-up-mesh.patch | 132 ++ .../321-mac80211-fix-mesh-forwarding.patch | 32 + ...x-mesh-path-discovery-based-on-unica.patch | 52 + ...d-VHT-MU-MIMO-related-flags-in-ieee8.patch | 68 + ...d-HE-MU-MIMO-related-flags-in-ieee80.patch | 68 + ...troduce-ieee80211_refresh_tx_agg_ses.patch | 60 + ...fi-mac80211-add-mesh-fast-rx-support.patch | 77 + ...d-support-for-letting-drivers-regist.patch | 149 ++ ...x-receiving-mesh-packets-in-forwardi.patch | 50 + ...dd-AQL-support-for-broadcast-packets.patch | 293 ---- ...orrectly-mark-FTM-frames-non-buffera.patch | 134 ++ ...tend-IEEE80211_KEY_FLAG_GENERATE_MMI.patch | 70 - ...mac80211-flush-queues-on-STA-removal.patch | 36 + ...i-mvm-support-flush-on-AP-interfaces.patch | 34 + ...3-wifi-mac80211-add-flush_sta-method.patch | 91 + ...ifi-mvm-support-new-flush_sta-method.patch | 53 + ...d-LDPC-related-flags-in-ieee80211_bs.patch | 62 + ...0211-generate-EMA-beacons-in-AP-mode.patch | 372 ++++ ...sband-iftype-data-lookup-for-AP_VLAN.patch | 23 + ...esh-fast-tx-cache-into-local-proxied.patch | 219 +++ ...it-helper-function-from-nl80211_put_.patch | 145 -- ...d-support-for-advertising-multiple-r.patch | 348 ---- ...tend-interface-combination-check-for.patch | 172 -- ...d-helper-for-checking-if-a-chandef-i.patch | 69 - ...d-support-for-DFS-with-multiple-radi.patch | 88 - ...d-radio-index-to-ieee80211_chanctx_c.patch | 66 - ...tend-ifcomb-check-functions-for-mult.patch | 322 ---- ...ve-code-in-ieee80211_link_reserve_ch.patch | 175 -- ...d-wiphy-radio-assignment-and-validat.patch | 132 -- ...sim-add-support-for-multi-radio-wiph.patch | 199 --- .../patches/subsys/400-allow-ibss-mixed.patch | 2 +- .../subsys/401-mac80211-allow-vht-on-2g.patch | 36 + .../500-mac80211_configure_antenna_gain.patch | 162 ++ .../780-avoid-crashing-missing-band.patch | 2 +- .../subsys/800-rework-eth_hw_addr_set.patch | 11 + .../900-add-eth-ieee80211_bss_conf.patch | 55 + .../910-fix-build-for-kernel-5.10.patch | 20 - ...-channel-time-is-reset-by-ch_restore.patch | 58 - package/kernel/mac80211/realtek.mk | 172 +- package/kernel/mt76/Makefile | 28 +- .../patches-5.4/001-allow-vht-on-2g.patch | 59 + .../patches-5.4/002-fix-build-error.patch | 57 + .../mt76/patches-5.4/100-api_update.patch | 11 + ...ifi-mt76-ignore-key-disable-commands.patch | 301 ++++ .../patches-6.x/001-allow-vht-on-2g.patch | 59 + .../002-wifi-mt76-mt7915-fix-oops.patch | 100 ++ .../101-fixes-mt7925-build-error.patch | 23 + .../mt76/patches/001-allow-vht-on-2g.patch | 59 + .../mt76/patches/002-fix-page-pool.patch | 24 + package/kernel/rtw88-usb/Makefile | 105 ++ .../patches/001-fix-merge-error.patch | 96 + .../rtw88-usb/patches/101-wireless-6.1.patch | 432 +++++ .../rtw88-usb/patches/102-disable-pcie.patch | 69 + package/lean/autocore/files/x86/autocore | 2 - .../files/zzz-default-settings | 24 +- package/lean/r8101/Makefile | 39 + .../lean/r8101/patches/010-6.1-support.patch | 14 + package/utils/f2fs-tools/Makefile | 3 +- package/utils/lua/Makefile | 2 +- .../001-include-version-number.patch | 3 +- .../013-lnum-strtoul-parsing-fixes.patch | 11 +- .../lua/patches-host/100-no_readline.patch | 6 +- .../lua/patches-host/400-CVE-2014-5461.patch | 19 + .../patches/001-include-version-number.patch | 3 +- .../013-lnum-strtoul-parsing-fixes.patch | 11 +- .../utils/lua/patches/400-CVE-2014-5461.patch | 19 + package/wwan/luci-app-modem/Makefile | 1 - package/wwan/luci-app-sms-tool/LICENSE | 674 -------- package/wwan/luci-app-sms-tool/Makefile | 32 - .../luci-static/resources/icons/delsms.png | Bin 9221 -> 0 bytes .../luci-static/resources/icons/delsms2.png | Bin 1365 -> 0 bytes .../luasrc/controller/modem/sms.lua | 242 --- .../luasrc/model/cbi/modem/smsconfig.lua | 226 --- .../luasrc/view/modem/atcommands.htm | 136 -- .../luasrc/view/modem/readsms.htm | 285 --- .../luasrc/view/modem/sendsms.htm | 237 --- .../luasrc/view/modem/ussd.htm | 265 --- .../wwan/luci-app-sms-tool/po/pl/sms-tool.po | 288 --- .../luci-app-sms-tool/po/zh-cn/sms-tool.po | 246 --- .../root/etc/config/atcmds.user | 28 - .../root/etc/config/phonebook.user | 1 - .../root/etc/config/sms_tool | 14 - .../luci-app-sms-tool/root/etc/init.d/smsled | 26 - .../root/etc/uci-defaults/set_sms_ports.sh | 23 - .../root/etc/uci-defaults/start-smsled | 7 - .../luci-app-sms-tool/root/sbin/cronsync.sh | 21 - .../root/sbin/set_sms_ports.sh | 24 - .../root/sbin/smsled-init.sh | 21 - .../luci-app-sms-tool/root/sbin/smsled.sh | 39 - .../share/rpcd/acl.d/luci-app-sms-tool.json | 24 - target/linux/mediatek/Makefile | 4 +- .../lib/preinit/05_set_preinit_iface | 28 +- .../dts/mt7622-buffalo-wsr-2533dhp2.dts | 252 +-- .../dts/mt7622-buffalo-wsr-3200ax4s.dts | 175 ++ .../mediatek/dts/mt7622-buffalo-wsr.dtsi | 230 +++ .../mt7622-dlink-eagle-pro-ai-ax3200-a1.dtsi | 365 ++++ .../dts/mt7622-dlink-eagle-pro-ai-m32-a1.dts | 63 + .../dts/mt7622-dlink-eagle-pro-ai-r32-a1.dts | 78 + .../dts/mt7622-elecom-wrc-2533gent.dts | 2 +- .../dts/mt7622-elecom-wrc-x3200gst3.dts | 40 +- .../mediatek/dts/mt7622-linksys-e8450-ubi.dts | 88 +- .../mediatek/dts/mt7622-linksys-e8450.dts | 28 +- .../mediatek/dts/mt7622-linksys-e8450.dtsi | 17 +- .../mediatek/dts/mt7622-netgear-wax206.dts | 28 +- .../mediatek/dts/mt7622-reyee-ax3200-e5.dts | 96 + target/linux/mediatek/dts/mt7622-rfb1-ubi.dts | 4 +- .../mediatek/dts/mt7622-ruijie-rg-ew3200.dtsi | 240 +++ .../dts/mt7622-ruijie-rg-ew3200gx-pro.dts | 258 +-- .../mediatek/dts/mt7622-totolink-a8000ru.dts | 32 +- .../mt7622-ubnt-unifi-6-lr-v1-ubootmod.dts | 35 +- .../dts/mt7622-ubnt-unifi-6-lr-v1.dts | 28 +- .../dts/mt7622-ubnt-unifi-6-lr-v1.dtsi | 25 + .../mt7622-ubnt-unifi-6-lr-v2-ubootmod.dts | 35 +- .../dts/mt7622-ubnt-unifi-6-lr-v2.dts | 28 +- .../dts/mt7622-ubnt-unifi-6-lr-v2.dtsi | 26 + .../mt7622-ubnt-unifi-6-lr-v3-ubootmod.dts | 89 + .../dts/mt7622-ubnt-unifi-6-lr-v3.dts | 100 ++ .../dts/mt7622-ubnt-unifi-6-lr-v3.dtsi | 50 + .../mediatek/dts/mt7622-ubnt-unifi-6-lr.dtsi | 25 - .../dts/mt7622-xiaomi-redmi-router-ax6s.dts | 52 +- .../mediatek/dts/mt7623a-unielec-u7623-02.dts | 22 + .../dts/mt7623a-unielec-u7623-02.dtsi | 6 +- .../mediatek/dts/mt7629-iptime-a6004mx.dts | 298 ++++ .../mediatek/dts/mt7629-netgear-ex6250-v2.dts | 242 +++ .../mediatek/dts/mt7629-tplink_eap225-v5.dts | 196 +++ ...3000.dts => mt7981a-comfast-cf-e393ax.dts} | 192 +- .../mediatek/dts/mt7981a-edgecore-eap111.dts | 201 +++ ...mt7981a-glinet-gl-x3000-xe3000-common.dtsi | 273 +++ .../mediatek/dts/mt7981a-glinet-gl-x3000.dts | 8 + .../mediatek/dts/mt7981a-glinet-gl-xe3000.dts | 23 + .../dts/mt7981a-ubnt-unifi-6-plus.dts | 170 ++ .../dts/mt7981b-cetron-ct3003-mod.dts | 23 - .../mediatek/dts/mt7981b-cetron-ct3003.dts | 29 +- .../dts/mt7981b-cmcc-rax3000m-emmc.dts | 42 - .../dts/mt7981b-cmcc-rax3000m-emmc.dtso | 43 + .../dts/mt7981b-cmcc-rax3000m-nand.dts | 92 - .../dts/mt7981b-cmcc-rax3000m-nand.dtso | 127 ++ .../mediatek/dts/mt7981b-cmcc-rax3000m.dts | 10 +- .../dts/mt7981b-confiabits-mt7981.dts | 296 ++++ .../mediatek/dts/mt7981b-cudy-m3000-v1.dts | 214 +++ .../mediatek/dts/mt7981b-cudy-re3000-v1.dts | 221 +++ .../mediatek/dts/mt7981b-cudy-tr3000-v1.dts | 232 +++ .../mediatek/dts/mt7981b-cudy-wr3000-v1.dts | 279 +++ .../mt7981b-dlink-aquila-pro-ai-m30-a1.dts | 310 ++++ .../mediatek/dts/mt7981b-fzs-5gcpe-p3.dts | 268 --- .../mediatek/dts/mt7981b-glinet-gl-mt2500.dts | 56 +- .../mediatek/dts/mt7981b-glinet-gl-mt3000.dts | 37 +- .../dts/mt7981b-h3c-magic-nx30-pro.dts | 15 +- .../mediatek/dts/mt7981b-jcg-q30-pro.dts | 42 +- .../mediatek/dts/mt7981b-nokia-ea0326gmp.dts | 189 +- .../dts/mt7981b-openembed-som7981.dts | 227 +++ .../mediatek/dts/mt7981b-openwrt-one.dts | 457 +++++ .../mediatek/dts/mt7981b-qihoo-360t7.dts | 15 +- .../mediatek/dts/mt7981b-routerich-ax3000.dts | 337 ++++ .../dts/mt7981b-unielec-u7981-01-emmc.dts | 99 ++ .../dts/mt7981b-unielec-u7981-01-nand.dts | 116 ++ .../dts/mt7981b-unielec-u7981-01.dtsi | 124 ++ .../dts/mt7981b-wavlink-wl-wn586x3.dts | 270 +++ .../mediatek/dts/mt7981b-xiaomi-ax3000t.dts | 49 - ...981b-xiaomi-mi-router-ax3000t-ubootmod.dts | 16 + .../dts/mt7981b-xiaomi-mi-router-ax3000t.dts | 34 + .../dts/mt7981b-xiaomi-mi-router-ax3000t.dtsi | 29 + ...i => mt7981b-xiaomi-mi-router-common.dtsi} | 228 +-- .../mt7981b-xiaomi-mi-router-wr30u-stock.dts | 34 + ...t7981b-xiaomi-mi-router-wr30u-ubootmod.dts | 16 + .../dts/mt7981b-xiaomi-mi-router-wr30u.dtsi | 23 + .../mediatek/dts/mt7981b-xiaomi-wr30u.dts | 35 - .../mediatek/dts/mt7981b-yuncore-ax835.dts | 257 +++ .../dts/mt7981b-zbtlink-zbt-z8102ax.dts | 326 ++++ ...01.dts => mt7981b-zbtlink-zbt-z8103ax.dts} | 148 +- .../dts/mt7981b-zyxel-nwa50ax-pro.dts | 229 +++ .../dts/mt7986a-acelink-ew-7886cax.dts | 238 +++ .../mediatek/dts/mt7986a-acer-predator-w6.dts | 507 ++++++ .../mediatek/dts/mt7986a-asus-rt-ax59u.dts | 309 ++++ .../mediatek/dts/mt7986a-asus-tuf-ax4200.dts | 75 +- .../mediatek/dts/mt7986a-asus-tuf-ax6000.dts | 435 +++++ .../dts/mt7986a-bananapi-bpi-r3-mini.dts | 715 ++++++++ .../mediatek/dts/mt7986a-glinet-gl-mt6000.dts | 60 +- .../mediatek/dts/mt7986a-hf-m7986r1-emmc.dts | 100 -- .../mediatek/dts/mt7986a-hf-m7986r1-nand.dts | 76 - .../mediatek/dts/mt7986a-hf-m7986r1.dtsi | 251 --- ...cs-05.dts => mt7986a-jdcloud-re-cp-03.dts} | 306 ++-- .../mediatek/dts/mt7986a-netcore-n60.dts | 36 +- .../dts/mt7986a-ruijie-rg-x60-pro.dts | 42 +- .../mediatek/dts/mt7986a-smartrg-SDG-8612.dts | 76 + .../mediatek/dts/mt7986a-smartrg-SDG-8614.dts | 124 ++ .../mediatek/dts/mt7986a-smartrg-SDG-8622.dts | 38 + .../mediatek/dts/mt7986a-smartrg-SDG-8632.dts | 38 + .../dts/mt7986a-smartrg-bonanza-peak.dtsi | 481 ++++++ .../dts/mt7986a-tplink-tl-xdr-common.dtsi | 56 +- .../dts/mt7986a-tplink-tl-xdr4288.dts | 9 +- .../dts/mt7986a-tplink-tl-xdr6086.dts | 1 - .../dts/mt7986a-tplink-tl-xdr6088.dts | 9 +- .../dts/mt7986a-tplink-tl-xtr8488.dts | 228 --- ...7986a-xiaomi-redmi-router-ax6000-stock.dts | 39 + ...6a-xiaomi-redmi-router-ax6000-ubootmod.dts | 28 + ...> mt7986a-xiaomi-redmi-router-ax6000.dtsi} | 70 +- .../dts/mt7986a-zyxel-ex5601-t0-common.dtsi | 435 +++++ .../dts/mt7986a-zyxel-ex5601-t0-stock.dts | 119 ++ .../dts/mt7986a-zyxel-ex5601-t0-ubootmod.dts | 101 ++ .../dts/mt7986a-zyxel-ex5700-telenor.dts | 375 ++++ .../dts/mt7986b-mercusys-mr90x-v1.dts | 286 +++ .../mediatek/dts/mt7986b-netgear-wax220.dts | 293 ++++ .../mediatek/dts/mt7986b-tplink-re6000xd.dts | 298 ++++ .../mediatek/dts/mt7988a-smartrg-SDG-8733.dts | 17 + .../mediatek/dts/mt7988a-smartrg-SDG-8734.dts | 57 + .../dts/mt7988a-smartrg-mt-stuart.dtsi | 682 ++++++++ .../arch/arm64/boot/dts/mediatek/mt7981.dtsi | 801 --------- .../mt7986a-bananapi-bpi-r3-emmc.dtso | 29 - .../mt7986a-bananapi-bpi-r3-nand.dtso | 55 - .../mediatek/mt7986a-bananapi-bpi-r3-nor.dtso | 63 - .../mediatek/mt7986a-bananapi-bpi-r3-sd.dtso | 23 - .../dts/mediatek/mt7986a-bananapi-bpi-r3.dts | 501 ------ .../dts/mediatek/mt7986a-rfb-spim-nand.dts | 52 - .../dts/mediatek/mt7986a-rfb-spim-nor.dts | 51 - .../arm64/boot/dts/mediatek/mt7986a-rfb.dtsi | 390 ----- .../arch/arm64/boot/dts/mediatek/mt7986a.dtsi | 645 ------- .../arm64/boot/dts/mediatek/mt7986b-rfb.dts | 195 --- .../arch/arm64/boot/dts/mediatek/mt7986b.dtsi | 15 - .../boot/dts/mediatek/mt7988a-rfb-emmc.dtso | 33 - .../dts/mediatek/mt7988a-rfb-eth1-aqr.dtso | 41 - .../mediatek/mt7988a-rfb-eth1-i2p5g-phy.dtso | 30 - .../dts/mediatek/mt7988a-rfb-eth1-mxl.dtso | 39 - .../dts/mediatek/mt7988a-rfb-eth1-sfp.dtso | 47 - .../dts/mediatek/mt7988a-rfb-eth2-aqr.dtso | 41 - .../dts/mediatek/mt7988a-rfb-eth2-mxl.dtso | 39 - .../dts/mediatek/mt7988a-rfb-eth2-sfp.dtso | 47 - .../boot/dts/mediatek/mt7988a-rfb-sd.dtso | 31 - .../dts/mediatek/mt7988a-rfb-snfi-nand.dtso | 69 - .../dts/mediatek/mt7988a-rfb-spim-nand.dtso | 64 - .../dts/mediatek/mt7988a-rfb-spim-nor.dtso | 59 - .../arm64/boot/dts/mediatek/mt7988a-rfb.dts | 200 --- .../arch/arm64/boot/dts/mediatek/mt7988a.dtsi | 1441 ---------------- .../drivers/clk/mediatek/clk-mt7981-apmixed.c | 102 -- .../drivers/clk/mediatek/clk-mt7981-eth.c | 139 -- .../clk/mediatek/clk-mt7981-infracfg.c | 235 --- .../clk/mediatek/clk-mt7981-topckgen.c | 450 ----- .../drivers/clk/mediatek/clk-mt7986-apmixed.c | 100 -- .../drivers/clk/mediatek/clk-mt7986-eth.c | 132 -- .../clk/mediatek/clk-mt7986-infracfg.c | 224 --- .../clk/mediatek/clk-mt7986-topckgen.c | 342 ---- .../drivers/clk/mediatek/clk-mt7988-apmixed.c | 113 -- .../drivers/clk/mediatek/clk-mt7988-eth.c | 299 ---- .../clk/mediatek/clk-mt7988-infracfg.c | 406 ----- .../clk/mediatek/clk-mt7988-topckgen.c | 522 ------ .../drivers/net/phy/mediatek-2p5ge.c | 262 --- .../drivers/pinctrl/mediatek/pinctrl-mt7981.c | 1041 ----------- .../drivers/pinctrl/mediatek/pinctrl-mt7986.c | 1011 ----------- .../drivers/pinctrl/mediatek/pinctrl-mt7988.c | 1466 ---------------- .../dt-bindings/clock/mediatek,mt7981-clk.h | 215 --- .../dt-bindings/clock/mediatek,mt7988-clk.h | 276 --- .../include/dt-bindings/clock/mt7986-clk.h | 169 -- .../include/dt-bindings/reset/mt7986-resets.h | 55 - .../arch/arm64/boot/dts/mediatek/mt7981.dtsi | 808 --------- .../dts/mediatek/mt7986a-rfb-spim-nand.dts | 52 - .../dts/mediatek/mt7986a-rfb-spim-nor.dts | 51 - .../arm64/boot/dts/mediatek/mt7986a-rfb.dtsi | 389 ----- .../boot/dts/mediatek/mt7988a-rfb-emmc.dtso | 33 - .../dts/mediatek/mt7988a-rfb-eth1-aqr.dtso | 41 - .../mediatek/mt7988a-rfb-eth1-i2p5g-phy.dtso | 30 - .../dts/mediatek/mt7988a-rfb-eth1-mxl.dtso | 39 - .../dts/mediatek/mt7988a-rfb-eth1-sfp.dtso | 47 - .../dts/mediatek/mt7988a-rfb-eth2-aqr.dtso | 41 - .../dts/mediatek/mt7988a-rfb-eth2-mxl.dtso | 39 - .../dts/mediatek/mt7988a-rfb-eth2-sfp.dtso | 47 - .../boot/dts/mediatek/mt7988a-rfb-sd.dtso | 31 - .../dts/mediatek/mt7988a-rfb-snfi-nand.dtso | 69 - .../dts/mediatek/mt7988a-rfb-spim-nand.dtso | 64 - .../dts/mediatek/mt7988a-rfb-spim-nor.dtso | 59 - .../arm64/boot/dts/mediatek/mt7988a-rfb.dts | 200 --- .../arch/arm64/boot/dts/mediatek/mt7988a.dtsi | 1441 ---------------- .../drivers/clk/mediatek/clk-mt7988-apmixed.c | 113 -- .../drivers/clk/mediatek/clk-mt7988-eth.c | 141 -- .../clk/mediatek/clk-mt7988-infracfg.c | 376 ---- .../clk/mediatek/clk-mt7988-topckgen.c | 446 ----- .../drivers/net/phy/mediatek-2p5ge.c | 262 --- .../drivers/pinctrl/mediatek/pinctrl-mt7988.c | 1466 ---------------- .../dt-bindings/clock/mediatek,mt7988-clk.h | 276 --- .../arch/arm64/boot/dts/mediatek/mt7988a.dtsi | 14 +- .../mediatek/files/block/partitions/fit.c | 2 +- .../files/drivers/net/phy/mtk/mt753x/Kconfig | 3 - .../files/drivers/net/phy/mtk/mt753x/Makefile | 11 - .../files/drivers/net/phy/mtk/mt753x/mt7530.c | 631 ------- .../files/drivers/net/phy/mtk/mt753x/mt7530.h | 13 - .../files/drivers/net/phy/mtk/mt753x/mt7531.c | 918 ---------- .../files/drivers/net/phy/mtk/mt753x/mt7531.h | 13 - .../files/drivers/net/phy/mtk/mt753x/mt753x.h | 213 --- .../net/phy/mtk/mt753x/mt753x_common.c | 90 - .../drivers/net/phy/mtk/mt753x/mt753x_mdio.c | 597 ------- .../drivers/net/phy/mtk/mt753x/mt753x_nl.c | 382 ---- .../drivers/net/phy/mtk/mt753x/mt753x_nl.h | 43 - .../drivers/net/phy/mtk/mt753x/mt753x_regs.h | 294 ---- .../net/phy/mtk/mt753x/mt753x_swconfig.c | 510 ------ .../net/phy/mtk/mt753x/mt753x_swconfig.h | 29 - .../drivers/net/phy/mtk/mt753x/mt753x_vlan.c | 183 -- .../drivers/net/phy/mtk/mt753x/mt753x_vlan.h | 40 - .../files/drivers/net/phy/rtk/rtl8367c/acl.c | 30 +- .../files/drivers/net/phy/rtk/rtl8367c/cpu.c | 4 +- .../files/drivers/net/phy/rtk/rtl8367c/igmp.c | 10 +- .../net/phy/rtk/rtl8367c/include/acl.h | 32 +- .../net/phy/rtk/rtl8367c/include/cpu.h | 6 +- .../net/phy/rtk/rtl8367c/include/dot1x.h | 2 +- .../net/phy/rtk/rtl8367c/include/eee.h | 2 +- .../net/phy/rtk/rtl8367c/include/i2c.h | 2 +- .../net/phy/rtk/rtl8367c/include/igmp.h | 12 +- .../net/phy/rtk/rtl8367c/include/interrupt.h | 2 +- .../drivers/net/phy/rtk/rtl8367c/include/l2.h | 50 +- .../net/phy/rtk/rtl8367c/include/leaky.h | 2 +- .../net/phy/rtk/rtl8367c/include/led.h | 20 +- .../net/phy/rtk/rtl8367c/include/mirror.h | 8 +- .../net/phy/rtk/rtl8367c/include/port.h | 34 +- .../net/phy/rtk/rtl8367c/include/ptp.h | 4 +- .../net/phy/rtk/rtl8367c/include/qos.h | 8 +- .../net/phy/rtk/rtl8367c/include/rate.h | 2 +- .../net/phy/rtk/rtl8367c/include/rtk_error.h | 8 +- .../net/phy/rtk/rtl8367c/include/rtk_switch.h | 8 +- .../net/phy/rtk/rtl8367c/include/rtk_types.h | 4 +- .../include/rtl8367c_asicdrv_cputag.h | 2 +- .../rtl8367c/include/rtl8367c_asicdrv_green.h | 2 +- .../rtl8367c/include/rtl8367c_asicdrv_qos.h | 2 +- .../rtl8367c_asicdrv_unknownMulticast.h | 2 +- .../phy/rtk/rtl8367c/include/rtl8367c_base.h | 2 +- .../phy/rtk/rtl8367c/include/rtl8367c_reg.h | 4 +- .../files/drivers/net/phy/rtk/rtl8367c/l2.c | 48 +- .../files/drivers/net/phy/rtk/rtl8367c/led.c | 16 +- .../drivers/net/phy/rtk/rtl8367c/mirror.c | 4 +- .../files/drivers/net/phy/rtk/rtl8367c/port.c | 38 +- .../files/drivers/net/phy/rtk/rtl8367c/ptp.c | 2 +- .../files/drivers/net/phy/rtk/rtl8367c/qos.c | 8 +- .../files/drivers/net/phy/rtk/rtl8367c/rldp.c | 4 +- .../drivers/net/phy/rtk/rtl8367c/rtk_switch.c | 10 +- .../phy/rtk/rtl8367c/rtl8367c_asicdrv_acl.c | 34 +- .../rtk/rtl8367c/rtl8367c_asicdrv_cputag.c | 26 +- .../phy/rtk/rtl8367c/rtl8367c_asicdrv_eav.c | 18 +- .../phy/rtk/rtl8367c/rtl8367c_asicdrv_fc.c | 4 +- .../phy/rtk/rtl8367c/rtl8367c_asicdrv_green.c | 16 +- .../phy/rtk/rtl8367c/rtl8367c_asicdrv_hsb.c | 2 +- .../phy/rtk/rtl8367c/rtl8367c_asicdrv_igmp.c | 20 +- .../rtk/rtl8367c/rtl8367c_asicdrv_inbwctrl.c | 4 +- .../rtk/rtl8367c/rtl8367c_asicdrv_interrupt.c | 4 +- .../phy/rtk/rtl8367c/rtl8367c_asicdrv_led.c | 2 +- .../phy/rtk/rtl8367c/rtl8367c_asicdrv_lut.c | 60 +- .../phy/rtk/rtl8367c/rtl8367c_asicdrv_mib.c | 18 +- .../phy/rtk/rtl8367c/rtl8367c_asicdrv_port.c | 8 +- .../phy/rtk/rtl8367c/rtl8367c_asicdrv_qos.c | 2 +- .../rtl8367c/rtl8367c_asicdrv_scheduling.c | 8 +- .../phy/rtk/rtl8367c/rtl8367c_asicdrv_svlan.c | 16 +- .../rtl8367c_asicdrv_unknownMulticast.c | 2 +- .../files/drivers/net/phy/rtk/rtl8367c/smi.c | 4 +- .../files/drivers/net/phy/rtk/rtl8367c/stat.c | 8 +- .../drivers/net/phy/rtk/rtl8367c/storm.c | 24 +- .../drivers/net/phy/rtk/rtl8367c/svlan.c | 40 +- .../files/drivers/net/phy/rtk/rtl8367c/vlan.c | 12 +- .../files/drivers/net/phy/rtk/rtl8367s_mdio.c | 4 +- .../filogic/base-files/etc/board.d/01_leds | 117 +- .../filogic/base-files/etc/board.d/02_network | 170 +- .../base-files/etc/board.d/03_gpio_switches | 19 + .../base-files/etc/board.d/05_compat-version | 2 +- .../etc/hotplug.d/firmware/11-mt76-caldata | 44 +- .../etc/hotplug.d/ieee80211/11_fix_wifi_mac | 130 +- .../filogic/base-files/etc/init.d/bootcount | 19 + .../etc/uci-defaults/05_fix-compat-version | 2 +- .../lib/preinit/04_set_netdev_label | 15 + .../lib/preinit/05_extract_factory_data.sh | 25 + .../base-files/lib/preinit/09_mount_cfg_part | 24 + .../base-files/lib/preinit/10_fix_eth_mac.sh | 37 +- .../base-files/lib/preinit/75_rootfs_prepare | 35 + .../base-files/lib/preinit/81_fix_eeprom | 23 - .../base-files/lib/upgrade/platform.sh | 208 ++- target/linux/mediatek/filogic/config-5.15 | 442 ----- target/linux/mediatek/filogic/config-6.1 | 473 ----- target/linux/mediatek/filogic/config-6.6 | 1 - target/linux/mediatek/filogic/target.mk | 2 +- target/linux/mediatek/image/Makefile | 6 + target/linux/mediatek/image/filogic.mk | 1112 ++++++++++-- target/linux/mediatek/image/mt7622.mk | 203 ++- target/linux/mediatek/image/mt7623.mk | 10 + target/linux/mediatek/image/mt7629.mk | 56 + .../mt7622/base-files/etc/board.d/02_network | 42 +- .../base-files/etc/board.d/05_compat-version | 5 +- .../etc/hotplug.d/ieee80211/11_fix_wifi_mac | 9 + .../mt7622/base-files/etc/init.d/bootcount | 8 + .../etc/uci-defaults/05_fix-compat-version | 9 + .../base-files/etc/uci-defaults/09_fix_crc | 4 + .../mt7622/base-files/lib/upgrade/platform.sh | 53 +- target/linux/mediatek/mt7622/config-5.15 | 464 ----- target/linux/mediatek/mt7622/config-6.1 | 472 ----- target/linux/mediatek/mt7622/target.mk | 2 +- .../base-files/etc/board.d/05_compat-version | 14 + .../etc/uci-defaults/05_fix-compat-version | 10 + .../mt7623/base-files/lib/upgrade/platform.sh | 8 +- target/linux/mediatek/mt7623/config-5.15 | 579 ------- target/linux/mediatek/mt7623/config-6.1 | 609 ------- target/linux/mediatek/mt7623/target.mk | 2 +- .../mt7629/base-files/etc/board.d/01_leds | 20 + .../mt7629/base-files/etc/board.d/02_network | 15 + .../mt7629/base-files/etc/init.d/bootcount | 17 + .../mt7629/base-files/lib/upgrade/platform.sh | 3 + target/linux/mediatek/mt7629/config-5.15 | 328 ---- target/linux/mediatek/mt7629/config-6.1 | 349 ---- .../100-dts-update-mt7622-rfb1.patch | 119 -- .../101-dts-update-mt7629-rfb.patch | 60 - .../103-mt7623-enable-arch-timer.patch | 20 - .../104-mt7622-add-snor-irq.patch | 10 - .../105-dts-mt7622-enable-pstore.patch | 25 - .../110-dts-fix-bpi2-console.patch | 10 - .../111-dts-fix-bpi64-console.patch | 11 - .../112-dts-fix-bpi64-lan-names.patch | 37 - .../113-dts-fix-bpi64-leds-and-buttons.patch | 56 - .../114-dts-bpi64-disable-rtc.patch | 21 - .../115-dts-bpi64-add-snand-support.patch | 50 - ...-infrastructure-to-support-hardware-.patch | 214 --- ...ew-helper-to-retrieve-the-ECC-contex.patch | 31 - ...vide-a-helper-to-retrieve-a-pileline.patch | 73 - ...mem-Introduce-a-capability-structure.patch | 71 - ...ck-the-controller-extra-capabilities.patch | 51 - ...l-the-spi_mem_dtr_supports_op-helper.patch | 111 -- ...an-ecc-parameter-to-the-spi_mem_op-s.patch | 72 - ...lay-a-little-bit-the-dirmap-creation.patch | 50 - ...te-direct-mapping-descriptors-for-EC.patch | 98 -- ...nd-make-mtk_ecc.c-a-separated-module.patch | 1383 --------------- ...ver-for-MTK-SPI-NAND-Flash-Interface.patch | 1537 ----------------- ...-also-parse-nand-ecc-engine-if-avail.patch | 30 - ...dts-mediatek-add-mtk-snfi-for-mt7622.patch | 35 - .../121-hack-spi-nand-1b-bbm.patch | 20 - .../130-dts-mt7629-add-snand-support.patch | 94 - .../131-dts-mt7622-add-snand-support.patch | 68 - ...dts-fix-wmac-support-for-mt7622-rfb1.patch | 18 - ...s-mt7623-eip97-inside-secure-support.patch | 24 - .../160-dts-mt7623-bpi-r2-earlycon.patch | 11 - ...1-dts-mt7623-bpi-r2-mmc-device-order.patch | 11 - .../162-dts-mt7623-bpi-r2-led-aliases.patch | 29 - ...163-dts-mt7623-bpi-r2-ethernet-alias.patch | 10 - ...arm-dts-mt7623-add-musb-device-nodes.patch | 69 - ...80-dts-mt7622-bpi-r64-add-mt7531-irq.patch | 13 - ...-dts-mediatek-mt7622-fix-GICv2-range.patch | 106 -- ...mt7622-specify-the-L2-cache-topology.patch | 132 -- ...2-specify-the-number-of-DMA-requests.patch | 122 -- .../193-dts-mt7623-thermal_zone_fix.patch | 48 - .../194-dts-mt7968a-add-ramoops.patch | 17 - ...i-r3-leds-port-names-and-wifi-eeprom.patch | 196 --- ...-phy-phy-mtk-tphy-Add-hifsys-support.patch | 66 - ...-mediatek-add-support-for-MT7986-SoC.patch | 26 - ...k-Add-API-for-clock-resource-recycle.patch | 28 - ...lk-mediatek-add-mt7986-clock-support.patch | 39 - ...-spi-mediatek-add-mt7986-spi-support.patch | 917 ---------- ...lk-mediatek-add-mt7981-clock-support.patch | 39 - ...dblock-revert-warn-if-opened-on-NAND.patch | 26 - ...-mediatek-add-support-for-MT7981-SoC.patch | 26 - ...-mediatek-add-support-for-MT7988-SoC.patch | 26 - ...k-mediatek-Add-pcw-chg-shift-control.patch | 24 - ...lk-mediatek-add-mt7988-clock-support.patch | 31 - ...-mediatek-add-support-for-MT7986-SoC.patch | 44 - .../330-snand-mtk-bmt-support.patch | 34 - .../331-mt7622-rfb1-enable-bmt.patch | 10 - ...Add-support-for-the-Fidelix-FM35X1GA.patch | 122 -- ...-Cleanup-variables-and-error-handlin.patch | 166 -- ...ufreq-mediatek-Remove-unused-headers.patch | 25 - ...ediatek-Enable-clocks-and-regulators.patch | 117 -- ...diatek-Use-device-print-to-show-logs.patch | 161 -- ...freq-mediatek-Replace-old_-with-pre_.patch | 201 --- ...k-Record-previous-target-vproc-value.patch | 64 - ...ediatek-Make-sram-regulator-optional.patch | 30 - ...-Fix-NULL-pointer-dereference-in-med.patch | 32 - ...-Move-voltage-limits-to-platform-dat.patch | 227 --- ...-Refine-mtk_cpufreq_voltage_tracking.patch | 255 --- ...ediatek-Add-opp-notification-support.patch | 184 -- ...-Fix-potential-deadlock-problem-in-m.patch | 43 - ...freq-mediatek-Link-CCI-device-to-CPU.patch | 188 -- ...freq-mediatek-Add-support-for-MT8186.patch | 42 - ...-Handle-sram-regulator-probe-deferra.patch | 35 - ...-fix-error-return-code-in-mtk_cpu_dv.patch | 29 - ...mediatek-fix-passing-zero-to-PTR_ERR.patch | 47 - ...-fix-KP-caused-by-handler-usage-afte.patch | 149 -- ...-raise-proc-sram-max-voltage-for-MT8.patch | 55 - ...-Raise-proc-and-sram-max-voltage-for.patch | 58 - ...freq-mediatek-Add-support-for-MT7988.patch | 41 - ...-correct-voltages-for-MT7622-and-MT7.patch | 53 - ...ypto-add-eip97-inside-secure-support.patch | 27 - ...01-crypto-fix-eip97-cache-incoherent.patch | 26 - .../405-mt7986-trng-add-rng-support.patch | 41 - .../patches-5.15/410-bt-mtk-serial-fix.patch | 33 - ...or-add-support-for-Winbond-W25Q512JV.patch | 28 - ...xx-Move-chip_config-to-driver-s-priv.patch | 130 -- ...-Add-support-for-dynamic-calibration.patch | 236 --- ...ers-spi-mem-Add-spi-calibration-hook.patch | 41 - ...xx-Add-controller-s-calibration-para.patch | 43 - ...and-Add-calibration-support-for-spin.patch | 81 - ...nor-Add-calibration-support-for-spi-.patch | 57 - .../500-gsw-rtl8367s-mt7622-support.patch | 25 - ...ek-Split-PCIe-node-for-MT2712-and-MT.patch | 332 ---- ...ert-PERST-for-100ms-for-power-and-cl.patch | 34 - ...s-mediatek-add-mt7622-pcie-slot-node.patch | 28 - ...dts-mediatek-Update-mt7629-PCIe-node.patch | 203 --- ...diatek-fix-clearing-interrupt-status.patch | 23 - ...pers-to-extract-clause-45-regad-and-.patch | 53 - ..._eth_soc-implement-Clause-45-MDIO-ac.patch | 128 -- ...ediatek-add-support-for-coherent-DMA.patch | 91 - .../721-dts-mt7622-mediatek-fix-300mhz.patch | 27 - .../722-remove-300Hz-to-prevent-freeze.patch | 25 - ...er-for-MediaTek-SoC-built-in-GE-PHYs.patch | 1204 ------------- ...-ge-soc-initialize-MT7988-PHY-LEDs-d.patch | 213 --- ...-don-t-use-SGMII-AN-if-using-phylink.patch | 63 - ...phy-add-driver-for-MediaTek-2.5G-PHY.patch | 39 - ...support-minimum-one-byte-access-stri.patch | 47 - ...k-tphy-Add-PCIe-2-lane-efuse-support.patch | 225 --- ...-add-auto-load-valid-check-mechanism.patch | 149 -- .../804-pwm-add-mt7986-support.patch | 23 - ...mtk-use-function-pointer-for-raw_to_.patch | 56 - ...ek-add-support-for-MT7986-and-MT7981.patch | 240 --- ...-pwm-mediatek-Add-support-for-MT7981.patch | 122 -- ...dings-pinctrl-mt8195-add-rsel-define.patch | 33 - ...-moore-check-if-pin_desc-is-valid-be.patch | 93 - ...inctrl-mediatek-support-rsel-feature.patch | 457 ----- ...-add-a-check-for-error-in-mtk_pincon.patch | 31 - ...-Fix-EINT-pins-input-debounce-time-c.patch | 297 ---- ...mediatek-Export-debounce-time-tables.patch | 37 - ...-extend-pinctrl-moore-to-support-new.patch | 129 -- ...dd-bindings-for-Richtek-RT5190A-PMIC.patch | 180 -- ...a-Add-support-for-Richtek-RT5190A-PM.patch | 562 ------ ...et-the-handshake-signal-between-i2c-.patch | 74 - ...p-i2c-dma-register-when-a-timeout-oc.patch | 102 -- ...d-i2c-compatible-for-Mediatek-MT8186.patch | 45 - ...modify-bus-speed-calculation-formula.patch | 132 -- ...mediatek-remove-redundant-null-check.patch | 41 - ...18-i2c-mt65xx-Simplify-with-clk-bulk.patch | 234 --- ...d-i2c-compatible-for-Mediatek-MT8168.patch | 46 - ...imize-master_xfer-and-avoid-circular.patch | 101 -- ...-an-error-handling-path-in-mtk_i2c_p.patch | 48 - ...diatek-add-i2c-compatible-for-MT8188.patch | 82 - ...move-drivers-from-strlcpy-to-strscpy.patch | 579 ------- ...v6.2-i2c-mediatek-add-mt7986-support.patch | 44 - ...evm_platform_get_and_ioremap_resourc.patch | 42 - ...t65xx-drop-of_match_ptr-for-ID-table.patch | 33 - ...-mediatek-add-support-for-MT7981-SoC.patch | 47 - ...mt7622-bpi-r64-aliases-for-dtoverlay.patch | 65 - .../901-arm-add-cmdline-override.patch | 54 - .../910-dts-mt7622-bpi-r64-wifi-eeprom.patch | 31 - ...g-mtk-add-disable_wdt_extrst-support.patch | 50 - ...t-mt7986-Add-toprgu-reset-controller.patch | 49 - ...3-change-driver-name-to-mtk-pcie-gen.patch | 20 - .../930-spi-mt65xx-enable-sel-clk.patch | 29 - ..._wed-rename-mtk_wed_get_memory_regio.patch | 44 - ...986-move-cpuboot-in-a-dedicated-node.patch | 66 - ..._wed-move-cpuboot-in-a-dedicated-dts.patch | 89 - ...tk_wed-move-ilm-a-dedicated-dts-node.patch | 91 - ...tk_wed-move-dlm-a-dedicated-dts-node.patch | 57 - ...-mt7986-move-ilm-in-a-dedicated-node.patch | 83 - ...-mt7986-move-dlm-in-a-dedicated-node.patch | 81 - ...-overlays-to-built-from-.dtso-named-.patch | 44 - ...ek-mt7986-add-support-for-RX-Wireles.patch | 106 -- ...s-mt7986-harmonize-device-node-order.patch | 166 -- ...7986-add-crypto-related-device-nodes.patch | 68 - ...4-v6.2-arm64-dts-mt7986-add-i2c-node.patch | 37 - ...s-mediatek-mt7986-Add-SoC-compatible.patch | 61 - ...-mt7986-add-spi-related-device-nodes.patch | 157 -- ...-mt7986-add-usb-related-device-nodes.patch | 127 -- ...-mt7986-add-mmc-related-device-nodes.patch | 160 -- ...mt7986-add-pcie-related-device-nodes.patch | 118 -- ...6.3-arm64-dts-mt7986-add-Bananapi-R3.patch | 689 -------- ...ropagate-chassis-type-where-possible.patch | 323 ---- .../012-v6.5-arm64-dts-mt7986-add-PWM.patch | 38 - ...5-arm64-dts-mt7986-add-PWM-to-BPI-R3.patch | 43 - ...-set-Wifi-Leds-low-active-for-BPI-R3.patch | 27 - ...-use-size-of-reserved-partition-for-.patch | 46 - ...m64-dts-mt7986-add-thermal-and-efuse.patch | 80 - ...5-arm64-dts-mt7986-add-thermal-zones.patch | 51 - ...-add-pwm-fan-and-cooling-maps-to-BPI.patch | 64 - ...-increase-bl2-partition-on-NAND-of-B.patch | 41 - ...-define-3W-max-power-to-both-SFP-on-.patch | 34 - ...rm64-dts-mt7986-change-cooling-trips.patch | 59 - ...t7986-change-thermal-trips-on-BPI-R3.patch | 38 - .../100-dts-update-mt7622-rfb1.patch | 107 -- .../101-dts-update-mt7629-rfb.patch | 60 - .../103-mt7623-enable-arch-timer.patch | 20 - .../patches-6.1/104-mt7622-add-snor-irq.patch | 10 - .../105-dts-mt7622-enable-pstore.patch | 16 - .../110-dts-fix-bpi2-console.patch | 10 - .../111-dts-fix-bpi64-console.patch | 11 - .../112-dts-fix-bpi64-lan-names.patch | 37 - .../113-dts-fix-bpi64-leds-and-buttons.patch | 47 - .../114-dts-bpi64-disable-rtc.patch | 21 - .../115-dts-bpi64-add-snand-support.patch | 50 - .../121-hack-spi-nand-1b-bbm.patch | 20 - .../130-dts-mt7629-add-snand-support.patch | 94 - .../131-dts-mt7622-add-snand-support.patch | 68 - ...dts-fix-wmac-support-for-mt7622-rfb1.patch | 18 - ...s-mt7623-eip97-inside-secure-support.patch | 24 - .../160-dts-mt7623-bpi-r2-earlycon.patch | 11 - ...1-dts-mt7623-bpi-r2-mmc-device-order.patch | 11 - .../162-dts-mt7623-bpi-r2-led-aliases.patch | 29 - ...163-dts-mt7623-bpi-r2-ethernet-alias.patch | 10 - ...80-dts-mt7622-bpi-r64-add-mt7531-irq.patch | 13 - ...-dts-mediatek-mt7622-fix-GICv2-range.patch | 106 -- .../193-dts-mt7623-thermal_zone_fix.patch | 48 - .../194-dts-mt7968a-add-ramoops.patch | 17 - ...i-r3-leds-port-names-and-wifi-eeprom.patch | 196 --- ...-phy-phy-mtk-tphy-Add-hifsys-support.patch | 66 - ...llow-configuring-uart-rx-tx-and-rts-.patch | 88 - ...-add-pull_type-attribute-for-mediate.patch | 100 -- ....3-pinctrl-add-mt7981-pinctrl-driver.patch | 1094 ------------ ...-add-missing-options-to-PINCTRL_MT79.patch | 30 - ...diatek-fix-pull_type-data-for-MT7981.patch | 76 - ...ek-mt7981-add-additional-uart-groups.patch | 65 - ...-assign-functions-to-configure-pin-b.patch | 41 - ...mux-Propagate-struct-device-where-po.patch | 140 -- ...mediatek-clk-mtk-Add-dummy-clock-ops.patch | 74 - ...tch-to-mtk_clk_simple_probe-where-po.patch | 790 --------- ...-mt7986-topckgen-Properly-keep-some-.patch | 97 -- ...-mt7986-topckgen-Migrate-to-mtk_clk_.patch | 88 - ...986-apmixed-Use-PLL_AO-flag-to-set-c.patch | 38 - ...-clock-mediatek-add-mt7981-clock-IDs.patch | 237 --- ...lk-mediatek-add-MT7981-clock-support.patch | 932 ---------- ...-mediatek-add-support-for-MT7988-SoC.patch | 26 - ...k-mediatek-Add-pcw-chg-shift-control.patch | 24 - ...lk-mediatek-add-mt7988-clock-support.patch | 31 - ...-mediatek-add-support-for-MT7986-SoC.patch | 47 - ...d-Inline-Crypto-Engine-clock-control.patch | 57 - ...fix-two-spelling-mistakes-in-comment.patch | 36 - ...d-open-coding-by-using-mmc_op_tuning.patch | 39 - .../330-snand-mtk-bmt-support.patch | 34 - .../331-mt7622-rfb1-enable-bmt.patch | 10 - ...Add-support-for-the-Fidelix-FM35X1GA.patch | 122 -- ...freq-mediatek-Add-support-for-MT7988.patch | 41 - ...ypto-add-eip97-inside-secure-support.patch | 27 - ...01-crypto-fix-eip97-cache-incoherent.patch | 26 - ...405-v6.2-mt7986-trng-add-rng-support.patch | 43 - .../patches-6.1/410-bt-mtk-serial-fix.patch | 33 - ...xx-Move-chip_config-to-driver-s-priv.patch | 130 -- ...-Add-support-for-dynamic-calibration.patch | 236 --- ...ers-spi-mem-Add-spi-calibration-hook.patch | 41 - ...xx-Add-controller-s-calibration-para.patch | 43 - ...and-Add-calibration-support-for-spin.patch | 81 - ...nor-Add-calibration-support-for-spi-.patch | 57 - .../500-gsw-rtl8367s-mt7622-support.patch | 25 - ...ert-PERST-for-100ms-for-power-and-cl.patch | 34 - ...s-mediatek-add-mt7622-pcie-slot-node.patch | 28 - ...diatek-fix-clearing-interrupt-status.patch | 23 - ...ediatek-add-support-for-coherent-DMA.patch | 91 - .../721-dts-mt7622-mediatek-fix-300mhz.patch | 27 - .../722-remove-300Hz-to-prevent-freeze.patch | 25 - ...er-for-MediaTek-SoC-built-in-GE-PHYs.patch | 1204 ------------- ...phy-mediatek-ge-soc-support-PHY-LEDs.patch | 524 ------ ...-don-t-use-SGMII-AN-if-using-phylink.patch | 63 - ...phy-add-driver-for-MediaTek-2.5G-PHY.patch | 39 - .../804-pwm-add-mt7986-support.patch | 23 - ...mtk-use-function-pointer-for-raw_to_.patch | 56 - ...ek-add-support-for-MT7986-and-MT7981.patch | 240 --- ...-extend-pinctrl-moore-to-support-new.patch | 129 -- ...v6.2-i2c-mediatek-add-mt7986-support.patch | 44 - ...evm_platform_get_and_ioremap_resourc.patch | 42 - ...t65xx-drop-of_match_ptr-for-ID-table.patch | 33 - ...-mediatek-add-support-for-MT7981-SoC.patch | 47 - ...mt7622-bpi-r64-aliases-for-dtoverlay.patch | 65 - .../901-arm-add-cmdline-override.patch | 54 - .../910-dts-mt7622-bpi-r64-wifi-eeprom.patch | 31 - .../930-spi-mt65xx-enable-sel-clk.patch | 18 - ..._wed-rename-mtk_wed_get_memory_regio.patch | 44 - ...986-move-cpuboot-in-a-dedicated-node.patch | 66 - ..._wed-move-cpuboot-in-a-dedicated-dts.patch | 89 - ...tk_wed-move-ilm-a-dedicated-dts-node.patch | 91 - ...tk_wed-move-dlm-a-dedicated-dts-node.patch | 57 - ...-mt7986-move-ilm-in-a-dedicated-node.patch | 83 - ...-mt7986-move-dlm-in-a-dedicated-node.patch | 81 - 952 files changed, 38372 insertions(+), 66750 deletions(-) delete mode 100644 doc/h68k.jpg delete mode 100644 doc/r1.jpg delete mode 100644 doc/star.png delete mode 100644 package/firmware/ath11k-wifi/Makefile delete mode 100644 package/firmware/ath11k-wifi/board-2.bin.IPQ6018 delete mode 100644 package/firmware/ath11k-wifi/board-edgecore-eap102.bin.IPQ8074 delete mode 100644 package/firmware/ath11k-wifi/board-gl-ax1800.bin.IPQ6018 delete mode 100644 package/firmware/ath11k-wifi/board-gl-axt1800.bin.IPQ6018 delete mode 100644 package/firmware/ath11k-wifi/qdss_trace_config.bin delete mode 100755 package/firmware/b43legacy-firmware/Makefile create mode 100644 package/firmware/cypress-nvram/files/brcmfmac4339-sdio.AP6335.txt delete mode 100644 package/firmware/ipq-wifi/board-8dev_habanero-dvk.qca4019 delete mode 100644 package/firmware/ipq-wifi/board-aruba_ap-303.qca4019 delete mode 100644 package/firmware/ipq-wifi/board-asus_rt-acrh17.qca4019 delete mode 100644 package/firmware/ipq-wifi/board-avm_fritzrepeater-1200.qca4019 delete mode 100644 package/firmware/ipq-wifi/board-buffalo_wtr-m2133hp.qca4019 delete mode 100644 package/firmware/ipq-wifi/board-buffalo_wtr-m2133hp.qca9984 delete mode 100644 package/firmware/ipq-wifi/board-cellc_rtl30vw.qca4019 delete mode 100644 package/firmware/ipq-wifi/board-century_wr142ac.qca4019 delete mode 100644 package/firmware/ipq-wifi/board-devolo_magic-2-wifi-next.qca4019 delete mode 100644 package/firmware/ipq-wifi/board-dlink_dap2610.qca4019 delete mode 100644 package/firmware/ipq-wifi/board-edgecore_ecw5410.qca9984 delete mode 100644 package/firmware/ipq-wifi/board-edgecore_oap100.qca4019 delete mode 100644 package/firmware/ipq-wifi/board-engenius_eap2200.qca4019 delete mode 100644 package/firmware/ipq-wifi/board-engenius_eap2200.qca9888 delete mode 100644 package/firmware/ipq-wifi/board-engenius_emd1.qca4019 delete mode 100644 package/firmware/ipq-wifi/board-engenius_emr3500.qca4019 delete mode 100644 package/firmware/ipq-wifi/board-ezviz_cs-w3-wd1200g-eup.qca4019 delete mode 100644 package/firmware/ipq-wifi/board-glinet_gl-a1300.qca4019 delete mode 100644 package/firmware/ipq-wifi/board-glinet_gl-ap1300.qca4019 delete mode 100644 package/firmware/ipq-wifi/board-glinet_gl-s1300.qca4019 delete mode 100644 package/firmware/ipq-wifi/board-hiwifi_c526a.qca4019 delete mode 100644 package/firmware/ipq-wifi/board-linksys_ea8300.qca4019 delete mode 100644 package/firmware/ipq-wifi/board-linksys_ea8300.qca9888 delete mode 100644 package/firmware/ipq-wifi/board-linksys_mr8300-v0.qca4019 delete mode 100644 package/firmware/ipq-wifi/board-linksys_mr8300-v0.qca9888 delete mode 100644 package/firmware/ipq-wifi/board-luma_wrtq-329acn.qca4019 delete mode 100644 package/firmware/ipq-wifi/board-mikrotik_hap-ac2.qca4019 delete mode 100644 package/firmware/ipq-wifi/board-mikrotik_sxtsq-5-ac.qca4019 delete mode 100644 package/firmware/ipq-wifi/board-mobipromo_cm520-79f.qca4019 delete mode 100644 package/firmware/ipq-wifi/board-nec_wg2600hp3.qca9984 delete mode 100644 package/firmware/ipq-wifi/board-netgear_sxr80.ipq8074 delete mode 100644 package/firmware/ipq-wifi/board-p2w_r619ac.qca4019 delete mode 100644 package/firmware/ipq-wifi/board-plasmacloud_pa1200.qca4019 delete mode 100644 package/firmware/ipq-wifi/board-plasmacloud_pa2200.qca4019 delete mode 100644 package/firmware/ipq-wifi/board-plasmacloud_pa2200.qca9888 delete mode 100644 package/firmware/ipq-wifi/board-qnap_301w.ipq8074 delete mode 100644 package/firmware/ipq-wifi/board-qxwlan_e2600ac.qca4019 delete mode 100644 package/firmware/ipq-wifi/board-redmi_ax6.ipq8074 delete mode 100755 package/firmware/ipq-wifi/board-tplink_xtr10890.ipq8074 delete mode 100644 package/firmware/ipq-wifi/board-xiaomi_ax3600.ipq8074 delete mode 100644 package/firmware/ipq-wifi/board-xiaomi_ax3600.qca9889 delete mode 100644 package/firmware/ipq-wifi/board-xiaomi_ax9000.ipq8074 delete mode 100755 package/firmware/ipq-wifi/board-zte_mf263.qca4019 delete mode 100755 package/firmware/ipq-wifi/board-zte_mf269.ipq8074 create mode 100644 package/firmware/ipq-wifi/src/board-jdcloud_ax1800pro.ipq6018 create mode 100644 package/firmware/ipq-wifi/src/board-jdcloud_ax6600.ipq6018 create mode 100644 package/firmware/ipq-wifi/src/board-qihoo_360v6.ipq6018 create mode 100644 package/firmware/ipq-wifi/src/board-redmi_ax5-jdcloud.ipq6018 create mode 100644 package/firmware/ipq-wifi/src/board-xiaomi_rm1800.ipq6018 rename package/firmware/{ath11k-wifi/board-qihoo_360v6.bin.IPQ6018 => ipq-wifi/src/board-zn_m2.ipq6018} (86%) create mode 100644 package/firmware/linux-firmware/airoha.mk mode change 100644 => 100755 package/firmware/linux-firmware/brcm_firmware/ap6236/brcmfmac43430-sdio.bin mode change 100644 => 100755 package/firmware/linux-firmware/brcm_firmware/ap6236/brcmfmac43430-sdio.txt delete mode 100644 package/firmware/linux-firmware/brcm_firmware/ap6356s/brcmfmac4356-sdio.rongpin,king3399.bin delete mode 100644 package/firmware/linux-firmware/brcm_firmware/ap6356s/brcmfmac4356-sdio.rongpin,king3399.txt create mode 100644 package/firmware/linux-firmware/mellanox.mk create mode 100644 package/firmware/photonicat-firmware/Makefile create mode 100644 package/firmware/photonicat-firmware/files/board.bin create mode 100644 package/firmware/photonicat-firmware/files/firmware-sdio-5.bin create mode 100644 package/kernel/cryptodev-linux/patches/0005-fix-build-for-linux-5.10.220+.patch create mode 100644 package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh create mode 100644 package/kernel/mac80211/files/lib/wifi/mac80211.sh create mode 100644 package/kernel/mac80211/files/mac80211.hotplug create mode 100644 package/kernel/mac80211/patches/ath10k/911-ath10k-disable-caldata-prefetch-for-sdio-bus.patch rename package/kernel/mac80211/patches/ath10k/{974-wifi-ath10k-add-LED-and-GPIO-controlling-support-for.patch => 974-ath10k_add-LED-and-GPIO-controlling-support-for-various-chipsets.patch} (67%) create mode 100644 package/kernel/mac80211/patches/ath10k/985-ath10k-allow-vht-on-2g.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0001-wifi-ath11k-stop-tx-queues-immediately-upon-firmware.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0002-wifi-ath11k-Don-t-exit-on-wakeup-failure.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0005-wifi-ath11k-Fix-spelling-mistake-chnange-change.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0007-wifi-ath11k-suppress-add-interface-error.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0008-wifi-ath11k-add-support-to-configure-channel-dwell-t.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0010-wifi-ath11k-Fix-firmware-crash-on-vdev-delete-race-c.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0011-wifi-ath11k-fix-monitor-vdev-creation-with-firmware-.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0012-wifi-ath11k-Fix-qmi_msg_handler-data-structure-initi.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0013-wifi-ath11k-synchronize-ath11k_mac_he_gi_to_nl80211_.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0016-wifi-ath11k-Make-QMI-message-rules-const.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0017-wifi-ath11k-Trigger-sta-disconnect-on-hardware-resta.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0018-wifi-ath11k-Fix-race-condition-with-struct-htt_ppdu_.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0019-wifi-ath11k-update-hw-params-for-IPQ5018.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0020-wifi-ath11k-update-ce-configurations-for-IPQ5018.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0021-wifi-ath11k-remap-ce-register-space-for-IPQ5018.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0022-wifi-ath11k-update-hal-srng-regs-for-IPQ5018.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0023-wifi-ath11k-initialize-hw_ops-for-IPQ5018.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0024-wifi-ath11k-add-new-hw-ops-for-IPQ5018-to-get-rx-des.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0025-wifi-ath11k-add-ipq5018-device-support.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0026-wifi-ath11k-Fix-scan-request-param-frame-size-warnin.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0029-wifi-ath11k-Add-support-to-configure-FTM-responder-r.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0030-wifi-ath11k-add-channel-177-into-5-GHz-channel-list.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0031-wifi-ath11k-fix-ce-memory-mapping-for-ahb-devices.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0033-wifi-ath11k-Set-ext-passive-scan-flag-to-adjust-pass.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0034-wifi-ath11k-fix-return-value-check-in-ath11k_ahb_pro.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0035-wifi-ath11k-Use-platform_get_irq-to-get-the-interrup.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0036-wifi-ath11k-fix-SAC-bug-on-peer-addition-with-sta-ba.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0037-wifi-ath11k-allow-system-suspend-to-survive-ath11k.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0038-wifi-ath11k-modify-accessor-macros-to-match-index-si.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0039-wifi-ath11k-push-MU-MIMO-params-from-hostapd-to-hard.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0040-wifi-ath11k-move-HE-MCS-mapper-to-a-separate-functio.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0041-wifi-ath11k-generate-rx-and-tx-mcs-maps-for-supporte.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0042-wifi-ath11k-Add-tx-ack-signal-support-for-management.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0043-wifi-ath11k-use-proper-regulatory-reference-for-band.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0044-wifi-ath11k-add-support-to-parse-new-WMI-event-for-6.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0045-wifi-ath11k-add-debug-prints-in-regulatory-WMI-event.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0046-wifi-ath11k-Replace-fake-flex-array-with-flexible-ar.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0047-wifi-ath11k-fix-deinitialization-of-firmware-resourc.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0048-wifi-ath11k-fix-BUFFER_DONE-read-on-monitor-ring-rx-.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0049-wifi-ath11k-Optimize-6-GHz-scan-time.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0050-wifi-ath11k-Configure-the-FTM-responder-role-using-f.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0051-wifi-ath11k-fix-rssi-station-dump-not-updated-in-QCN.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0052-wifi-ath11k-Fix-invalid-management-rx-frame-length-i.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0053-wifi-ath11k-fix-writing-to-unintended-memory-region.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0054-wifi-ath11k-Send-11d-scan-start-before-WMI_START_SCA.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0055-wifi-ath11k-Remove-redundant-pci_clear_master.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0056-wifi-ath11k-Disable-Spectral-scan-upon-removing-inte.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0057-wifi-ath11k-enable-SAR-support-on-WCN6750.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0058-wifi-ath11k-pci-Add-more-MODULE_FIRMWARE-entries.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0059-wifi-ath11k-print-a-warning-when-crypto_alloc_shash-.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0060-wifi-ath11k-Ignore-frags-from-uninitialized-peer-in-.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0061-wifi-ath11k-fix-undefined-behavior-with-__fls-in-dp.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0062-wifi-ath11k-fix-double-free-of-peer-rx_tid-during-re.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0063-wifi-ath11k-Prevent-REO-cmd-failures.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0064-wifi-ath11k-add-peer-mac-information-in-failure-case.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0065-wifi-ath11k-fix-tx-status-reporting-in-encap-offload.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0066-wifi-ath11k-Fix-incorrect-update-of-radiotap-fields.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0067-wifi-ath11k-Fix-SKB-corruption-in-REO-destination-ri.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0068-wifi-ath11k-Remove-disabling-of-80-80-and-160-MHz.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0069-wifi-ath11k-fix-registration-of-6Ghz-only-phy-withou.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0070-wifi-ath-work-around-false-positive-stringop-overrea.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0071-wifi-ath11k-driver-settings-for-MBSSID-and-EMA.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0072-wifi-ath11k-MBSSID-configuration-during-vdev-create-.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0073-wifi-ath11k-rename-MBSSID-fields-in-wmi_vdev_up_cmd.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0074-wifi-ath11k-MBSSID-parameter-configuration-in-AP-mod.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0075-wifi-ath11k-refactor-vif-parameter-configurations.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0076-wifi-ath11k-MBSSID-beacon-support.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0077-wifi-ath11k-EMA-beacon-support.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0078-wifi-ath11k-Relocate-the-func-ath11k_mac_bitrate_mas.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0079-wifi-ath11k-Send-HT-fixed-rate-in-WMI-peer-fixed-par.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0080-wifi-ath11k-add-support-default-regdb-while-searchin.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0081-wifi-ath11k-remove-unused-function-ath11k_tm_event_w.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0082-wifi-ath11k-factory-test-mode-support.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0083-wifi-ath11k-Allow-ath11k-to-boot-without-caldata-in-.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0084-wifi-ath11k-Add-HTT-stats-for-PHY-reset-case.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0085-wifi-ath11k-fix-memory-leak-in-WMI-firmware-stats.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0086-wifi-ath11k-Add-missing-check-for-ioremap.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0087-wifi-ath11k-Add-missing-ops-config-for-IPQ5018-in.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0088-wifi-ath11k-Restart-firmware-after-cold-boot-calibration.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0089-wifi-ath11k-Add-missing-hw_ops-get_ring_selector-for.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0090-Revert-wifi-ath11k-Enable-threaded-NAPI.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0091-wifi-ath11k-Split-coldboot-calibration-hw_param.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0092-wifi-ath11k-Add-coldboot-calibration-support-for-QCN.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0093-wifi-ath11k-Remove-cal_done-check-during-probe.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0094-wifi-ath11k-mhi-add-a-warning-message-for-MHI_CB_EE.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0095-wifi-ath11k-add-chip-id-board-name-while-searching-b.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0096-wifi-ath11k-fix-boot-failure-with-one-MSI-vector.patch delete mode 100644 package/kernel/mac80211/patches/ath11k/0906-wifi-ath11k-disable-coldboot-for-ipq6018.patch delete mode 100644 package/kernel/mac80211/patches/ath11k/101-wifi-ath11k-add-support-DT-ieee80211-freq-limit.patch create mode 100644 package/kernel/mac80211/patches/ath11k/901-wifi-ath11k-pci-fix-compilation-in-5.16-and-older.patch create mode 100644 package/kernel/mac80211/patches/ath11k/902-ath11k-Disable-coldboot-calibration-for-IPQ8074.patch create mode 100644 package/kernel/mac80211/patches/ath11k/906-ath11k-Disable-coldboot-calibration-for-IPQ6018.patch create mode 100644 package/kernel/mac80211/patches/brcm/860-brcmfmac-register-wiphy-s-during-module_init.patch create mode 100644 package/kernel/mac80211/patches/brcm/865-brcmfmac-Read-alternative-firmware-names-from-DT.patch delete mode 100644 package/kernel/mac80211/patches/brcm/865-brcmfmac-disable-dump_survey-on-bcm2835.patch delete mode 100644 package/kernel/mac80211/patches/build/004-fix-kconf-compiling.patch create mode 100644 package/kernel/mac80211/patches/build/050-lib80211_option.patch create mode 100644 package/kernel/mac80211/patches/build/080-resv_start_op.patch create mode 100644 package/kernel/mac80211/patches/build/099-netlink-range.patch delete mode 100644 package/kernel/mac80211/patches/build/110-backport_namepace_const.patch create mode 100644 package/kernel/mac80211/patches/build/110-backport_napi_build_skb.patch delete mode 100644 package/kernel/mac80211/patches/build/120-headers_version_fix.patch delete mode 100644 package/kernel/mac80211/patches/build/130-iommu_backport.patch delete mode 100644 package/kernel/mac80211/patches/build/200-iwlwifi_thermal_backport.patch delete mode 100644 package/kernel/mac80211/patches/build/210-backport_genl_split_ops.patch delete mode 100644 package/kernel/mac80211/patches/build/220-list-don-t-backport-list_count_nodes.patch delete mode 100644 package/kernel/mac80211/patches/build/230-brcmfmac_usb_driver_backport.patch create mode 100644 package/kernel/mac80211/patches/build/990-add_kernel_6.6_support.patch delete mode 100644 package/kernel/mac80211/patches/rt2x00/602-02-wifi-rt2x00-Add-option-to-pass-EEPROM-file-name-from.patch delete mode 100644 package/kernel/mac80211/patches/rt2x00/602-04-wifi-rt2x00-Support-EEPROM-swap-binding.patch delete mode 100644 package/kernel/mac80211/patches/rt2x00/602-05-wifi-rt2x00-support-loading-eeprom-from-NVMEM-cells.patch rename package/kernel/mac80211/patches/rt2x00/{602-01-wifi-rt2x00-Add-support-for-loading-EEPROM-from-user.patch => 602-rt2x00-introduce-rt2x00eeprom.patch} (53%) create mode 100644 package/kernel/mac80211/patches/rt2x00/603-rt2x00-of_load_eeprom_filename.patch rename package/kernel/mac80211/patches/rt2x00/{602-03-wifi-rt2x00-Add-support-for-loading-EEPROM-from-MTD.patch => 604-rt2x00-load-eeprom-on-SoC-from-a-mtd-device-defines-.patch} (63%) delete mode 100644 package/kernel/mac80211/patches/subsys/130-disable_auto_vif.patch create mode 100644 package/kernel/mac80211/patches/subsys/306-01-v6.2-wifi-mac80211-add-internal-handler-for-wake_tx_queue.patch create mode 100644 package/kernel/mac80211/patches/subsys/306-02-v6.2-wifi-mac80211-add-wake_tx_queue-callback-to-drivers.patch create mode 100644 package/kernel/mac80211/patches/subsys/306-03-v6.2-wifi-mac80211-Drop-support-for-TX-push-path.patch create mode 100644 package/kernel/mac80211/patches/subsys/306-04-v6.2-wifi-realtek-remove-duplicated-wake_tx_queue.patch delete mode 100644 package/kernel/mac80211/patches/subsys/306-wifi-mac80211-clear-vif-drv_priv-after-calling-remov.patch create mode 100644 package/kernel/mac80211/patches/subsys/310-v6.2-mac80211-add-support-for-restricting-netdev-features.patch create mode 100644 package/kernel/mac80211/patches/subsys/311-v6.2-wifi-mac80211-fix-and-simplify-unencrypted-drop-chec.patch create mode 100644 package/kernel/mac80211/patches/subsys/312-v6.3-wifi-cfg80211-move-A-MSDU-check-in-ieee80211_data_to.patch create mode 100644 package/kernel/mac80211/patches/subsys/313-v6.3-wifi-cfg80211-factor-out-bridge-tunnel-RFC1042-heade.patch create mode 100644 package/kernel/mac80211/patches/subsys/314-v6.3-wifi-mac80211-remove-mesh-forwarding-congestion-chec.patch create mode 100644 package/kernel/mac80211/patches/subsys/315-v6.3-wifi-mac80211-fix-receiving-A-MSDU-frames-on-mesh-in.patch create mode 100644 package/kernel/mac80211/patches/subsys/316-v6.3-wifi-mac80211-add-a-workaround-for-receiving-non-sta.patch create mode 100644 package/kernel/mac80211/patches/subsys/318-wifi-mac80211-fix-race-in-mesh-sequence-number-assig.patch create mode 100644 package/kernel/mac80211/patches/subsys/319-wifi-mac80211-mesh-fast-xmit-support.patch delete mode 100644 package/kernel/mac80211/patches/subsys/320-cfg80211-allow-grace-period-for-DFS-available-after-.patch create mode 100644 package/kernel/mac80211/patches/subsys/320-wifi-mac80211-use-mesh-header-cache-to-speed-up-mesh.patch create mode 100644 package/kernel/mac80211/patches/subsys/321-mac80211-fix-mesh-forwarding.patch create mode 100644 package/kernel/mac80211/patches/subsys/322-wifi-mac80211-fix-mesh-path-discovery-based-on-unica.patch create mode 100644 package/kernel/mac80211/patches/subsys/323-v6.3-wifi-mac80211-Add-VHT-MU-MIMO-related-flags-in-ieee8.patch create mode 100644 package/kernel/mac80211/patches/subsys/324-v6.3-wifi-mac80211-Add-HE-MU-MIMO-related-flags-in-ieee80.patch create mode 100644 package/kernel/mac80211/patches/subsys/325-wifi-mac80211-introduce-ieee80211_refresh_tx_agg_ses.patch create mode 100644 package/kernel/mac80211/patches/subsys/326-wifi-mac80211-add-mesh-fast-rx-support.patch create mode 100644 package/kernel/mac80211/patches/subsys/327-wifi-mac80211-add-support-for-letting-drivers-regist.patch create mode 100644 package/kernel/mac80211/patches/subsys/329-wifi-mac80211-fix-receiving-mesh-packets-in-forwardi.patch delete mode 100644 package/kernel/mac80211/patches/subsys/330-mac80211-add-AQL-support-for-broadcast-packets.patch create mode 100644 package/kernel/mac80211/patches/subsys/330-wifi-ieee80211-correctly-mark-FTM-frames-non-buffera.patch delete mode 100644 package/kernel/mac80211/patches/subsys/331-wifi-mac80211-extend-IEEE80211_KEY_FLAG_GENERATE_MMI.patch create mode 100644 package/kernel/mac80211/patches/subsys/331-wifi-mac80211-flush-queues-on-STA-removal.patch create mode 100644 package/kernel/mac80211/patches/subsys/332-wifi-iwlwifi-mvm-support-flush-on-AP-interfaces.patch create mode 100644 package/kernel/mac80211/patches/subsys/333-wifi-mac80211-add-flush_sta-method.patch create mode 100644 package/kernel/mac80211/patches/subsys/334-wifi-iwlwifi-mvm-support-new-flush_sta-method.patch create mode 100644 package/kernel/mac80211/patches/subsys/335-wifi-mac80211-add-LDPC-related-flags-in-ieee80211_bs.patch create mode 100644 package/kernel/mac80211/patches/subsys/336-v6.4-wifi-mac80211-generate-EMA-beacons-in-AP-mode.patch create mode 100644 package/kernel/mac80211/patches/subsys/337-mac80211-fix-sband-iftype-data-lookup-for-AP_VLAN.patch create mode 100644 package/kernel/mac80211/patches/subsys/338-mac80211-split-mesh-fast-tx-cache-into-local-proxied.patch delete mode 100644 package/kernel/mac80211/patches/subsys/340-wifi-nl80211-split-helper-function-from-nl80211_put_.patch delete mode 100644 package/kernel/mac80211/patches/subsys/341-wifi-cfg80211-add-support-for-advertising-multiple-r.patch delete mode 100644 package/kernel/mac80211/patches/subsys/342-wifi-cfg80211-extend-interface-combination-check-for.patch delete mode 100644 package/kernel/mac80211/patches/subsys/343-wifi-cfg80211-add-helper-for-checking-if-a-chandef-i.patch delete mode 100644 package/kernel/mac80211/patches/subsys/344-wifi-mac80211-add-support-for-DFS-with-multiple-radi.patch delete mode 100644 package/kernel/mac80211/patches/subsys/345-wifi-mac80211-add-radio-index-to-ieee80211_chanctx_c.patch delete mode 100644 package/kernel/mac80211/patches/subsys/346-wifi-mac80211-extend-ifcomb-check-functions-for-mult.patch delete mode 100644 package/kernel/mac80211/patches/subsys/347-wifi-mac80211-move-code-in-ieee80211_link_reserve_ch.patch delete mode 100644 package/kernel/mac80211/patches/subsys/348-wifi-mac80211-add-wiphy-radio-assignment-and-validat.patch delete mode 100644 package/kernel/mac80211/patches/subsys/349-wifi-mac80211_hwsim-add-support-for-multi-radio-wiph.patch create mode 100644 package/kernel/mac80211/patches/subsys/401-mac80211-allow-vht-on-2g.patch create mode 100644 package/kernel/mac80211/patches/subsys/500-mac80211_configure_antenna_gain.patch create mode 100644 package/kernel/mac80211/patches/subsys/800-rework-eth_hw_addr_set.patch create mode 100644 package/kernel/mac80211/patches/subsys/900-add-eth-ieee80211_bss_conf.patch delete mode 100644 package/kernel/mac80211/patches/subsys/910-fix-build-for-kernel-5.10.patch delete mode 100644 package/kernel/mac80211/patches/subsys/920-mac80211-mtk-ACS-channel-time-is-reset-by-ch_restore.patch create mode 100644 package/kernel/mt76/patches-5.4/001-allow-vht-on-2g.patch create mode 100644 package/kernel/mt76/patches-5.4/002-fix-build-error.patch create mode 100644 package/kernel/mt76/patches-5.4/100-api_update.patch create mode 100644 package/kernel/mt76/patches-5.4/110-wifi-mt76-ignore-key-disable-commands.patch create mode 100644 package/kernel/mt76/patches-6.x/001-allow-vht-on-2g.patch create mode 100644 package/kernel/mt76/patches-6.x/002-wifi-mt76-mt7915-fix-oops.patch create mode 100644 package/kernel/mt76/patches-6.x/101-fixes-mt7925-build-error.patch create mode 100644 package/kernel/mt76/patches/001-allow-vht-on-2g.patch create mode 100644 package/kernel/mt76/patches/002-fix-page-pool.patch create mode 100644 package/kernel/rtw88-usb/Makefile create mode 100644 package/kernel/rtw88-usb/patches/001-fix-merge-error.patch create mode 100644 package/kernel/rtw88-usb/patches/101-wireless-6.1.patch create mode 100644 package/kernel/rtw88-usb/patches/102-disable-pcie.patch create mode 100644 package/lean/r8101/Makefile create mode 100644 package/lean/r8101/patches/010-6.1-support.patch create mode 100644 package/utils/lua/patches-host/400-CVE-2014-5461.patch create mode 100644 package/utils/lua/patches/400-CVE-2014-5461.patch delete mode 100644 package/wwan/luci-app-sms-tool/LICENSE delete mode 100644 package/wwan/luci-app-sms-tool/Makefile delete mode 100644 package/wwan/luci-app-sms-tool/htdocs/luci-static/resources/icons/delsms.png delete mode 100644 package/wwan/luci-app-sms-tool/htdocs/luci-static/resources/icons/delsms2.png delete mode 100644 package/wwan/luci-app-sms-tool/luasrc/controller/modem/sms.lua delete mode 100644 package/wwan/luci-app-sms-tool/luasrc/model/cbi/modem/smsconfig.lua delete mode 100644 package/wwan/luci-app-sms-tool/luasrc/view/modem/atcommands.htm delete mode 100644 package/wwan/luci-app-sms-tool/luasrc/view/modem/readsms.htm delete mode 100644 package/wwan/luci-app-sms-tool/luasrc/view/modem/sendsms.htm delete mode 100644 package/wwan/luci-app-sms-tool/luasrc/view/modem/ussd.htm delete mode 100644 package/wwan/luci-app-sms-tool/po/pl/sms-tool.po delete mode 100644 package/wwan/luci-app-sms-tool/po/zh-cn/sms-tool.po delete mode 100644 package/wwan/luci-app-sms-tool/root/etc/config/atcmds.user delete mode 100644 package/wwan/luci-app-sms-tool/root/etc/config/phonebook.user delete mode 100644 package/wwan/luci-app-sms-tool/root/etc/config/sms_tool delete mode 100755 package/wwan/luci-app-sms-tool/root/etc/init.d/smsled delete mode 100755 package/wwan/luci-app-sms-tool/root/etc/uci-defaults/set_sms_ports.sh delete mode 100755 package/wwan/luci-app-sms-tool/root/etc/uci-defaults/start-smsled delete mode 100755 package/wwan/luci-app-sms-tool/root/sbin/cronsync.sh delete mode 100755 package/wwan/luci-app-sms-tool/root/sbin/set_sms_ports.sh delete mode 100755 package/wwan/luci-app-sms-tool/root/sbin/smsled-init.sh delete mode 100755 package/wwan/luci-app-sms-tool/root/sbin/smsled.sh delete mode 100644 package/wwan/luci-app-sms-tool/root/usr/share/rpcd/acl.d/luci-app-sms-tool.json create mode 100644 target/linux/mediatek/dts/mt7622-buffalo-wsr-3200ax4s.dts create mode 100644 target/linux/mediatek/dts/mt7622-buffalo-wsr.dtsi create mode 100644 target/linux/mediatek/dts/mt7622-dlink-eagle-pro-ai-ax3200-a1.dtsi create mode 100644 target/linux/mediatek/dts/mt7622-dlink-eagle-pro-ai-m32-a1.dts create mode 100644 target/linux/mediatek/dts/mt7622-dlink-eagle-pro-ai-r32-a1.dts create mode 100644 target/linux/mediatek/dts/mt7622-reyee-ax3200-e5.dts create mode 100644 target/linux/mediatek/dts/mt7622-ruijie-rg-ew3200.dtsi create mode 100644 target/linux/mediatek/dts/mt7622-ubnt-unifi-6-lr-v3-ubootmod.dts create mode 100644 target/linux/mediatek/dts/mt7622-ubnt-unifi-6-lr-v3.dts create mode 100644 target/linux/mediatek/dts/mt7622-ubnt-unifi-6-lr-v3.dtsi create mode 100644 target/linux/mediatek/dts/mt7629-iptime-a6004mx.dts create mode 100644 target/linux/mediatek/dts/mt7629-netgear-ex6250-v2.dts create mode 100644 target/linux/mediatek/dts/mt7629-tplink_eap225-v5.dts rename target/linux/mediatek/dts/{mt7981b-abt-asr3000.dts => mt7981a-comfast-cf-e393ax.dts} (56%) create mode 100644 target/linux/mediatek/dts/mt7981a-edgecore-eap111.dts create mode 100644 target/linux/mediatek/dts/mt7981a-glinet-gl-x3000-xe3000-common.dtsi create mode 100644 target/linux/mediatek/dts/mt7981a-glinet-gl-x3000.dts create mode 100644 target/linux/mediatek/dts/mt7981a-glinet-gl-xe3000.dts create mode 100644 target/linux/mediatek/dts/mt7981a-ubnt-unifi-6-plus.dts delete mode 100644 target/linux/mediatek/dts/mt7981b-cetron-ct3003-mod.dts delete mode 100644 target/linux/mediatek/dts/mt7981b-cmcc-rax3000m-emmc.dts create mode 100644 target/linux/mediatek/dts/mt7981b-cmcc-rax3000m-emmc.dtso delete mode 100644 target/linux/mediatek/dts/mt7981b-cmcc-rax3000m-nand.dts create mode 100644 target/linux/mediatek/dts/mt7981b-cmcc-rax3000m-nand.dtso create mode 100644 target/linux/mediatek/dts/mt7981b-confiabits-mt7981.dts create mode 100644 target/linux/mediatek/dts/mt7981b-cudy-m3000-v1.dts create mode 100644 target/linux/mediatek/dts/mt7981b-cudy-re3000-v1.dts create mode 100644 target/linux/mediatek/dts/mt7981b-cudy-tr3000-v1.dts create mode 100644 target/linux/mediatek/dts/mt7981b-cudy-wr3000-v1.dts create mode 100644 target/linux/mediatek/dts/mt7981b-dlink-aquila-pro-ai-m30-a1.dts delete mode 100644 target/linux/mediatek/dts/mt7981b-fzs-5gcpe-p3.dts create mode 100644 target/linux/mediatek/dts/mt7981b-openembed-som7981.dts create mode 100644 target/linux/mediatek/dts/mt7981b-openwrt-one.dts create mode 100644 target/linux/mediatek/dts/mt7981b-routerich-ax3000.dts create mode 100644 target/linux/mediatek/dts/mt7981b-unielec-u7981-01-emmc.dts create mode 100644 target/linux/mediatek/dts/mt7981b-unielec-u7981-01-nand.dts create mode 100644 target/linux/mediatek/dts/mt7981b-unielec-u7981-01.dtsi create mode 100644 target/linux/mediatek/dts/mt7981b-wavlink-wl-wn586x3.dts delete mode 100644 target/linux/mediatek/dts/mt7981b-xiaomi-ax3000t.dts create mode 100644 target/linux/mediatek/dts/mt7981b-xiaomi-mi-router-ax3000t-ubootmod.dts create mode 100644 target/linux/mediatek/dts/mt7981b-xiaomi-mi-router-ax3000t.dts create mode 100644 target/linux/mediatek/dts/mt7981b-xiaomi-mi-router-ax3000t.dtsi rename target/linux/mediatek/dts/{mt7981b-xiaomi_mi-router.dtsi => mt7981b-xiaomi-mi-router-common.dtsi} (69%) create mode 100644 target/linux/mediatek/dts/mt7981b-xiaomi-mi-router-wr30u-stock.dts create mode 100644 target/linux/mediatek/dts/mt7981b-xiaomi-mi-router-wr30u-ubootmod.dts create mode 100644 target/linux/mediatek/dts/mt7981b-xiaomi-mi-router-wr30u.dtsi delete mode 100644 target/linux/mediatek/dts/mt7981b-xiaomi-wr30u.dts create mode 100644 target/linux/mediatek/dts/mt7981b-yuncore-ax835.dts create mode 100644 target/linux/mediatek/dts/mt7981b-zbtlink-zbt-z8102ax.dts rename target/linux/mediatek/dts/{mt7981b-imou-lc-hx3001.dts => mt7981b-zbtlink-zbt-z8103ax.dts} (51%) create mode 100644 target/linux/mediatek/dts/mt7981b-zyxel-nwa50ax-pro.dts create mode 100644 target/linux/mediatek/dts/mt7986a-acelink-ew-7886cax.dts create mode 100644 target/linux/mediatek/dts/mt7986a-acer-predator-w6.dts create mode 100644 target/linux/mediatek/dts/mt7986a-asus-rt-ax59u.dts create mode 100644 target/linux/mediatek/dts/mt7986a-asus-tuf-ax6000.dts create mode 100644 target/linux/mediatek/dts/mt7986a-bananapi-bpi-r3-mini.dts delete mode 100644 target/linux/mediatek/dts/mt7986a-hf-m7986r1-emmc.dts delete mode 100644 target/linux/mediatek/dts/mt7986a-hf-m7986r1-nand.dts delete mode 100644 target/linux/mediatek/dts/mt7986a-hf-m7986r1.dtsi rename target/linux/mediatek/dts/{mt7986a-jdcloud-re-cs-05.dts => mt7986a-jdcloud-re-cp-03.dts} (65%) create mode 100644 target/linux/mediatek/dts/mt7986a-smartrg-SDG-8612.dts create mode 100644 target/linux/mediatek/dts/mt7986a-smartrg-SDG-8614.dts create mode 100644 target/linux/mediatek/dts/mt7986a-smartrg-SDG-8622.dts create mode 100644 target/linux/mediatek/dts/mt7986a-smartrg-SDG-8632.dts create mode 100644 target/linux/mediatek/dts/mt7986a-smartrg-bonanza-peak.dtsi delete mode 100644 target/linux/mediatek/dts/mt7986a-tplink-tl-xtr8488.dts create mode 100644 target/linux/mediatek/dts/mt7986a-xiaomi-redmi-router-ax6000-stock.dts create mode 100644 target/linux/mediatek/dts/mt7986a-xiaomi-redmi-router-ax6000-ubootmod.dts rename target/linux/mediatek/dts/{mt7986a-xiaomi-redmi-router-ax6000.dts => mt7986a-xiaomi-redmi-router-ax6000.dtsi} (80%) create mode 100644 target/linux/mediatek/dts/mt7986a-zyxel-ex5601-t0-common.dtsi create mode 100644 target/linux/mediatek/dts/mt7986a-zyxel-ex5601-t0-stock.dts create mode 100644 target/linux/mediatek/dts/mt7986a-zyxel-ex5601-t0-ubootmod.dts create mode 100644 target/linux/mediatek/dts/mt7986a-zyxel-ex5700-telenor.dts create mode 100644 target/linux/mediatek/dts/mt7986b-mercusys-mr90x-v1.dts create mode 100644 target/linux/mediatek/dts/mt7986b-netgear-wax220.dts create mode 100644 target/linux/mediatek/dts/mt7986b-tplink-re6000xd.dts create mode 100644 target/linux/mediatek/dts/mt7988a-smartrg-SDG-8733.dts create mode 100644 target/linux/mediatek/dts/mt7988a-smartrg-SDG-8734.dts create mode 100644 target/linux/mediatek/dts/mt7988a-smartrg-mt-stuart.dtsi delete mode 100644 target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7981.dtsi delete mode 100644 target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-emmc.dtso delete mode 100644 target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-nand.dtso delete mode 100644 target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-nor.dtso delete mode 100644 target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-sd.dtso delete mode 100644 target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts delete mode 100644 target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7986a-rfb-spim-nand.dts delete mode 100644 target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7986a-rfb-spim-nor.dts delete mode 100644 target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7986a-rfb.dtsi delete mode 100644 target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7986a.dtsi delete mode 100644 target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7986b-rfb.dts delete mode 100644 target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7986b.dtsi delete mode 100644 target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7988a-rfb-emmc.dtso delete mode 100644 target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth1-aqr.dtso delete mode 100644 target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth1-i2p5g-phy.dtso delete mode 100644 target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth1-mxl.dtso delete mode 100644 target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth1-sfp.dtso delete mode 100644 target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth2-aqr.dtso delete mode 100644 target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth2-mxl.dtso delete mode 100644 target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth2-sfp.dtso delete mode 100644 target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7988a-rfb-sd.dtso delete mode 100644 target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7988a-rfb-snfi-nand.dtso delete mode 100644 target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7988a-rfb-spim-nand.dtso delete mode 100644 target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7988a-rfb-spim-nor.dtso delete mode 100644 target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7988a-rfb.dts delete mode 100644 target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7988a.dtsi delete mode 100644 target/linux/mediatek/files-5.15/drivers/clk/mediatek/clk-mt7981-apmixed.c delete mode 100644 target/linux/mediatek/files-5.15/drivers/clk/mediatek/clk-mt7981-eth.c delete mode 100644 target/linux/mediatek/files-5.15/drivers/clk/mediatek/clk-mt7981-infracfg.c delete mode 100644 target/linux/mediatek/files-5.15/drivers/clk/mediatek/clk-mt7981-topckgen.c delete mode 100644 target/linux/mediatek/files-5.15/drivers/clk/mediatek/clk-mt7986-apmixed.c delete mode 100644 target/linux/mediatek/files-5.15/drivers/clk/mediatek/clk-mt7986-eth.c delete mode 100644 target/linux/mediatek/files-5.15/drivers/clk/mediatek/clk-mt7986-infracfg.c delete mode 100644 target/linux/mediatek/files-5.15/drivers/clk/mediatek/clk-mt7986-topckgen.c delete mode 100644 target/linux/mediatek/files-5.15/drivers/clk/mediatek/clk-mt7988-apmixed.c delete mode 100644 target/linux/mediatek/files-5.15/drivers/clk/mediatek/clk-mt7988-eth.c delete mode 100644 target/linux/mediatek/files-5.15/drivers/clk/mediatek/clk-mt7988-infracfg.c delete mode 100644 target/linux/mediatek/files-5.15/drivers/clk/mediatek/clk-mt7988-topckgen.c delete mode 100644 target/linux/mediatek/files-5.15/drivers/net/phy/mediatek-2p5ge.c delete mode 100644 target/linux/mediatek/files-5.15/drivers/pinctrl/mediatek/pinctrl-mt7981.c delete mode 100644 target/linux/mediatek/files-5.15/drivers/pinctrl/mediatek/pinctrl-mt7986.c delete mode 100644 target/linux/mediatek/files-5.15/drivers/pinctrl/mediatek/pinctrl-mt7988.c delete mode 100644 target/linux/mediatek/files-5.15/include/dt-bindings/clock/mediatek,mt7981-clk.h delete mode 100644 target/linux/mediatek/files-5.15/include/dt-bindings/clock/mediatek,mt7988-clk.h delete mode 100644 target/linux/mediatek/files-5.15/include/dt-bindings/clock/mt7986-clk.h delete mode 100644 target/linux/mediatek/files-5.15/include/dt-bindings/reset/mt7986-resets.h delete mode 100644 target/linux/mediatek/files-6.1/arch/arm64/boot/dts/mediatek/mt7981.dtsi delete mode 100644 target/linux/mediatek/files-6.1/arch/arm64/boot/dts/mediatek/mt7986a-rfb-spim-nand.dts delete mode 100644 target/linux/mediatek/files-6.1/arch/arm64/boot/dts/mediatek/mt7986a-rfb-spim-nor.dts delete mode 100644 target/linux/mediatek/files-6.1/arch/arm64/boot/dts/mediatek/mt7986a-rfb.dtsi delete mode 100644 target/linux/mediatek/files-6.1/arch/arm64/boot/dts/mediatek/mt7988a-rfb-emmc.dtso delete mode 100644 target/linux/mediatek/files-6.1/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth1-aqr.dtso delete mode 100644 target/linux/mediatek/files-6.1/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth1-i2p5g-phy.dtso delete mode 100644 target/linux/mediatek/files-6.1/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth1-mxl.dtso delete mode 100644 target/linux/mediatek/files-6.1/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth1-sfp.dtso delete mode 100644 target/linux/mediatek/files-6.1/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth2-aqr.dtso delete mode 100644 target/linux/mediatek/files-6.1/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth2-mxl.dtso delete mode 100644 target/linux/mediatek/files-6.1/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth2-sfp.dtso delete mode 100644 target/linux/mediatek/files-6.1/arch/arm64/boot/dts/mediatek/mt7988a-rfb-sd.dtso delete mode 100644 target/linux/mediatek/files-6.1/arch/arm64/boot/dts/mediatek/mt7988a-rfb-snfi-nand.dtso delete mode 100644 target/linux/mediatek/files-6.1/arch/arm64/boot/dts/mediatek/mt7988a-rfb-spim-nand.dtso delete mode 100644 target/linux/mediatek/files-6.1/arch/arm64/boot/dts/mediatek/mt7988a-rfb-spim-nor.dtso delete mode 100644 target/linux/mediatek/files-6.1/arch/arm64/boot/dts/mediatek/mt7988a-rfb.dts delete mode 100644 target/linux/mediatek/files-6.1/arch/arm64/boot/dts/mediatek/mt7988a.dtsi delete mode 100644 target/linux/mediatek/files-6.1/drivers/clk/mediatek/clk-mt7988-apmixed.c delete mode 100644 target/linux/mediatek/files-6.1/drivers/clk/mediatek/clk-mt7988-eth.c delete mode 100644 target/linux/mediatek/files-6.1/drivers/clk/mediatek/clk-mt7988-infracfg.c delete mode 100644 target/linux/mediatek/files-6.1/drivers/clk/mediatek/clk-mt7988-topckgen.c delete mode 100644 target/linux/mediatek/files-6.1/drivers/net/phy/mediatek-2p5ge.c delete mode 100644 target/linux/mediatek/files-6.1/drivers/pinctrl/mediatek/pinctrl-mt7988.c delete mode 100644 target/linux/mediatek/files-6.1/include/dt-bindings/clock/mediatek,mt7988-clk.h delete mode 100644 target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/Kconfig delete mode 100644 target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/Makefile delete mode 100644 target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt7530.c delete mode 100644 target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt7530.h delete mode 100644 target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt7531.c delete mode 100644 target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt7531.h delete mode 100644 target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt753x.h delete mode 100644 target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt753x_common.c delete mode 100644 target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt753x_mdio.c delete mode 100644 target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt753x_nl.c delete mode 100644 target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt753x_nl.h delete mode 100644 target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt753x_regs.h delete mode 100644 target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt753x_swconfig.c delete mode 100644 target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt753x_swconfig.h delete mode 100644 target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt753x_vlan.c delete mode 100644 target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt753x_vlan.h create mode 100644 target/linux/mediatek/filogic/base-files/etc/board.d/03_gpio_switches create mode 100755 target/linux/mediatek/filogic/base-files/etc/init.d/bootcount create mode 100644 target/linux/mediatek/filogic/base-files/lib/preinit/04_set_netdev_label create mode 100644 target/linux/mediatek/filogic/base-files/lib/preinit/05_extract_factory_data.sh create mode 100644 target/linux/mediatek/filogic/base-files/lib/preinit/09_mount_cfg_part create mode 100644 target/linux/mediatek/filogic/base-files/lib/preinit/75_rootfs_prepare delete mode 100644 target/linux/mediatek/filogic/base-files/lib/preinit/81_fix_eeprom delete mode 100644 target/linux/mediatek/filogic/config-5.15 delete mode 100644 target/linux/mediatek/filogic/config-6.1 delete mode 100644 target/linux/mediatek/mt7622/config-5.15 delete mode 100644 target/linux/mediatek/mt7622/config-6.1 create mode 100644 target/linux/mediatek/mt7623/base-files/etc/board.d/05_compat-version create mode 100644 target/linux/mediatek/mt7623/base-files/etc/uci-defaults/05_fix-compat-version delete mode 100644 target/linux/mediatek/mt7623/config-5.15 delete mode 100644 target/linux/mediatek/mt7623/config-6.1 create mode 100644 target/linux/mediatek/mt7629/base-files/etc/board.d/01_leds create mode 100755 target/linux/mediatek/mt7629/base-files/etc/init.d/bootcount delete mode 100644 target/linux/mediatek/mt7629/config-5.15 delete mode 100644 target/linux/mediatek/mt7629/config-6.1 delete mode 100644 target/linux/mediatek/patches-5.15/100-dts-update-mt7622-rfb1.patch delete mode 100644 target/linux/mediatek/patches-5.15/101-dts-update-mt7629-rfb.patch delete mode 100644 target/linux/mediatek/patches-5.15/103-mt7623-enable-arch-timer.patch delete mode 100644 target/linux/mediatek/patches-5.15/104-mt7622-add-snor-irq.patch delete mode 100644 target/linux/mediatek/patches-5.15/105-dts-mt7622-enable-pstore.patch delete mode 100644 target/linux/mediatek/patches-5.15/110-dts-fix-bpi2-console.patch delete mode 100644 target/linux/mediatek/patches-5.15/111-dts-fix-bpi64-console.patch delete mode 100644 target/linux/mediatek/patches-5.15/112-dts-fix-bpi64-lan-names.patch delete mode 100644 target/linux/mediatek/patches-5.15/113-dts-fix-bpi64-leds-and-buttons.patch delete mode 100644 target/linux/mediatek/patches-5.15/114-dts-bpi64-disable-rtc.patch delete mode 100644 target/linux/mediatek/patches-5.15/115-dts-bpi64-add-snand-support.patch delete mode 100644 target/linux/mediatek/patches-5.15/120-01-v5.18-mtd-nand-ecc-Add-infrastructure-to-support-hardware-.patch delete mode 100644 target/linux/mediatek/patches-5.15/120-02-v5.18-mtd-nand-Add-a-new-helper-to-retrieve-the-ECC-contex.patch delete mode 100644 target/linux/mediatek/patches-5.15/120-03-v5.18-mtd-nand-ecc-Provide-a-helper-to-retrieve-a-pileline.patch delete mode 100644 target/linux/mediatek/patches-5.15/120-04-v5.18-spi-spi-mem-Introduce-a-capability-structure.patch delete mode 100644 target/linux/mediatek/patches-5.15/120-05-v5.18-spi-spi-mem-Check-the-controller-extra-capabilities.patch delete mode 100644 target/linux/mediatek/patches-5.15/120-06-v5.18-spi-spi-mem-Kill-the-spi_mem_dtr_supports_op-helper.patch delete mode 100644 target/linux/mediatek/patches-5.15/120-07-v5.18-spi-spi-mem-Add-an-ecc-parameter-to-the-spi_mem_op-s.patch delete mode 100644 target/linux/mediatek/patches-5.15/120-08-v5.18-mtd-spinand-Delay-a-little-bit-the-dirmap-creation.patch delete mode 100644 target/linux/mediatek/patches-5.15/120-09-v5.18-mtd-spinand-Create-direct-mapping-descriptors-for-EC.patch delete mode 100644 target/linux/mediatek/patches-5.15/120-11-v5.19-mtd-nand-make-mtk_ecc.c-a-separated-module.patch delete mode 100644 target/linux/mediatek/patches-5.15/120-12-v5.19-spi-add-driver-for-MTK-SPI-NAND-Flash-Interface.patch delete mode 100644 target/linux/mediatek/patches-5.15/120-13-v5.19-mtd-nand-mtk-ecc-also-parse-nand-ecc-engine-if-avail.patch delete mode 100644 target/linux/mediatek/patches-5.15/120-14-v5.19-arm64-dts-mediatek-add-mtk-snfi-for-mt7622.patch delete mode 100644 target/linux/mediatek/patches-5.15/121-hack-spi-nand-1b-bbm.patch delete mode 100644 target/linux/mediatek/patches-5.15/130-dts-mt7629-add-snand-support.patch delete mode 100644 target/linux/mediatek/patches-5.15/131-dts-mt7622-add-snand-support.patch delete mode 100644 target/linux/mediatek/patches-5.15/140-dts-fix-wmac-support-for-mt7622-rfb1.patch delete mode 100644 target/linux/mediatek/patches-5.15/150-dts-mt7623-eip97-inside-secure-support.patch delete mode 100644 target/linux/mediatek/patches-5.15/160-dts-mt7623-bpi-r2-earlycon.patch delete mode 100644 target/linux/mediatek/patches-5.15/161-dts-mt7623-bpi-r2-mmc-device-order.patch delete mode 100644 target/linux/mediatek/patches-5.15/162-dts-mt7623-bpi-r2-led-aliases.patch delete mode 100644 target/linux/mediatek/patches-5.15/163-dts-mt7623-bpi-r2-ethernet-alias.patch delete mode 100644 target/linux/mediatek/patches-5.15/173-arm-dts-mt7623-add-musb-device-nodes.patch delete mode 100644 target/linux/mediatek/patches-5.15/180-dts-mt7622-bpi-r64-add-mt7531-irq.patch delete mode 100644 target/linux/mediatek/patches-5.15/190-arm64-dts-mediatek-mt7622-fix-GICv2-range.patch delete mode 100644 target/linux/mediatek/patches-5.15/191-v5.19-arm64-dts-mt7622-specify-the-L2-cache-topology.patch delete mode 100644 target/linux/mediatek/patches-5.15/192-v5.19-arm64-dts-mt7622-specify-the-number-of-DMA-requests.patch delete mode 100644 target/linux/mediatek/patches-5.15/193-dts-mt7623-thermal_zone_fix.patch delete mode 100644 target/linux/mediatek/patches-5.15/194-dts-mt7968a-add-ramoops.patch delete mode 100644 target/linux/mediatek/patches-5.15/195-dts-mt7986a-bpi-r3-leds-port-names-and-wifi-eeprom.patch delete mode 100644 target/linux/mediatek/patches-5.15/200-phy-phy-mtk-tphy-Add-hifsys-support.patch delete mode 100644 target/linux/mediatek/patches-5.15/210-v6.1-pinctrl-mediatek-add-support-for-MT7986-SoC.patch delete mode 100644 target/linux/mediatek/patches-5.15/211-v5.16-clk-mediatek-Add-API-for-clock-resource-recycle.patch delete mode 100644 target/linux/mediatek/patches-5.15/212-v5.17-clk-mediatek-add-mt7986-clock-support.patch delete mode 100644 target/linux/mediatek/patches-5.15/213-spi-mediatek-add-mt7986-spi-support.patch delete mode 100644 target/linux/mediatek/patches-5.15/214-v6.3-clk-mediatek-add-mt7981-clock-support.patch delete mode 100644 target/linux/mediatek/patches-5.15/215-mtdblock-revert-warn-if-opened-on-NAND.patch delete mode 100644 target/linux/mediatek/patches-5.15/215-v6.3-pinctrl-mediatek-add-support-for-MT7981-SoC.patch delete mode 100644 target/linux/mediatek/patches-5.15/240-pinctrl-mediatek-add-support-for-MT7988-SoC.patch delete mode 100644 target/linux/mediatek/patches-5.15/241-clk-mediatek-Add-pcw-chg-shift-control.patch delete mode 100644 target/linux/mediatek/patches-5.15/242-clk-mediatek-add-mt7988-clock-support.patch delete mode 100644 target/linux/mediatek/patches-5.15/320-mmc-mediatek-add-support-for-MT7986-SoC.patch delete mode 100644 target/linux/mediatek/patches-5.15/330-snand-mtk-bmt-support.patch delete mode 100644 target/linux/mediatek/patches-5.15/331-mt7622-rfb1-enable-bmt.patch delete mode 100644 target/linux/mediatek/patches-5.15/340-mtd-spinand-Add-support-for-the-Fidelix-FM35X1GA.patch delete mode 100644 target/linux/mediatek/patches-5.15/350-01-cpufreq-mediatek-Cleanup-variables-and-error-handlin.patch delete mode 100644 target/linux/mediatek/patches-5.15/350-02-cpufreq-mediatek-Remove-unused-headers.patch delete mode 100644 target/linux/mediatek/patches-5.15/350-03-cpufreq-mediatek-Enable-clocks-and-regulators.patch delete mode 100644 target/linux/mediatek/patches-5.15/350-04-cpufreq-mediatek-Use-device-print-to-show-logs.patch delete mode 100644 target/linux/mediatek/patches-5.15/350-05-cpufreq-mediatek-Replace-old_-with-pre_.patch delete mode 100644 target/linux/mediatek/patches-5.15/350-06-cpufreq-mediatek-Record-previous-target-vproc-value.patch delete mode 100644 target/linux/mediatek/patches-5.15/350-07-cpufreq-mediatek-Make-sram-regulator-optional.patch delete mode 100644 target/linux/mediatek/patches-5.15/350-08-cpufreq-mediatek-Fix-NULL-pointer-dereference-in-med.patch delete mode 100644 target/linux/mediatek/patches-5.15/350-09-cpufreq-mediatek-Move-voltage-limits-to-platform-dat.patch delete mode 100644 target/linux/mediatek/patches-5.15/350-10-cpufreq-mediatek-Refine-mtk_cpufreq_voltage_tracking.patch delete mode 100644 target/linux/mediatek/patches-5.15/350-11-cpufreq-mediatek-Add-opp-notification-support.patch delete mode 100644 target/linux/mediatek/patches-5.15/350-12-cpufreq-mediatek-Fix-potential-deadlock-problem-in-m.patch delete mode 100644 target/linux/mediatek/patches-5.15/350-13-cpufreq-mediatek-Link-CCI-device-to-CPU.patch delete mode 100644 target/linux/mediatek/patches-5.15/350-14-cpufreq-mediatek-Add-support-for-MT8186.patch delete mode 100644 target/linux/mediatek/patches-5.15/350-15-cpufreq-mediatek-Handle-sram-regulator-probe-deferra.patch delete mode 100644 target/linux/mediatek/patches-5.15/350-16-cpufreq-mediatek-fix-error-return-code-in-mtk_cpu_dv.patch delete mode 100644 target/linux/mediatek/patches-5.15/350-17-cpufreq-mediatek-fix-passing-zero-to-PTR_ERR.patch delete mode 100644 target/linux/mediatek/patches-5.15/350-18-cpufreq-mediatek-fix-KP-caused-by-handler-usage-afte.patch delete mode 100644 target/linux/mediatek/patches-5.15/350-19-cpufreq-mediatek-raise-proc-sram-max-voltage-for-MT8.patch delete mode 100644 target/linux/mediatek/patches-5.15/350-20-cpufreq-mediatek-Raise-proc-and-sram-max-voltage-for.patch delete mode 100644 target/linux/mediatek/patches-5.15/350-21-cpufreq-mediatek-Add-support-for-MT7988.patch delete mode 100644 target/linux/mediatek/patches-5.15/351-cpufreq-mediatek-correct-voltages-for-MT7622-and-MT7.patch delete mode 100644 target/linux/mediatek/patches-5.15/400-crypto-add-eip97-inside-secure-support.patch delete mode 100644 target/linux/mediatek/patches-5.15/401-crypto-fix-eip97-cache-incoherent.patch delete mode 100644 target/linux/mediatek/patches-5.15/405-mt7986-trng-add-rng-support.patch delete mode 100644 target/linux/mediatek/patches-5.15/410-bt-mtk-serial-fix.patch delete mode 100644 target/linux/mediatek/patches-5.15/420-mtd-spi-nor-add-support-for-Winbond-W25Q512JV.patch delete mode 100644 target/linux/mediatek/patches-5.15/431-drivers-spi-mt65xx-Move-chip_config-to-driver-s-priv.patch delete mode 100644 target/linux/mediatek/patches-5.15/432-drivers-spi-Add-support-for-dynamic-calibration.patch delete mode 100644 target/linux/mediatek/patches-5.15/433-drivers-spi-mem-Add-spi-calibration-hook.patch delete mode 100644 target/linux/mediatek/patches-5.15/434-drivers-spi-mt65xx-Add-controller-s-calibration-para.patch delete mode 100644 target/linux/mediatek/patches-5.15/435-drivers-mtd-spinand-Add-calibration-support-for-spin.patch delete mode 100644 target/linux/mediatek/patches-5.15/436-drivers-mtd-spi-nor-Add-calibration-support-for-spi-.patch delete mode 100644 target/linux/mediatek/patches-5.15/500-gsw-rtl8367s-mt7622-support.patch delete mode 100644 target/linux/mediatek/patches-5.15/600-v5.16-arm64-dts-mediatek-Split-PCIe-node-for-MT2712-and-MT.patch delete mode 100644 target/linux/mediatek/patches-5.15/601-PCI-mediatek-Assert-PERST-for-100ms-for-power-and-cl.patch delete mode 100644 target/linux/mediatek/patches-5.15/602-arm64-dts-mediatek-add-mt7622-pcie-slot-node.patch delete mode 100644 target/linux/mediatek/patches-5.15/603-v5.16-ARM-dts-mediatek-Update-mt7629-PCIe-node.patch delete mode 100644 target/linux/mediatek/patches-5.15/610-pcie-mediatek-fix-clearing-interrupt-status.patch delete mode 100644 target/linux/mediatek/patches-5.15/702-v5.17-net-mdio-add-helpers-to-extract-clause-45-regad-and-.patch delete mode 100644 target/linux/mediatek/patches-5.15/703-v5.17-net-ethernet-mtk_eth_soc-implement-Clause-45-MDIO-ac.patch delete mode 100644 target/linux/mediatek/patches-5.15/710-pci-pcie-mediatek-add-support-for-coherent-DMA.patch delete mode 100644 target/linux/mediatek/patches-5.15/721-dts-mt7622-mediatek-fix-300mhz.patch delete mode 100644 target/linux/mediatek/patches-5.15/722-remove-300Hz-to-prevent-freeze.patch delete mode 100644 target/linux/mediatek/patches-5.15/730-v6.5-net-phy-add-driver-for-MediaTek-SoC-built-in-GE-PHYs.patch delete mode 100644 target/linux/mediatek/patches-5.15/731-net-phy-mediatek-ge-soc-initialize-MT7988-PHY-LEDs-d.patch delete mode 100644 target/linux/mediatek/patches-5.15/732-net-phy-mxl-gpy-don-t-use-SGMII-AN-if-using-phylink.patch delete mode 100644 target/linux/mediatek/patches-5.15/733-net-phy-add-driver-for-MediaTek-2.5G-PHY.patch delete mode 100644 target/linux/mediatek/patches-5.15/800-v5.17-nvmem-mtk-efuse-support-minimum-one-byte-access-stri.patch delete mode 100644 target/linux/mediatek/patches-5.15/801-phy-phy-mtk-tphy-Add-PCIe-2-lane-efuse-support.patch delete mode 100644 target/linux/mediatek/patches-5.15/802-phy-phy-mtk-tphy-add-auto-load-valid-check-mechanism.patch delete mode 100644 target/linux/mediatek/patches-5.15/804-pwm-add-mt7986-support.patch delete mode 100644 target/linux/mediatek/patches-5.15/805-v6.2-thermal-drivers-mtk-use-function-pointer-for-raw_to_.patch delete mode 100644 target/linux/mediatek/patches-5.15/806-v6.2-thermal-mediatek-add-support-for-MT7986-and-MT7981.patch delete mode 100644 target/linux/mediatek/patches-5.15/811-pwm-mediatek-Add-support-for-MT7981.patch delete mode 100644 target/linux/mediatek/patches-5.15/820-v5.16-dt-bindings-pinctrl-mt8195-add-rsel-define.patch delete mode 100644 target/linux/mediatek/patches-5.15/821-v5.16-pinctrl-mediatek-moore-check-if-pin_desc-is-valid-be.patch delete mode 100644 target/linux/mediatek/patches-5.15/822-v5.16-pinctrl-mediatek-support-rsel-feature.patch delete mode 100644 target/linux/mediatek/patches-5.15/823-v5.17-pinctrl-mediatek-add-a-check-for-error-in-mtk_pincon.patch delete mode 100644 target/linux/mediatek/patches-5.15/824-v6.1-pinctrl-mediatek-Fix-EINT-pins-input-debounce-time-c.patch delete mode 100644 target/linux/mediatek/patches-5.15/825-v6.1-pinctrl-mediatek-Export-debounce-time-tables.patch delete mode 100644 target/linux/mediatek/patches-5.15/826-v6.2-pinctrl-mediatek-extend-pinctrl-moore-to-support-new.patch delete mode 100644 target/linux/mediatek/patches-5.15/830-v5.18-regulator-Add-bindings-for-Richtek-RT5190A-PMIC.patch delete mode 100644 target/linux/mediatek/patches-5.15/831-v5.18-regulator-rt5190a-Add-support-for-Richtek-RT5190A-PM.patch delete mode 100644 target/linux/mediatek/patches-5.15/840-v5.16-i2c-mediatek-Reset-the-handshake-signal-between-i2c-.patch delete mode 100644 target/linux/mediatek/patches-5.15/841-v5.16-i2c-mediatek-Dump-i2c-dma-register-when-a-timeout-oc.patch delete mode 100644 target/linux/mediatek/patches-5.15/842-v5.18-i2c-mediatek-Add-i2c-compatible-for-Mediatek-MT8186.patch delete mode 100644 target/linux/mediatek/patches-5.15/843-v5.18-i2c-mediatek-modify-bus-speed-calculation-formula.patch delete mode 100644 target/linux/mediatek/patches-5.15/844-v5.18-i2c-mediatek-remove-redundant-null-check.patch delete mode 100644 target/linux/mediatek/patches-5.15/845-v5.18-i2c-mt65xx-Simplify-with-clk-bulk.patch delete mode 100644 target/linux/mediatek/patches-5.15/846-v5.18-i2c-mediatek-Add-i2c-compatible-for-Mediatek-MT8168.patch delete mode 100644 target/linux/mediatek/patches-5.15/847-v5.19-i2c-mediatek-Optimize-master_xfer-and-avoid-circular.patch delete mode 100644 target/linux/mediatek/patches-5.15/848-v5.19-i2c-mediatek-Fix-an-error-handling-path-in-mtk_i2c_p.patch delete mode 100644 target/linux/mediatek/patches-5.15/849-v6.0-i2c-mediatek-add-i2c-compatible-for-MT8188.patch delete mode 100644 target/linux/mediatek/patches-5.15/850-v6.0-i2c-move-drivers-from-strlcpy-to-strscpy.patch delete mode 100644 target/linux/mediatek/patches-5.15/851-v6.2-i2c-mediatek-add-mt7986-support.patch delete mode 100644 target/linux/mediatek/patches-5.15/852-v6.3-i2c-mt65xx-Use-devm_platform_get_and_ioremap_resourc.patch delete mode 100644 target/linux/mediatek/patches-5.15/853-v6.3-i2c-mt65xx-drop-of_match_ptr-for-ID-table.patch delete mode 100644 target/linux/mediatek/patches-5.15/854-v6.4-i2c-mediatek-add-support-for-MT7981-SoC.patch delete mode 100644 target/linux/mediatek/patches-5.15/900-dts-mt7622-bpi-r64-aliases-for-dtoverlay.patch delete mode 100644 target/linux/mediatek/patches-5.15/901-arm-add-cmdline-override.patch delete mode 100644 target/linux/mediatek/patches-5.15/910-dts-mt7622-bpi-r64-wifi-eeprom.patch delete mode 100644 target/linux/mediatek/patches-5.15/920-v5.16-watchdog-mtk-add-disable_wdt_extrst-support.patch delete mode 100644 target/linux/mediatek/patches-5.15/921-v5.19-watchdog-mtk_wdt-mt7986-Add-toprgu-reset-controller.patch delete mode 100644 target/linux/mediatek/patches-5.15/922-v6.1-PCI-mediatek-gen3-change-driver-name-to-mtk-pcie-gen.patch delete mode 100644 target/linux/mediatek/patches-5.15/930-spi-mt65xx-enable-sel-clk.patch delete mode 100644 target/linux/mediatek/patches-5.15/940-net-ethernet-mtk_wed-rename-mtk_wed_get_memory_regio.patch delete mode 100644 target/linux/mediatek/patches-5.15/941-arm64-dts-mt7986-move-cpuboot-in-a-dedicated-node.patch delete mode 100644 target/linux/mediatek/patches-5.15/942-net-ethernet-mtk_wed-move-cpuboot-in-a-dedicated-dts.patch delete mode 100644 target/linux/mediatek/patches-5.15/943-net-ethernet-mtk_wed-move-ilm-a-dedicated-dts-node.patch delete mode 100644 target/linux/mediatek/patches-5.15/944-net-ethernet-mtk_wed-move-dlm-a-dedicated-dts-node.patch delete mode 100644 target/linux/mediatek/patches-5.15/945-arm64-dts-mt7986-move-ilm-in-a-dedicated-node.patch delete mode 100644 target/linux/mediatek/patches-5.15/946-arm64-dts-mt7986-move-dlm-in-a-dedicated-node.patch delete mode 100644 target/linux/mediatek/patches-6.1/000-v6.2-kbuild-Allow-DTB-overlays-to-built-from-.dtso-named-.patch delete mode 100644 target/linux/mediatek/patches-6.1/001-v6.2-arm64-dts-mediatek-mt7986-add-support-for-RX-Wireles.patch delete mode 100644 target/linux/mediatek/patches-6.1/002-v6.2-arm64-dts-mt7986-harmonize-device-node-order.patch delete mode 100644 target/linux/mediatek/patches-6.1/003-v6.2-arm64-dts-mt7986-add-crypto-related-device-nodes.patch delete mode 100644 target/linux/mediatek/patches-6.1/004-v6.2-arm64-dts-mt7986-add-i2c-node.patch delete mode 100644 target/linux/mediatek/patches-6.1/005-v6.2-arm64-dts-mediatek-mt7986-Add-SoC-compatible.patch delete mode 100644 target/linux/mediatek/patches-6.1/006-v6.2-arm64-dts-mt7986-add-spi-related-device-nodes.patch delete mode 100644 target/linux/mediatek/patches-6.1/007-v6.3-arm64-dts-mt7986-add-usb-related-device-nodes.patch delete mode 100644 target/linux/mediatek/patches-6.1/008-v6.3-arm64-dts-mt7986-add-mmc-related-device-nodes.patch delete mode 100644 target/linux/mediatek/patches-6.1/009-v6.3-arm64-dts-mt7986-add-pcie-related-device-nodes.patch delete mode 100644 target/linux/mediatek/patches-6.1/010-v6.3-arm64-dts-mt7986-add-Bananapi-R3.patch delete mode 100644 target/linux/mediatek/patches-6.1/011-v6.5-arm64-mediatek-Propagate-chassis-type-where-possible.patch delete mode 100644 target/linux/mediatek/patches-6.1/012-v6.5-arm64-dts-mt7986-add-PWM.patch delete mode 100644 target/linux/mediatek/patches-6.1/013-v6.5-arm64-dts-mt7986-add-PWM-to-BPI-R3.patch delete mode 100644 target/linux/mediatek/patches-6.1/014-v6.5-arm64-dts-mt7986-set-Wifi-Leds-low-active-for-BPI-R3.patch delete mode 100644 target/linux/mediatek/patches-6.1/015-v6.5-arm64-dts-mt7986-use-size-of-reserved-partition-for-.patch delete mode 100644 target/linux/mediatek/patches-6.1/016-v6.5-arm64-dts-mt7986-add-thermal-and-efuse.patch delete mode 100644 target/linux/mediatek/patches-6.1/017-v6.5-arm64-dts-mt7986-add-thermal-zones.patch delete mode 100644 target/linux/mediatek/patches-6.1/018-v6.5-arm64-dts-mt7986-add-pwm-fan-and-cooling-maps-to-BPI.patch delete mode 100644 target/linux/mediatek/patches-6.1/019-v6.5-arm64-dts-mt7986-increase-bl2-partition-on-NAND-of-B.patch delete mode 100644 target/linux/mediatek/patches-6.1/020-arm64-dts-mt7986-define-3W-max-power-to-both-SFP-on-.patch delete mode 100644 target/linux/mediatek/patches-6.1/021-arm64-dts-mt7986-change-cooling-trips.patch delete mode 100644 target/linux/mediatek/patches-6.1/022-arm64-dts-mt7986-change-thermal-trips-on-BPI-R3.patch delete mode 100644 target/linux/mediatek/patches-6.1/100-dts-update-mt7622-rfb1.patch delete mode 100644 target/linux/mediatek/patches-6.1/101-dts-update-mt7629-rfb.patch delete mode 100644 target/linux/mediatek/patches-6.1/103-mt7623-enable-arch-timer.patch delete mode 100644 target/linux/mediatek/patches-6.1/104-mt7622-add-snor-irq.patch delete mode 100644 target/linux/mediatek/patches-6.1/105-dts-mt7622-enable-pstore.patch delete mode 100644 target/linux/mediatek/patches-6.1/110-dts-fix-bpi2-console.patch delete mode 100644 target/linux/mediatek/patches-6.1/111-dts-fix-bpi64-console.patch delete mode 100644 target/linux/mediatek/patches-6.1/112-dts-fix-bpi64-lan-names.patch delete mode 100644 target/linux/mediatek/patches-6.1/113-dts-fix-bpi64-leds-and-buttons.patch delete mode 100644 target/linux/mediatek/patches-6.1/114-dts-bpi64-disable-rtc.patch delete mode 100644 target/linux/mediatek/patches-6.1/115-dts-bpi64-add-snand-support.patch delete mode 100644 target/linux/mediatek/patches-6.1/121-hack-spi-nand-1b-bbm.patch delete mode 100644 target/linux/mediatek/patches-6.1/130-dts-mt7629-add-snand-support.patch delete mode 100644 target/linux/mediatek/patches-6.1/131-dts-mt7622-add-snand-support.patch delete mode 100644 target/linux/mediatek/patches-6.1/140-dts-fix-wmac-support-for-mt7622-rfb1.patch delete mode 100644 target/linux/mediatek/patches-6.1/150-dts-mt7623-eip97-inside-secure-support.patch delete mode 100644 target/linux/mediatek/patches-6.1/160-dts-mt7623-bpi-r2-earlycon.patch delete mode 100644 target/linux/mediatek/patches-6.1/161-dts-mt7623-bpi-r2-mmc-device-order.patch delete mode 100644 target/linux/mediatek/patches-6.1/162-dts-mt7623-bpi-r2-led-aliases.patch delete mode 100644 target/linux/mediatek/patches-6.1/163-dts-mt7623-bpi-r2-ethernet-alias.patch delete mode 100644 target/linux/mediatek/patches-6.1/180-dts-mt7622-bpi-r64-add-mt7531-irq.patch delete mode 100644 target/linux/mediatek/patches-6.1/190-arm64-dts-mediatek-mt7622-fix-GICv2-range.patch delete mode 100644 target/linux/mediatek/patches-6.1/193-dts-mt7623-thermal_zone_fix.patch delete mode 100644 target/linux/mediatek/patches-6.1/194-dts-mt7968a-add-ramoops.patch delete mode 100644 target/linux/mediatek/patches-6.1/195-dts-mt7986a-bpi-r3-leds-port-names-and-wifi-eeprom.patch delete mode 100644 target/linux/mediatek/patches-6.1/200-phy-phy-mtk-tphy-Add-hifsys-support.patch delete mode 100644 target/linux/mediatek/patches-6.1/210-v6.2-pinctrl-mt7986-allow-configuring-uart-rx-tx-and-rts-.patch delete mode 100644 target/linux/mediatek/patches-6.1/211-v6.2-pinctrl-mediatek-add-pull_type-attribute-for-mediate.patch delete mode 100644 target/linux/mediatek/patches-6.1/215-v6.3-pinctrl-add-mt7981-pinctrl-driver.patch delete mode 100644 target/linux/mediatek/patches-6.1/216-v6.3-pinctrl-mediatek-add-missing-options-to-PINCTRL_MT79.patch delete mode 100644 target/linux/mediatek/patches-6.1/217-v6.5-pinctrl-mediatek-fix-pull_type-data-for-MT7981.patch delete mode 100644 target/linux/mediatek/patches-6.1/218-pinctrl-mediatek-mt7981-add-additional-uart-groups.patch delete mode 100644 target/linux/mediatek/patches-6.1/219-pinctrl-mediatek-assign-functions-to-configure-pin-b.patch delete mode 100644 target/linux/mediatek/patches-6.1/221-v6.3-clk-mediatek-cpumux-Propagate-struct-device-where-po.patch delete mode 100644 target/linux/mediatek/patches-6.1/224-v6.3-clk-mediatek-clk-mtk-Add-dummy-clock-ops.patch delete mode 100644 target/linux/mediatek/patches-6.1/225-v6.3-clk-mediatek-Switch-to-mtk_clk_simple_probe-where-po.patch delete mode 100644 target/linux/mediatek/patches-6.1/227-v6.3-clk-mediatek-clk-mt7986-topckgen-Properly-keep-some-.patch delete mode 100644 target/linux/mediatek/patches-6.1/228-v6.3-clk-mediatek-clk-mt7986-topckgen-Migrate-to-mtk_clk_.patch delete mode 100644 target/linux/mediatek/patches-6.1/229-v6.4-clk-mediatek-mt7986-apmixed-Use-PLL_AO-flag-to-set-c.patch delete mode 100644 target/linux/mediatek/patches-6.1/230-v6.4-dt-bindings-clock-mediatek-add-mt7981-clock-IDs.patch delete mode 100644 target/linux/mediatek/patches-6.1/231-v6.4-clk-mediatek-add-MT7981-clock-support.patch delete mode 100644 target/linux/mediatek/patches-6.1/240-pinctrl-mediatek-add-support-for-MT7988-SoC.patch delete mode 100644 target/linux/mediatek/patches-6.1/241-clk-mediatek-Add-pcw-chg-shift-control.patch delete mode 100644 target/linux/mediatek/patches-6.1/242-clk-mediatek-add-mt7988-clock-support.patch delete mode 100644 target/linux/mediatek/patches-6.1/320-v6.2-mmc-mediatek-add-support-for-MT7986-SoC.patch delete mode 100644 target/linux/mediatek/patches-6.1/321-v6.2-mmc-mtk-sd-add-Inline-Crypto-Engine-clock-control.patch delete mode 100644 target/linux/mediatek/patches-6.1/322-v6.2-mmc-mtk-sd-fix-two-spelling-mistakes-in-comment.patch delete mode 100644 target/linux/mediatek/patches-6.1/323-v6.2-mmc-Avoid-open-coding-by-using-mmc_op_tuning.patch delete mode 100644 target/linux/mediatek/patches-6.1/330-snand-mtk-bmt-support.patch delete mode 100644 target/linux/mediatek/patches-6.1/331-mt7622-rfb1-enable-bmt.patch delete mode 100644 target/linux/mediatek/patches-6.1/340-mtd-spinand-Add-support-for-the-Fidelix-FM35X1GA.patch delete mode 100644 target/linux/mediatek/patches-6.1/350-21-cpufreq-mediatek-Add-support-for-MT7988.patch delete mode 100644 target/linux/mediatek/patches-6.1/400-crypto-add-eip97-inside-secure-support.patch delete mode 100644 target/linux/mediatek/patches-6.1/401-crypto-fix-eip97-cache-incoherent.patch delete mode 100644 target/linux/mediatek/patches-6.1/405-v6.2-mt7986-trng-add-rng-support.patch delete mode 100644 target/linux/mediatek/patches-6.1/410-bt-mtk-serial-fix.patch delete mode 100644 target/linux/mediatek/patches-6.1/431-drivers-spi-mt65xx-Move-chip_config-to-driver-s-priv.patch delete mode 100644 target/linux/mediatek/patches-6.1/432-drivers-spi-Add-support-for-dynamic-calibration.patch delete mode 100644 target/linux/mediatek/patches-6.1/433-drivers-spi-mem-Add-spi-calibration-hook.patch delete mode 100644 target/linux/mediatek/patches-6.1/434-drivers-spi-mt65xx-Add-controller-s-calibration-para.patch delete mode 100644 target/linux/mediatek/patches-6.1/435-drivers-mtd-spinand-Add-calibration-support-for-spin.patch delete mode 100644 target/linux/mediatek/patches-6.1/436-drivers-mtd-spi-nor-Add-calibration-support-for-spi-.patch delete mode 100644 target/linux/mediatek/patches-6.1/500-gsw-rtl8367s-mt7622-support.patch delete mode 100644 target/linux/mediatek/patches-6.1/601-PCI-mediatek-Assert-PERST-for-100ms-for-power-and-cl.patch delete mode 100644 target/linux/mediatek/patches-6.1/602-arm64-dts-mediatek-add-mt7622-pcie-slot-node.patch delete mode 100644 target/linux/mediatek/patches-6.1/610-pcie-mediatek-fix-clearing-interrupt-status.patch delete mode 100644 target/linux/mediatek/patches-6.1/710-pci-pcie-mediatek-add-support-for-coherent-DMA.patch delete mode 100644 target/linux/mediatek/patches-6.1/721-dts-mt7622-mediatek-fix-300mhz.patch delete mode 100644 target/linux/mediatek/patches-6.1/722-remove-300Hz-to-prevent-freeze.patch delete mode 100644 target/linux/mediatek/patches-6.1/730-v6.5-net-phy-add-driver-for-MediaTek-SoC-built-in-GE-PHYs.patch delete mode 100644 target/linux/mediatek/patches-6.1/731-v6.5-net-phy-mediatek-ge-soc-support-PHY-LEDs.patch delete mode 100644 target/linux/mediatek/patches-6.1/732-net-phy-mxl-gpy-don-t-use-SGMII-AN-if-using-phylink.patch delete mode 100644 target/linux/mediatek/patches-6.1/733-net-phy-add-driver-for-MediaTek-2.5G-PHY.patch delete mode 100644 target/linux/mediatek/patches-6.1/804-pwm-add-mt7986-support.patch delete mode 100644 target/linux/mediatek/patches-6.1/805-v6.2-thermal-drivers-mtk-use-function-pointer-for-raw_to_.patch delete mode 100644 target/linux/mediatek/patches-6.1/806-v6.2-thermal-mediatek-add-support-for-MT7986-and-MT7981.patch delete mode 100644 target/linux/mediatek/patches-6.1/826-v6.2-pinctrl-mediatek-extend-pinctrl-moore-to-support-new.patch delete mode 100644 target/linux/mediatek/patches-6.1/851-v6.2-i2c-mediatek-add-mt7986-support.patch delete mode 100644 target/linux/mediatek/patches-6.1/852-v6.3-i2c-mt65xx-Use-devm_platform_get_and_ioremap_resourc.patch delete mode 100644 target/linux/mediatek/patches-6.1/853-v6.3-i2c-mt65xx-drop-of_match_ptr-for-ID-table.patch delete mode 100644 target/linux/mediatek/patches-6.1/854-v6.4-i2c-mediatek-add-support-for-MT7981-SoC.patch delete mode 100644 target/linux/mediatek/patches-6.1/900-dts-mt7622-bpi-r64-aliases-for-dtoverlay.patch delete mode 100644 target/linux/mediatek/patches-6.1/901-arm-add-cmdline-override.patch delete mode 100644 target/linux/mediatek/patches-6.1/910-dts-mt7622-bpi-r64-wifi-eeprom.patch delete mode 100644 target/linux/mediatek/patches-6.1/930-spi-mt65xx-enable-sel-clk.patch delete mode 100644 target/linux/mediatek/patches-6.1/940-net-ethernet-mtk_wed-rename-mtk_wed_get_memory_regio.patch delete mode 100644 target/linux/mediatek/patches-6.1/941-arm64-dts-mt7986-move-cpuboot-in-a-dedicated-node.patch delete mode 100644 target/linux/mediatek/patches-6.1/942-net-ethernet-mtk_wed-move-cpuboot-in-a-dedicated-dts.patch delete mode 100644 target/linux/mediatek/patches-6.1/943-net-ethernet-mtk_wed-move-ilm-a-dedicated-dts-node.patch delete mode 100644 target/linux/mediatek/patches-6.1/944-net-ethernet-mtk_wed-move-dlm-a-dedicated-dts-node.patch delete mode 100644 target/linux/mediatek/patches-6.1/945-arm64-dts-mt7986-move-ilm-in-a-dedicated-node.patch delete mode 100644 target/linux/mediatek/patches-6.1/946-arm64-dts-mt7986-move-dlm-in-a-dedicated-node.patch diff --git a/config/Config-kernel.in b/config/Config-kernel.in index 2b904b57f..f7a8d5181 100644 --- a/config/Config-kernel.in +++ b/config/Config-kernel.in @@ -50,6 +50,11 @@ config KERNEL_ARM_PMU default n depends on (arm || aarch64) +config KERNEL_ARM_PMUV3 + bool + default y if TARGET_armsr_armv8 + depends on (arm_v7 || aarch64) && LINUX_6_6 + config KERNEL_RISCV_PMU bool select KERNEL_RISCV_PMU_SBI @@ -81,6 +86,7 @@ config KERNEL_PERF_EVENTS bool "Compile the kernel with performance events and counters" default n select KERNEL_ARM_PMU if (arm || aarch64) + select KERNEL_ARM_PMUV3 if (arm_v7 || aarch64) && LINUX_6_6 select KERNEL_RISCV_PMU if riscv64 config KERNEL_PROFILING @@ -1145,6 +1151,13 @@ config KERNEL_NET_L3_MASTER_DEV This module provides glue between core networking code and device drivers to support L3 master devices like VRF. +config KERNEL_XDP_SOCKETS + bool "XDP sockets support" + default y if KERNEL_DEBUG_INFO_BTF + help + XDP sockets allows a channel between XDP programs and + userspace applications. + config KERNEL_PAGE_POOL def_bool n diff --git a/doc/h68k.jpg b/doc/h68k.jpg deleted file mode 100644 index ee6658faa3d546bb45de64616e8940fed3dff1d1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 63089 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 VEvMMB7aH)RsjjP5rDF5$e*vdk(P01p diff --git a/include/kernel-5.15 b/include/kernel-5.15 index a03ed80f9..02ccce117 100644 --- a/include/kernel-5.15 +++ b/include/kernel-5.15 @@ -1,2 +1,2 @@ -LINUX_VERSION-5.15 = .161 -LINUX_KERNEL_HASH-5.15.161 = d629f78680dc4b65e3d78b61406fb7757b960c83c206e63ad8c2606b3e3c474c +LINUX_VERSION-5.15 = .162 +LINUX_KERNEL_HASH-5.15.162 = 91bfc0ea152ce7b102a0b79d35a7c92843874ebf085c99d2ba8b4d85e62b1a7c diff --git a/include/kernel-6.1 b/include/kernel-6.1 index e8acd5ca1..1f97e8f30 100644 --- a/include/kernel-6.1 +++ b/include/kernel-6.1 @@ -1,2 +1,2 @@ -LINUX_VERSION-6.1 = .96 -LINUX_KERNEL_HASH-6.1.96 = 3e77c9069de5e7ab02ff9c2dcfe77dab193613fc1de21071901b4153374862a9 +LINUX_VERSION-6.1 = .98 +LINUX_KERNEL_HASH-6.1.98 = 97cdc9127c7700556ea0891267a0c24cf372f4b81636fb8203a914f3a69f3406 diff --git a/include/target.mk b/include/target.mk index e5c064759..f59661f62 100644 --- a/include/target.mk +++ b/include/target.mk @@ -53,9 +53,9 @@ DEFAULT_PACKAGES.nas:=\ mdadm # For router targets DEFAULT_PACKAGES.router:=\ - dnsmasq-full firewall iptables ppp ppp-mod-pppoe \ + dnsmasq-full firewall iptables ppp ppp-mod-pppoe odhcp6c odhcpd-ipv6only \ block-mount coremark kmod-nf-nathelper kmod-nf-nathelper-extra kmod-ipt-raw kmod-tun \ - iptables-mod-tproxy iptables-mod-extra ipset ip-full default-settings luci \ + iptables-mod-tproxy iptables-mod-extra ipset ip-full default-settings luci luci-proto-ipv6 \ ddns-scripts_aliyun ddns-scripts_dnspod luci-app-ddns luci-app-upnp luci-app-autoreboot \ luci-app-arpbind luci-app-filetransfer luci-app-vsftpd luci-app-ssr-plus luci-app-vlmcsd \ luci-app-accesscontrol luci-app-nlbwmon luci-app-turboacc luci-app-wol curl ca-certificates diff --git a/include/trusted-firmware-a.mk b/include/trusted-firmware-a.mk index e469dae98..0c0118e09 100644 --- a/include/trusted-firmware-a.mk +++ b/include/trusted-firmware-a.mk @@ -63,11 +63,9 @@ define Build/Trusted-Firmware-A/Target URL:=https://www.trustedfirmware.org/projects/tf-a/ endef - ifndef Package/trusted-firmware-a-$(1)/install - define Package/trusted-firmware-a-$(1)/install + define Package/trusted-firmware-a-$(1)/install $$(Package/trusted-firmware-a/install) - endef - endif + endef endef define Build/Configure/Trusted-Firmware-A diff --git a/include/u-boot.mk b/include/u-boot.mk index 454880989..d824d97ff 100644 --- a/include/u-boot.mk +++ b/include/u-boot.mk @@ -1,5 +1,3 @@ -include $(INCLUDE_DIR)/prereq.mk - PKG_NAME ?= u-boot ifndef PKG_SOURCE_PROTO @@ -20,31 +18,6 @@ PKG_LICENSE_FILES:=Licenses/README PKG_BUILD_PARALLEL ?= 1 -ifdef UBOOT_USE_BINMAN - $(eval $(call TestHostCommand,python3-pyelftools, \ - Please install the Python3 elftools module, \ - $(STAGING_DIR_HOST)/bin/python3 -c 'import elftools')) -endif - -ifdef UBOOT_USE_INTREE_DTC - $(eval $(call TestHostCommand,python3-dev, \ - Please install the python3-dev package, \ - python3.11-config --includes 2>&1 | grep 'python3', \ - python3.10-config --includes 2>&1 | grep 'python3', \ - python3.9-config --includes 2>&1 | grep 'python3', \ - python3.8-config --includes 2>&1 | grep 'python3', \ - python3.7-config --includes 2>&1 | grep 'python3', \ - python3-config --includes 2>&1 | grep -E 'python3\.([7-9]|[0-9][0-9])\.?')) - - $(eval $(call TestHostCommand,python3-setuptools, \ - Please install the Python3 setuptools module, \ - $(STAGING_DIR_HOST)/bin/python3 -c 'import setuptools')) - - $(eval $(call TestHostCommand,swig, \ - Please install the swig package, \ - swig -version)) -endif - export GCC_HONOUR_COPTS=s define Package/u-boot/install/default @@ -69,7 +42,6 @@ endef TARGET_DEP = TARGET_$(BUILD_TARGET)$(if $(BUILD_SUBTARGET),_$(BUILD_SUBTARGET)) UBOOT_MAKE_FLAGS = \ - PATH=$(STAGING_DIR_HOST)/bin:$(PATH) \ HOSTCC="$(HOSTCC)" \ HOSTCFLAGS="$(HOST_CFLAGS) $(HOST_CPPFLAGS) -std=gnu11" \ HOSTLDFLAGS="$(HOST_LDFLAGS)" \ @@ -111,14 +83,9 @@ endef define Build/Configure/U-Boot +$(MAKE) $(PKG_JOBS) -C $(PKG_BUILD_DIR) $(UBOOT_CONFIGURE_VARS) $(UBOOT_CONFIG)_config - $(if $(strip $(UBOOT_CUSTOMIZE_CONFIG)), - $(PKG_BUILD_DIR)/scripts/config --file $(PKG_BUILD_DIR)/.config $(UBOOT_CUSTOMIZE_CONFIG) - +$(MAKE) $(PKG_JOBS) -C $(PKG_BUILD_DIR) $(UBOOT_CONFIGURE_VARS) oldconfig) endef -ifndef UBOOT_USE_INTREE_DTC - DTC=$(wildcard $(LINUX_DIR)/scripts/dtc/dtc) -endif +DTC=$(wildcard $(LINUX_DIR)/scripts/dtc/dtc) define Build/Compile/U-Boot +$(MAKE) $(PKG_JOBS) -C $(PKG_BUILD_DIR) \ diff --git a/package/base-files/files/bin/config_generate b/package/base-files/files/bin/config_generate index 4c83b49f7..a9ca4d5b2 100755 --- a/package/base-files/files/bin/config_generate +++ b/package/base-files/files/bin/config_generate @@ -305,10 +305,10 @@ generate_static_system() { set system.ntp='timeserver' set system.ntp.enabled='1' set system.ntp.enable_server='1' - add_list system.ntp.server='ntp.aliyun.com' - add_list system.ntp.server='time1.cloud.tencent.com' - add_list system.ntp.server='time.ustc.edu.cn' - add_list system.ntp.server='cn.pool.ntp.org' + add_list system.ntp.server='time.apple.com' + add_list system.ntp.server='time.google.com' + add_list system.ntp.server='time.windows.com' + add_list system.ntp.server='time.cloudflare.com' EOF if json_is_a system object; then diff --git a/package/base-files/files/lib/upgrade/common.sh b/package/base-files/files/lib/upgrade/common.sh index af1182cb1..ef8d01e16 100644 --- a/package/base-files/files/lib/upgrade/common.sh +++ b/package/base-files/files/lib/upgrade/common.sh @@ -165,6 +165,23 @@ part_magic_fat() { [ "$magic" = "FAT" ] || [ "$magic_fat32" = "FAT32" ] } +fitblk_get_bootdev() { + [ -e /sys/firmware/devicetree/base/chosen/rootdisk ] || return + + local rootdisk="$(cat /sys/firmware/devicetree/base/chosen/rootdisk)" + local handle bootdev + for handle in /sys/class/block/*/of_node/phandle /sys/class/block/*/device/of_node/phandle; do + [ ! -e "$handle" ] && continue + if [ "$rootdisk" = "$(cat $handle)" ]; then + bootdev="${handle%/of_node/phandle}" + bootdev="${bootdev%/device}" + bootdev="${bootdev#/sys/class/block/}" + echo "$bootdev" + break + fi + done +} + export_bootdevice() { local cmdline uuid blockdev uevent line class local MAJOR MINOR DEVNAME DEVTYPE @@ -196,6 +213,7 @@ export_bootdevice() { done ;; /dev/*) + [ "$rootpart" = "/dev/fit0" ] && rootpart="$(fitblk_get_bootdev)" uevent="/sys/class/block/${rootpart##*/}/../uevent" ;; 0x[a-f0-9][a-f0-9][a-f0-9] | 0x[a-f0-9][a-f0-9][a-f0-9][a-f0-9] | \ diff --git a/package/base-files/files/lib/upgrade/stage2 b/package/base-files/files/lib/upgrade/stage2 index da84698dd..c6bb150f5 100755 --- a/package/base-files/files/lib/upgrade/stage2 +++ b/package/base-files/files/lib/upgrade/stage2 @@ -45,7 +45,8 @@ switch_to_ramfs() { mtd partx losetup mkfs.ext4 nandwrite flash_erase \ ubiupdatevol ubiattach ubiblock ubiformat \ ubidetach ubirsvol ubirmvol ubimkvol \ - snapshot snapshot_tool date \ + snapshot snapshot_tool date logger \ + /usr/sbin/fw_printenv /usr/bin/fwtool \ $RAMFS_COPY_LOSETUP $RAMFS_COPY_LVM \ $RAMFS_COPY_BIN do diff --git a/package/firmware/ath11k-firmware/Makefile b/package/firmware/ath11k-firmware/Makefile index ea4977aa6..0e1c548e2 100644 --- a/package/firmware/ath11k-firmware/Makefile +++ b/package/firmware/ath11k-firmware/Makefile @@ -8,9 +8,9 @@ include $(TOPDIR)/rules.mk PKG_NAME:=ath11k-firmware -PKG_SOURCE_DATE:=2023-08-22 -PKG_SOURCE_VERSION:=d8f82a98ff1aef330d65d8b5660b46d1a9809ee3 -PKG_MIRROR_HASH:=3dba19449758c3b17f117990d7ad4086554e012b579f1de16e9d9196a7fbaaa7 +PKG_SOURCE_DATE:=2023-03-31 +PKG_SOURCE_VERSION:=a039049a9349722fa5c74185452ab04644a0d351 +PKG_MIRROR_HASH:=ed401e3f6e91d70565b3396139193f7e815f410db93700697205ac8ed1b828c5 PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git @@ -32,6 +32,11 @@ define Package/ath11k-firmware-default DEPENDS:= endef +define Package/ath11k-firmware-ipq6018 +$(Package/ath11k-firmware-default) + TITLE:=IPQ6018 ath11k firmware +endef + define Package/ath11k-firmware-ipq8074 $(Package/ath11k-firmware-default) TITLE:=IPQ8074 ath11k firmware @@ -57,21 +62,30 @@ define Download/qcn9074-board endef $(eval $(call Download,qcn9074-board)) +define Package/ath11k-firmware-ipq6018/install + $(INSTALL_DIR) $(1)/lib/firmware/IPQ6018 + $(INSTALL_DIR) $(1)/lib/firmware/ath11k/IPQ6018/hw1.0 + $(INSTALL_DATA) \ + $(PKG_BUILD_DIR)/ath11k-firmware/IPQ6018/hw1.0/2.5.0.1/WLAN.HK.2.5.0.1-01208-QCAHKSWPL_SILICONZ-1/* \ + $(1)/lib/firmware/IPQ6018/ +endef + define Package/ath11k-firmware-ipq8074/install $(INSTALL_DIR) $(1)/lib/firmware/IPQ8074 $(INSTALL_DATA) \ - $(PKG_BUILD_DIR)/ath11k-firmware/IPQ8074/hw2.0/2.9.0.1/WLAN.HK.2.9.0.1-01890-QCAHKSWPL_SILICONZ-1/* \ + $(PKG_BUILD_DIR)/ath11k-firmware/IPQ8074/hw2.0/testing/2.9.0.1/WLAN.HK.2.9.0.1-01385-QCAHKSWPL_SILICONZ-1/* \ $(1)/lib/firmware/IPQ8074/ endef define Package/ath11k-firmware-qcn9074/install $(INSTALL_DIR) $(1)/lib/firmware/ath11k/QCN9074/hw1.0 $(INSTALL_DATA) \ - $(PKG_BUILD_DIR)/ath11k-firmware/QCN9074/hw1.0/2.9.0.1/WLAN.HK.2.9.0.1-01890-QCAHKSWPL_SILICONZ-1/* \ + $(PKG_BUILD_DIR)/ath11k-firmware/QCN9074/hw1.0/testing/2.9.0.1/WLAN.HK.2.9.0.1-01385-QCAHKSWPL_SILICONZ-1/* \ $(1)/lib/firmware/ath11k/QCN9074/hw1.0/ $(INSTALL_BIN) \ $(DL_DIR)/$(QCN9074_BOARD_FILE) $(1)/lib/firmware/ath11k/QCN9074/hw1.0/board-2.bin endef +$(eval $(call BuildPackage,ath11k-firmware-ipq6018)) $(eval $(call BuildPackage,ath11k-firmware-ipq8074)) $(eval $(call BuildPackage,ath11k-firmware-qcn9074)) diff --git a/package/firmware/ath11k-wifi/Makefile b/package/firmware/ath11k-wifi/Makefile deleted file mode 100644 index 2c33df970..000000000 --- a/package/firmware/ath11k-wifi/Makefile +++ /dev/null @@ -1,94 +0,0 @@ -include $(TOPDIR)/rules.mk -include $(INCLUDE_DIR)/version.mk - -PKG_NAME:=ath11k-wifi -PKG_RELEASE:=1 -PKG_FLAGS:=nonshared - -include $(INCLUDE_DIR)/package.mk - -define Build/Prepare - mkdir -p $(PKG_BUILD_DIR) -endef - -define Build/Compile -endef - -# Use ath10k-bdencoder from https://github.com/qca/qca-swiss-army-knife.git -# to generate the board-* files here. -# -# This is intended to be used on an interim basis until device-specific -# board data for new devices is available through the upstream compilation -# -# Please send a mail with your device-specific board files upstream. -# You can find instructions and examples on the linux-wireless wiki: -# - -ALLWIFIBOARDS:= \ - edgecore-eap102 \ - gl-ax1800 \ - gl-axt1800 \ - qihoo_v6 - -ALLWIFIPACKAGES:=$(foreach BOARD,$(ALLWIFIBOARDS),ath11k-wifi-$(BOARD)) - -define Package/ath11k-wifi-default - SUBMENU:=ath11k Board-Specific Overrides - SECTION:=firmware - CATEGORY:=Firmware - DEPENDS:=@TARGET_ipq60xx - TITLE:=Custom Board -endef - -define ath11k-wifi-install-one-to - $(INSTALL_DIR) $(2)/lib/firmware/ath11k/$(3)/ - $(INSTALL_DATA) $(1) $(2)/lib/firmware/ath11k/$(3)/board-2.bin -endef - -define ath11k-wifi-install-one - $(if $(filter $(suffix $(1)),.IPQ6018 .ipq6018),\ - $(call ath11k-wifi-install-one-to,$(1),$(2),IPQ6018/hw1.0),\ - $(error Unrecognized board-file suffix '$(suffix $(1))' for '$(1)')\ - ) - -endef -# Blank line required at end of above define due to foreach context - -define generate-ath11k-wifi-package - define Package/ath11k-wifi-$(1) - $(call Package/ath11k-wifi-default) - TITLE:=board-2.bin Overrides for $(2) - CONFLICTS:=$(PREV_BOARD) - endef - - define Package/ath11k-wifi-$(1)/description -The $(2) requires board-specific, reference ("cal") data -that is not yet present in the upstream wireless firmware distribution. - -This package supplies board-2.bin file(s) that, in the interim, -overwrite those supplied by the ath10k-firmware-* packages. - -This is package is only necessary for the $(2). - -Do not install it for any other device! - endef - - define Package/ath11k-wifi-$(1)/install-overlay - $$$$(foreach IPQ_WIFI_BOARD_FILE,$$$$(wildcard board-$(1).*),\ - $$$$(call ath11k-wifi-install-one,$$$$(IPQ_WIFI_BOARD_FILE),$$(1))) - endef - - PREV_BOARD+=ath11k-wifi-$(1) -endef - -# Add board name to ALLWIFIBOARDS -# Place files in this directory as board-. -# Add $(eval $(call generate-ath11k-wifi-package,,)) - -$(eval $(call generate-ath11k-wifi-package,edgecore-eap102,Edgecore EAP102)) -$(eval $(call generate-ath11k-wifi-package,gl-ax1800,Gl.iNET AX1800)) -$(eval $(call generate-ath11k-wifi-package,gl-axt1800,Gl.iNET AXT1800)) -$(eval $(call generate-ath11k-wifi-package,qihoo_v6,QIHOO 360V6)) - - -$(foreach PACKAGE,$(ALLWIFIPACKAGES),$(eval $(call BuildPackage,$(PACKAGE)))) diff --git a/package/firmware/ath11k-wifi/board-2.bin.IPQ6018 b/package/firmware/ath11k-wifi/board-2.bin.IPQ6018 deleted file mode 100644 index 8c384dc89b367f1aab745d0e004bbd29c767432a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 787208 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�PGEB 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 diff --git a/package/firmware/ath11k-wifi/board-edgecore-eap102.bin.IPQ8074 b/package/firmware/ath11k-wifi/board-edgecore-eap102.bin.IPQ8074 deleted file mode 100644 index 211b995352b2e3992825da0f1e3f64e3fc07f651..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 131072 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 T0tx|zfI>hapb$_9L=pJ^wl@k( diff --git a/package/firmware/ath11k-wifi/board-gl-ax1800.bin.IPQ6018 b/package/firmware/ath11k-wifi/board-gl-ax1800.bin.IPQ6018 deleted file mode 100644 index 9ee8d0a756d70b33321ed5da30e7d43501d533fa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 787208 zcmeFa3wTr4nJ)b8E%_p2jBMl!;249AEfb)|TmuFyUu7)G!j^5>aT5oeVkk_UYnekPmU}|pl`ET;S2ufFYH9D@y~JrX zDR`q|er~_@=1tf2ZC`fd-d)Rg^zG_jzN>drxyH8NaNSM48r7{8Ze_P?4e4~PqLA(G ztkvz>Ylrq4)?Pcc*Dme#YTcS&mqcrrdAlWG0(p3UF7{%rO zpH#g%*(FKYR>*)d(qgNdsz3Q^Bu~WXWza1_G?|r8v6-4 zfG8jehytR(#1-hj?|AfJ>fFTrNXtu00bfgad*8qVM~T5GFdGr+g|1(Iv0`?1w;W+Kok%KL;+Di6c7bO0Z~8{5Cud5Q9u+B1w;W+ zKok%KL;+Di6c7bO0a4&`P{2V0+WDudJt;LUJ!6hDGi$CZJ0~}9-uwmmR}?HPT(r0d zKY~gbBk5YXsF2EOJynsHf)u76>Z5+zNBij@9iqc@lpdqgbcUXzAJflv7N1Iw@XKY{j`QwpUV7#qm3{h6i7~q@>hcwsdBVp{&g9E-5j`QGBi} zG6r48i}3ZL{w<~D9O?A*^ovmaOD5zrvZr7${r7$2lzuAL=&zT|peHyGU%0z(;OJ8? zuAF3=VE58Y6c7bO0Z||U3e2MKXAg3><#+^wTe1*s5Z1Bs)F@IRTODF4O5q z4su~VnePUTee-(PuQyB0d@$(sR#vW9F}xi7@iX}912ULzR$EEMfy2GKM&u7hdYl-)ETprKt z1%vTy)2-WgOP)J0_XVT9N5^ex7gwM0#5H|3R*kLs#OOVJ_?qg-UoZ<(SL?P+qk z>5Ms^p-*l!W4E4ZozOV`3uD{U3G~b<9Pi~*SLrGGu}AIYd^fdMDm#y+j!#{%{~#DjnV&>(d&~OvsNnez6}}0blpi!*4pK8TtmE8nMA> z~|MvOL!RX`hK|HMX@#J+M zdfRVOD?jw!<7q24GgpC+oabllb3U4m=V(#tbIq0AR&b zM4mPP%#9vG0N6sl%b2GN09(dARJQ_P<lUI46uTBy1f09#FqsJa>e>t~U{$aT0bsS{pz3A-tR8h90L;g~U8&{(^wIXfG60~i z7nThGSi6nKP!E9J!gWnv0Bj$#8b1Jb2diD<0l*IO*qb^5umNT@^?=*W^T6#wwE*f4 z(?3y-4*)wt9aIwlz>cF`7yvs7)(n810c!%lz6aIuNdy)V&1O1%UmGS#1*l_8PCPT0a2xIxAn>41m4CtgZ$CtFW!5x&{F3*Bn`E zI{@~t?6a;80Q)^y2mt$cX7x<~*dM`~0kHoBYXrdl3#4gf1;%^JJ_STQUc0kCCYEdW?Km=6G3t!$u%S^#W4>Vg1RCFY5?pc>RJJ??|?M|U}wNW0N8iI+5oU;*o(gz04wFF{Y?Pa3vB7{0Kk5t z%p-p%0QQPHfL2J(9Wus2Y*4FLN!SPKC57FZhq_AOr5ogo11tg?mt zVF0Xweb)N{uy@g}76AJg|^>-BX0ATIvMhZ3n zU}3OM0IVCV4gl)`XV&Tkz`nv;_ND*;_El!S8UXAew)EEnU|(Yv z^aEgzFl(;?z;5C--_Z(SUv(Tk_yN?N;8v~C5! z&cU({0DGTVjTZoWg!f#b4gjp$)&(zh;<1y0MI3!j|)N}0Cg_juPuk#S^=;+m6;y^ z>#{APwoU-7n`3F~0>FxS4DD?I*fqAr)LsXGJ%_pgfUSOuZ3DG80-6`z_Ov$uV0*A8 z>H)CNFzc)Xz<$blc69(?2bH&JYY+hY)*NOl*BFc>javc!V}R-;g)&J|3rXeUWK~^E zYSIR>@o|-nx2LwGEdI7Imy-CnJXv*7GUZST%_9eY9@BUmH;cFN8R}Y^qn7iQdJ|=; zn|T{u%*TOCxK#Z{wRIi~z)k}r;8Y)b=mKLeaw3xP0k=n(pu7j4Som8UsQ>nU_N|Sz1?xeTK zoqQveCHTsF--rG{v-y~M7M~e4$iG9E=SUiC zcRc2B6YkHe=WwEfo-5XJPjanZhMaDPT(maVuybj44?7-rAg9v9jwg-WNyjss%jNH7 zdd|h)DleQ?%)M)_?$4*?7P0w>x$hWd6|MuWAb%408-|uc1bPmU>N!NJ=kg*s{<~t- zPK~tHa{Aa%ruA#o;tcYL7cP6%byORho`dHDTo&Z9r5ZU`B$pM*6-07~RBwU!^juz~ z7Mkj17>8MF=D1AN%eXf!hnOw>YGsICuSHa(-juyP=P02MJ%^dmbBMsKHFNN%mtjO^ z3p2;H>@UFnbUWlQUcGFAk<+8n%k+L>H$P&hdk*BdNN@3acF>3qIXx=mpvFzv|EQIr zkF3ZzN+SItr~5l^*k$Ex&(ZzqIr!6a@V7JPC9cIR=sDEtIVi5@u-42n)yQF{^)joM zRHF=P?96$SJ!i1uJ9FMM#-``=KHlTnXpZf;1+% zfG8jehytQOA{EG|aP&`yiR?&xivps6C?E=4HVRxpCoYn)7SQ__Nu*O7=0ZBLcxpY0 zH&H+o5Cud5Q9u+B1w;W+Kok%KL;+Di6c7bO0Z~8{5Cud5Q9u+B1w;W+Kok%KL;+Di z6c7bO0a0Ky1y=KUwMaOjWc#f*Z@R8;`?4GN?pnU1Z&&~FUA>#iHMaeR>u%}=U8!5+ z+;Y2d`uyM3Dtzkw-C3*Kwbu^qHLSgMYOh_|>(yE}{Gu!|b3@+`v1?U#KeR&F2nu8= znaUbvv$9dyplngrac-S*l~T#CtGT>FaVq)7qmtj}M|4f6v0Cb#p@HQ`%!8h=A>ad<+lE{{fb%8y>I zX2_6v?>i-FVprywlCG!B$y8~9D==MZ$rlWTyL)>31`a)V_{h;mA3JsWsWVT1|A#NW zJZzv!vcus>(~z2KPfkr?>PY3nVRjRsT@z>{P2y4@iLaa)m!TMm0y9*BWWL7n3=K`f zy2uqsp;N{P6uNtGaPaOTEfxGhkhuoIsaWHov$mG;^glp@8G(G7fzFH5AT!p zG1>MKLv)TOtL0?d&y=}{Dk3>iKok%KL;+D?;tKTNcRYG9b#CH*q~)chfUhOIy>H-w zBgaoYdFJWoUp5cSBkxO}Br4%QWEbrxTG&IhfUl68TgZ1fV;M4Dk1i>uBc{o=httXW zm~4BAAv(2_)pD}!WiDhcq6+A_$*!r%wwE;-osr3EIob9y7ty(poG2g)hytR3C?E=m z0-}H@APR^AqJStM3Wx%tfG8jehytR3C?E=m0-}H@APR^AmxBTh8qm%^RqaWsY3Uhr zoS9j3UD-LgdGqEk$iJdsVd0|1Mfed^${0!4%0-1#PV1?PycDD`^-v$*D|jF6r-O8e z&jUV6kI`v5L(kEV>1V?pXSjAhw<)Jo`sbJ*R2}X0xaVn|6fY^Z;#?QoE2*gB_?=n9 zgD+lEQtB>SIl$hfvK35hQgRbL6_p`L-m zkDh+|#S2?i431>SrywUFa@}P*9mzp1tS9r`ps{aW@A~y-shJN3z23^o6)T39gMS=0 z)_#ZNd7M2)3Wq}>YhG95@_h}Ck=&e2lW4xY-0dzbj4claFIAh%cZJBvMSJ-|_mi#xoQ0i zN2X^s`POa;O)`(uGmieWYF0p@WEHoT{g9s_}*8&sCm?z$!s4U`1!=zpH6qF6ZoBl*}uGt0-}H@APS7Ez#MwtHF8aC=|I*G z(qDD#&gz|gBu#&PH|>R#%31HG;`v%qp?39^*mlE9rpnK7zZ2n036E^;VQqgW;ju+~ zT>szSKL73WorBTGSoKJ>QVq*i|Dy~op5Y-X+kA34v@+UI;U9naCC)aRb> z!>B!?R{A<4($`qD+?vzZU9?1BJ5eqTO%c+fG8jehytR3C~&DOkV$){b%j1!tsfavn0GJy+gaELGe3vm#7XY@5d#G*&z{;tUs=WYM z1+`FhEdaKf7EyII0M^ewtJ%1dSs~x`j9DFkx)5!m>Mj7Rl1E$Z2f(Ue83Mp+$wAf4 z09ZZhJOG%Ff4fr60qCRcfn@+dT`w#f0I+r&kD(p_yM^nTya3ofW;K2Q><(7D#sh#I zBoYU%;Eo9BVsg=zuR9j1Sx8Xo|5ggU4u0Dv7wyD$KD608{jI|J4PfPD|F z1pwQxFlz+Bp5^|$EdbbD^;)XoPW0LQ0oT=Z0;qcltP2498ME3Z0PHnhTeW@w>~&VY zwiy6>gIQe-09IjJOLYwZ*snRV)^-5wU)g6}9RT)wun++D@676(0I)xTH3MM(3DyXJ z{TEmZ0Ct{PLp=bdD(fg%4}jU3h3WyYbY=~80GNweZ5;qs$eJ~H0kC3NHUePFz*+#X zaxfnNwp!Uh4YdH+dej90uu9am0bo_A3jttTY|I(}Ft5U9odB4R+j&C(SU@QvuO9#l zvX^!b02bn?y#W9$4AumIb+e_n4FKz5*4PSw^(r?~V*mi_Q#{mI3%G;)`Ge&)0Cl&3 z)d650j=IqgfbCP7sL=<2-2uxG0Cul(mbUr_6YaT)B%8@Bc10PI`5t~)~j*jZ%@`NIHM1N*G^17Po>T`d6iZ(ub5*g1?S0D!%Rx;g;t zeXv#l>;q*j`8@zwA8(=kegMp_{+0qB04!bo4F!S#n3MMp0UrRCg}p@p0Lw>R4FI-O z-9mvb0Bo&#H3b>~uv(}T1i)4>3p4^?8{nl40Nbnu7x*s`S#06PHI41nFEZlabp0QPl+$0ANq3XQ?#+fSu-cEv*39GicWUfaSnv7yx?~tO)@7K3F3F_5!!-@&I73aa~<2 z0CpCZEdbad-lO}P0I)ys3TfR6fSrS79RT(|vl=e|_6YB}LLC5DwXKChT>#ie+bX10DBH~ z0RUV57TX4DZv-?iyzOak0KoQOP1FNmpJCQn2Y~&Q_3Y{Zzz!;J)7BsW_N_V0R<1D^ zNgB5T{Ko**NeX3>q85_M$H}U?nAD^VWaHy18*fi-Nm=}DVJ;={ae1=pqGZaU6q-j4 z{ye7fHf|Pg<1^H?G)FDxE%heKR5$ZBx|ojxmvE~Ra;a`U!Y}1dWf|r2Cpu5vO7qkv zny@qkvsWDDogq;?+1QESE}#OvZMpF-2O1FupOio_WS4) z_FquB{Y_eFf14`oJ+wOQI(}~F=MGxsxSpTAv?}#ev^sScKX=k>hSJ?m$kZhaFEExs#4(IG4-c%k-R!zg1p1t(be)T-~2f%PnH_6La4&$|_t3TtWUM z@HY%ChY0i>BGq$TA zV@ox1u1GE`k}HVh5UJh*@#(p|NG&wg%P*MNap3-muHc*`A~O({u2r=iqN=&P!a2 zS&ta{ZWvY?GOzUM3zJ%wb2~gaSN0| zznwXMAF0)IW*KG>wfbjaXU>;$+*9OVk?hs2}%GvX`fQ-p1lmS1L!r(8{f2W&>Q zgnE@y=SDcMO*`4Mi;Vut`Iv%v=5iyRa+U8TPL6^rLuPyM^o8a1CPzGuf|5!rPs?A@ zXyx|I(yc@J661bnNqd+$Q_YA4BvNEn`4*%C|x>GKFG~Hd!sQ&V3kG64NF*v!0 zc@O!?d07#;7yW2{5_w6n;#)IFpdU$}4J=u;zJ8@K=7<3mj2BJ=sb*+_W>1qJ$Z zQE^_uB7F6WNek%S=vSDSS}70(L;+Di6c7bOfkY~hPvPjF4injt_!b330Z~8{xNH=- zf=*l{V=bWfFOo>7Hq3=|V)4{^6mOz{C?E=m0-}H@APR^AqJStM3Wx%tfG8jehytR3 zC?E=m0-}H@APR^AqJStM3Wx%tfG8jehytR(XbP<6^JFaVq)7qmtj} zM|4f6v0CcApn>H_%!lr4%?U*k2|D@^_diA-V@Bd}h zujuVD&0`D>>nWx@o`S>i7+t0|cFK=lu4ae^y!V}wG_fo5Oi9;M=47h0z!jJ-wd4zi z!reW+eFKLcJbdKnqmP|B{nVMKzyHG*UmiA4CE4L{q-jV^wI`>hFmEBk(LVnpz<*To)tuM z<`fl;Fia(HXalxZ`8j%n5qylhD3u0qQ9|nH3#1%B#Q|%HsPI+3e))I#dLaBo+;sinnm^wFcKhpBjQoz>|-rhIxz>(vpo;>sP^DmnR=8^ZMPZE{zAF_+~6D{l^ zTEJIG&Mo9SoUsfUuSb^@(-G5T+r#N(eN48!#1Ng@$!a;-_A(bT7f}WD++^3(WZTP{ zjLyhpwVZ5wnTzOLNKO?-jg{_R~Q+M2G1pJw~VL3_V9brk@RaoZ;I2+@_pT>7QeM zP<6D|C75KS()2iQeuvy_*_|J47!dN z;p;{HTT070(&_2x7oqx>Ovq_u*Y0)Pf8RGw>8Emy{(8v_dV&M-g}ZT6>K9i|GEK01 zX(kGY0-}H@kN^c{(f2g36@wRkgn9-JKYIG<7cXp8F*uSPpMso#$aR@)m`!gLqG#I#u1wp1JQ{PqdHGQ;vgWr;QHu67x!iQd9M8}v zH=40q&$RK*1Wj%?{@ruCv3||>cw(E3&DgUwIg81}W^FsUD8_CrYcf_N(L^+fRX|EE zq=0psmFWD1;+U?wM2~U2{-N`|05~9n%bb15b_EV6^g?uqF}_ z!-yhGVWH@sh*^vEIfYX;qN~6)&;Dq5Md1D?h8NLDWwFs-+9jjhJTpeCi59eMe?HQ* z<$>rQey#bLrf?+SY0g~EI!x!-6Fsf6ADN!nCbNBb;O7%-e>&ZzPT+SI zX8-ao3Wx%tfG9As0(0nn*T^-or2|<%NPpF_JF9p0ku?4F-Lw}{Drdc$isx%dh1%6u zV%rTbnJPcS{Z520B|NgVhqe8kgvS=`as7XP`~0`hcMe7$j}PKuwT~yS`_S8dlUn(q z_a0AMv6;CFeB?YoYoGJcbUa6kQlERi52N;oTIuVINMB>oa%)aschM4k?L@icL;+Di z6c7bO0Z~8{5Cud5Q9u+B1w;W+Kok%KVijkwN0-}H@APR^AqQIrDKql>( z)*)sQ{|x3bPjl%b+hs0+3||zuY!z^kJs*R&(>n6h1MZ_lAJ9hfgaNQr)cF9gbn2p7 z4PZ{%K%Q0r%mvF@0PI1PSt9_J51$PHSRw5tPYVFHimJ)u2f(t?t^)uorXupR0bp+Q z5CXs!@?FL}T>#iJ?xDIB04t|Xs`dh471To2wE);^T13^=09Zf!tY+g*W`%s$GiG%F z>O!=Ms=ENNN*-;s9{{U@We5PPB?nbE17P*2^8jEz{_RRN2cVC(2bKW=v$T@&aJ{nAP|Jusc}o8V>+=kjLKC34jeStEmUvZk`8j7petNcbNW(YJ33L z5$d3t004Fz?ZN=qNw8)B>E!8yuV87J(V)(n9CCs-o@_FrHv0N8nE4fOz+s;r}6Jpg8B7ODrp(wQ~X z0bnj>wRHekA#2v)1;C17*$99w18V`m%E5d9*lJ}1HPixN>rod3z$#JK27pzeE(CyW zu`z1^z`P2Zbpl{MZs!dFU;(9wynX;I$X?n#09c5l_67j3Fjx}+*3FjQHUO-LSz{{z z)~nn|jR63xPw`M=E#MCF=MR?K0My+ARtJE2IO;|}0JcwQqDCJ8b_Xm&0NB0CS=#Cc zz^b_2);a*}kWx)sn*p%_76QP&3)TjJJ;Pr7%>Y;_N9}I{z+PZWe+K~e6J;LxI{~m) zl&i_#4uHK5%MbwORX32|3xK_Wx@`d1ufbXXu(!b40I+ZIy6y}CU}u#rgoWn_rY2Lun&~A{)f8v|z-pmV5CB`jEYJvmZGe|H z0Bo~bM1gt$tQvLA02ncA_5)yB)iw$?0bq^nGuQ!uHLJg)pa%eJS2t3y0RRhwbpl}B zV08dk4;bHuQ=iQ~?l0&AP`3vx1c2R!{#pRA+to7K<^jO&V#}5~0PFx*GXQpvx`|ra z0PO!h$NjZ*0H_;a%W5A0c0aRLF97xx-m*6Z0I;tz^VI-g53!}c9sv6qv!EXUdxTkg z4FGl%ulbHv0Q;)r=)n)5?gYou8Unyhsw=701AslDo~70R0Ct+&wX_0Y&!Alc0G0!v zVF2t|uqFWP`(TX#*bCgQ%L9PD#&vbA0N7brwg6yJ*jE2MQR0Co3UvTr)wUK2bpc=>aql5707k4!r~!a3>3m!e3IV8d@g6S}0KoEK$&U2M z@?lv6pstWvTLS=AY}-t29so1#w3U*l4nW-o_R>%dfO%~>)Yb}s)v3(<09co85w&#! zVBH)`TNeOU%wuS81Hi7aEvEK50PH!`1psXITWlMsy%Es7@V2MD0RY>BHBk?MeTG?Q z9RT)I*0ZYv06VC>O?+qhZ0jn7cm(j2v%x73>`Q{Bwl=wdz& zT*9qN$fdgZ2)~p+m1UI6pXfYwE6r1zXujG)3wZmvAgPYG;_Z~5-f2ypF3!k<9dGf z(yG)?(dyJ){M<>a9ew=V&CfmjbWn==NB%za2b#^t)U)`^s6qZ6x;#hHV7ucnhnsMJ zUOk5s9rRqWmV1(G^)lpiJLICZxrUufvwPU_xC1$r9(FuwRqZVh7N4#*^tFEKk*z_DcAKX%Kk^K41Hup#!(XK z7dhSEdBZL%XM2wBPtU=ho`b)gIWKW7W{dVU3eWX^;nPr$k)asvwojG61acj}P#J#x; ze<`_`52816|yFMk?obh4(&Ys^W}F$!S)u@LtGF zy1m_`{C6OUQn5LwgNtubtX!m-c$K))l`v^%KcJhn$Lfh?zR1#B3q&u?l1< znaUbvv$9dyplngrac-S*l~T#CtGT>FaVq)7qmtj}M|4f6v0CbVp@HRx%!>nWyO3MQw3o${lX ztQq2p_r7B$Mfrg6yil6h)p;)Dar*1x(Lz=JgO4-*de#M|KW=-4;!eG>~J{JG^D25lT%ZeI#RiCnB4?u*96)~leiQ};;U!E zP~o-Bp91Rzphhf<%c&TN0@J8KGGFI-8oQIOE+Yj}=#)NM-ZDWUsD6=T^ust zSwu8vP7%K;6~D0y0gA}tlXZ?oA{JS#?PFeR#{(f}?@Nd0_~l;fv3U@Z|9oZ)Mj z|1HtHhxk4ipWzVrs&HwAL`i=dB;|EnoAAP^;Ax@-+&=F?zDo3M+@3E~m&R8VvHvHx ze`DVUZ$8fWuC9j|)`1s}6KC~FVMU=~9n9J=mpyPOBzmTj)5-& zsLkj5977!QS@4fU^B)@)LmBJv|8e^_#~y>G!?PR%)&u7AR*nJli8b{f>?4l(EO?${ z;JM6wfOX(8WMD4G83W>wBnpTEqQFQBJn;EzKI7Tt4rkXyYd`mw9d~ZHq3D`C-UpiL z@WCDXR$W&V%BeL=h`#v6uDdF4SaPkaF4RGi+mzf5pG> zJyQ5ss^AVjCgRHr=4|Bl3-o8kN6{sDAx~Nie5nX6hHV_fN^Z}`#!kMbc19fEu$OTR zi;r^qyE%qyIR?J8a~A)37|#scz9Npa>}~eJ$8-gsV;w>q!zymi$Ar#o_A$c$iiW#f z_LiaJXD6m3{4K>?j244^c#pAs={ww>=OX_vIEFBff&cI6%+sG4sj>DWl?;iYb=Z1{ zBL+9-g1;l=^LohZ zmNhw_+w;>Ixz7GbqmPy?<#A~1dY>f*{#XdlNI;APowNAZEVh{K0Am;9Zx@F45J zpQ{|+zPR|icUBg+kK?ng#bB(5f;VfMl6+EvUxa@a>4TH>=^{7sJG^W2`-v=&3* zIAeH=ePA44U>|MlV>QQsHObqkc-G_!wC6Qhcz{0}yp77^i`TpI^`~gd5Vdib^U3?H9Nu5J5Cg`cj6H}UG4Ohd#K516cw<#*g5{Y7voegbPwfuX)s?MUP@I`P%h(pYWZ(xN&!Fcv<88b(!v2c`2#z__gal z*}AE=xFWa6=}I%~{{D{sPuF$^w$5LlSvG5)Zg+5JYkNg);hMRNXS-4jyAyZy{aID_ zlC60gGs@EDr>4Q*oqhiH6}1IxvWn7ODMox>zN7oo>$(;-WZIMpy`*dG* zM`_*swR4KnvXixyecQgReaqYPYqQqODoV*t(prCG-;Tb@_Tsv{H5o-|F22zTr|%rx zeQVA2Wud%kXGPkgWZqKpoeKZFYuCDPVSUcJ*~N|=qmR$;xTUJMv^Cc=ry{LTxBKjE zt)E)mwy?&vI(>2KT)r^}r(*}My;y%Kg|xd@uZgR4;+8;`4Kjt=i+HCHllziAPR^AqJStM3Wx%tfG8je zhytR3C?E=m0-}H@APR^AqJStM3Wx$1ivkWB(Ej(O*ppJz(lh2bGqdKpvU76t=FMM_ ze?>v$_fIKfBwSS>he~KId8vzfXgA*{cpvSj&(Zz#ARVDc`81&$8aiMQfz|Hh*QpWQL1rnM}{-Y68gfzMT?7ymz0#c z%a&fbY&nl)j3MyYjm7W(%;b;dX|1jFVm~^ z2E9YSGe+|-bd<*&q;kq*Py9psVJSL>WlNX3i}j?9p)4|nVNEU`dQtx$k$>D_ru1~< zKk;V4%z3xjC`tcs_{@oEsv}7wyY{<){` z#VumFUcGznM3;v!lgm9aB6DLic07ir&N5j_5t|=WQxJOXixkuH~uL zJD$&g*oXq6fG8jehytR3C?E=m0;0gjqrhx>s}McgjC1VA6GcB?pTbQ2e2qpkS@T<_ zD4D(|`#zm9$20WFj%Td)Gi|&xL6h5!fA`#OtY7mzp4cX1GuB*9wth0PS=&xFjJ-|_mi#xoQ0j9 z4pV08Xv_BJBhFeLi2mW%nxAP3M*^Pa%;l`ZbdEjI(<=Ls>6uOKqP_{7Oqs{&na2c9 zq2^lV@zR*bM6VO^FA7){$e^>@b@B&aNq5=QUgCRS5#L9e9(w55G1#3sL!;)ce$4ja zfuB#T{poaHL)cFSwBdB)v-IPclMDq{q^0n z7g8!`y_<^XYe|LL)mLKM4KJB0Kg0b_gfAsLvbBe`{hfrz7VUBUe}DV@x6gMDMjww4 z;$gLqC$Ia^+kTT;`Jwk7Pg}8>xe9#bJU?rn^U-uXM~hOQd%pjm_J~^P>x@WWW6^SJ zPG5J?5`FDNx#UCvQ9u+B1w;W+Kok%KL;+Di6c7bO0Z~8{5CvitaFSiScXe!yl!yYN zfG8jehytR(rLI6G?U~jgW)c4k<}y!n=_4B?C=3i0;>@g}T$m^z3S4>$xX7N5QQ2{~ zta`wGl;{K6NS-hNmWnzb0G7`81*_En=A;eeX$8Psu&f2Z9#ok%0$};@*#LkQ(q8hk z0AQ=Anmm30EF0}Q0I*^zB2OCt=0*=80Bj-Oqs!9;fGy)5s#^iDa=!0ZwHE-ZpcbmG z1;AF*BC4(i!1~!|H5+#_E2Q;cbpYx@w27*_0I*6PZM7c&tAb?+0IMYjRW}1*^{Ddz zU_SosN;LeW&rFASQ7yDJ+Kx4Y`?;+ z5deFZ`}4K{U~|=LsfIhzXY&VKSJMfg?j^7;0PJVXYMTJC*LZE!`T?-lS^3�PGEB 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≪$jj3NLn_#-o#x3KO3P=T{0vEFaGw6A3cq<3a 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�PGEB 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 Mqykcb;S~7)0R(CGkpKVy diff --git a/package/firmware/ath11k-wifi/qdss_trace_config.bin b/package/firmware/ath11k-wifi/qdss_trace_config.bin deleted file mode 100644 index c212560df..000000000 --- a/package/firmware/ath11k-wifi/qdss_trace_config.bin +++ /dev/null @@ -1,99 +0,0 @@ -//This comment and parser will ignore -//Tracer scenario(or commands) always -//starts with start keyword -//Below commands to enable Event traces on UMAC,MAC0,MAC1 -//seq_start; -//seq_type:mem_req; -//memory size always given in KB. beow example reserves 3 buffers segments of 16 KB. -//sink:etr_ddr,0x1,0x1000; -//seq_end; -//Below commands to enable Event traces on UMAC,MAC0,MAC1 -seq_start; -seq_type:mac_event_trace; -sink:etr_ddr; -subsys_cfg_start:mac0; -hwsch:0x1, 0x000FFFF1,0x1036052C,0x0,0x0; -rxdma:0x2, 0x3400,0x8000,0x0,0x0; -crypto:0x3, 0xF79B3770,0x0,0x0,0x0; -txpcu:0x4, 0xD687F4E7,0x20000092,0x0,0x0; -txole:0x5, 0x640F0622,0x2,0x0,0x0; -pdg:0x6, 0x3C800706,0x0,0x0,0x0; -subsys_cfg_end:mac0; -subsys_cfg_start:mac1; -hwsch:0x7, 0x000FFFF1,0x1036052C,0x0,0x0; -rxdma:0x8, 0x3400,0x8000,0x0,0x0; -crypto:0x9, 0xF79B3770,0x0,0x0,0x0; -txpcu:0xA, 0xD687F4E7,0x20000092,0x0,0x0; -txole:0xB, 0x640F0622,0x2,0x0,0x0; -pdg:0xC, 0x3C800706,0x0,0x0,0x0; -subsys_cfg_end:mac1; -swap:0xFFFFFFFF; -trigger_start:trc; -wfi:0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF; -ts0:0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF; -ts1:0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF; -ts2:0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF; -ts3:0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF; -ts4:0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF; -trigger_end:trc; -memw:0xFFFFFFFF,0xFFFFFFFF; -seq_end; -// Below commands to enable obo trace on the mac0 -//seq_start; -//seq_type:mac_obo_trace; -//sink:etb_wcss; -//subsys_cfg_start:mac0; -//hwsch:0x1,0xABCDABCD; -//subsys_cfg_end:mac0; -//swap:0xABCDABCD; -//trigger_start:trc; -//wfi:0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF; -//ts0:0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF; -//ts1:0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF; -//ts2:0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF; -//ts3:0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF; -//ts4:0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF; -//trigger_end:trc; -//memw:0xFFFFFFFF,0xFFFFFFFF; -//seq_end; -// Below commands to enable TLV trace on the mac0 -//seq_start; -//seq_type:mac_tlv_trace; -//sink:etb_wcss; -//subsys_cfg_start:mac0; -//tlv_port:PDG_TXDMA_TLV; -//subsys_cfg_end:mac0; -//seq_end; -// Below commands to enable q6 etm -//seq_start; -//seq_type:q6_etm_trace; -//sink:etr_ddr; -//seq_end; -// Below commands to enable umac noc traces -//seq_start; -//seq_type:umac_noc_trace; -//sink:etb_wcss; -//ctrl:0x12; -//port_sel:0x4; -//lut:0xA; -//routeid_base:0x01000000; -//routeid_mask:0x01c00000; -//addr_lo:0x0; -//addr_hi:0x0; -//win_size:0x25; -//req_opcode:0x3; -//res_status:0x3; -//fltr_len:0xF; -//async_period:0xC; -//seq_end; -// Below commands to enable umac noc traces -//seq_start; -//seq_type:phy_tlv_trace; -//sink:etr_ddr; -//seq_end; -//seq_start; -//seq_type:phy_event_trace; -//sink:etr_ddr; -//phya:0x1,0x1; -//phyb:0x1,0x1; -//seq_end; diff --git a/package/firmware/b43legacy-firmware/Makefile b/package/firmware/b43legacy-firmware/Makefile deleted file mode 100755 index b7f325e13..000000000 --- a/package/firmware/b43legacy-firmware/Makefile +++ /dev/null @@ -1,72 +0,0 @@ -# -# Copyright (C) 2016 OpenWrt.org -# -# This is free software, licensed under the GNU General Public License v2. -# See /LICENSE for more information. -# - -include $(TOPDIR)/rules.mk - -PKG_NAME:=b43legacy-firmware -PKG_VERSION:=3.130.20.0 -PKG_RELEASE:=1 - -PKG_SOURCE:=wl_apsta-$(PKG_VERSION).o -PKG_SOURCE_URL:=@OPENWRT -PKG_HASH:=7dba610b1d96dd14e901bcbce14cd6ecd1b1ac6f5c0035b0d6b6dc46a7c3ef90 - -include $(INCLUDE_DIR)/package.mk - -define Package/b43legacy-firmware - SECTION:=firmware - CATEGORY:=Firmware - URL:=$(PKG_SOURCE_URL) - TITLE:=Broadcom bcm43xx b43legacy firmware -endef - -define Package/b43legacy-firmware/config - if PACKAGE_b43legacy-firmware - - config B43LEGACY_FW_SQUASH - bool "Remove unnecessary firmware files" - default y - help - This options allows you to remove unnecessary b43legacy firmware files - from the final rootfs image. This can reduce the rootfs size by - up to 50k. - - If unsure, say Y. - - config B43LEGACY_FW_SQUASH_COREREVS - string "Core revisions to include" - depends on B43LEGACY_FW_SQUASH - default "1,2,3,4" - help - This is a comma separated list of core revision numbers. - - Example (keep files for rev4 only): - 4 - - Example (keep files for rev2 and rev4): - 2,4 - - endif -endef - -define Build/Prepare - mkdir -p $(PKG_BUILD_DIR) -endef - -define Build/Compile - -endef - -define Package/b43legacy-firmware/install - $(INSTALL_DIR) $(1)/lib/firmware - b43-fwcutter --unsupported -w $(1)/lib/firmware/ $(DL_DIR)/$(PKG_SOURCE) - ifneq ($(CONFIG_B43LEGACY_FW_SQUASH),) - b43-fwsquash.py "G" "$(CONFIG_B43LEGACY_FW_SQUASH_COREREVS)" "$(1)/lib/firmware/b43legacy" - endif -endef - -$(eval $(call BuildPackage,b43legacy-firmware)) diff --git a/package/firmware/cypress-firmware/Makefile b/package/firmware/cypress-firmware/Makefile index c5f41e0cb..6a14ff993 100644 --- a/package/firmware/cypress-firmware/Makefile +++ b/package/firmware/cypress-firmware/Makefile @@ -1,19 +1,14 @@ -# -# Copyright (C) 2019-2020 OpenWrt.org -# -# This is free software, licensed under the GNU General Public License v2. -# See /LICENSE for more information. -# +# SPDX-License-Identifier: GPL-2.0-or-later include $(TOPDIR)/rules.mk PKG_NAME:=cypress-firmware -PKG_VERSION:=5.4.18-2021_0812 +PKG_VERSION:=5.10.9-2022_0909 PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://github.com/Infineon/ifx-linux-firmware/ -PKG_MIRROR_HASH:=ac882b482dd401b53cdecc6004cd2bd3d65e888c19206dcf10931a28033ada4d +PKG_MIRROR_HASH:=944faae3a80013f1a963b6692d7f50a38c97edcf91fd163de521df755e6922b5 PKG_SOURCE_VERSION:=release-v$(PKG_VERSION) PKG_MAINTAINER:=Álvaro Fernández Rojas @@ -38,12 +33,19 @@ define Package/cypress-firmware-43012-sdio endef define Package/cypress-firmware-43012-sdio/install - $(INSTALL_DIR) $(1)/lib/firmware/brcm + $(INSTALL_DIR) $(1)/lib/firmware/cypress $(INSTALL_DATA) \ $(PKG_BUILD_DIR)/firmware/cyfmac43012-sdio.bin \ - $(1)/lib/firmware/brcm/brcmfmac43012-sdio.bin + $(1)/lib/firmware/cypress/ $(INSTALL_DATA) \ $(PKG_BUILD_DIR)/firmware/cyfmac43012-sdio.clm_blob \ + $(1)/lib/firmware/cypress/ + $(INSTALL_DIR) $(1)/lib/firmware/brcm + $(LN) \ + ../cypress/cyfmac43012-sdio.bin \ + $(1)/lib/firmware/brcm/brcmfmac43012-sdio.bin + $(LN) \ + ../cypress/cyfmac43012-sdio.clm_blob \ $(1)/lib/firmware/brcm/brcmfmac43012-sdio.clm_blob endef @@ -56,9 +58,13 @@ define Package/cypress-firmware-43340-sdio endef define Package/cypress-firmware-43340-sdio/install - $(INSTALL_DIR) $(1)/lib/firmware/brcm + $(INSTALL_DIR) $(1)/lib/firmware/cypress $(INSTALL_DATA) \ $(PKG_BUILD_DIR)/firmware/cyfmac43340-sdio.bin \ + $(1)/lib/firmware/cypress/ + $(INSTALL_DIR) $(1)/lib/firmware/brcm + $(LN) \ + ../cypress/cyfmac43340-sdio.bin \ $(1)/lib/firmware/brcm/brcmfmac43340-sdio.bin endef @@ -73,9 +79,13 @@ define Package/cypress-firmware-43362-sdio endef define Package/cypress-firmware-43362-sdio/install - $(INSTALL_DIR) $(1)/lib/firmware/brcm + $(INSTALL_DIR) $(1)/lib/firmware/cypress $(INSTALL_DATA) \ $(PKG_BUILD_DIR)/firmware/cyfmac43362-sdio.bin \ + $(1)/lib/firmware/cypress/ + $(INSTALL_DIR) $(1)/lib/firmware/brcm + $(LN) \ + ../cypress/cyfmac43362-sdio.bin \ $(1)/lib/firmware/brcm/brcmfmac43362-sdio.bin endef @@ -85,12 +95,18 @@ $(eval $(call BuildPackage,cypress-firmware-43362-sdio)) define Package/cypress-firmware-4339-sdio $(Package/cypress-firmware-default) TITLE:=CYW4339 FullMac SDIO firmware + PROVIDES:=brcmfmac-firmware-4339-sdio + CONFLICTS:=brcmfmac-firmware-4339-sdio endef define Package/cypress-firmware-4339-sdio/install - $(INSTALL_DIR) $(1)/lib/firmware/brcm + $(INSTALL_DIR) $(1)/lib/firmware/cypress $(INSTALL_DATA) \ $(PKG_BUILD_DIR)/firmware/cyfmac4339-sdio.bin \ + $(1)/lib/firmware/cypress/ + $(INSTALL_DIR) $(1)/lib/firmware/brcm + $(LN) \ + ../cypress/cyfmac4339-sdio.bin \ $(1)/lib/firmware/brcm/brcmfmac4339-sdio.bin endef @@ -105,17 +121,49 @@ define Package/cypress-firmware-43430-sdio endef define Package/cypress-firmware-43430-sdio/install - $(INSTALL_DIR) $(1)/lib/firmware/brcm + $(INSTALL_DIR) $(1)/lib/firmware/cypress $(INSTALL_DATA) \ $(PKG_BUILD_DIR)/firmware/cyfmac43430-sdio.bin \ - $(1)/lib/firmware/brcm/brcmfmac43430-sdio.bin + $(1)/lib/firmware/cypress/ $(INSTALL_DATA) \ $(PKG_BUILD_DIR)/firmware/cyfmac43430-sdio.clm_blob \ + $(1)/lib/firmware/cypress/ + $(INSTALL_DIR) $(1)/lib/firmware/brcm + $(LN) \ + ../cypress/cyfmac43430-sdio.bin \ + $(1)/lib/firmware/brcm/brcmfmac43430-sdio.bin + $(LN) \ + ../cypress/cyfmac43430-sdio.clm_blob \ $(1)/lib/firmware/brcm/brcmfmac43430-sdio.clm_blob endef $(eval $(call BuildPackage,cypress-firmware-43430-sdio)) +# Cypress 43439 SDIO Firmware +define Package/cypress-firmware-43439-sdio + $(Package/cypress-firmware-default) + TITLE:=CYW43439 FullMac SDIO firmware +endef + +define Package/cypress-firmware-43439-sdio/install + $(INSTALL_DIR) $(1)/lib/firmware/cypress + $(INSTALL_DATA) \ + $(PKG_BUILD_DIR)/firmware/cyfmac43439-sdio.bin \ + $(1)/lib/firmware/cypress/ + $(INSTALL_DATA) \ + $(PKG_BUILD_DIR)/firmware/cyfmac43439-sdio.clm_blob \ + $(1)/lib/firmware/cypress/ + $(INSTALL_DIR) $(1)/lib/firmware/brcm + $(LN) \ + ../cypress/cyfmac43439-sdio.bin \ + $(1)/lib/firmware/brcm/brcmfmac43439-sdio.bin + $(LN) \ + ../cypress/cyfmac43439-sdio.clm_blob \ + $(1)/lib/firmware/brcm/brcmfmac43439-sdio.clm_blob +endef + +$(eval $(call BuildPackage,cypress-firmware-43439-sdio)) + # Cypress 43455 SDIO Firmware define Package/cypress-firmware-43455-sdio $(Package/cypress-firmware-default) @@ -125,12 +173,19 @@ define Package/cypress-firmware-43455-sdio endef define Package/cypress-firmware-43455-sdio/install - $(INSTALL_DIR) $(1)/lib/firmware/brcm + $(INSTALL_DIR) $(1)/lib/firmware/cypress $(INSTALL_DATA) \ $(PKG_BUILD_DIR)/firmware/cyfmac43455-sdio.bin \ - $(1)/lib/firmware/brcm/brcmfmac43455-sdio.bin + $(1)/lib/firmware/cypress/ $(INSTALL_DATA) \ $(PKG_BUILD_DIR)/firmware/cyfmac43455-sdio.clm_blob \ + $(1)/lib/firmware/cypress/ + $(INSTALL_DIR) $(1)/lib/firmware/brcm + $(LN) \ + ../cypress/cyfmac43455-sdio.bin \ + $(1)/lib/firmware/brcm/brcmfmac43455-sdio.bin + $(LN) \ + ../cypress/cyfmac43455-sdio.clm_blob \ $(1)/lib/firmware/brcm/brcmfmac43455-sdio.clm_blob endef @@ -143,12 +198,19 @@ define Package/cypress-firmware-4354-sdio endef define Package/cypress-firmware-4354-sdio/install - $(INSTALL_DIR) $(1)/lib/firmware/brcm + $(INSTALL_DIR) $(1)/lib/firmware/cypress $(INSTALL_DATA) \ $(PKG_BUILD_DIR)/firmware/cyfmac4354-sdio.bin \ - $(1)/lib/firmware/brcm/brcmfmac4354-sdio.bin + $(1)/lib/firmware/cypress/ $(INSTALL_DATA) \ $(PKG_BUILD_DIR)/firmware/cyfmac4354-sdio.clm_blob \ + $(1)/lib/firmware/cypress/ + $(INSTALL_DIR) $(1)/lib/firmware/brcm + $(LN) \ + ../cypress/cyfmac4354-sdio.bin \ + $(1)/lib/firmware/brcm/brcmfmac4354-sdio.bin + $(LN) \ + ../cypress/cyfmac4354-sdio.clm_blob \ $(1)/lib/firmware/brcm/brcmfmac4354-sdio.clm_blob endef @@ -161,12 +223,19 @@ define Package/cypress-firmware-4356-pcie endef define Package/cypress-firmware-4356-pcie/install - $(INSTALL_DIR) $(1)/lib/firmware/brcm + $(INSTALL_DIR) $(1)/lib/firmware/cypress $(INSTALL_DATA) \ $(PKG_BUILD_DIR)/firmware/cyfmac4356-pcie.bin \ - $(1)/lib/firmware/brcm/brcmfmac4356-pcie.bin + $(1)/lib/firmware/cypress/ $(INSTALL_DATA) \ $(PKG_BUILD_DIR)/firmware/cyfmac4356-pcie.clm_blob \ + $(1)/lib/firmware/cypress/ + $(INSTALL_DIR) $(1)/lib/firmware/brcm + $(LN) \ + ../cypress/cyfmac4356-pcie.bin \ + $(1)/lib/firmware/brcm/brcmfmac4356-pcie.bin + $(LN) \ + ../cypress/cyfmac4356-pcie.clm_blob \ $(1)/lib/firmware/brcm/brcmfmac4356-pcie.clm_blob endef @@ -179,12 +248,19 @@ define Package/cypress-firmware-4356-sdio endef define Package/cypress-firmware-4356-sdio/install - $(INSTALL_DIR) $(1)/lib/firmware/brcm + $(INSTALL_DIR) $(1)/lib/firmware/cypress $(INSTALL_DATA) \ $(PKG_BUILD_DIR)/firmware/cyfmac4356-sdio.bin \ - $(1)/lib/firmware/brcm/brcmfmac4356-sdio.bin + $(1)/lib/firmware/cypress/ $(INSTALL_DATA) \ $(PKG_BUILD_DIR)/firmware/cyfmac4356-sdio.clm_blob \ + $(1)/lib/firmware/cypress/ + $(INSTALL_DIR) $(1)/lib/firmware/brcm + $(LN) \ + ../cypress/cyfmac4356-sdio.bin \ + $(1)/lib/firmware/brcm/brcmfmac4356-sdio.bin + $(LN) \ + ../cypress/cyfmac4356-sdio.clm_blob \ $(1)/lib/firmware/brcm/brcmfmac4356-sdio.clm_blob endef @@ -197,17 +273,49 @@ define Package/cypress-firmware-43570-pcie endef define Package/cypress-firmware-43570-pcie/install - $(INSTALL_DIR) $(1)/lib/firmware/brcm + $(INSTALL_DIR) $(1)/lib/firmware/cypress $(INSTALL_DATA) \ $(PKG_BUILD_DIR)/firmware/cyfmac43570-pcie.bin \ - $(1)/lib/firmware/brcm/brcmfmac43570-pcie.bin + $(1)/lib/firmware/cypress/ $(INSTALL_DATA) \ $(PKG_BUILD_DIR)/firmware/cyfmac43570-pcie.clm_blob \ + $(1)/lib/firmware/cypress/ + $(INSTALL_DIR) $(1)/lib/firmware/brcm + $(LN) \ + ../cypress/cyfmac43570-pcie.bin \ + $(1)/lib/firmware/brcm/brcmfmac43570-pcie.bin + $(LN) \ + ../cypress/cyfmac43570-pcie.clm_blob \ $(1)/lib/firmware/brcm/brcmfmac43570-pcie.clm_blob endef $(eval $(call BuildPackage,cypress-firmware-43570-pcie)) +# Cypress 4373 PCIe Firmware +define Package/cypress-firmware-4373-pcie + $(Package/cypress-firmware-default) + TITLE:=CYW4373 FullMac PCIe firmware +endef + +define Package/cypress-firmware-4373-pcie/install + $(INSTALL_DIR) $(1)/lib/firmware/cypress + $(INSTALL_DATA) \ + $(PKG_BUILD_DIR)/firmware/cyfmac4373-pcie.bin \ + $(1)/lib/firmware/cypress/ + $(INSTALL_DATA) \ + $(PKG_BUILD_DIR)/firmware/cyfmac4373-pcie.clm_blob \ + $(1)/lib/firmware/cypress/ + $(INSTALL_DIR) $(1)/lib/firmware/brcm + $(LN) \ + ../cypress/cyfmac4373-pcie.bin \ + $(1)/lib/firmware/brcm/brcmfmac4373-pcie.bin + $(LN) \ + ../cypress/cyfmac4373-pcie.clm_blob \ + $(1)/lib/firmware/brcm/brcmfmac4373-pcie.clm_blob +endef + +$(eval $(call BuildPackage,cypress-firmware-4373-pcie)) + # Cypress 4373 SDIO Firmware define Package/cypress-firmware-4373-sdio $(Package/cypress-firmware-default) @@ -215,12 +323,19 @@ define Package/cypress-firmware-4373-sdio endef define Package/cypress-firmware-4373-sdio/install - $(INSTALL_DIR) $(1)/lib/firmware/brcm + $(INSTALL_DIR) $(1)/lib/firmware/cypress $(INSTALL_DATA) \ $(PKG_BUILD_DIR)/firmware/cyfmac4373-sdio.bin \ - $(1)/lib/firmware/brcm/brcmfmac4373-sdio.bin + $(1)/lib/firmware/cypress/ $(INSTALL_DATA) \ $(PKG_BUILD_DIR)/firmware/cyfmac4373-sdio.clm_blob \ + $(1)/lib/firmware/cypress/ + $(INSTALL_DIR) $(1)/lib/firmware/brcm + $(LN) \ + ../cypress/cyfmac4373-sdio.bin \ + $(1)/lib/firmware/brcm/brcmfmac4373-sdio.bin + $(LN) \ + ../cypress/cyfmac4373-sdio.clm_blob \ $(1)/lib/firmware/brcm/brcmfmac4373-sdio.clm_blob endef @@ -233,12 +348,19 @@ define Package/cypress-firmware-4373-usb endef define Package/cypress-firmware-4373-usb/install - $(INSTALL_DIR) $(1)/lib/firmware/brcm + $(INSTALL_DIR) $(1)/lib/firmware/cypress $(INSTALL_DATA) \ $(PKG_BUILD_DIR)/firmware/cyfmac4373-usb.bin \ - $(1)/lib/firmware/brcm/brcmfmac4373-usb.bin + $(1)/lib/firmware/cypress/ $(INSTALL_DATA) \ $(PKG_BUILD_DIR)/firmware/cyfmac4373.clm_blob \ + $(1)/lib/firmware/cypress/ + $(INSTALL_DIR) $(1)/lib/firmware/brcm + $(LN) \ + ../cypress/cyfmac4373-usb.bin \ + $(1)/lib/firmware/brcm/brcmfmac4373-usb.bin + $(LN) \ + ../cypress/cyfmac4373.clm_blob \ $(1)/lib/firmware/brcm/brcmfmac4373.clm_blob endef @@ -251,13 +373,114 @@ define Package/cypress-firmware-54591-pcie endef define Package/cypress-firmware-54591-pcie/install - $(INSTALL_DIR) $(1)/lib/firmware/brcm + $(INSTALL_DIR) $(1)/lib/firmware/cypress $(INSTALL_DATA) \ $(PKG_BUILD_DIR)/firmware/cyfmac54591-pcie.bin \ - $(1)/lib/firmware/brcm/brcmfmac54591-pcie.bin + $(1)/lib/firmware/cypress/ $(INSTALL_DATA) \ $(PKG_BUILD_DIR)/firmware/cyfmac54591-pcie.clm_blob \ + $(1)/lib/firmware/cypress/ + $(INSTALL_DIR) $(1)/lib/firmware/brcm + $(LN) \ + ../cypress/cyfmac54591-pcie.bin \ + $(1)/lib/firmware/brcm/brcmfmac54591-pcie.bin + $(LN) \ + ../cypress/cyfmac54591-pcie.clm_blob \ $(1)/lib/firmware/brcm/brcmfmac54591-pcie.clm_blob endef $(eval $(call BuildPackage,cypress-firmware-54591-pcie)) + +# Cypress 54591 SDIO Firmware +define Package/cypress-firmware-54591-sdio + $(Package/cypress-firmware-default) + TITLE:=CYW54591 FullMac SDIO firmware +endef + +define Package/cypress-firmware-54591-sdio/install + $(INSTALL_DIR) $(1)/lib/firmware/cypress + $(INSTALL_DATA) \ + $(PKG_BUILD_DIR)/firmware/cyfmac54591-sdio.bin \ + $(1)/lib/firmware/cypress/ + $(INSTALL_DATA) \ + $(PKG_BUILD_DIR)/firmware/cyfmac54591-sdio.clm_blob \ + $(1)/lib/firmware/cypress/ + $(INSTALL_DIR) $(1)/lib/firmware/brcm + $(LN) \ + ../cypress/cyfmac54591-sdio.bin \ + $(1)/lib/firmware/brcm/brcmfmac54591-sdio.bin + $(LN) \ + ../cypress/cyfmac54591-sdio.clm_blob \ + $(1)/lib/firmware/brcm/brcmfmac54591-sdio.clm_blob +endef + +$(eval $(call BuildPackage,cypress-firmware-54591-sdio)) + +# Cypress 55560 PCIe Firmware +define Package/cypress-firmware-55560-pcie + $(Package/cypress-firmware-default) + TITLE:=CYW55560 FullMac PCIe firmware +endef + +define Package/cypress-firmware-55560-pcie/install + $(INSTALL_DIR) $(1)/lib/firmware/cypress + $(INSTALL_DATA) \ + $(PKG_BUILD_DIR)/firmware/cyfmac55560-pcie.trxse \ + $(1)/lib/firmware/cypress/ + $(INSTALL_DIR) $(1)/lib/firmware/brcm + $(LN) \ + ../cypress/cyfmac55560-pcie.trxse \ + $(1)/lib/firmware/brcm/brcmfmac55560-pcie.trxse +endef + +$(eval $(call BuildPackage,cypress-firmware-55560-pcie)) + +# Cypress 55572 PCIe Firmware +define Package/cypress-firmware-55572-pcie + $(Package/cypress-firmware-default) + TITLE:=CYW55572 FullMac PCIe firmware +endef + +define Package/cypress-firmware-55572-pcie/install + $(INSTALL_DIR) $(1)/lib/firmware/cypress + $(INSTALL_DATA) \ + $(PKG_BUILD_DIR)/firmware/cyfmac55572-pcie.trxse \ + $(1)/lib/firmware/cypress/ + $(INSTALL_DATA) \ + $(PKG_BUILD_DIR)/firmware/cyfmac55572-pcie.clm_blob \ + $(1)/lib/firmware/cypress/ + $(INSTALL_DIR) $(1)/lib/firmware/brcm + $(LN) \ + ../cypress/cyfmac55572-pcie.trxse \ + $(1)/lib/firmware/brcm/brcmfmac55572-pcie.trxse + $(LN) \ + ../cypress/cyfmac55572-pcie.clm_blob \ + $(1)/lib/firmware/brcm/brcmfmac55572-pcie.clm_blob +endef + +$(eval $(call BuildPackage,cypress-firmware-55572-pcie)) + +# Cypress 55572 SDIO Firmware +define Package/cypress-firmware-55572-sdio + $(Package/cypress-firmware-default) + TITLE:=CYW55572 FullMac SDIO firmware +endef + +define Package/cypress-firmware-55572-sdio/install + $(INSTALL_DIR) $(1)/lib/firmware/cypress + $(INSTALL_DATA) \ + $(PKG_BUILD_DIR)/firmware/cyfmac55572-sdio.trxse \ + $(1)/lib/firmware/cypress/ + $(INSTALL_DATA) \ + $(PKG_BUILD_DIR)/firmware/cyfmac55572-sdio.clm_blob \ + $(1)/lib/firmware/cypress/ + $(INSTALL_DIR) $(1)/lib/firmware/brcm + $(LN) \ + ../cypress/cyfmac55572-sdio.trxse \ + $(1)/lib/firmware/brcm/brcmfmac55572-sdio.trxse + $(LN) \ + ../cypress/cyfmac55572-sdio.clm_blob \ + $(1)/lib/firmware/brcm/brcmfmac55572-sdio.clm_blob +endef + +$(eval $(call BuildPackage,cypress-firmware-55572-sdio)) diff --git a/package/firmware/cypress-nvram/Makefile b/package/firmware/cypress-nvram/Makefile index 806bfa2d9..dcf09d959 100644 --- a/package/firmware/cypress-nvram/Makefile +++ b/package/firmware/cypress-nvram/Makefile @@ -1,108 +1,38 @@ -# -# Copyright (C) 2019 OpenWrt.org -# -# This is free software, licensed under the GNU General Public License v2. -# See /LICENSE for more information. -# +# SPDX-License-Identifier: GPL-2.0-or-later include $(TOPDIR)/rules.mk PKG_NAME:=cypress-nvram -PKG_SOURCE_DATE:=2019-09-03 -PKG_SOURCE_VERSION:=e7b78df22f2a0c5f56abb7b5880661611de35e5f -PKG_MIRROR_HASH:=1cb20a749696852be0a512d51961365dd9c031362af0af1a2b9f5a3fb894885f -PKG_RELEASE:=2 - -PKG_SOURCE_PROTO:=git -PKG_SOURCE_URL:=https://github.com/openwrt/cypress-nvram.git +PKG_RELEASE:=7 PKG_MAINTAINER:=Álvaro Fernández Rojas -PKG_FLAGS:=nonshared - include $(INCLUDE_DIR)/package.mk define Package/cypress-nvram-default SECTION:=firmware CATEGORY:=Firmware - URL:=https://community.cypress.com/community/linux endef define Build/Compile true endef -# Cypress 43430 SDIO Raspberry Pi 3B NVRAM -define Package/cypress-nvram-43430-sdio-rpi-3b +# Cypress 4339 SDIO NVRAM +define Package/cypress-nvram-4339-sdio $(Package/cypress-nvram-default) - TITLE:=CYW43430 NVRAM for Raspberry Pi 3B - DEPENDS:=@TARGET_bcm27xx - PROVIDES:=brcmfmac-firmware-43430-sdio-rpi-3b - CONFLICTS:=brcmfmac-firmware-43430-sdio-rpi-3b + TITLE:=BCM4339 SDIO NVRAM + CONFLICTS:=brcmfmac-nvram-4339-sdio endef -define Package/cypress-nvram-43430-sdio-rpi-3b/install +define Package/cypress-nvram-4339-sdio/install $(INSTALL_DIR) $(1)/lib/firmware/brcm $(INSTALL_DATA) \ - $(PKG_BUILD_DIR)/brcmfmac43430-sdio.raspberrypi,3-model-b.txt \ - $(1)/lib/firmware/brcm/brcmfmac43430-sdio.raspberrypi,3-model-b.txt + ./files/brcmfmac4339-sdio.AP6335.txt \ + $(1)/lib/firmware/brcm/ + $(LN) \ + brcmfmac4339-sdio.AP6335.txt \ + $(1)/lib/firmware/brcm/brcmfmac4339-sdio.technexion,imx7d-pico-pi.txt endef -$(eval $(call BuildPackage,cypress-nvram-43430-sdio-rpi-3b)) - -# Cypress 43430 SDIO Raspberry Pi Zero W NVRAM -define Package/cypress-nvram-43430-sdio-rpi-zero-w - $(Package/cypress-nvram-default) - TITLE:=CYW43430 NVRAM for Raspberry Pi Zero W - DEPENDS:=@TARGET_bcm27xx - PROVIDES:=brcmfmac-firmware-43430-sdio-rpi-zero-w - CONFLICTS:=brcmfmac-firmware-43430-sdio-rpi-zero-w -endef - -define Package/cypress-nvram-43430-sdio-rpi-zero-w/install - $(INSTALL_DIR) $(1)/lib/firmware/brcm - $(INSTALL_DATA) \ - $(PKG_BUILD_DIR)/brcmfmac43430-sdio.raspberrypi,model-zero-w.txt \ - $(1)/lib/firmware/brcm/brcmfmac43430-sdio.raspberrypi,model-zero-w.txt -endef - -$(eval $(call BuildPackage,cypress-nvram-43430-sdio-rpi-zero-w)) - -# Cypress 43455 SDIO Raspberry Pi 3B+ NVRAM -define Package/cypress-nvram-43455-sdio-rpi-3b-plus - $(Package/cypress-nvram-default) - TITLE:=CYW43455 NVRAM for Raspberry Pi 3B+ - DEPENDS:=@TARGET_bcm27xx - PROVIDES:=brcmfmac-firmware-43455-sdio-rpi-3b-plus - CONFLICTS:=brcmfmac-firmware-43455-sdio-rpi-3b-plus -endef - -define Package/cypress-nvram-43455-sdio-rpi-3b-plus/install - $(INSTALL_DIR) $(1)/lib/firmware/brcm - $(INSTALL_DATA) \ - $(PKG_BUILD_DIR)/brcmfmac43455-sdio.raspberrypi,3-model-b-plus.txt \ - $(1)/lib/firmware/brcm/brcmfmac43455-sdio.raspberrypi,3-model-b-plus.txt -endef - -$(eval $(call BuildPackage,cypress-nvram-43455-sdio-rpi-3b-plus)) - -# Cypress 43455 SDIO Raspberry Pi 4B NVRAM -define Package/cypress-nvram-43455-sdio-rpi-4b - $(Package/cypress-nvram-default) - TITLE:=CYW43455 NVRAM for Raspberry Pi 4B - DEPENDS:=@TARGET_bcm27xx - PROVIDES:=brcmfmac-firmware-43455-sdio-rpi-4b - CONFLICTS:=brcmfmac-firmware-43455-sdio-rpi-4b -endef - -define Package/cypress-nvram-43455-sdio-rpi-4b/install - $(INSTALL_DIR) $(1)/lib/firmware/brcm - $(INSTALL_DATA) \ - $(PKG_BUILD_DIR)/brcmfmac43455-sdio.raspberrypi,4-model-b.txt \ - $(1)/lib/firmware/brcm/brcmfmac43455-sdio.raspberrypi,4-model-b.txt - $(INSTALL_DATA) \ - $(PKG_BUILD_DIR)/brcmfmac43455-sdio.raspberrypi,4-model-b.txt \ - $(1)/lib/firmware/brcm/brcmfmac43455-sdio.raspberrypi,4-compute-module.txt -endef - -$(eval $(call BuildPackage,cypress-nvram-43455-sdio-rpi-4b)) +$(eval $(call BuildPackage,cypress-nvram-4339-sdio)) diff --git a/package/firmware/cypress-nvram/files/brcmfmac4339-sdio.AP6335.txt b/package/firmware/cypress-nvram/files/brcmfmac4339-sdio.AP6335.txt new file mode 100644 index 000000000..1ddd92950 --- /dev/null +++ b/package/firmware/cypress-nvram/files/brcmfmac4339-sdio.AP6335.txt @@ -0,0 +1,99 @@ +#AP6335_NVRAM_V1.5_03112014 +NVRAMRev=$Rev: 410316 $ +sromrev=11 +boardrev=0x1203 +boardtype=0x06c5 +boardflags=0x00000c01 +boardflags2=0x00002000 +boardflags3=0x101188 +macaddr=00:90:4c:c5:12:38 +ccode=0 +regrev=0 +antswitch=0 +pdgain2g=7 +pdgain5g=7 +tworangetssi2g=0 +tworangetssi5g=0 +femctrl=7 +pcieingress_war=15 +vendid=0x14e4 +devid=0x43ae +manfid=0x2d0 +nocrc=1 +otpimagesize=502 +xtalfreq=37400 +extpagain2g=2 +pdetrange2g=2 +extpagain5g=2 +pdetrange5g=2 +rxgains2gelnagaina0=0 +rxgains2gtrisoa0=7 +rxgains2gtrelnabypa0=0 +rxgains5gelnagaina0=0 +rxgains5gtrisoa0=11 +rxgains5gtrelnabypa0=0 +rxchain=1 +txchain=1 +aa2g=1 +aa5g=1 +tssipos5g=0 +tssipos2g=0 +pa2ga0=-161,6269,-723 +pa2gccka0=-116,7568,-852 +pa5ga0=0xFF61,0x163C,0xFD55,0xFF5D,0x1671,0xFD4F,0xFF5F,0x16CA,0xFD45,0xFF60,0x1676,0xFD4D +pa5gbw40a0=0xFF61,0x163C,0xFD55,0xFF5D,0x1671,0xFD4F,0xFF5F,0x16CA,0xFD45,0xFF60,0x1676,0xFD4D +pa5gbw80a0=0xFF61,0x163C,0xFD55,0xFF5D,0x1671,0xFD4F,0xFF5F,0x16CA,0xFD45,0xFF60,0x1676,0xFD4D +pdoffset40ma0=0 +pdoffset80ma0=0 +pdoffsetcckma0=0 +maxp2ga0=75 +maxp5ga0=64,64,72,72 +cckbw202gpo=0x0000 +cckbw20ul2gpo=0x0 +mcsbw202gpo=0x99445533 +mcsbw402gpo=0x99775533 +dot11agofdmhrbw202gpo=0x2233 +ofdmlrbw202gpo=0x0000 +tssifloor2g=500 +mcsbw205glpo=0x66333330 +mcsbw405glpo=0x66665530 +mcsbw805glpo=0xAA555530 +mcsbw1605glpo=0x99555530 +mcsbw205gmpo=0x99BB5530 +mcsbw405gmpo=0x99BB5530 +mcsbw805gmpo=0xEE555530 +mcsbw1605gmpo=0x99555530 +mcsbw205ghpo=0x99995530 +mcsbw405ghpo=0x99BB5530 +mcsbw805ghpo=0xEE555530 +mcsbw1605ghpo=0x99555530 +mcslr5glpo=0x0000 +mcslr5gmpo=0x0000 +mcslr5ghpo=0x0000 +sb20in40hrrpo=0x0 +sb20in80and160hr5glpo=0x0 +sb40and80hr5glpo=0x0 +sb20in80and160hr5gmpo=0x0 +sb40and80hr5gmpo=0x0 +sb20in80and160hr5ghpo=0x0 +sb40and80hr5ghpo=0x0 +sb20in40lrpo=0x0 +sb20in80and160lr5glpo=0x0 +sb40and80lr5glpo=0x0 +sb20in80and160lr5gmpo=0x0 +sb40and80lr5gmpo=0x0 +sb20in80and160lr5ghpo=0x0 +sb40and80lr5ghpo=0x0 +dot11agduphrpo=0x0 +dot11agduplrpo=0x0 +phycal_tempdelta=25 +cckdigfilttype=2 +pacalidx2g=65 +dacrate2g=160 +swctrlmap_5g=0x00000008,0x00000010,0x00000008,0x000000,0x038 +swctrlmap_2g=0x00000001,0x00000002,0x00000001,0x040002,0x0ff +swctrlmapext_5g=0x00000000,0x00000000,0x00000000,0x000000,0x000 +swctrlmapext_2g=0x00000000,0x00000000,0x00000000,0x000000,0x000 +rssicorrnorm_c0=3,3 +rssicorrnorm5g_c0=2,3,4,2,3,3,0,1,2,0,1,2 +muxenab=0x10 diff --git a/package/firmware/intel-microcode/Makefile b/package/firmware/intel-microcode/Makefile index 91a697c67..bdd8ae73d 100644 --- a/package/firmware/intel-microcode/Makefile +++ b/package/firmware/intel-microcode/Makefile @@ -8,12 +8,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=intel-microcode -PKG_VERSION:=20240312 +PKG_VERSION:=20240531 PKG_RELEASE:=1 PKG_SOURCE:=intel-microcode_3.$(PKG_VERSION).1.tar.xz PKG_SOURCE_URL:=@DEBIAN/pool/non-free-firmware/i/intel-microcode/ -PKG_HASH:=25f53bab1bf0c84aba927a77a97a9f1147c94199fa95b5187d874f839f022808 +PKG_HASH:=808cbb57a790dab7060b59b31e70e54ac47d3798d75e9784ed57a65b9f951fc4 PKG_BUILD_DIR:=$(BUILD_DIR)/intel-microcode-3.$(PKG_VERSION).1 PKG_CPE_ID:=cpe:/a:intel:microcode diff --git a/package/firmware/ipq-wifi/Makefile b/package/firmware/ipq-wifi/Makefile index 3729ee65f..b79ccf647 100644 --- a/package/firmware/ipq-wifi/Makefile +++ b/package/firmware/ipq-wifi/Makefile @@ -2,13 +2,13 @@ include $(TOPDIR)/rules.mk include $(INCLUDE_DIR)/version.mk PKG_NAME:=ipq-wifi -PKG_RELEASE:=2 +PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL=$(PROJECT_GIT)/project/firmware/qca-wireless.git -PKG_SOURCE_DATE:=2023-06-03 -PKG_SOURCE_VERSION:=cd9c30ca47b8e5388b770c523a7f6b8b969e2f92 -PKG_MIRROR_HASH:=45e623fcc512b514ade0f22e217275536aa8de4afba7dfdb11696482b8fa71a2 +PKG_SOURCE_DATE:=2024-04-16 +PKG_SOURCE_VERSION:=1d51799e6768a304da7840b8346e7487efd77f49 +PKG_MIRROR_HASH:=9cf0917532283c1a1708643022a5ed1ec4af6bb9ebaff57fc2f0f2c229f2469e PKG_FLAGS:=nonshared @@ -28,21 +28,38 @@ endef # ALLWIFIBOARDS:= \ + arcadyan_aw1000 \ buffalo_wxr-5950ax12 \ compex_wpq873 \ dynalink_dl-wrx36 \ edgecore_eap102 \ edimax_cax1800 \ + glinet_gl-ax1800 \ + glinet_gl-axt1800 \ + jdcloud_ax1800pro \ + jdcloud_ax6600 \ + linksys_mr7350 \ + linksys_mx4200 \ + linksys_mx5300 \ + netgear_lbr20 \ netgear_rax120v2 \ + netgear_wax214 \ netgear_wax218 \ - p2w_r619ac \ + netgear_wax620 \ + netgear_wax630 \ prpl_haze \ + qihoo_360v6 \ qnap_301w \ + redmi_ax5-jdcloud \ redmi_ax6 \ wallys_dr40x9 \ xiaomi_ax3600 \ xiaomi_ax9000 \ - zte_mf289f \ + xiaomi_rm1800 \ + yuncore_ax880 \ + yuncore_fap650 \ + zte_mf269 \ + zte_mf287 \ zte_mf287plus \ zyxel_nbg7815 @@ -52,7 +69,7 @@ define Package/ipq-wifi-default SUBMENU:=ath10k Board-Specific Overrides SECTION:=firmware CATEGORY:=Firmware - DEPENDS:=@(TARGET_ipq40xx||TARGET_ipq806x||TARGET_ipq807x) + DEPENDS:=@(TARGET_ipq40xx||TARGET_ipq806x||TARGET_qualcommax) TITLE:=Custom Board endef @@ -77,12 +94,14 @@ define ipq-wifi-install-one $(call ipq-wifi-install-one-to,$(1),$(2),QCA9984/hw1.0),\ $(if $(filter $(suffix $(1)),.QCA99X0 .qca99x0),\ $(call ipq-wifi-install-one-to,$(1),$(2),QCA99X0/hw2.0),\ + $(if $(filter $(suffix $(1)),.IPQ6018 .ipq6018),\ + $(call ipq-wifi-install-ath11-one-to,$(1),$(2),IPQ6018/hw1.0),\ $(if $(filter $(suffix $(1)),.IPQ8074 .ipq8074),\ $(call ipq-wifi-install-ath11-one-to,$(1),$(2),IPQ8074/hw2.0),\ $(if $(filter $(suffix $(1)),.QCN9074 .qcn9074),\ $(call ipq-wifi-install-ath11-one-to,$(1),$(2),QCN9074/hw1.0),\ $(error Unrecognized board-file suffix '$(suffix $(1))' for '$(1)')\ - ))))))) + )))))))) endef # Blank line required at end of above define due to foreach context @@ -118,21 +137,38 @@ endef # Place files in this directory as board-. # Add $(eval $(call generate-ipq-wifi-package,,)) +$(eval $(call generate-ipq-wifi-package,arcadyan_aw1000,Arcadyan AW1000)) $(eval $(call generate-ipq-wifi-package,buffalo_wxr-5950ax12,Buffalo WXR-5950AX12)) $(eval $(call generate-ipq-wifi-package,compex_wpq873,Compex WPQ-873)) $(eval $(call generate-ipq-wifi-package,dynalink_dl-wrx36,Dynalink DL-WRX36)) $(eval $(call generate-ipq-wifi-package,edgecore_eap102,Edgecore EAP102)) $(eval $(call generate-ipq-wifi-package,edimax_cax1800,Edimax CAX1800)) +$(eval $(call generate-ipq-wifi-package,glinet_gl-ax1800,GL.iNet GL-AX1800)) +$(eval $(call generate-ipq-wifi-package,glinet_gl-axt1800,GL.iNet GL-AXT1800)) +$(eval $(call generate-ipq-wifi-package,jdcloud_ax1800pro,JDCloud AX1800 Pro)) +$(eval $(call generate-ipq-wifi-package,jdcloud_ax6600,JDCloud AX6600)) +$(eval $(call generate-ipq-wifi-package,linksys_mr7350,Linksys MR7350)) +$(eval $(call generate-ipq-wifi-package,linksys_mx4200,Linksys MX4200)) +$(eval $(call generate-ipq-wifi-package,linksys_mx5300,Linksys MX5300)) +$(eval $(call generate-ipq-wifi-package,netgear_lbr20,Netgear LBR20)) $(eval $(call generate-ipq-wifi-package,netgear_rax120v2,Netgear RAX120v2)) +$(eval $(call generate-ipq-wifi-package,netgear_wax214,Netgear WAX214)) $(eval $(call generate-ipq-wifi-package,netgear_wax218,Netgear WAX218)) -$(eval $(call generate-ipq-wifi-package,p2w_r619ac,P&W R619AC)) +$(eval $(call generate-ipq-wifi-package,netgear_wax620,Netgear WAX620)) +$(eval $(call generate-ipq-wifi-package,netgear_wax630,Netgear WAX630)) +$(eval $(call generate-ipq-wifi-package,qihoo_360v6,Qihoo 360V6)) $(eval $(call generate-ipq-wifi-package,qnap_301w,QNAP 301w)) $(eval $(call generate-ipq-wifi-package,prpl_haze,prpl Haze)) +$(eval $(call generate-ipq-wifi-package,redmi_ax5-jdcloud,Redmi AX5 JDCloud)) $(eval $(call generate-ipq-wifi-package,redmi_ax6,Redmi AX6)) $(eval $(call generate-ipq-wifi-package,wallys_dr40x9,Wallys DR40X9)) $(eval $(call generate-ipq-wifi-package,xiaomi_ax3600,Xiaomi AX3600)) $(eval $(call generate-ipq-wifi-package,xiaomi_ax9000,Xiaomi AX9000)) -$(eval $(call generate-ipq-wifi-package,zte_mf289f,ZTE MF289F)) +$(eval $(call generate-ipq-wifi-package,xiaomi_rm1800,Xiaomi RM1800)) +$(eval $(call generate-ipq-wifi-package,yuncore_ax880,Yuncore AX880)) +$(eval $(call generate-ipq-wifi-package,yuncore_fap650,Yuncore FAP650)) +$(eval $(call generate-ipq-wifi-package,zte_mf269,ZTE MF269)) +$(eval $(call generate-ipq-wifi-package,zte_mf287,ZTE MF287)) $(eval $(call generate-ipq-wifi-package,zte_mf287plus,ZTE MF287Plus)) $(eval $(call generate-ipq-wifi-package,zyxel_nbg7815,Zyxel NBG7815)) diff --git a/package/firmware/ipq-wifi/board-8dev_habanero-dvk.qca4019 b/package/firmware/ipq-wifi/board-8dev_habanero-dvk.qca4019 deleted file mode 100644 index 9048239cf9f59bbc4df70251b73adfe93382ae62..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24324 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 diff --git a/package/firmware/ipq-wifi/board-aruba_ap-303.qca4019 b/package/firmware/ipq-wifi/board-aruba_ap-303.qca4019 deleted file mode 100644 index 4848115cfbe3a4a0ed6b17cac929731ecbd7968c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24316 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 NIrrxNmNc!u{{!hMI2Hf^ diff --git a/package/firmware/ipq-wifi/board-asus_rt-acrh17.qca4019 b/package/firmware/ipq-wifi/board-asus_rt-acrh17.qca4019 deleted file mode 100644 index d45d16af7f7bc8de104558f09fccb34619557071..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12164 zcmWG^cGPtY@h~*-)^+lC402(}&CO*1f((5S$-rO^#7U*awuu=@I!U>iy2%-t1-h9j zwgzBcQhs7l3W#fDpi`Dul$n@UVjC2q>*yThVQ8Mq2-K?pG)Fk9)_8L29OC3 zpzE6ev5Db75CG+%JgBNA=&E6SeuhQ`M+Qe176t(*gvo&12xB8?d-7e3Fa*frg4?UW z0D(Y31!N^6LdZOO5q5TVR#sMKB*4J17vxhSfhbTNG8O~!kuj0Rz?Ja>0h}|$83lc7 zK*V)F^LHi+!7CPp-_33h{K>w`z8KS5ao5r`f*MKvr>Pkf-SnAUJwl zQ=MVo+Sy%|Nl~6a$qln7RAxp6c-rk-2~q|WvjA%7?kbP+@w5hOIH9h^uy5n+UZ4%W zo|gO812trUH7o-fk`d)?p#d~*Qe{C@kc9zMgF34F2=FR_fPfNI=}`@+;enku96|}Z z&xV%hlJ3NE%T)C+8Sg`ri|XBS_2NaH_O2?N>DI1MB#|(4b@WWjc75AMGc&MSW`hFu6%7#v5+`Z{jO0{Qlz~W9Nl{T*Nl{5DjD-WOO#*Y$ zC{4oUCQ&N%#+VK7Rr}zKuMh1F1S|9;1Ljx=|NW{P%KqCa@1O*-C z90d*K3|*SP>-3ItUzKSnG5r#jSbw#!-gp=C;U!WP+Cq}Puj;>&iS3Qptqd2p0|&& zobfwjL2Ef{J!>Cu+JL4ANZc&e)?U3@13w84HAsL_M1qoSLFe2x$XJy^fK;_$Wuj#j zinzm}O*-laVv@jUD2;{^ju0448aM(5MR-Jp5=sb+az;a7Gz3ONU^E0qLtr!nMsNs- z8;J|b3%MJ)3;GM08<`8*3vs{zLr~JBMVk&Ili;I@TWb+}C!lrlas89iIhGB5z?ik<~q&Z5(Lx;i>KS{f<}a)Xlvbexu! zh8oa)gOmky9@KqnZ0oUiq16Kp70GC230WpZ4AY{m( zq$DGwga)Pn#W6*dlwu~UFxXfyGJMHrV3@)#$mn3gz@Wh)$Y8@@!;-)z$iO7Z#1#Xi z1q8s8jz}&UWe&Fx_`iWigo!ByI0FHkU1nn8m<|LBfdJ;u9Y8>dm`?<-a9yzFBraNA zO;u$eF=XZrGFJzgo%0C@iHJ!^$>^CdWyYKZOIEDeuw}>IgGW!EC0&An4eF+n*YHzPMeKOr+CGeJ9{s97M0sTo$!!RVpT#Q^|dOd@#z diff --git a/package/firmware/ipq-wifi/board-avm_fritzrepeater-1200.qca4019 b/package/firmware/ipq-wifi/board-avm_fritzrepeater-1200.qca4019 deleted file mode 100644 index d78a49d4dbf3fc22c40a83d052fc7c55542ff8e3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24332 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 F{|7QKi|GIW diff --git a/package/firmware/ipq-wifi/board-buffalo_wtr-m2133hp.qca4019 b/package/firmware/ipq-wifi/board-buffalo_wtr-m2133hp.qca4019 deleted file mode 100644 index 8305ba0166a2c07054d0789f1abaf3119c7c31bf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24332 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 S+N+$ubtLzGvG1Cu$NxVG<{kV1 diff --git a/package/firmware/ipq-wifi/board-buffalo_wtr-m2133hp.qca9984 b/package/firmware/ipq-wifi/board-buffalo_wtr-m2133hp.qca9984 deleted file mode 100644 index 656cb99cbb2b6de86639ae8dc8eee73c5c7cb490..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12172 zcmeHMYfuwc6ut={h*+{oL=CvSb$k#Zp@14*ks_5_udf5lX@?4@DwWdTYFAyIniscvQ<%#zn3`Yg@ zbGN;V(mE0m-#j)dm`52i+B=W;y}`$>^TD}u^8sz_fR|_likKteh9X35lX#|^o12S^ z3xz^~wN(JXdcLf^~g`f-1y zvLqud4NHyzG@8elbIi)n;GiIX*!%03pPrA7E`plXMi`&}`h@E0`nScG0w6xiiudwz z9mD74WeBad7cYJvv(08BYm?Qr!GN-3b!|i;Vh7I=nT`hpMUX@^5s5$}5Lxk&W0fcB z&YYd90N$8%JEhQ3I-CB0j<8S`n}yL(8nOiCqkK010Uz0nZf0-B63_%B1?8X|Hs=8c zS&yz~ugAjCa3lsDpM?6-^y>JWc)amhk?NG^GZRV}DB~#u@kM>vzSu@|Boa^+F5fGP z9~soQs=k!(5v?Ntr-%^@Cbd>kCEX`TGTbLL@vf9ueV@9$v`U* zuhhxq$}1^?4kSw?OAZ(yUkwMuykvHorI*lThhzYp?91umU0&JbbG*{<$yIIxsz792 zCfSWGEvssMOIy1o*EgwGR4*yk4;;O-<(gk5B5%2Kpq*aM zaoe`$)zz$$#{S*k#p(QU`jPts{EI7apU=GW)!mZzC{=(0DZJ2?-x{g(FQer*4@>Vv zYXg)>>A=t??JDJxQrdof->&xP^Zr$gVp%)?TxjLuq6Nb0q4ciR%}Y-%EV?pu;C7V8 z{}fW(a4%K2s(wkC_r7m?cD6<~EIUdstmxU%5!%2!<|U~##%Y7SYFMP zdF|;p#We*h82i04Zw!}oZ@v~#OFw+ZnB20wmRaPLJ=C|MDX;>OdWu?ZORk33vJQKT zHN%JQ32ua6WR@!oyz>E-A4omZ+f0%UcKy<_g*j*LWq0tJS>+$>BVQqs0g{2a%Yd8v z`~?fW5yqm$OMREwt;~onv0nH$ai1*H(4Z;LN(dM_D&U}@p&{@L4hjqi4h#$m6uNoX za+K4+W@w^NUEHXE>f$=j-33CZ?(>LkHg|U_Y~0;lhz7jcXEA3n;!oei*@SGPM{}Z) zc)Ev8z>e(tOE-Hb*S4jL=)2}F)YB0QAG z=3$Yuw!WSi)fvr)GDowHrn(QooUe?~Zr diff --git a/package/firmware/ipq-wifi/board-cellc_rtl30vw.qca4019 b/package/firmware/ipq-wifi/board-cellc_rtl30vw.qca4019 deleted file mode 100644 index 2fff2bf5fc7ce41c624ef14f5ed5d5f2df2015b3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24316 zcmeHPTTl~O8a`mSsHk)J_&hB&GIg&!COSJ(mYbTN4k{}v0Tgug+CwoSH~@q_~r$+S+i@Q|5SLh)WnsWRQ8?2DHV(<=&0DuR&fhw$y-?ci8bW1%83GXlD{G?psT z;jml1ZO}DaB6u>^d%01g$d^P7WmoX`_@q1>s5+Ze zE-VVbp5JNwCik4ECb0C|k$U}}3z7AlqtC8unlg^?G8u_a2di4Ls>1g9q~E@!?3TCv zsy?9n;aFW?)Ttm1qj+_pL}hD6z|CXh<}KS02Fuq!ATY@Mi9g#CpRu!I_Ofc>1rY!) zF0QVwE=0XygPWV1`?Porbu<*qU!2YpFhfH4@F$cP9L(nh^LPa`PcVIjVl^ApSy2Q! zI_m27?!_`BVDn~ocQTYj7|Q4If?$W~@t^k}KCqxh+6ZHymxn8j_FvOb7hubuoMq)| z%_zJcfzxYFwT}{oh$NVnunQ6go;5(O=RLHp&*UF>llx@k3>(OeA|LL$c5; zQ5KehrXX@ujEY6#mtrIlO%x?!(P%UxL1&UM4A@p@a*|4CvZB;^$HyK>7%1Z{0|`I_ zL;+YDn)Wsg$wsq9*;p(Z`!*IyLX$*E7E7w$>!{*>lF_Kq{IQBqa!XpP&%gDE7PsO69G~nrKJD_{Pn4@8GsnTM<9<1 z5^s2r&too9XqUMOU&}m%e}jc+O~spr0FP!j?ht(c&Fi1RPe1)^Y6+bvl&oC@e!1(# zbfuNS9S8tiTxp))K)C_Myy6E?mSV#S;fHJg_>T*<;bEa6pR$lUcjR6jxjTpD?JYc5 zTvo2@xYB*Ce{g8@?)ZbpfBNCaSB}47v5)82mFub*4NUu>7`@fJ6KdK6#bmAKT~O2h zCnjz+?|?cE;({J)AKg`R8mz5E?b$QVDL8brz3cidd}8u13+ZbMmD$xWKQIvv$`Nre zCP@E~j$kMz!mxA@_aP3EqEe9*i(9t)>)EJ|Xg*>e1f^$)Gmsp5yf_}&MOX9?ulaMB zzvs;DYPrR6lyjf(QO>qr1BH|L(nk%)m>1+vY3UlGo|9dRAu+ye%KVY6^J96%H=FE2;R z#*HhnIdr~(+MxwRiHF54*^6d$IiIn?L ztdMxn{rHu|?S++U>-WXdHg(>p#xX;Tjx*J2tiZDkVqM_mgrQ4&yeLBwI(ZKt)M-^k z5)ScqV%NIE1z@Vv*oZ3(DZ0q1t41w;z#!8_;p2vWm8vL55;6Hl!)0w{kxarR91QyK za4^+lJcA!I9OYQsKlB>t_gOI0mTmx!T5r&eutxULTu0yyjVI;-_vJ zJMjixp-PHR>UveR^4$VIQ-liD0Wu{+50R3=*oIeV(~Cl;28@^RYTZ87F8n*4UR5WT z3j!t|7_OR93L;Xv-Xnk!x{Y7qrP^I`Hgs*pm0FoR0RMxbPgN;Tl|&i8!v}PYs{Il+ z;n3G33awGObkZ4-?UAPZVWKgvJTHM^~-Nm4}cKgfOK`#s<7l zE0!~-zBZo36;MNr5Ahoi%M=Ov=Kkb0L%k|Z?oUR5Yj8xI@KT>j$({p9p+upy00L{_ z)L39?lzH7EFmb-=x4UB^IsWc9Th#{>#KD1EJ!`u%T7<{hC0-fd4<5O=Q_DZ*TlDA7 z21RmY7|YM?{?(?6ESWee!0%FjL3_+eu4-G(^E>LxDb1mk{)b-lDDx7+!+ZgF(sxoV zPZLE320j=%-j#A%SWVyebXeJ$+{{<|9eUPRQ!I-Q<@k9$x~V=Um!mvyhORf~OiV3n z|CZek@046lJjJbG9e8X|AIwXS2tjD$19jEA#h^qk1?`u4OR6dweYK%hi+fel%yx|IUHus*JVd`XGMrv?2GOD zzl>Ay4$xEX4cA=DxhSajJF;$19BSbd0&4()rTzyF4@Z>HRPF57=G;-9?9mr9nP@Dq1yTBzTMse;}`djn=&;LIU C>x%IJ diff --git a/package/firmware/ipq-wifi/board-century_wr142ac.qca4019 b/package/firmware/ipq-wifi/board-century_wr142ac.qca4019 deleted file mode 100644 index d4efac2816cb81a13218f324d2be3b4cad0246b4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24308 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 H&A^OYaxqRxxu}Q{ z8BvCd5wuWI@T{wpt23+2u8!+$Y0BN&s(JHe-{wK8tgS6y*4gfJI3bZlh={}G{GtE; z`~LTLI_K6O`64qTCS#K(E;cVly)mOO3shBA0VtKLkp>_YhSGzzYj>8HMweFUV|JD6 zjWPPNwXtNXw0dVv8A`?_M%V4E(eK=MU~O5YeqTj&*-m4OGBGaJ1GX2yz67hK|MKtv zOOCJ-wxE8a`k^WTV3}_KGys5F7!PAV_;Dt3c|7V0fcW_M|Ga(;QaL{0&A-p2(P0V4 zS*xk@1i<6TyS3V>k-#rd-Ys*TUS%r^fU`j#T9A*lJrSol_4uwEBT{`WBfWj}%pVBG zKNDk67Kde@<9yr)Zj6g&W*^uvjRJo>z{o9GzI^3Mw;DL9EOe6hYh)SQhS9Pa7e^0X z4&H2SHRyA6X)kZ~wltRM@^aQZywQ82wMPF%PU6EMXw~WqbAIy%%I&*yDR_0`=CRfa z{RUn7%c0)mjpaIRPU^$!sG2S(M+F<4YORNPDO3Y#6nHgo^KfI4E;%O}Hf?U)rOSfV zuJ*RVrg$@$FYSMKBfim!4F zv0H=EhA-B(B$Y*O=H@-PvA;X}gsdi{qbp0bimB)Cd3@1$ID5A+hn@Urpt?D?TCzDP>)KU)m!|cz zdS3bcn{|DwkAxf9CG!g<##Ca}(o2?jdwctgi|=52Ly6|;(E=GqEEd7PNMS^TNEjg$Zt?O186CB_FzIppL5L#3o$_(@O_4M-kA6eA{IBQS!GJD!M z4DUx^_r@b_!ziGUWDX)03UDgp<5&_g-QP?tXQ*I!D4v1m;BojG+<5TNk>-ua`9Y6t~MP{$27PS zS1OdxlvpyJtVq_z;<1=&!W+wFn?DXFh?L0WQJ+Q0WwL8CHziWKvq9&k7>b0Hff<`u zQ4eBqB$O-8O|DIPY!=sr$+5{fo5is=r|f}^vtO|>9?nznw3&G3t4u5p&r{@Sd&^Zd!AFxt{aIKzafIW)|jwHXz!^<8$M&%nyUyt5mOafPue1k~aYm2Sga; zQ9^^KrtBtyfEO~O?c7m&b=2;hwqR4y z_L8!4bNjij3;hFw!?#B6J^0HHKR$QA07$6q(#hKW0vr#6!sAh=P-<(9)b1CA;gn2r z%l!gC?t^MsE%Z((xd*CMx6r$w5t*+TDtx(}ku7C<^_0^=F;tN>1~8*|Dds^Ws(F?&#lK*#bLXW@3kjN08l4 zp&?9CX~cVV7|B7QH07(krt*W7K^V@;R%T=QtVCrZwvMIiL7&Ob_4IX)j_1oGj=P-u zq$xS~)-OFgAmP5Don(Lq_CrKU00{J@kb$?8B%nR5@h2WfQpP|iIZ z<$K4G0GJ8q9&z8_<=i75(HOYHK+d`EAHcb{_3DyyZ>xa}=i|D=xd&`E+i8H;7=VJm zzrQC)Nc+^2K;IWL_4e}e-oE)zpTLoUlE7r|6nL(HGgCZ;xz;H*X)1 z&=#Q=-4CAIJzhANQ=L4bj(o(rSNf{Bg((gcLcC&mxx70uT`+?o3*P29ogNy&# z(V$C^9&9`+ro z)MP4R!ouzi?(a-LDz9N}esn|Mk=7)t4B7FxueL;;7|9Ru|MQi~y&4TJ3}Bmk^N+!JuXXEN)*X!6%g(zxSlyG-EUMw`xOT=^nw28r^Eo|Vm+fAk8?6lF zo^IRvRf0jdjg@};M(u_C)3W-I-HUeNFcW7GSO5sj^cOgM?ZpWm{Vhg~szH~klto6u zXHhZy^$me2B0?Ck#e2^D0tdsncXHsEti_GMbO|3HyWZkP9dYd$&iyR%_2(wje!{D{ zzWfIvm!9IjV++Y-8(+YftC@ntXdSHp9868MZKH zIQMp7Q0Awg@6R)8y-RmL1-0Jg8001^RFjUN`vnZ=o&pgeN5g4vGo1U`zG}X||NjGr C`f|_! diff --git a/package/firmware/ipq-wifi/board-edgecore_ecw5410.qca9984 b/package/firmware/ipq-wifi/board-edgecore_ecw5410.qca9984 deleted file mode 100644 index 2c1992001d86268e0483b9e53ed4b563e224ada4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24324 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 diff --git a/package/firmware/ipq-wifi/board-edgecore_oap100.qca4019 b/package/firmware/ipq-wifi/board-edgecore_oap100.qca4019 deleted file mode 100644 index 9f1b5c93b5ebc7561987aa86f138e86c00d954b6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24324 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 diff --git a/package/firmware/ipq-wifi/board-engenius_eap2200.qca9888 b/package/firmware/ipq-wifi/board-engenius_eap2200.qca9888 deleted file mode 100644 index 2e938f4785c5cf4dd088028bfe37c5985c3a9a5e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12172 zcmeHNZBSEJ8a_c>z=f52312ZDLqu{(A%x(rS3U$Ht|_@-uz?!t2VZKqg^-F+Fn;cA zYvNpztcYJF7E@(xi&>__?AY$^xE-g{c1E54=#S3qpZ)1Cf4Gj*KTGzUTrUQa)MSgh zc6*M(jbwL8{0;_B#xb3hq4X;hTcv>0sxr+BvoJ`Y2^xBEJb%Wz@Y%BsHk}S z=n<%v{sIJp!CE1$kS_IzyZ-m3ExnsV#PWH8`mNiu#6RG#50RFyJxbYCaLB z1hpU~C1vHxmC4D;5{ZNt0JxPvk9@RMlH#N^aOqMSFiH3;ycaAlrlxjrb!p>x>RDM? z04D)CIXM6)0qN=K0H-*SmKJBjpFlIbXP)6dAMhwbLf)c7JamaHy%3h-2`aV`84wu| z8Az0Y>mCV6l}M73Q_%+r@%S?xJ)HNOZ@vvR6oUE5)w#AYRJ1JA%ilF zjLC$VL>|;by+(gmPc*_tO(RnW>j(qXL7hf-S4ULBN=+rBg<67!3w`^Zjc1X#FsAD2 zg;9xO#QMZTNfyj{m_@9CYcy+^t#IqZt%MO8HAbcaRy?dAs$i9-is9EIJP&onQ~$#A zXnXg^>X=>DXD=2}r02!w0_<7KFx`@;cKF!|gOzU0E8%XiPD>x%NR|6OcDPuFVJBVp zJpxcsD!~1b9mfvTCdYO5f@KsrsJWZ$m}P)AQd-XM@UW*0W?CO|ps<6VJ#DekO_YxN zi1i>>bKWaR;w*!-iTbtgrsE8I)bQFfQw^U zqeUBXP*cUvTc$;J@pWYp9Wg2*OEHL9q!w9PL`RH@$WjbqM77Ak4=`}y{ex%AhS%;V zS|%s9jg(mPThpt5cm8!J)tA5LSB;k^cf0hCwVl~JKYo93TsI86$(EZJjH8-^^45&a z*CyW_(+tS>W*R^9+dQwHQtX$Sulm_@#?yti+&vQ>!*JO_xjCb9_VQ7#apqc{lmmnMsSg_S8D7)G|FW=-Omc?#*HD`1iO<2ju&Rrmtp4ea-H&W2?=RQ$3!l z<0?C8{_^6WlNl*^BinfHvc*|*1hw07=VtR*nPZKWY=6(+IbM09=q*4Aguh_C%KmBC%gR*zv;mj`ImHpo8V=5bI;#_-1solAat2dvX*!3W`?|e9I3| zE1EkA5$1#KV|pNyJ1>?gfbvw!>M9}gZph%$mGA(vg1tIH+Uk=u3Ki5=u7-6o=z zOceljcAfQqawj|&Ui}j*Bl}1buxx!SJ27Iw|62y0JbCi?@#BAnVaZhE`g=9sY0#XhY%uGVv#O{8=4;I>(sIyLNZ_& zpbY60PC`Rxpp4!roPvhVKN+1s7$ z5)(H>#QupYV(zPDG$g)7WA5FUhIr15o7?staG$?29r)AjFJsB_q9VDll;N@x{SSqp z&rv9Ho+k_TA6tgs^Wk#%EsyVWp`V!Yyp)hbxkk=NLBo6l!9YgCFb!bi{6?Z0R%@!6 yjZxmO<#HTXsl<6sXwKm|*2V|^dyD^)l1i~pc+SU&{55O8jIYQZB3r)vntuZV+o7WX diff --git a/package/firmware/ipq-wifi/board-engenius_emd1.qca4019 b/package/firmware/ipq-wifi/board-engenius_emd1.qca4019 deleted file mode 100644 index 3a2d77597df2899722962245a3832e45b9f3bfa2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24316 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 M-<$he(lmSj12G&o9smFU diff --git a/package/firmware/ipq-wifi/board-glinet_gl-a1300.qca4019 b/package/firmware/ipq-wifi/board-glinet_gl-a1300.qca4019 deleted file mode 100644 index d8695c983641b25f4e059f65a0ce8b4f2501338c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24308 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 diff --git a/package/firmware/ipq-wifi/board-linksys_ea8300.qca4019 b/package/firmware/ipq-wifi/board-linksys_ea8300.qca4019 deleted file mode 100644 index 0a1f6ebd4785369593653491d70efc358c1238a9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 97236 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 L2*fwBdH4Sh_9QQ4 diff --git a/package/firmware/ipq-wifi/board-linksys_ea8300.qca9888 b/package/firmware/ipq-wifi/board-linksys_ea8300.qca9888 deleted file mode 100644 index e3c2039924f483ecc3679ee005c0a1f73c6bbcc4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 48628 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 Y3=Rt&nS*)vCPAN`MyjX(-@N<(0qkJ6aR2}S diff --git a/package/firmware/ipq-wifi/board-linksys_mr8300-v0.qca4019 b/package/firmware/ipq-wifi/board-linksys_mr8300-v0.qca4019 deleted file mode 100644 index 689d9c481dbe84def37a9d9a22c4bae4ef59e452..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 97268 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 RT3s&UvhIO<@8A1^{|8J-1^oa3 diff --git a/package/firmware/ipq-wifi/board-linksys_mr8300-v0.qca9888 b/package/firmware/ipq-wifi/board-linksys_mr8300-v0.qca9888 deleted file mode 100644 index 90b6bac08ca6b2f05d4a6ba60b7c09422bbad2eb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 48644 zcmeHQ>r)e17QaDU(UFl30Tr=DL`Y%?Az{ZBqC8|ZOIk!HxP3(IE~pN-;CYP%gFQ&SJTiWsO#ewY9Y$rfR?JU*HGVvgXT@y`8opq!URbV1}F% zy8GPI=iJBd-VS~H{%Ce>%}vcU8PYYz)V!U!yYo?PZ7srbEREYEl!v#9Z;8eXR4yU{Ad-I)aq1CyB-%sjfTH*wUC<2Y0EgL|j$~ z>2$hRFJB^~Y$l8U@K0Ai&-&eonk|ti!WN@z*A}B93IB1Amn;&Zbh6iQYz`sHljSyf>v-zb-Lx4Nk}wz5aQ8JO*pLjWe!Z zx+p9>{D0WC2;aQo_%c2|GBWH<{Gmgodw5%1Ty!*_XCU_tgAMJ2IKzfB?StIL<()Ap zT8&zzlqY3myipSIsi3iW!hs+OBA3i1(#dq9;rNL&f3&q<>Jus5+$4dMKkM|ojJ`SQ z#fpnbN=ntzXHp`Lj8n(aQDhXcg3KfH)OpYHhyt=eT|noMIfQ}Kl3KO)nU=^TGu4^2 zhSU%gDO94{K2e{kDpCk_&?`Kvnh6Jug0DZ`d+}9H_$pn(loMf-=O^2zpD$`O8T}%f zSVgWg5RsOTJ7C5R|~H@ zQ5~K6-qYBfsg3RG9l1X?Ik#}vrpuolVlJASs9h_R);^}oV4;dvsMrCf)m%dr$kXlL zS#6Bfu$#*H84F60ry%xw<`Nem-)OzfTs61g03~~eX*1VTM!AOVvvx4&3??ei86f8Z z`k3?PI%JHd>c|y(9j^; ziBA?$8eD>nX)zQ~n}%+)Uoh32?fKx)pV%5^hgr)9DCKCVA6Mxp&Mn=3%i4xZD5SC; z^x19J8s>n3dVYJz#xji2tZ@b?<%;RLY07z+u1tZ$O9D{x0?ZUMpfm*zF9|@&3ou{? z1m1$c)vpd;Olw+wkl5AJ^_ymuWo7YF{qL{*u2o*Ma^Hsq*L(Kb@~o@NV|IV{RpTXX z6Im(Ub?2(FMSVEFIC9gio+EAQ`uP1(#vl6XI(~aD;h@ZPvyZuKJfBpzd|y|Gp(*Wf zyeTqs`1(mUvoWb6rl{*i>4of*@s-k#FZ7t(v(K%u$jtp+jkb+-iTh*eM}7NjsrB&( zh#gOcTkM7HX{VN%dU~rmvQDQoNKHR>H@4EvYd?uGUcPQ_-FyQ3?R<2nur1BH$|5cO zvakG7=9%PA3De2;U8mO_h}{vn<=U53Y>st9T}<&`@3wrM_BnYhs=|KbV5k06N}aTb zwe4$>?_FN7Y}5I!k}s&^^6KcKzYTt7*PJ42q@O(Ouk6@zR&i8Xe5IfIyHV5VjzE;jb1&EMD@#(#Q{&MG?|ySxoGT zxK+X|jl2E#B)&FlxV542xHe(k+O>&m_n-)FWi&yqp>hmGC1sX| z=CiGx-Ms_D_x}Fm$rGV`U(1<^-*WA8VvTgWb~~|Cx>384$d*P3f_7J2?7REObwBY0 z!!Jc##$rJNR>n*)fY{JN;Pva*uU@_SuZy^~->2u*I4013Zq*32B)!+dj*KCMkIiiF z$e8<4c+#CLJpE2iOaL2Tpq!&|5Ng*Ww09B#$M8~FcvuxG=^l72!SuJQSZ-nwJnmtc ziA~67wvKcO{&MXddFt($lDt0YeQx~99lut`ug=j$rjos7RTj4Ma(7Sft%1Sek$d+a zK7Kmp{|U4KFR~?KNpcbAx?4KFk(Fanx`^}M)@y`ccfNDxjGXJBw6s-N33aZ4(s`}I zDyVb)lh(EhE1>>^=rzJSx?Vx_|AhY?<$oD-)>}}JPYC$3W?Z;u|DpCPH~NSE^592r zxs{^Mbe}3chfcC_84*v$tK(@I${)`sXp&abbUw-$&mi=q zUahAyJj}0CI4o3ZuHAZG7w-erh*)hbK}xr2w-JTXkF*~VTcoAexsN#i+4{XV+xZ5P zdw=jaaPPVP!q305xg&7zITWzCaq)qB&%@%nhc#eVG`#76k~d^r?X!=PYiXbZ0)PM@ z5GVwId;ji80{5PunT-k)G_f*CNFN36{RBKg&C~bgISO#^-M=+}dk@@u_c4Lc?9UCL z1TpGj3!o&%L~H?+#F&UJvyYOvOt6GD0>Hfo?tN%q0nqwTMgX|?2#I;|0`)$^!@9lj zNXEaTxD0`Mzc^rJgz`9sw)=+waPR%YYp%S3d#_T$-xUNe26J^CKsmvO0C4YTmzxjV zd;jjK-MoQ&@A6j_NzOm30Pelp82QB|eOWX1#7p=PiL6Dxt%@-->Tp zX8PXyLzR{A-g}HAaPQy#9(>^5i{}TkzkUiOh*1|?03|UdU;zXG0YG4G5CHD|yWw$Y8oc#{m`{3oB!~YjZ zObE`a25L1I2mtpUxc5#<_vD&ZFloTO2kw0^jmLo0#g{c>SB||m9k}+y*lT^3N5t3mtLO_DEZP(@Bst>0YJcC1b}<*FJhDa zz`f@u?xVu|U9152egYHV-aCg0kH?JmlUHEiG`6dELK23MfDn%a2pmL+5(2UTMnDevh@J#yVBXN( zZ};@u@7vFGl9}m;>`qA*CFd!lqcTN`?Bv{3pw(&t6kQ~d1F!?8(qlE-OUg?lO0{ay zfpWD@q%PYYWvP``l~k7z)#$j0+LCH@$>&G6W5={5qJrGK-J%%Dw&av7t=0vO!Gq)R zB02wbaRF;iFkRql@&IrD zaUqFHYgo3dKHSCwE>GX@)lPZ>KSO!{*!=ZP(}#TEY={>nM2wU^QzqGrc-#Sx=gjhCH zVjaP&!O_-MjXGVG^lG%HrJ+ofnZE7OP|umxYW42)xJScKt5N5s|N1SIJLAGI@Oo(U zRBMHLmrDL>xaV|3xe7~{J-S77Q>CX%p~1P`EclnG3`uvwSTd3c&~BW8D0&u+Cb)n!p3!4A&WVofFk@4?Vf6YfL-HPiH1P9;j;0sM@l}FZJdPb(gaB zS9P57`=hnJktc$5%;M#R5*;mtfV=0~^&2)JOyA7`oWLOJ6Mv>8K4WKuva%}S1rY!) zF0QVwE=0a&jk~+M$CP*uw$~RcpPkGJXN80a;9n>|I9R|B=JWI2yuj2Iiq&XzWl0fe zZ?CP*%fr&7VEuXz57L!X7%JfNgJ6Z_`R}*y-uXg}Y$F;2y**vs-2Q9n>H=)plcOwM zt{Z{ZBXD@#iMA0U5uP|x!Y2epQ8s&VH13qJ*)tj(-XdJC4gZd!;r~*}p70(q&2AUzxz~rbLQKAx5 zB9=UtAPH!KI01`7qYx=N9fYahwmKb?Og0@Atxz~21!H{#fcbs5@zQXS0waHo)c?Vch)pAJB5Cv%zU%h)@;3B7TUHFu1V=R z*mL%2lxURZL4aNw^8jPjyed($LV&K&2+#=72+#=72+#l>248+9`O8ZoKX{rqO zLVyg&+~fcOe|;=$0w5X)5Xhr~#2Y^3^H50!+ZFD@mkLke-(Vt2OY(6;fM=6CZx9}T z_3|h1z)#bxD&_Dfw?`UVC^Zjar2_^0oGc;WbgS^Id7UAZos z-oUaCiZNQKolwgjD5hwkc0n!spO~bD+5vSO#Ca`NKDx_h8LX^8?b$QV%HMyet@G*) ze0<_B^XV%Km6_SF-mwra$`x}l7D#=UieM-v#;{Zn`z{udp)#=yi(Rz)>lv?(Xnqnu z1ZAX2(vU1hoFop}!BBM*ueoDT-*Z&CTyAk3<=w~I#k>DcrHczB-PgBUSm3^W5S3y8 zd_75Y;3cJncMpJ@8`)x=3w|?~cMtgoNmN=W?;d*j&e{_Ii_N6m^(>it z+}@T|xt&W-+Mea%gech)HrJ)rK+eo3Ku_tWUuLw~0r{lE9M=NZau#yzQ9!X+oT$1 zp3S)@^pB+7hhl}q!|sPKX5C&`sUQ0Am^^E)#4%H}fjik^uD~-*5<}p`xT#Zrq$o`q zI&lXdFz7W!QZDhoVpqDt!og&RxdB(17rg+ zq>%Cm1Cuc<3`};LPvM76Ifm_%z2>ucrD=~|gnwh`)Kn`|r4ne+p|7M2t{TIH0Cqc% z>kPS?xXJ704!qt_sFC3lh91pP<<4+_i-!u$UNR(8HxZJ_+=^G|Q;R|-`^^{dYQrAQ z4*Xk#QB$i_hI1zFnJ!yG3L-+f+8qu(beX@z59oI&+0e8FSL+o@4*myIuSTm(mPVSt z#rq8nngS`CFzD?TZUK{><|e#YpP&qwG@6_7GQCV000S}Vj}>J~h30X*+fc2^R)&xs zgfOHF=6bwPFHy24zcL@kRZv6B_wj2GOSu$%b$8;5sZNuk3?MzgIXEItc&Sf^WX}nt zQKC_r2Z5EaH0GHa-MnfM7(d(i+nv!OZh*)2mdbtclHkCNUPn9AnuSN$rQT`Z4IDhb zT`xGix#-Uw^{OP%7GHn&yO$d)G8B?Xj{k+e{I=-hJk6%8r?)CE%9}#90sEhIt8?PR zwrmFAQSb3eWr|o77Xyu$r;w@sPSBsYy`jzyC>ZO|c>_l)6(5i<*5b;91c8JhBm@Xe0tBiNP#{E3LPlXJB1CKXrjkIG7!bs;N6!`& zFd{1}OMnQ=!Ebz-Qsq$HRk79G?w+GL{R{l1zms-PPmeu4#lFcTkc0%2Wsv}LlQ-|a zH}B59?=vsVWbTK2oR`bbEs>_C$ob;J++qo&R;wW(nq+(nK?gvoI@`FvvbKs>rB?E* zYn2+lvSxpZrB&5Xsjb1Ase5?Mm0D%xCr$egDeJTiCCWN}ZEg|2vRbHC`+;LH!SR^M z{YF1OKmTn3fkF7OlbB#r0YN*0K@B7nywgCv9lTr#mz#zk3WCzo(*E`1k5Cph2zvYX z>)E!ljq1wEqrT_Pqk0HW&^sW```ov8E$#{hv%z0B!DF=POLex(h-ba2>e&5`i>grM{Ws2-KQ-d9?H43?G-?Q<-D_vUU$Fe=oCVASx zu4lHfdS8yzeOjPOIU1fld8@HwZw=>2l>F)V8AJY+L~TTcVd9u!-xX$KSmom(Wt+T? zeJDKV@o2;4%vx?a9sTZp>z9RB1dY+vUr)3c4qfH9FiyR^rD@AQ$&!U-ycla}FKCEA z5-z!WN7*m!`c(_P_VHBnaPoy1O<2XoLWzvlhCpEOFMhdm7aT_09Z8RlvHitgs{iXC zHYW#mQgRNStN;=v z5+yeXkW0f2Fb>^Y5+w%&$Oef3i2#WJi2#WJi2#WJi2#WJiNJaz;Aw`y({bxPA20o* z$7}U7uOSH3=ky~pubpe(eCEA@qDooJ9{8l@<#PGp!zB>xm$Z+O`@tQP4mUjl@1{ej z{sA>00|Bzj{sG&+1o9OS+r%FMSxp~W2L8B?%>3Z4PKf8kt!E)JcSNp^$j+ffC1uAe zYHIa8U-S=+jNO}@o_X~2&)@#=+WQ@Lc|2S4YLnHFB@c>HI&7IxOAZtjci6I^mi#9w z?674(y$8{)#pXwMlP#8wG96EH#)nH!oa*kobqAZB`>Q*Bqs-UaIH?O%n1L_^43r8< z79=o=paK+?KNo`)I_T zcTZyi{3;-bX64<(R^C0dJ;WvPp8cEUynDbu$hMVL@b2$8pUKtm?s5LRGw&Xc5%*yw zYgyg7=D!2py~q4_;y?uN9@pLS?yVk)%C%p>yZ2nER4Qa&7z_qvUqV7cATP?#%e!}; zMhQz)T3iK%Tw-o3ykR@Oa>X?ue1TbirIL-Ov4Z>~?4 zzQArl)str^_KbT%w?IaqwdPxV?b>thaebAvdk$KLKkR<`+V1OxgX-$@V&7-(G}U9M zF;&kncbMuhxlyQ(o|`rH>CTkri#T%+ura+(RW4%S|C2k^pO6TddrhsF!kDAyn{S$Q z*fFD6pN!2IM^viv!y?|?pNuzj>TySz;p>aZ7kC7HxHXSv3lbX9UuEz z->1?_B_bg(=+)KR3~m_`xDXh24b$k0ReQ|0O}*GTeVHl?o6`@fnxqF4BP<^3RL6*r zj01Q`MpGA7r<0V&nMY06F|GcH>HzkQ-k@rhN)zdGkBm1hA;sV!-5N*)9{Nqc$EtM) zq*1`M15@h6QabiWP-g zX(R~5pgUVG7jaFq*nnQEDwM_%9=IT+>!x#9nNBFBnm;$4#}q(=O^>m!0G2r-K!GCkt@NNIQK zd8TUD;qUI(-^jVhQAeKmen45YHz9sE1U(x*UoXuQ@S~$2-8<8l^BGr5Ir3s$*_(Zl zT_17c<#1z#cn^mW5%T1A{b{KbVTFe22M=FLZK56BdGPW5sv8*>n02&cPmT4*izK`_ zIACV9S$j~*N~A?~8453_H%F9*NFPr8?xyIo7&Yz0On+0g>;R7)7Bp^bZj_-y5sf}G ztnJQgvXEgPC#Oyy-6w-ra-{z9dSf)-TMS zPZOKCc{Kt}EQCXQNbl%$$>=cMZqL3_?%K^s%fglpzx;6AQU%iiqjg?_1&Eg61 zy_FDz^$j&~?b@|a<}fzyo(WPIr*)W5Kw5`e(1i~OVi8{BQ3{Vua3*4uf}y;|BfulT zBe3xhXl$(CUsFSr8G%q3ALrknQIoDxDpTM<9Q)tj=I13)^V>LMvLJR-boBpxu2JCZ z+3rSvd|ce72mbh@M+0k0rSO^Rv6FM!IW!Gdb)FiU=9o*MUnFg2rdpkrrc|KMrWOhe z1VxZyv=}j<2E=*1_f-Gj(D3M51(+7;>xdK~D%1<_2oWhN)k}$ZG#*JrEvQ9rxnn`f z(Q1sTB?dy*Ib|VKq5j#_eF>d zmFZEI<2F`Jw;A&)mK19Hgh0bNcTjqPCTq zn7Ms7_;#^U3-x(fZu1VZc7~u0l-xVOwlNhnMkUY9(j)GUx-w(>+zsY3D9GY4r4mBq}^6C_zzY1GbrPM>o->MTYD7eJ3?WB{*+eTO+l zS5pPvadwcg)BD^y=1XdXbm3Mb1_OrO_CUbJu?!7>Zl@V1wU^xEy}}MNJyb1eV&cBX!c#E&26nq^G>p77#FpVEM&f-#>j3QSIg#Z(dT_7rEn!( z^r&HmQTA=-u)7eK!q5T6=CiFiN?AagSyf@Q$#3Ortvw zPx6kj{Y;D7geSp5#@xs2DvTO-mhn(7vI6e9lVyVg7w{(q^^=mq$&4RLTFCRHw;8q<=sQYfXr@lzHOOhCK^Zd!SatoFv zOFT2Nf5_0QAa_*$^ojkPxi8(3)bO*%R-K!%D*=FS#(V8}iC&kSd~2#>#Qc`VCEWM@ zRoie;pUR%t@WXg#qh(LJJW=rV75gz9N0sp+>ch%+3|*1~aiw2;(tIxOl%h>?@HTBf zRBhF!A<;9F-L6txsg_9J9jp3VPIqFR0Ka+d_4CHJQXG5Sg~v0G zi7GytYWL*#t6buSkIy)pt@$dsTs z)6?LON|~xqrKT!V_s47ji~Y(FVNcYQfF&R)!k4g@kSbv=mWvb#w*(06Z9X@749;zhM;!PznJsL%FSA(`N++kolsr*v}~)nJ@bIQhc-l z#P-D~{Jd>Z#wbkC-x902XNl4L3o<9~apR}FJwE+I5Lmb_5JyM1fZEZiAEP!!Z}|Yy zB}jpgTabQ_EwIiXC5c-2%XMPrmvAy;S9;phWPj(*->dU?=ZNZ>+Cz;kt<>4~M=wlV zo|?WsbL;j$e*EQb$UzJn zvGLJ;Zf=8(Rp@$p#+CaUjt-4n{D_&I`)4?PW1$ke9ju0TJ*LLVyHAfPfk#%2OI3f<;9FECN*|sZkz=hoK90d{Bsp zKrI*|Xc?48Q$)ta2gG7+?ToVf$NsUif3%%_bZ6FG+tKc{GrNm>?hSz?B$`N=2Do21 z=X~e8=R4;+znmoZ-t*(Wofsb)zef-eo)(&r5ucd^q*5t>QWA#c0BnJ&NLI0}u%w7x zBo&9gQz9-66(86Zj@OEg7M35ts@!mPWnsCv@W`=ki90uO!$Y@3Cre4tmj?Txg$YVX zB;Zg-iORzI4C#Sc0RU^A-Jk*h6@WJ*am{qbV$rd#0Emo?{PEc{5}&#X{QQ@5vAW~{ zJ9tgGXYALa9SOXE0*}qqW?Ji={d{J3Bc!Ip_%hg zU~rai+GJaKU9yz3-y>mspsX|b471#;pmQ*{Gx`jz!o9Gsu}~IW6tsIo%H5VDwL8S@ zT#xNv^w)fpafVZ|;ho!qRh>JVLaTg>N6(g2Z$HS&LZa`$c1aRWuKV_@ec}#5Bwimg8!pa}r%hM7f9vWM^ll)9HS2 zgr9zT_WkrUb_T>_1qNts|NZ_?-|5@1h8tX*$&QZygY8`58#d?v{Q1)-+O~@rF5Y$N z5Ii4&T4`PL5SB0_M_)pi3& z$q$;_I_4{YKO=XoQYa{eLwQ6&yisqCx6loBL%h%gG=Y=wC;>@DQ#q-^I5Z9spj?#8 z;XdLbThXnYt-^3L9O0p}L8z{nR%c`4^Jk+X)OqiZC6KtI?oZtjAJm8ABTPgSpC%${ zXc{L?7>PzcjYMM57*32(`zGk;_)uEt7d^+8ZRrQ9A^jA%K+*eYF{v7TR2EcS4(FuA z94uJ^1WE)-W)L8jh8bWC%qtQl0|bZ)fdGL3fdGL3fdGNP3PxZZcOBwKd5ilNl0n(R z-GanYR_g?07PVd(xv!t=F8!@5=Z~>QCpH^n1;2&F)U8C|`8=_*gT-oY$XYNzilyz$ z_h6Stgn1>3(Z>M5vRctI`q;SSgtFOec&D3&+NTDC3khKc!T9V{gW=7@XP25?E=s+i z;s65Nzhl({5CMW9KgSQUff$eqMTZG1TPP8LPWSbt8%aB~&$rU)d2I~9=aImVM*(Pe zMo4i{05Df0fDibN1*;H1_8_m#gQc4rzUinJ385}G1YQigP|4&2a0deJE|VQse+1<+ z6x}?>pe)2D%!XgCJ)>WlD}#dq8NX!G?%Zkj>a@Fa!d-i^^9l}>C|cS(x_WxA4GoWu zjeqvwtH;(K(A&qe?#y+`v)+88uts@+ zSY^gFj@m>0J@uXk&2yJ$z31>;lxEr+oByem&yDSd^{%d|sjeOu7egwHVH;~|D{>o` zn6xEJ#12uiBy8KXK^g$q4ZomeUSx3f4Nhl7)|Z9*V=ArK%CSaAr<@#RhN?f>(Szkd78H-ChvXgT;8-~PqF{{H7D zPyPmN=J@t}epI-YuRlHg?;mW>!8gUX4-4aPu!QY1V0X;v_>RNEHTFjQ20R_^5ZFXB zwZI6zz4q$z?%YM@3REq*ccRa<*XlTATC^5D$JVYs*B;XsNVg9ZW@9(G#~&MBVa(M` zeO~l!Uyo?oRh9BAQP|hFG)h&iJYU4q+*DnVmx+>jftnF@uR<;n@qDrW5xaXYmxA`zwY*qYy}TIEtv0*{6{j86s!1H73;o+Zzkx~=X~ z$RxW(ThzA|7bN9^Bpw$!w8;MN>7=$x*;qv(`W3It3a&6w&#JS0CXq2U9J`v(7S`Y+8yPNErJmpT z8=s@+da{}$j?*Nr>0k68ZjGxCl&;TL4Dapco%gGyNE-U{ySS%O8Kr3KTG@rT_gUqX zz4r&iZL#$MhrRM^2lrkIZSbyqvv6Rz>f^X(X6?EXg);qA#4(S3Z|u0$U(~v_j`prc z?&r7U0~yNT6P{A_b=j4eMtUV>e`9CH>8MICk&EEQ;QkMJ@B2wT^83`{?xb@x8B)+c zSfS#dqL;aeM!UmNSUlibQUPA%>jIC3erF{qkac(qg9 zuw52%$UUv^+R=+KCj-i<`4{^OJL8-DD=7Kxed3G!(*YIkd1ssVy%!~+=ThQE1}eJJ z&oZmL4zAdRLrk1NU>P8=(5G*}XJE~V2|R`y3V3e#(>DSG8SoE2d4m?Gl&Gzc&kD;U6ud&$}Cg3Mb1Og@zm`AsNZq&?DvWKnP8HKUZs;}hRy$dGs2EZ@1eCE-)~HZ*S{gN$dLiKO*im(f|Me diff --git a/package/firmware/ipq-wifi/board-nec_wg2600hp3.qca9984 b/package/firmware/ipq-wifi/board-nec_wg2600hp3.qca9984 deleted file mode 100644 index f95ccd251e785d4db96b9953b655801e95b02431..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24332 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 Bvkw3O diff --git a/package/firmware/ipq-wifi/board-netgear_sxr80.ipq8074 b/package/firmware/ipq-wifi/board-netgear_sxr80.ipq8074 deleted file mode 100644 index 446876c00371eb4cfb097ac593bd2a128590c6c1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 131176 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 T76FTZMZh9p5wHk+-U$4EL<2qz diff --git a/package/firmware/ipq-wifi/board-p2w_r619ac.qca4019 b/package/firmware/ipq-wifi/board-p2w_r619ac.qca4019 deleted file mode 100644 index a1b1166f6f9dd713fd5d45bbf50767a03703e902..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24300 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 diff --git a/package/firmware/ipq-wifi/board-plasmacloud_pa2200.qca4019 b/package/firmware/ipq-wifi/board-plasmacloud_pa2200.qca4019 deleted file mode 100644 index d1db0f5f4b8b734c0c43df38d9eedb0b84f72109..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24324 zcmeHPdr(tX8b3S~>)Of<0TJRggb)%M0tBj2qdcWNQlPY=K}&)9AgNIv2E@<>J3bI2 zDp1NRg497?O%WOE6RfR$%qX)n`_In)(eCV{JG0K(9qmp#v%9$8$>oLwhy;Z;!2ObQ z&UYT)Ip6u+M{aU{Ij_e?2S>k|5Ehyo9FrQI9)~m<4Fbsz!7)Nn5OTFe8*}n<#km?) z@H=^`{9x72jiIJo?*5#@oj5BE6&L3es&e)n*qF9Ar%00%yLZ2KXK-4yR2mxU1buL! zKW@ldpE)@pmvUA_1{9&7Hi)tjTI%Kw3PNmzUJ5s9lSd*E4|j!7czF1aj~+S6*^AN7 ze>ojV2N&qz8RhnPyED{C=m`kajpoL;8lPW|4s)YXbet=4AAQj+u#dDpmPS6i$77v< zw$wZ>7f~;(YRIrzmL-vFH#fIMix#<92tv2;Ozjj;XlEI`Aa5D$?8e+|Ifywk$Cdo* zUVPe&iuGg$dz(*|?#fI~lnq{Pt}WGMzL^*^*xh`*s!;WM;+nx8(27*)iLd+&a`!7y zAR7F*xvDfbGZ8BLn$MJ~GSd<_4R+yXP$mO|lT{^|io^{jgRcXF(BP%!Q!v77iR%VG z0Ry$kpaVL|%S@IDp}U&W{LFM&=%_)UwSQCON4lRy zCF^ztW^j`4)E1V*MF)cfoA(xfDx?+@<)o}ZsT&yUB;a9v{WGYRc0lRiHJ+qR{r z@OZ1Cqo00y^ux#qegcw-0{p46|NijD?=8!4!&S@NoLyc22kn-_0UNV_{P^Jms_pZ8 z_4FR{d*OKmn&g*P_u_zC^UT8Kk|c-Ys3?uTjhmM@6ZfNfX zr5v={26G9_v7IOG6?b+Dg`Glaztm`ykIGH6!eZ6HyRNRr+q(hYO-&6fk|kl?V-Y^2 zkHkmePP!A`WDFT2iMba;B#}vyBt;Y%MI?|?QYw+&lM?I6^^*09P%@N|k!B|>{4unf zOAYOa#3B#~I@$pC$y7cTu~^*OA@Ih+<#OAad?r_+j?1MwgIFM-%zUs=X7n`Wa`TL5 zQT3WiIAg+^N-X*sv*K7-d5|6tJqTaYSK_OPC1W4P63Jw;Bv}zohCd7^Hjo=68x(;2 ziH1@9DV@Vzg20#3s}zz--1|Uf6_+p*IjXjX*48eD3C-F!Wl6 zfaes8kCsW*$*z}YEt?O|q|6-bIr3<3-S3<3-S z3<3)nffdpf#A?>7(pQO8)>`RWB9gU)7L=Y_)87BNWo-JcJ?&`X7%$K=V`D7fL&!{h zng~3eAk*w%wwl|?T9~gZ35p$g`hoihL3&W%HgJD@DhY<4OoN1cF6o#WI2RNo6o7vY zs)2i>{yC&JTbI>L^&5o<08EjcHIdp5U{%J?7HMbknP3*OcxgP5!dfF;Lu_JYHsRMq zWBPNBPUp%4&vbeBVRrHE*{htKfOLQGjEM#A*#@X&1Ap6%LI+q(Pv_k$XN`A%net#P zo-N)zNsNtw5XFCYTkNvP)y#lL=*pAn((&!!-CGU|<632(CBtU35e~EfQwHHc%QW*Z zg3zYVn(}NKMzP!2zhmF_tSK?JT1{QPAeVEQNl$%Z zAmo53+2c0ThCzTqfI(ocA~43ApNx0^pMU)IPv3p_2bdhi#mBt+C;$BWpC3H<8p%ia_WaQufnt3k%Jm=k;>GtCk^RG8I=`Uq=DKo;mw<6nH^6qI@W|98BK!&jA zHxvqa%h&`Cbso%mjPG%loO`T4C+$7}e(An--~9FB_hyY&@R(1NZ~KSp48^((WyrVJ zhMEm!x-6w^=!&6USD=iS1q}5YFX(k@rHq6BD|YjCpb&vUtwF2XqLd8x8PDqXtJ9S- zqR9lUw4O)FRxMVOK z)fecL#!H4)wI(527BYOp*sd>CZ&v_7gZwD3z+E}eT38)h zCf0bRfBi|)Npb1Q-R@hv`u4QN*YFRqcQSYt8?9(|SBGI!H19037*c*71HTz@}5o?ixXm|Zv~a^h*){gN45v!6Hy zO}l?##>SWgex`^)U{VAo(C#0PYi2L$W2W1Ub7P@pr{di^=3X<5S2MK>kfWdPTtqkx zxa?iZfwU!6x6+b-e*t!(8D3#rz=fJS#Fs3ug^bamfDpp1&mas4TC3>5!V%OW{@}~DxbUGEL%{N9 zrimrbA*sgrE6Bl$&A16xnGDl$(`KBECzE8x_T)!?WTt=m)4%+~^?359sJl8J7D$Sv z2DeUg&uMqxecyfG-FcQ3WUzLn>9_sBJI9zS+>m2IutnV8f?kP3b>2zAH z1jSIGc#5(s4H5~txoy--A{EH4MOg;`!*3=b0f0;Zk}9x}w0adTmZQ5H;7|ZmR8%~E z^a$vsKLf#FutrF$q{}_xuK#^`OK+$r3639JZi`)C3r;G4qOKts%>~US40w#Vnooo& zK@CVrNm;#mb#ijDL?Yn@0B$AFBOh&zq&O)JT)LD7%o6?z?*+?Csi|37UEVmJdRA5z zz)3((P7c6HKze#Qz$s3orN!CsN6-xKnP>RV2Rw$5khka%4_zWlFNCFdf{JZK21Eu# z1`=i9x<>+1C6c7%RP;eYJpN2a59j^*n{RR3Z-aB_nd;-96eWBK{)dBx;Qe4na1EFT z)94bg2FwM|qtu4l&IHdcw)c8R+AS95H#Er1Ont<+ri(XiR4O;1iZtcPcMA*INaA%^ zxjsE5DLMIHNSA^hUXgzX@1K#8^wj^rf%Z0DCzFLePw~N5Ah*xj-Loi;{e*iKCmgaQ z3~Du11R++ud{VUO6ObV4U>#8o%L)7NkrTgnxhMRBaB)!p`lt9?LIMd%4SAO&WKgD& zF_|!v$b$xG&=~F-h(_3`X=G|)En$Q@sMF}~>WE5Msi|bNP)pEov2WkA@hlM+$E4RU zj!G0G)+ZiHvS8N3EMgs8r&-6;!}^EygbA87CZ+;bJggw9V3nqd;nyQP4|T;;|HAWV zd-sRxm|eDKFBVax=f&p&>{;sw-IAwv_}NLLjc&~=;cl=_YaiW6mHR$)xLAjACtdp; z0#H#Z!2OAxzz){3! z>p`xTyjPIKS%+vd^-JGP#~Jph@ztje#VQK;ZaCalo6$;@a5Jn6xiVBa3gSXNpdf)c z&dm;5Ep)}=kbKjehqYss?~e{AJ8Cr1l_-dlJ!0HJR|l^8#vL}c-KYsU6sy$0=jSHa zH?RYD)!}B38=L5Dfe$#29k902y4&yj-sTRo79+*aL8StLS2%>h?w(1Hair{^+>%i_cljt+IaJt{ZJxZ+ zex~NAyqkRW%#_t#b83T4YMq%Ja%~wKv~>$UO0d@^e8u%Gl!&wcv!KOQ`I5M=~WLaw+fSC>m{Ah+wb6FbN)x-CQv znJNJ6>^kfJ=uUVpy!t0rM)r{=V8!}aabm=P|F;Z0dGh4(-R`FjAMa+I5%zqhqjh}&A2p15pA_!iI z=meh^RWiHKm+SQWSFuV}(Wb)xW#Uin__I3xbdE7wcJ1!yv2osW7pJDL-I$%5zxByy zpMP~PaRX2k78WTGBA#1|)asHVgb0HSLWK+=!mxr06h03lA|x6q#E39RrBV_j!T>_& zpbY60PC`Rxpp3yOoPvhVKN+1s7$ z5)(H>#Qu>gV(zOIG$g)7WA5FUhIr15o7?staG$?26ZrG(FJj5^q9VDll;N@x{SSqp z&rv9Ho+k_TA6kar^Wk#%EsyVWp`V!Yf|QU$xkk=NLBm1=!9YgCFb!by!e&Ab^%_01 xIm-LBT#n-^l{n7{%{e^B+W5eKZ}DGJQYrQc&-oaUzh>>1@fF!aWXqRd^Ka5;p}hbA diff --git a/package/firmware/ipq-wifi/board-qnap_301w.ipq8074 b/package/firmware/ipq-wifi/board-qnap_301w.ipq8074 deleted file mode 100644 index 6b8f8b9ce8470b4d141ac5547361176cc25542fd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 131172 zcmeHw33OD~ndV=wN~HxMgea-1K!Btw2|;W(#%7ZQNCJT{k`UTAKnQHW1}rukW6Ta_ z5vzp3j^hyGCCA6z?Kn>2Gbgr5oMqBU=Je^)lS$m^EZxo|-P6;Fj|G)pe@9I5j#loWdi)u`8}DDcVPpIK8`sU7u5)cquGzMZ?2MT+?|W*^wvB7H?3lNrqNwuz zho(RHv_r2!6Nk85dUF59Pkb(M?n`;NPXD)F|F=Q^w^9GMN&mN5FO7fB&S2_c{$o_e z6vA0>T11YK-^0JHJ>-qBtQ5ys{WH@sU;pGg^7PLF$87yGKlDAkkPGjEY&c&5pZ5x$PDzY_ zWB^n&pjGVuEBTwN|8@UQ3;$kzb@h|pSA8iIdM|lv35PGvc{j&f_dNO)m!uo}g6Kt~ zmvA`#fMujRMwb}AC0xMac5yh3ysWaOp`~@*hK{pcmtMa7>X+Vn``!26|K@kT|DziQ z>55B;XGlm$h~u}5|GE)xDAxzJsSh$rBsu~yagA$`C+#W z4_T|KA%(!;AP_4)~ zv&6nt(z~8mI@RZ7oc!=53b*e*e(B0v*F!-h<71HtABgx~6Y(4b9xWmXIMj-rfP2LM zbvLHQ1$&mji8}dIDNk{wsS3~kRUmGOb3GiT=+LagT-kzeSgS1|j3`P{)U%I*u3^jLHKBew!F@4CsTO814^YFt-;N zKnFSoZvcbCq4s-&!Oub%ypHxMZ(@+rOAJgqIBL`p#^73X95aETj=>i#dNeWk=jieo z#E^DiV$cXXfFAAI!DQMo?ErQ(?tsz%c%0D2rUQfDMQ=ZB2POs~ThcKYk2?N$^g4*a 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 SvE1>Q568KurQ3I$`+ot*{f0IG diff --git a/package/firmware/ipq-wifi/board-redmi_ax6.ipq8074 b/package/firmware/ipq-wifi/board-redmi_ax6.ipq8074 deleted file mode 100644 index 98ed9c6f65961ad496025053b64b5c340bda8d36..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 131172 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 diff --git a/package/firmware/ipq-wifi/board-tplink_xtr10890.ipq8074 b/package/firmware/ipq-wifi/board-tplink_xtr10890.ipq8074 deleted file mode 100755 index 2815a4d661471ac403d9c0f38258aa8cd95a266f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 131176 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 CPBuUQ diff --git a/package/firmware/ipq-wifi/board-xiaomi_ax3600.ipq8074 b/package/firmware/ipq-wifi/board-xiaomi_ax3600.ipq8074 deleted file mode 100644 index db8ef4cefbb50a6df27ebe3554e2d27cb72a88ec..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 131176 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 diff --git a/package/firmware/ipq-wifi/board-xiaomi_ax3600.qca9889 b/package/firmware/ipq-wifi/board-xiaomi_ax3600.qca9889 deleted file mode 100644 index af4405cd53cb9ca94b9fd2b75856bf84ac0d22cf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2260 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 diff --git a/package/firmware/ipq-wifi/board-zte_mf269.ipq8074 b/package/firmware/ipq-wifi/board-zte_mf269.ipq8074 deleted file mode 100755 index 050b1259cca44d8d1bc5079fe3494ed9d466e2e0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 131172 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 dpcGIFC0A literal 0 HcmV?d00001 diff --git a/package/firmware/ipq-wifi/src/board-xiaomi_rm1800.ipq6018 b/package/firmware/ipq-wifi/src/board-xiaomi_rm1800.ipq6018 new file mode 100644 index 0000000000000000000000000000000000000000..8a5c47b282350c29f32565678928063c8dddc6ac GIT binary patch literal 65620 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 Mdd3Lov7(;;4s?Eq?f?J) delta 23171 zcmeHP3vd)g8vdtuW|Q3nvb)*rX7k$Yd&47aLLLy11c)330RjdM5+NucB5(l}5IB~X zBtSwEH=%h267+Z^97%{Uh#UrdT$SR9mR09jmajWKw5;;V^Qyc%&)na$JIN-9=oMns z-E?-KAOC#)|9|()Ki&OzS8exIZTHpPOGeWAvh--Z3FN?ugE`X5iEC9toJt&|R=rMW znMSxqc`ff0muQ8zBRGy;(yQ_{G1my;IK1dT4eInj#nOyGhh8&m$H|_)0N}U?U_S?7 zeF`99GeBG!fG!6h+6W-f1+glJ)o}*N@Jej~NZJNqnggKEM3N|g$j^EL3zoX9ju!!J z2$O;|7KAY(O$^d#BLVn7G8$X5<2>Tvm3kB)aVz4?!>SmLj#XvzsXfV#Zsg`UB^8KC_7UW3|Rn4XK<16hI zrgAw4;E7!&>qoC}ifa=1Zcaz!g8I5zXlMwC*#n>QTR5&Uyo@TgIp5)<|5Cxmk zh5EHEM3kvvD1q^d5Tp}eD7KPk3xYh1t%3C<4M7kC)`b*^(H+Ea@5IJH3hP~nffQ!c zu!-tzDg=23L6BL`c5Kqc2r>gfh9d~JlbJ4X@Q88&UGF?I4_}6k;H}l$%ed2x*v+gs1p-i>DD*` zS7Ui`t&R5z{@SjUZDSgo+hUhNZ>T)F{BT~Cdu?oaZx+;bJ=!|9!M)WOMi)4~x+Qaq zXI<E5inzc26b$;AhAw%b-4@DY(i_0d&_^R~PEYYbr>u<68-16f;A zAJNT~$pDVDEp5tq!uFUxJg;@x!R)Q}M~q<=?>@e&Ij_pukLlJ^70sh69c%Pqb)4M4 zY-i3&$AUQQZUEvT58uRDNnd@zSWPuR^)7(gT7ccVSvP;r5-6DPTk-D``KO}%%Yp%x zEL>P#URGLqqyI}vii_nk7B4SDV*J0TX!7Ln{P6e>pz+@-pnlASGqHpPR7JnMkgz2s zq`3GPs)XxmF5b)gnF`8KsvG@}(iX{OEY4I=Qj8iXEG!Jq50C!{8vm^V`Y&;&2c;h< zWw z;K2Iz0MFsKPXGA9gDn62dAhq&NU=9IHaD}hC<0L0a)iatN%3YW{;VkezEb$auB{+{ z4ZV;lXH|Iu-S4isF0W##L-e(&OuYDVyKpoq0_;}5|cfzN%{0bMDKcvUo!>;t6 zv>qSEf)|UY^U1MB`R2mUI^4=Puz~flINbGw*SSIgS%I67C~`edB(DpRi7Gu~s-w#PVn|d6TW$ z@M83vnx%$?gAQtg|9+``Ibv+omyzsxOGstk5I3h1^);lOM171e!AhrA_F zQKP1(YPnTnaT*`5@A{^>VGuVaP=D$!ZVa`xbGdX#hcG^HU;9ulm2w@#O3!u(Nt_1b zTw+WkU+~jxD+~}Qy9X%L6>(5*$L-h3{0HLevI}4OU+_G zZ!6jdo2Zb}(k5Rk>d4Y`1L}X=J=P`Qfw6KD{bDE^kVO>JBYC7i#)SgbH zd0oONn$pD`=Ozbsb)|{kXM{|S&O1X^aryL(GbD{(IU_{t^GGgCpUr*@c^q*B4xh=T z{8{0&kP6$$m_W_hT_|n6NOG~hnPM*8C<;SRxT2}-$8NfYH(e6b=$oQYg^FlD$K6Ap zJ}2Zn`D}?eF^$jS_B=-l{kbrhfth4L zJedL(G8GcYEJ!4?AyK#!lE~eVB#eh7^#n*Jb0LM?2UaouV?3WL2esLT zAJ!olkkX+$g5?qB?D3&;AXu(TaLVOUTHTlCSb4+%JbzyWK0-hR+9dqUmx7N73<3uq za++W|5{D6?G#C+(k8^}7^bskoA0A@JN3>Y3Nf}xq-_O#~R^KE!jpzarxX04w7r5kD zy=O{T3D)c?qE}zwhV|(Pe8>R@IHCy!mPVAZy=h4X!7whAp~Ex*V~9h50)Z)&*SkY^ z_#`Fs#xxw?uz+dgF)Df3FG6XC=LbG(MlcOQCGq;)P`ZF;O5^qUp|lRGLnWq$rv*@% zGV_8wuyO(T_>p5KNOxc>VujcUlY;;ZpT|aUg#egyi*#92p-koiyr z8!tR9;1mGS2XhLroP+d$?Imk$OhM=-=#jXMu@^8SY3AtBHuV(t*8N=7wdoaAPUG_= zmYkMs0~u%=VpZa60twE7C>BDo5Q>FREChQuDHej6473RU2NvS3?8YmqNhIrUY_eR3 zQ+uHxO_sNX1`%i|!luh#)TpHC^5{tME4}KgbvGX++~TpsHjOx{O{L?N5rs0MP(~EN zZ%=u|AbkugBMP)(%7_Bkh=C0UZ{djIt!x_2@smi-Mrn05UA7nSJqANwUqyqFW#AQq zp-e$3Q&7qjROrp&Q>LH*{)eZaqydI6e$?{i%Q>mZIh@4e`C#i;FJe~2&^z~cV=M9r zJsXL`4qU?cG-6Q9mm&8Y&hhov^jm}46vJ`xe)I?NJERaJat4((+UiCB1vmOYIG;q{ zg$ndr$VP_{oc%OL0T})rbgl86M(2fQq}hu!tI>qo zjY#qc!k}AC96DOy8W7MHhu}>1pi_tI2s%mBBgNwgl7%4XBw@e_JOgv;@FqTstjHLT zB83kz%wZT-&l$vc3Nesb>q?}^K@4;XF+|`5^w*NF&;VAx8|Imt!X$Zd9nAe}6sQ5& zMHI{E>zH9EOrRSxWA%2TXUK7++k>tjs5wg(qM%NU8f5w#NxRq6j119eWg3^&+lAb; zAUAc0vt~dmeH&~gFY@C?ew<9fs2mF_C(ejkEhmc`dhmfjrC3~?Q zdaDYjk*jj_C%FMPH$v&H$(Ag2Pi%3id#*xmaKa%DTiiIPPbelg>c&L}=(tyZwxCcU z{e5>YM;*&J*voI&RySgq2_95VP|5hTNc=p8EVK61huZvKp|8>lT#>q%x!?l}?aI**2tL^6^Ojat;PjMC7DVzTr{=|B{Grd$CeS&7a|*qSC2 zlHlvb7<5niev}New#^^-&E5O6cciX0K8TNVC_Hgu#@=zYo{i>Zat^?r_Bl;C)%Nv9 zbhna2W!qi*3+la_Ex(j=0QR=eZ5mzU*bw({Utaae*$1+B+SbK})zQ#i+LT*k_xB^* z)fObQpg3}}uQkxUhqHkww*cLHoZK4VY8Ztq4*SYA_C zSxa7>({GlT_6Lc#x6a%*zCLwrIENcr=eLZhbNS=Lq^oHy*_T~q>!+=aZ3~W!sdsLQ z$EQUO^=)_W%c-(|2VKfqa~NHN|77X@+#UAEu^A2d)t(KOu=YIAaZgj$uGGiFn`zszX$^Nsbm&!+DSqHpxf7?Mb0s8!3(_GQ z?tnXS-D@_K!6H}zYhe>qK^^RcW@v>DI1k1;tCLg|_c2_i^R((IEOuJFH%dKy%Wbz3n{a8URc#cM z6&huQMp>azR%n=2P<+1FQp`{9^Yu9={`oa^dKS5SgqaCjwpd6aWHZ5BzSL@T`I5}U zA#KDIw(;#+gm~2u5x@Sn+X=-hSQ$qs;|OIOfnK|cg^--iZij_nYxpE`66rq841~j_ z7zkzCh_Y=&**2nV8&S56NZUrxKok+pBw`)Rmgjv1y|a4*oxExyG&q*9SCY$OidI+@ zDQ=C`eEhRG1S^XY$`(Uqi=nhrQJHR11{1e$i(!pkyz@Oxjgve$oQ)?Xz?{vEG^ZS%z4i}ay NXY$>iGx>@#{{zBN#x(!{ diff --git a/package/firmware/linux-firmware/Makefile b/package/firmware/linux-firmware/Makefile index ef6cd075d..d056140f4 100644 --- a/package/firmware/linux-firmware/Makefile +++ b/package/firmware/linux-firmware/Makefile @@ -8,12 +8,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=linux-firmware -PKG_VERSION:=20230804 +PKG_VERSION:=20240220 PKG_RELEASE:=1 PKG_SOURCE_URL:=@KERNEL/linux/kernel/firmware PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz -PKG_HASH:=88d46c543847ee3b03404d4941d91c92974690ee1f6fdcbee9cef3e5f97db688 +PKG_HASH:=bf0f239dc0801e9d6bf5d5fb3e2f549575632cf4688f4348184199cb02c2bcd7 PKG_MAINTAINER:=Felix Fietkau diff --git a/package/firmware/linux-firmware/airoha.mk b/package/firmware/linux-firmware/airoha.mk new file mode 100644 index 000000000..627541ba9 --- /dev/null +++ b/package/firmware/linux-firmware/airoha.mk @@ -0,0 +1,8 @@ +Package/en8811h-firmware = $(call Package/firmware-default,Airoha EN8811H PHY firmware) +define Package/en8811h-firmware/install + $(INSTALL_DIR) $(1)/lib/firmware/airoha + $(CP) \ + $(PKG_BUILD_DIR)/airoha/*.bin \ + $(1)/lib/firmware/airoha +endef +$(eval $(call BuildPackage,en8811h-firmware)) diff --git a/package/firmware/linux-firmware/brcm_firmware/ap6236/brcmfmac43430-sdio.bin b/package/firmware/linux-firmware/brcm_firmware/ap6236/brcmfmac43430-sdio.bin old mode 100644 new mode 100755 diff --git a/package/firmware/linux-firmware/brcm_firmware/ap6236/brcmfmac43430-sdio.txt b/package/firmware/linux-firmware/brcm_firmware/ap6236/brcmfmac43430-sdio.txt old mode 100644 new mode 100755 diff --git a/package/firmware/linux-firmware/brcm_firmware/ap6356s/brcmfmac4356-sdio.rongpin,king3399.bin b/package/firmware/linux-firmware/brcm_firmware/ap6356s/brcmfmac4356-sdio.rongpin,king3399.bin deleted file mode 100644 index 63896b607c4450238190cefc8b17f98bc7d01ebb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 580258 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 lbz} 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�dQLkdL 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®T-+QFIL@Ox&od1Les#m{?$ZlKaF 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

>v<7#z9XWyf|&{9_ug_BD(rg$ta z+PeR=5zATVFThXRtpSDt*S^eOuF!ei+)fgJ@dWuHiH*>$c_)k`;k`Jr9b>)a(m--% zLo6x!r-9*U#5$;+j(TrLqC|$!k^j6i+?Q08)b*C*c#AFnCTte(^*`FqjUF(Hw)Q`G z6Xgc)^-n!feDY3RhTO0Ml0;};6vw&sN zoDpsC|2FD6e28R3PM6#K( zx`Hz$l+o4S+tCNJ^uEeV&YEkka7QV|)T&t9POBMQEchu^>ckY@NB6HHW+zt<{OHfG z#F7v8$C5gX_EsN)Jhh!qqEWl z3*PYI+Py+IAE)?eFBe^d)&lShqcKZ=BM)I9Tc#@x!jrYUFcw zrLRG_JMXgyZ|;hJuIvApla?-1R~yUJXP|FcrmlgWWtsXc`+W|-8`Nr)tLn<{LHJ-- z_z=QxcZCmQp8ViQ4bxc$EwU~{Zy?Y)t+oq zGS=f>&Bw4uLI2kR{@7pES)wM*D^abF1U+I+TupM3ps=3m2I7>MB1JHW3t}X6L=e@9VZ7aO)G@2&m9GH_PN!dg5=FD+A z)1_EtM!T)BVeww*VK|iXsPaq-=^FO>N46PE_hj=@$U&`duYY*k-Pr~cg<_TQ?I}{o zo9Q`YC&wxZyr%Tsohpri-x4>cLhGJbr{Nr>G;jkjDq_v?azhJT2Ga(0RdJ|fEu5{i zw~jWAli&dqW7pP^lykj+%IWXxbj~N%k@W@e?6*NZPz-zE9XMmi%)>Nw0K%2Tig1WL zEPykIsF1n`{GYV@=GS`)TpQGz#j$9^WMYwUX6+Qft&DM4T`}3?6>(~H@sKAqkgS^il8TC68u_Om0OUCo`#>S z3#t&A1m7}N}QZJ~}qk=JCvzX~=7t}d1!I&>t%$!ju)i)S}6^D9+(HGR4{em&4 zSO_xL1}2HzrO3Snuud*#dA9(r`O*Brbd zRPKXwL@S#+FoLX}G}ij*$h#acC--BmUk-Q;EBh9E?;5~vz@hRoHX3fgs~EhCrLO|K znU#Nv!J7eZVdXz%?b-tP0X=QYaMt?=#vs2SdP3x9*!wq+M1BSzW$+fjr3}tx{VWAs zj{17ZS?vAgs82?Hz2sjQETg_Kz@hRwR(}}aw=sKyypZ+hZOq<5z@eCDIyMIZR|Dqc zT9#f7*vInU!(boa1qRWx&mYO^UyzRXAw5KXnWf7}Kdm!h9v;Aq)v?edgif$fCPK$p z=pKa5vQRogRp$v!8(XS=sv^VvSlp-mpNc;z1g)5CtoPM3fSPYE!Foq{H_gj#ew>W%b^rzoK)eDZ-+;4 zM-X~h6^I>i#`fr(n65aI__C^HvD)?#(#xujaPO^p#HJhztUPpc1~=;Y%wx5%7Cu}# zL_Nz9pFy+~ZBPZS^W*0EQ&6?v1j_1`D+^`*&N{Y%N5H{KQDdl?+U;QkwK?r%=;l_f`b zJ?d(a>h~RLUcWfrC0wPucq~$5d^FVG9BVfE{&c$>IKpOw?+esMp z0?*{jr{NT_?PIg#>Ezrc7O!?>@<^BkW2c;3T9@R;zF z?{V?lH=gh+d_tDR?ZQtR97?)-R>XiL=R6H3(eb1u;}Ffwjw zm0C2tN?m|w5uRc^OYtnnvvPWdVvDI#pNrO*s?=4}^@&xgJ6b^aULD25s?^ofbDJiw zs8ZKNBOUZ+LVlGx9#~s?eu+91Pa+=8+!FN&{>RKUxz?!(sF7GU`^ zIJEJPqj;n`@m^m_34B|Ys6Wq0Q=Vcbn3vs~E zeuakI%;R(q<;{I_wDNn7M2B983#a^&I#tig9UvJY!fgKxoj^mDad)7vMw_QQ7& zSJ=xFm&f@&R_i18fd57H<#`ES2(AC|(mud%Jo6=Lfc!$2T`~K`Ol`d;?Qrw9wSI56 z20E#|itmw*cfC6EA!2$SGW6W0ZA-0EKV@|19Qc5O`zClqbx++0O>E9`L4AyyqqMaL ztZqq*FFm#}&UMXy7d$*zT(5!mI;7~)qAGP>31>52GBjmm{-rr%LU!gdSLTnLrVPGL zqHYD)jfBv&>8iy^Oz*3PQpjPOoHNI`#wqW09BUSz(B4W9?NxuQnLH7S-?}G4@auje zx;E4jja|0VqVY|!5T6ws(|}o1ItBbd9m$4v3;o{uKTZ8ety1b*>AdEO+w^?>51TV( zQS*blOr0to@}vT96}*SlFYKp&B^JF;ldP)^LKzlfxpK(nIja86o+WGe*YM9c4V%_i z8;?dOX4ViqIGqzxgc2Aa5w`YS>*mKIM$)ns84SYlJF8k3dg@UxPI>S}55ZF)O zD+^ovN7{k2=_rkJbsacR@^*O3!~q8QOTb!rB6gv2fx@2y=H>T6-&r{d{}XVCyc+2V z3_c$$54yXG)%Pz3H^OJ@5eEOA!4HG?njwF}!iQM6j)gC?@P{m%j+K`oA7SA|Ec`AD zmw;zXQ~tV6W1_f5DB4>LI_4~^|J8L#(kV!oPUXON?Di0ONyo=I@dNw2^q;+qZPZ{g zgQA1~^?(T6dIh-cA#!;OIK`}QC8$3{z6^K^gP&t?G5T7{;8lP%@=T14m5t3(z??iA z@1Du}zJS54=&PN<^BC;L*p6hdlfh>(R_P3$&ES02=SL6@j-!*MOr$9p`-0UE?)i~qdSM?%38N2N0cZ|t(7~`?#V269INXGwBrE=j|8lh*PzrC2Hyo( zknQNl+ic8|0Efy(lt0K|3oE~kwQDdd3#<|+I&DE5E9;}TBIFo^iR?t{mb0`zfO$C? z?_I;-5Wpeu8w=W#!2*MQNMFU^0J!2rt^>T8!7YG!`EMAXEe!sZ!J!zx2lVvaKLZYx zLs4HjOaG3Qe;)5IW$-sF{V}w)lEGI1{|7ojPSB^J@)sy4vwHr=4bC+7`A19|AN%Ln z*yBB6Ed3*t)5`619kB5@4p@*Y>3bM_6!2bHuRaZ2oVM#dz(iJ&Ud__q0L;t10s9zy z0I)$m2UuqCK9+tJ^;fZW?gFfpQ&FG5-oF)asGI@Vz~Gkvhsf<1r*sByWbo@K?*<%J z`teKTt{CYHoow{Y7km2_iebJ*VyJJiXz(o+ zb-rby;9Dtbe5*v_TO(3QC#jtx{ekFk`sg6PKccRVu2k2IB!#o!E9eMtlMszXdf|{@ zKCF(@h>-gkvJN1mN#n*fdxLztR3){Ba_qXfM)xQWw@^wQ98?`Rs6$M^(uOK)RB%cm z$pj4@l?GiP8u}?ZP5FX_(h=uv1wF(YK!22={9X;EtUhIw&)(FbxPfN$ak#;D0k@#O zRITm?HP#q`)wx!A3)BpJY>hdq#@a2eM~n7l{&1coUQk`Bvu4p8k3ok>7$pvG1_tpM z$IBgfW2gTx_>fjmN1XgUdxv!tjr|6^dyTvr+;d>Q#^>Ww;EN2lw4qU9ah(EoPUC&V ziZ-UU1mk?-1@*!-df($0*B<}SmU|>JT=kl;vs{=ax&p9_Ac6uiW9QredeH@rYKZ(G z)~9PKxDV(f8Dh74sLa;gZF?oD|1L;Z)Rbik7SYQ5hs}_G z+CcS*Qk9|Lm*~MQ%)!oZ9y^|kGt~649J>A-=s7BVd=~PHXPNxsS;w>4nqB;^yOp6G z29MEFd7bJm4yd3UzJYtF{R_Sfwd|(8RyA@~TUaT5&#?_u_JZ|8xaPN)boloNEZ}B# zf^S--PSG7v-{tOBUTO(_BS@Kq+NVPjV#ycr#eI&mVS-mLh3>(bpE6eJ^QMUQ2Gp@Q zc~7e2;g>R1X;*c3-SXx(iOX`EX5!|SY!Ab|p?`@PjX#)iU(22X=$t4*T5!UiVL7AL z*(c)ntQ``tg4fj3_JBVG+yYP)V=f{`iA{5<1nDP`E)-YbmLN_5jiDyml6)O8kP!D% zOf6>UWqz(!X(*SjGI9bulhXgGxIzEY5-v@!$zFP=sLW0=#%uoXAkpT?Ms+#~!e4g| zchvn_hnN}UBEFv8{@C`5_?9vn7fmfIdMQ&c8R{dS1pSK}S`T}@@UQm0Ez%ojrWoG_ z)gc0NX7tzWIdednuEv@Orr5<9zQfI%*Y^7SaPy|MBR>DdHmsfphcl`EhRx_}y4!-( zinRlgTE2F01I>BQrNhlHtc|;r(bzAtEOWFs+IJHB`WG=4{l)-C23#FTE`lBuhZzX{ zmW}~;KG0mTj7oaNhSaXNt`_IqZkf?X`QI;QM!@6eWpGc!y>oy=Z%fM|{a{|E{(_I}WPZY&?Q7e`du-;*HGGM5QwJ6`1iuzbG z8Uv~ORYMBo;%cagYlgSNTkRT7eiq!4^J=?zN>%a5;(2I0oKlfkdg#E> zo6S7%dr{h`=3*rq3#e|(YoG#xbOK2Q4*+Xts%R=2kdmfshTmv<{)m-hl{ta6%olFx zttlMz<4Qx}asA)WMWQE3`ThIOgWshjw`4TF56T-@#AxUuv;@EN)9WZlQ)AlKGE7_v z-?o&K-{~(6K)0oZOu(Oxd@0bTIon2Ke@t8X&1v0%J+rLn8*T{B5X5a%-*#%`gpOiQM&r+EfBa@B*6cVubMc(Q^8g+l z9?)@1FG3FWn(7oo&GGKsrs+#(yHA@hLg#0Yd$yb6YZIN6hwV@TVQcrF8the zU$XYAGTc3k!u}8bLFy6p->F$mbq{69gZL_hgWqvm`$xEW6#V)wFAuP3&HpRZqab&67>dTqb2I~e0(42CF-^O6y-d8 zv7}Uq;}Ws(Zs!+OD&A`QpgIE3>l7dS-DY9FW9 zT%`M&nA)bJHVz1K+tp+G$cw~u035_$Yl)f2cL(rA8Sauy z>>C)Tl;I3t5IHBi$CrSaovtQ2)1;gJjh)qb2pcyS(lzlw)&k!H_9-b=d`Dk*(3Koq zigRF$^HDv2 z;rK%85BK<7Q5vu8!Z|oXS=nxJU0GC)(WB5tx-;7^KlzttYu2^9;luD!w(>1sk!keO zy=xRs`f)9KtFE3xsesY|;g)P6X9BiT2zg1$?$wVd6QQrt>CX)qJ&;pO)VMrhr z>({$1tZb++NJGp9kI_uIvN#d=mSPVt#WGKg@t#4B7ayCd_haTl!P9xF^|ZQOSLq_A zSN%(HW1&PnJBE4;?pIGN@Ir5o@`aa+o(g{<&91DQTWcD*%6>!kV+-BR{M;1h`qpGb5hX5X!F&|Dhh zO~?V?3AW^{E;HheG8|=?7yfCv*WF6~f1PbsUh6>(!8b=~2?%m5FD=6DqzFDWh=@NZ-C`##XYTUf6l zSJD2r-i;$A;|zrMWjX#65&zr%AL{JxzvXuSj~u7{CpWtF6~fT_SD3cKeV7xilQY3$ zAnb;S*$C0^37Oc!j4p>8vyD&v^D*B|E|~s78{G$K#Q-2YLr;8 z8*57WQlV5^8VxCGG{&hwEv|`TBgbRpA`ug-T7i!yyAC+ltMA}eGwtUqxAhcuU(}Et zcm^JdBm3|_wn0Nq;{W6q8gdT(rF}Sp{|SJDx);P+P;WqgMzj9>k@Y9Kt3UQ^JNjc| z{h5AcL=OCXN6;QU$=Ys1+xKH`CwY@|a+^w*(3Ax%Whhd%BW0X7@pj5$mSRTACZr7a znsP$f=qzIKgAo4=;!R$%Bh*C4Ymqq~ad~ZZHE|f5IIO8Swx)t()DPp+FMFJFK9Es^ z`<&S6t3lxjSn*U_1GWPEms?4K|GSG(uFwgT^!Ek5%~J{LqLs@!#_3Z|5mzdA`GU zRt!Ct=d0;BuVvZ>Yw9!E$Y`B**wW-m@5`Zm=H(XP4vW0^+#a<`Hag=l600yedEWG{ z)njMzqY>{zi5cFJUGc&Esfc$XzXQ8il}>B2n@8l3?Y#UUX7awSxJq*}iyMu*i=$Xv z9r6ufajzqvtt+n5Y-VxhHsf(xn;W?XvzXkLvo&N02f5CG>;XAsC%0WA$Fx*uI-TKH z;<~f~tgcu`Y<9P9z&NF?Gw6YOE?cow%Z$`sx~U;4cz(w72RuhVjwAY0aU}7hIPy52 z{k3t#aT0U*qlWCqQ;0m;?=^(Oqy0fcw%=_abc`uY-hXI@`O~?5hPo}A=H@oZPYH>e z<^fNb@4gvEViW4rBfysAf{pp{iJ#6hnDp~QU{|OPYX|zZVH=!A%f~pMqYavZOxQ=& z&J`0k%^x}Rv@*4Tskc}0o}0w9Vur;JHqY^4cc^0j6k>vxiTKAgU&s$ zseI^|7uTs{)ig^UedW~pzJjUKtoxMnLMb*3AEZ)<=avPDmAnv?c zl}b-RT3!!Mg>iTjI2BbaM*#TucF1%q{H;u8yB#v!pBUW8;GY1egNp&YfWhgb(od!z zHMqhg-lug{_`g=IpnY4sqO<$#`r;ULn?u{MRyv3?-VMs}74>G`Di77eJ=F=!6EQo~GpN_< zIgPLU&j_Q=8hW=JUN~_FpK83(6-qr=WB&68O1vvwq|%z1Srz`LK$o8d-*!elli(0H zsqimE+&K-!dz#Z;0T+$n9R-LR#yESgx-sVYBHlHN()7re+w|PB7m;rp^5r6KCQr*Y zrn!AvkV`_$c7evUq&?+xi}Q*q{NvSX+)l`71BqCfLAm)OiihO4g_({+a zC;&Eo1Nt~rC+Y;#Nw`6E2%vMY+g}mXAsB7KJ)Z7#OV_Hz{h``)tcG7F=s*E2C!1mY zYOu5$a&$qWefS~G=o@00fOR5|8i(JeQHDKrs(p+d@A;rpbjBjjk7+jNDBqy$42$4& zV-@8#g%(>}k>J{ui}Bg?pP1s%Zwlf`AYJ*JkHsm@D#%C(*NWm8V`U#+SX@9~l7lD+$mT?t~Y>;1{;rudg+p{DBW4ZnZLs z-g}XcZUS}*Pj|R!_cZ44W@nJgTIbFfLbaNoUfNfg3MvBf)`Ao0M*}$B#Z2DuI&>vZ z0FTU6Im@@pCp22899VjNsbyKgvIEPmFS9H!SbkvncJ-sQ`)uX4*OzNe0pQg`jT%s9 zR@lVZK61}0=SB^5_A@L-3n!MSe@mm()o_GHkP@|$$M@$nt$>_mg&B0*FuSurE7q^j zi1kldu$J7#RqAP8;}gaG_~+8NR85M(_Oln~<51kwXtYi(QSU;l?ZsKJRiptmzES<( zr4yC49VP0q0s&`eQg#wML*dn~qdN1n>f^^>q49~?i7ehAn^bzXrd+{!TxNzoH*hID z0v@W>YIT_$W}LL+6i1s{Bj!Nry)=GcP?lwu`a{1@Z-Q5<)&RH$CF;pE8zhREMoAgn zdKNMGqEaU+8G%^z`D1)R7rJI`48Dfl{*g>ukKSc@;S=Z&oWa?Q|0M!XnnQV#cQuZT z>cf+C;7gBQi6h5w9@9Df31_lKiuDke1{U(y9K-z9ei=pe$Dgkb%b}8J*n{iRp$j1DH!m74Z1P_xh2K5E{^3%>39Q4|Mx(0{OdSE>k6K7Be@vl{i-tw zJdSjZ(kw(Cf_-0*WY2`cLQg3q>is=DG?){WYS4dq&>4pyVes3tsSJQh3&coOjp!86ouSsH68SPC1b_I_BS1xpK7 zm#8D{TIgt4!24Xi?E1R17R!1{4_fVX_NL-43FQOnEw5vxPgY`}#e&<4*`}^_l-pjN zDHe=it7u^MAQr2aJ3HwrvRt8>`0?miN&gl#i{~Df=9p;Tvh!X{n)A+ z)QY{T#s+<;GBwLMNhu9L=hmtB1;@_IeO?I5NoA#*p>c}-1c1SI;{1VR9Mts6z>+y-~~zh<2dtYDr5=y}gMgFiym$Bw0pB9JqAJ?OMc{ja=MY>=+fL9m{B>kV z7u{8iHS{#2pzpydDaI=KcZbcD=oG~Q=WhRkc5xoD4nvBFl!lHu$erKrn->dPSaT5b zKOIq+F9N@3Tv=p}1`m%%z(Z%v>59NNbbpHzlp^j=tWS~-tPl7f0=J#VZGeD(av(@I zR^Fx?FFwSR=z9z#PmLpI8bKpterC1D5!znR{H{&a`a*i6V>fQR1=s!S?pRoBj8R_1 zS5$J-Ni0hbES=)`0%vzQY(o~f>JB-VLN8q8ljmL{)<4wit%VJlhjL|m-qwty3%T;m z30pIq7kTTJT0zu^nGSI&#R<#dIn;efZ*@Q;`Ci5=Dfd6kVlogjwkxI>F}&4;m{DCZ z^I>;bZ`F8pX7f_PCqNHHEAnEnPMf3L{|HLxaDSq}mDE+@K^7AOdUt?NNRIN-x0{eN zlfA8%x4<>1E9Y3m#MZ!r%u-m{^c8@&RAP?>{|GmI(C2i?wEAIX64t+Ps~5+aCo9dc zF-9RHgZ|SRj+p{&zk}Yl5q4;IggTtAP|VK?aERzvv$2idL!!GYsjb7fe}?CO@NAsT zlLpMmd(pu=HIDYMmNADs+g} zg1dI^=d0_~*ijT`73aQ9=fBHx;9G7ol$hSeT704XuHs?1(RxNraAzyqI|b82*>_9U z0`MevaXUD-@ULZEnQK|Jx;ZJ%I0^CRjve}6J%ZBC8fZuU76Wqu@6ycR{?eg6IpCzHmWyOrK>Xy zH;XK$xs~3ltkRVt2DCFu9c(ewSl9E+j$SOI7rO2R)pk72ll{-|MEggcJQ^8KnwRtB z0@lYeLp)i2uYu5c+t0_76-#;YRUyvgl{|@9!Q;*rPdNN{;2DMRNBDml|NmUYle?nh zady_L2{Qy~g~#B~NYCNUs2=M}#QJ)@-HLTNmTBcCfWjiR8wbUc{BJ4$Phj_TLY=$) z@vXSQRRe7vEj^>P-%$K4G(QG+g0#0po(!=$4HmPj$@F9%IIVf-=RT9Yrt1tk(N>*# zFi(4#?nNg8iy=Mx*0&NCCUGOu)~FwRksG?q5xOcoS>LMZb3J4hzFPfu@Bl5IugiM8Ge! zm+@;LbT^x7iYEgt@nit*K{~-ti>Tn)8rnZNp6q*tCl~i)eIhQbWH6!Ys~9#kG8-S( z43b`Yp)4~@GBjj1&VZhs<@3zODfl1ZHTW_cod^xCf3UGRvn(^wJJ|P+7dV>$4Z*v4 zo3jsY>Mxe>M<^OL4tOR7xFqzyXme@qwmJJDEt{o9bcOm@!VublxSbZ-2byYeakl8% zXiFc|a6vV4)cRxwcDcT-ZVO;jR5ATca!qCbW%M^C)pfbJ7Gr2kiC@CA|I2R49KSBq zJbN8yuE780b;T!7EiQ+41GQcnhBJ?VO9MMENh)a1Xi$Gdo|DWBQQ&^QKnzzxoBx8%t=)hc9F_auGBHYIaHM3)PdWB=+d*Bx>%38v9HX-LI)f2>_k+zZ6?!B$-Z-kJvcnKG4jqwQ$_M~kb~ z2VpVb#iGNWfUWPP*j`*ZXN_*ajc6wc4YBrVSOuLHnUq>X8+hFM4#8;;-B3~R#o`7o z2aYXl96%C&W5Slq81G-2*XQZSa!GsxrO~MVXGUWfq|JKhVw>y1qaI+T*rt&D44y-J-Sat(72!o98aZd+Ko?igWDpC!HX*RnqjF|bbl!~Rn8#(nz6Fueros16XrCP8v5EfgYR%uXjTIF`~1V!zb1mb%74t zdtg9h$Obp9CxO+Yzgp{+C z#Fr*<&4wk^&f&wjRXZ8DK_-XuY;=u_-zw~EacQ?+ROJ}mR>K=#t4G%T6LyhX{nNT| zpfm1dX)d%Xp}Xsk?@Wfy77fo+;vxOqY$rP=OXFOIH@IzlvvJwA#SH)3sokO55v=7d zSTLY1I^Z5BJ%m~)*U8^84!9tPI#k?m+H9W;t4`Mz^UdP2mv4%~?`!DYRl|DJkkwVg z7pw*iYWVUuHQ4`a4L?J_337${aZ*}W`S)3Q9_2syP5F%fTK=D``~;M@bd}%9$_psJ z>o?`6{MYjDpuF)g?fW<>GG_=zU?p%{Ep95#Q=aN5F0^}k=kx|1zQtZX=@Ye%K<{m| zZg?Zs*>)qw+H6P(_`^H7p~R<`(xp(kYBt%iUXDc#B6RP%@Bw6A;8PioQYx(7f6uW9 zSZQhV=fQ@MdQ<>SLxxSM_u-~)oBw6J8FuhH$q>|D+!vB;iKHtdKs7;|V#unZSll!k z2#)qM`L?1va>pTQ+-PWc;2bz+eTlrL2={QMKJH~D>R+6v zQ6q1uf-Pzde&4j~@mpmV@cX(QcU1T)rm59;*=wpeS_e(9L8B?(Ze$8)DOgVTO6S4v zj$v=e-Bn!yTPMWum0D8W_pKLT!3DV6%d=p&ON%j_+jYZt#0G2LK4=C|UPB~jb7jI# z&Q$`+&v_nl8R!()ee>yDiOQ$oU2i5goxa6`6-#^N9J(@g2kg>cv6m&bSUnTKDUE>* zF6jQjqTvC=#a~=n-{K9o?Z@$64s9E(Hf9?p<(R(`8lVAq6ExKHw(PxT zmzJO}b!q@MUO2HzeUQ-9UZ}l~<>hNn;%3_}zeg={z@`cAtnKo@rMevATpD^^o#$|} z(0+9;(noPLc8_{}F*MyYCF*D{?#Zp0qIXZxgEj-SWFE9<*y1i(pr4`PEpwxNH-N>_ z*u%{SpV0Y!vGwv|{w;_RD>AhW$k*gXK5*>jK8RNQb@499N77gRWpUJVvj+YBkS0lU ziMK?p)cP8r^--`88ajNzT+71UI^iORbsQ=^to%JNvGMs-j59RCs3vwUtUrxRrQtW+ zLlN%J!Ux<&gd6!vHhzc_BUlX|q*_tKNx(x;LtUx~&~-qA>wDu(Umz6E@|{nOM#?3?k;wOTYB->u z0QF+2-@|s+#Kv%7I2}itwD|lMVspYbREqLPr(X7K7LC??5N`Ge5%KGub3>o0sGJwfN^ahhMG9b zq;IY-{>uX0Hq55@j+!i9ezMoL_yu9xW-kceMr-Z8t)i$8QXdqJ+v1;$*k)cBxh;Po zUnZ2&)u2zMV!@eZRU<{K;SfDr?9PDdp} zXS8WlZc|_xl?=MFtT98wxE2d!-FT$OLAiLliB zXl>stnpyOkuZws3t2!+UFYD_Lp=TEh7WUT- zyl{PSMPVt?T)bT9g%zJGg_rf*g_-(@i`N(JCcQ7(rBRNZ{%1Swo-};ZJN+e{A05KU zET85#{fPXM-`t4sp4O zrzL{lOb&YZReL;fQ4fb{scBLX?!%oxC_R@Mua~EZb9*ya(@AA<-9mM1adffXN%fY znYoZ~3BdESnJ#*IJETE@a)tX@1 z06@j9bzP7MsIYZ23M9r&0!|BCEy=@ z|3W;8Ss@VGRvG*!>jdI@%~e;Jv2bH%#OL3+MsVDyV{so&&2nn@Y`~qgQ%(Tt3qmrW`yI!+ zpzi@?I@B)c8lVivF<>;b+!a9gIMTb)E&z`cOyjaur&aoHKIMX@=jh~S@HxdfGp<;r z(OByN|5RYS4}u>`%0_|@I}&`@k>D_m1TPj^Mwn--E6tIXovy^-*4H?1Y8MabEYnE3 zD+hK|I#+dR3Y|3%18I<2=LNq<&-)mClT71qcL;DGCCXfskQ~J9?@AF ziCG(mGi$onRzx+*!RvUI$`JcPK^;`N#T+})UX6PLQOp11JqYf6682h)vIjDD5p5b< zPoE)*7cBCu|Vd@~T#78`$i7n!-T-s7GFUwj*Ef6HqngnVjEFB$ap(A2Y;+p%`Xz^( z?_KMi@An$Te;+2!BSIRJ7V%s-Q&2X)>? zd^eEHI4Y1cM+CAPPsRiTNkAOzrh&^r`S4bp4cFA}I+ig>O?t*I|DwOqd~_eOdp`7Y zEZ&It{J#bHP6_DQluqIioY;d{zB*49_Ny?qU)4arY9vSH>bP+R4Xj;$33Tdq7MgIo zuJNdg)P9fmP-zeux-@5V^+Lt62ej{K-cqj`Wz?-5_o+KtrJ^}d)T8%Gj`xMGMD4&8my?83|R89H+*n9K1 zrmw7j{C=_#79p;UEE*C~6qm3mb*Ts%4b+NTYim1(O@g2xi(9v-pmtYrtF|*J)@q%0 z0Bc*?TBz0POgkOuGF7Qh)9O5R>MUS2pARI!_kC_YLF~-){Jzik`S15CdULn)xy!ld z?&qFUA>GV)Pkgy63>=oxEEJa~VYrt#UCIEUIpwDYgN1D<`@KNts%)cg{f+I4D-xp$y;BMw) zqa$)Ezb_=bZo^Fts|veg^`!@2v>sTU&9O>j4fVc79IJDK)T|%O?*3}F5$5-Bj~k?B ze}{dg8QLOSLRou&n&rd&3d~de)a)S49|Hjc^IWi+4FWeHpl-NG;LI~hfy~(`avRa z@gJZiqO@$+y;2BjX2^GoL%R>=XV#e>H`O`qCdjSE{8;X^AIvvFz8W*tWY*YGX5kBz z|CV?bc-SlMano%Dr8x=xB?(ly5uElJbvR>=SKHL!-%zJ%Kqa}5<108%iD{tcdrmE$ zsb-JB%!TpNvkqToavpuclg`LS4s?C$iLwcicufjz~A?5NeZ?9O4_XIQ}dpVN( z;a-b+&x3S^jvd*J_+d_!t&4l3B{kw#+278RibtY5nKmX#YcoDqbHW zLBHp`o0qe}`#ur(^5AY?H?c{2Y@z_(b_ZM)6TSSOx8F{<#YbgcsJ&tke;4uI^#~@k zwFz{7TPx`twbFp+RpoQZx&(8&h0gY{bdf4?`zO18Rjh{ASFWb!et(X6WZgtrr&hm! zuOfvcoM5*JW1tE6xob?*Bj)z#8-#>@W5Hbt?qv^j`Vs#0z+Y(fxo4iLeaW)<8NZz> zivrxhpXYy$cL&>NWn9{{o{h<9K}wo)Lnrp%G_$_GFP4=5Esn}M{}o3o{vUDV_o4!L zA{=Fd8_3#edWPd@GjR_L=GYk`W9Prd%cXydmq-6CUJSsCvHIMzTL~}Es{7#OJn(Wa z$IHF{4PJ)+TiOX~Qh|1^b*K)^`|-R&dHwg$uX|P)==!$fvV^$*56aQ?p&T`*9Od;- z1j0v4hv`|4kBYwd@Z;2?w9j*OuWmaT6xEu40zFafR@{t_Gqx!eLc(GF3AA%$vc{rl zAI?^!&d_Is&vSW70+Kf&<~%fBb+0}F>He&JxT=40roIUw6f2k=dc>6|+lLE^dJwT<;j7-x*~`9%ddUMFL<{#=LIM5$zNinounz3Skl(h2SH zOp&a13z3I5QOZJWKr+gvJ0Jf2rtr9(^*VjlX8KBof!hajo?teI$FV35RpEtFT>nrI zVh_RBjq;)nx=+Htub`B&DnCaVsjL)NQ>ncEAvmu?lfSQwnD>B`XwI%1Erg|CHqto< z-K4b%L(?I<6l*bKtB}}l-1Qa~MQ{rNciHHLpnYeL_&vBvbsXj&EiAGhc6eN7Hs`Ow ztuXj&Cb{E|N^oaT>1tR~r8JxVZ3d zak24^{>*VP8~Va+`|(yo`x_;0+k>0~B_VK2Nk26Y=W&0#wkV&*>83hESuX5(u&uBkf$dA%#P>qJ)CoV2;aqBRiw{4v zuM#+ZiaodSL!ogTKe?XU_@PjeVAmr)9kSS}5PYK#LAI?q!Kj5s1miXHXtpP(Jy z>&H45{_7}jf7H7G<(q(VmcsUf{Uq$mS3=o~u4|BRCn-x z>U`}690eonIqZP@^@hb60}-|vE6IS~Fr`t8u=VbHPQ8eHMtz68VaLMGg*^@SblB;z zefetBYmu*xw+-QZshjFli+zEL*J&f_bmIF^wiMqChwb~0ZEwOG0fzH6tns?q@J$m+ z>7|_GUA5e=k?E$UtC;(bqNNE>k=>L>Q{+ChGWmyg-*ZYt`js#TVH#n+gP}F;?R8%# z&NRKN{yid2sBo@y@^Ac{3p`YNLyMu5FSK|<%5Arg;Njeo>x7mJa zn=tv3V~=B_G^F}~MfuEG{l^cT#QoaGSlex_O?`UbEcK3EmbgoW+h)%4 zo4IM`kV|I}qr$51?xE2C$JczirU9;g-F&@Qt#GRj(t2-zOVxc@(lr%q6XFkr6*!K= z4vIYPcxR~Y09JKX>H~_ZY>VL593;8lJ>oyRyj)6y!R3hY;ssu+XKJNkRH|qDma4Kg z^_hLMlql8s-ck+zH>J{|RHwTFu!;z{eny}b1@3mbE@Lg(w@mL0J?;p&{;{CsrOLK= zOY=@|X*kc+3*d+)dGhlrYX@6SZ&OzJfqygDLhtLE&HGc9Uh=QIFZ`|geswfPYT8FB zF@tVU{umGtgt@$XozktTLCB**yz)mauj`dR1_lORKdTVp0D;+7*{<(OW+j5EZZZx_!+9VrjP$K zlud#8>pw!lqjz)q^ai5rGyy+8?<kN64p zpZ`>baax5wq#h;h@9nfV?G#6S06A!&QF@09OhOJKQgtAQNrR&H=SE}aeJS_%#*c8e z?FWgrHiKY%WO)$ou`>+b+h3CWGOtacCHX4~<1ib^8(n97C|8Y}?1i9t+W)iYG|~zl zpmqmvEUx7oWz(9c8kigMj>RI}w?-PGj*n2Y7|XCsVPdFlYTTfB z%Pi?~^pDrpOf?A;Nun!SPcz7rWKp`cONe{ss1#&w6c2Pyv7eVzjBsy;eR1QMTS$^~yCzCR4vOROpucP@CH0i%Rb!FW%T zC%XQKRr@TQn@Z|zS8TTp@9*w`+!peU>8^%vlI$~e8#1?@@Ww>oZtEqM0S-hOTj&Oy z;0JU&^VkWh`8wPZ6qgc~A-~vcs2jpD{iC!E)GkEYT{RxaG*0#2lphspz@Ky_H_l{Q zu7jLE@5#_rK4Q`NwjH!ccwhO9nyHWBT=gig{%rGb7^-fhC~P^D&>8i637iXZ8NE2dJ9PQnV$G9-|KJt4B=I3id-QTlGI9*j=Si89NgNwX z47Nyosa2&(d@JCa%6(_y%WjFb+znrsSj}I#F6C4~Z+R2b56zSV|oR~vfvtl8%HD}i? zurH{K6`s2`h@ZXk^KE0dc)5$cCrs=&{;w@~Cye{-h&1eKclz$MqwS&AF!afA5B142 zVz8U;V}!`l;%W5B>_U>Um7U|Iw{T8xbRKdTc>Xzl3Fmju4P$@5H;jE75Bu&g-WF4F z7w}3}7>lunu`fXj)JD_?n{khzt=ldBggG>|A=qikUnnKwbbPn?W4DlqRbkW>Xw&+s z)sVki{0_4v-8=0Tzxe?Dliyv_o7LTD51P5-n`7))M;Kc3Tl0nZC8@h1v!U9Sd?LoK zN7$wOrA1k`E4JO@8<-!ifddThTSxYH?dh3h33djj<8_bYz)<~q2iuKyGUd;KriKF# zYA2@RrNtHdZ=e;d0IQJwwr^}+Jb2&M(#iQ@)a|RUXbo}(lFkD!v3z#@L)D1&hf=hc zGNf1?Gt9t?a9U>!#yZ3M3%ZKKiqrg&^jHiyB4eQO7W%GUigiehaisT(-VTMQf0P}b z4yiL{$d<|pPv4vio6Pd?^i(nkgFG5@Sh_MVEIkzll4Ic8oI|ed=1}}T3mzMX6p#S9 zGiFGlfoV1mM)-ODd&WEn?hE|)8#D53eEh?3_DEA0JCKilb1{sGx5C&(nE7x=ycf={ zuMB6etPW!*V6MRA9t~$ZV7`7Kj8($_B+T(I@C|I71v0 z$WU92xn8TfrLrBCQuI@e6_O=sG~Un8P8wha2lYN$T~|ofCG*;bL5gD~G)S)}PIXI*bQVMhgQsY55~cRQ5=w2!(F*B7z%F{HLb@N{J`9r$ zQ?#!_dURWbv~`~fyhR!BRNDx{qV`3=51j_=;y zRv~?~4eM)jm6T*OHoPr$8V1})gl-0VFup9)&b(pA+U?i+q4;)Ak_zAEpnSGyNV~Mpay8u#{;FtbY|v@}wGN@x zOTeQH4G1s6{W8pN^&$B3Xfy+^a+4q@6Xr2(h4eV=gGu1cM{2LbeGKL`q*QN*6bpTY z)ByjRFehQ&iq68#(uPcuHI4E?3>xZ%^s@9+msNU{5%t@EGNSg{VW`Q9=wQVER*w>* zhI5io)BAbZk#ljh67^fNM2l~#QNIiua^k1g?*m+H43W!#T4 z9z^&{FfYUWn(Bd+sUAlG!|MWfZ#@up66UQW=t_NonTl~Lb~Qrla~*tGL*6?e2)rj!V1L)Du9$U-DXsNF%$`PV zn%24iQe`Qg;J!c_{aufAL4p(Jsf60$%q~W-Pd^`yv5=W4SC!?ojGrZvK$5 z8#nxCB~M^+-CXb;)2PA5B76b4mB`nFRO66p(kcB_@Otn!-uTu5&6ARrQbBEkxP1tF zAMziP25@_mG)Ruu%k~Jei}y-tpyuQ@w_~3)IZidjFNWQ?<@om6z_z>CPfW{-SvC8Z zx!4q8pEM;-3CM>w;`K^N@{NEQ11;Y`j-prc4#f&nG%@N6-(JHDK}|@AHXwj$qx_w7 zqWqk}QEI1Pni{ngrC`pfQLDgRggO;tgm<5lv_Z7@n6S|o_Bq0Wcv#d%Z@R7Z8en;Q z+KxHEGU^>_8A{*V&OI!|{#nu%K2`trf^&Kbd2*X7{?AfS;oA!oamP~rhF3gSAyKEg zq(&O>umDcH>wHH%9)| z@CU)a(i6m6NiZOFv{QA-&(mMon|@Po`q{ndza^*tD>?mHa{5c<^rvxuka2`lhqBJ@ zO>4hHCzo|vZ(7@VS~}xgIW6KrziQSQ)8w@7;(o31=Oyjidad=UnEj2@)BgN$>d0~y zZP_jMlk>DSN6YP{LI`2!fo5OJsA4o1;?s!wqc<+(yBmJO zTMPHgtx|YrtC&&K&vC=84KklF%eDMNC$&f$?}27xxLm_Gcq(S&P`QRj-1<9OBl(Wj z@Ya(x7NZ|}whm`Uw+v@#RgmWgW7$5O)jvO+-P|#pJ&X8VFon=m;@UHusdgf6-*D!9 zVK|FOZ#(%6bPlRtQ?~2Wdix;DgLZBF@f775qeX0imdq%F4Ks#q5ME#oOpCGfcUe41 zmV8UASlErT320+7;%yuG9o?GiGnGO@z}On-{<+cO=Zx2@UmNg{!aOJ%AtS{WA#u<| z#kh+tfmnYH`yFIDqde@^YYTCXHDhT3y%@WiA;hR#-nZfs4Cf2)rRyEc_#SjkA1P=R zle?L*!CGxOBE5qfGYXl6kdxLU(z~*M0{r#xzc2eo!T&q>Kal;yyK{`cg}+Jm-_TvNNcM~Hzie%)|5(z>U;G0h`+0~; z4*3g0_VAFG0d7`$D;Ian~c< zH;nu4>v{-fuaJgw-|Vg>+-Kmv{o4e48@~C~uHkGq;4i_g!#8gstvP`GJI00k5%<{s;VcXB z7hqn*ce@Z4i8ReHjeva&-xQ)O_aW`|u$RJa6*qX!@>ZL}YhLOh?eV9rwPjR0+?B!C zXsxXvU%BUfv>`K@E6KMCJpK*vxAC|<&)Z0)n8(cboU|$|wdDrOg8Ei5&9kRth@lRB zZ5;YUtC-^X9U!+r+8Oz#cwUFk4A@pN(Q};A;O+^YV{o^vrSQ?7SFJ^DSqf^eEM7_j z+Q*9aIYi;SZ;bN9S$@NP+oUuOGYlaw@epC+HfaG58|2ZB-zGhzqSr;=w(Rb0Maf;o z-IPN%hy15|I}gE%mivEjKPUThx&K@D)3Sd#_kZo)D*N-e|4)!8@1-a^_n(72d9Od8 z`y1UA(u!URdlVG*v70DN1qv$wh4nyodZqLv^m>#d?kMzRlvykBrkC(>5Wdy$b*ss@ zAHE{^dbqC&zC!pO=8(_Aw*tPg+*b)-9(?1t?+N&F;q&nC*20$sUl;ckyKTI*l@jBy zcD$;81hE45Wx6Y+m2i=MR%Tqn``rV8xE~M-4v~S>7QvSpL?y&~c;kHdvbZnBJr6Bg zDd8#uaZ?a?FXHmJFTtJ0{hx3v&YIewYUoUd;hh<7x^vT9>Z;=%-}hdK!G(jWXXOyPM#ylidvM zR}XjCN@be>cq@0~+tNyDmJh~MDOqH9GT>*+Fb=rq$l;FcO39trDt336afXx$su|E( zDg8PSe0BKx*Ha9ZM-cW;yrwo-mcpg%r0@w7E2Z%om9vN38o1E|7a_Kl!!6)n5L_(a z%raao;LLzaN9;MCo0We7O)P4`Nxufjm1-3mcpTC1A3M%U*Ld7Dbu#)7!y4(Wj(b4u z-}C-=m_tqm9y<=M{T(<#Pzp}^ zHQ=1CRb0p8M#1$g;&$-39f%u&UWf6$!vy;k>2HD5<5qPT;Dg>QK3?T@48vHDw~M@I z+B(8`Kh5U82RqKxSJZta6&K#u5MbCPrar7&eM6T~(S zv0H|CuQ#PXAte=0DF^x9E$90sln6wNM2bgoCh3fJUhngTmEtclUQ27KUDV_T) zFG6FigTrQU*r77)bjcvYE|i+;8%T3NOH%{gUu&BOIUCyjLi)FaM2EDz(=LPrwd~?; zRhqbqw^cc8YPYh)K&OAZ(qCns_oLN68EsIy8!cFg81-!o#`AnHcX``O*;|vl?x@Ka z4)q5PbxCaN@zq52Z)#%Tuy4w+m!MOe(!M1AqsLd1ZSQ$&GLF||3~Cb1YZ8T;5T!ke z8W5#D4x6a%vBVM3eHMx_dmU(fCFuV@FrI%7e>nO7Gwm@)V2`PD4WipxU~Mv9A$eW*^=y%f0tq65Lnvj4(Y+AU z08tDG_0ho`;s!Xn)yFQ0dep`18jChKB9(BMejLUr!)SV8LOD!Xppd8-SKkuAWovH0 z*z*tIHWWC18f)azlS*i3!^$jHI0~G3c40KWgqKV>5isnuCjX>mm3S#WzWy!fT_4mK z15LJvrDx+0Nrh7`;b!0&K;XR!cpm7h@4H{_P??4J^{pI}nwZzm5@&7KzvvQ7S6K?1D5pwkI(9Xy?c6STL#XrmO=Fe*Qf1BfZ zImh#Ta{L%MPPLL;;jC$~?LTZQz;gvU;8L!aJ{zH%9T z-hlPoco^?n8}yiw@s>f6#x$b7C*8uaXwcCIT_js>P-H|}Sg3HcLi$reJo-^FR?5P$ zuRsmL#GT@VZh{dI5=PHP6DWMAID&^lDg+PxLJl3uLzQyqS8`}D52dfaP7o3l2Tipb{+csDdu*1G2I=aqDOBAX}>hU*QX!UVP zoZSazEQeVIn8IF|Xuu@)ff>PJ9tMn~7sdb>Qy-Xc4wD9$T{6s2^bP89;azv}bA(Fi zD0T^#Ah!W}t+9f6jr;m_4Zw=(x7_Xa*z1DjucEqw_*&+59y6?~QhGxn;T-%m)cs+s zsSjdoNI+Y?gmKw{waKeki+qjtBW}0db6=*_2hPV;I|sk9`&tOoC2qm*?rVN5{J82j z%D?(CW_-so&GIfugWK!3SG_YjGVtg&jI=M{hB@%qCGjNQq?0QSCH~g)id2D>ApH{D zlYo0vhCArVXgDfuQy-O{hItm|d6@0${?K{M{M8324gc#(#U=55kM_D%NxGRE+SMU7 z_~xH2l-f$9wn$EGL!Vp^BiEOBt}pRia{!kt!!7Rvw;gcR9Il$fEd|_I8E!!zxW@o@ zn8O|Ba0>vZm*MW|17`=^Q4V*M!&w2RlHtbi+WrQf$#ooZZQ{8$@m$9N?)Ng>Ki#+6VkqFwaJVxZZUo>?%5bfH;M9OS&*9E< zxG=ySl;O_xfopd|V<3n7l*0{x)H|K)SsAk4-PTYky@`F&NyR8<0?tqc%uDg0!6#u$ zpuY*Azr}Fx0u9cGy9Vwej2+)#P5d_C0*`rn!6|p(Ftea|-4Im`0c;m=9r2!+fOB?gy;}{ZZ0aAGauX=34ys zp0*5is;>tkFT(Sa?m(PfE*&Z)D#vX`+U+fY?aILS+Jmspn``;@2YelP4C{iw{4n%5 z+e4+wOS`^A=kk|JHNoAC7m9+GjXGx808r}1i`~itDVEDaQL9PXc7?W5YQP@l63!8V zCtz=?{1GYpJC*wf>IE}121jp}8cds|cGImE~|21d*zvN73h?m45_fX{AsJb)fp~!jkh|N;t2yf0qmg_3?LEdAo550T#rWU(o3!Xi+?XqsM?+j+_b5?9tmHB%Wo+n2khG&uSib7 z4l=<`Bt1D-&C!ts_~Ik!%f-hnA+Bux9l~vw#Oe;VU)YIVaL{Bb^qqE9$Yy9@`CE&ByV`%pENU?Y`1+Xk$`2~E^q>i6TG#<|RKNC_0c@1o ztw~hhy1$%CF(d6ENi{vh6(pAz3fERbniSDurDR|@wPX<}OQ0fc zrnfZK4q^X$`qY`6t3KX4+fiwjD6h9@+f~}_vlNhULS>=4efNWx@|s$NmxYOe?LmR& zM8$Yvw_h{cA05TZ7Nx#5vApmH<{7_#+W@Cel7eujNPB1 zkNpHg_hf_TZm9)#-iSew!qI`?K@V{~0a;Q4@P1gTmPf_O@SD-6K9N%3y0)0yXC=j? zfC*|z%c#%&y#@DliHfnUSijK;3u|=Z?%{dNAH)mS4T-KeZz~9lQC`3~Q(H^dQP3dX zg<$-JOl-`(&|3?h!ya)v|D6rqCUCOx*w=dm1Nf0mr6*sy)H13JXrO`V7}{@w76 z0dLN_M=PXCm@P0{VYV%;ke*t4QM^Y=zA+goJ|AedTofn4N9k|pJ~Moy;oHf5qv4B$ z?`iHcO7m|1B@??!?hAwODtx=RZxDPN;oHM~{qWsgGY(7pxK9J$5cu}PcR}pwQJaPv z4@UXeaKDec zAZO%d<9CJ%DaK4%Ye?6~!Scv8hVnyejBCFu&s<|G|9(x@+6t)x>E}!(y*}4YL|~th z0gnG<*Sh3TdrF(22(?v-MmO{+aenU|4#cFe$Pm{v9^9}k1pPo#3Ej0VEf8X~jg``x ziGh(9L`M(q0~qw2U?1KszK0pENBpci5br%MK%P-hB+kRvLKJOz4xx`U+i%2$KyF4&fw|#?bi<%%3sKaN?equt z!wm!J&4C23sa;}6mjivZOHAyxao&O|?8V|6C}e>w(Nj7lKwfLm&|%=)p`HXOvyrM> z-L@gd0CNcV`B~%;qw1Dm3vpd{t8OW5&VnXmbF5W6TWUqrr_BU=kvgMu)Tor?(DC+kaz$L)r@e z=>&Un$6CorGE9E#g0RT<{FJ}ZG#fOv;AC>Bxy5*^Tg$8IH-R!i$lPZ|*umxGi> zMAEIBLt?QiQ?)cR(jmPM-v@EfTz9e-9C9qmAyp*O*cJ@VYDdQAf{46F@}}ZVM)CY6 z$sVhNs}Qn(=Yc8|ft=FkVcCIk&Jv`WPnZ{^C<2QoInavIJX{C$t#N z{{pGWgXV;|zH?94>mVgN$xM?!Z0oXD`zn^3&{a3+3r&*#-$G&C*R9i-~Kd zykB*1vKWzfjeFC~fOcKL@Xn_@Gmvr_@(0&^^V|4pK1z^k2}KD~+)0p(d{MM_`C06B zX1I5V0o}=Ub7pBSlP?W^SJx(-@gCykvvs@xX@@fqDt0Xals}+m07^lnoxMYJp7O$G zctf_{E;IPcjQt?fPKDg2bwz^)PQ^9VA58&IpX$p-_!Mv@B%KO5K~P=Y?%`c;N;f0XtCR!$sc)tJs2tc|G2=%? z+`v?uHT6e^eh!^*u@}Vv@GC$w9REtywG{3*xx3r*AX0O2x8!*MZi%~ZcoxI$;qJeA z7Q)@h-T&#Ck8j`MZl`A+-0ySuCC^;Ao4ET+Pdebcx%)GZ6>f$#)!`#h82 zruE!Kai=E{ZsI<`rp3!g* z;BLET6x@35&hkXTJ&3y>_8gW%6}nR=(2jS*RDfO=yabwsxki4_umbMuuoDpX65NA- zjkOcppCc>@?!UnOCc+B;ZMM>LfGqYd*I#z zc-_gnIL+xiP4#qkE+jS8cSS2M?g0fphST}S5{VDy@x)+IS+|>Do=|J+LZInK4TvWQ zB5D`xFG9hklSt>a4xHz2N{okVW1{ZVUX-~X@{~>rpzjBGUVn7oj}xZ~={@WrFXDcG zq16vQ2lq9)=Uee5cfam-)Xl}Y^O1s!Vv{@FYKDAAa=+_VjH@Xq&QrI9V$2z78HIhc z;C!e^`T?)7Oey%{qIld*?qsWwxK-N3Q#%Bitd+zY1GxiJkU#02Ajm!LNjUW)p8~wC z+c@mA?sypjYZxA~**!sqs*s-JAsgHk((@|HWfae`gy$HA9JfeMbBKI5)@CYUqMA!O zp!M@`V6nuVjZ=YOtQ%fa-Gl@L3J*p2avrWn_)dhYO&Z|j-2{VW5aJS$*E=dYHHU^J zVD_B^xl^8(uU1GIB0Odb4-5SK#+{$q%PoI6O3 z+f%$#6ghAHM7*klza+$!B|#Fft-yZ8cHC~tyl&67#pGva#yne7QSj`Qih>n2S;tpg z$-2J6lpRx$on26nopZdPCg*y=m7JJDQ*J?Fc5Xp_P44mhE4d+fhc(rdy?mXiX1Rdb zk|d2^Sxz*v%S^9}wRJnia~~AX)}5?)CdeT?+aG!$@)eJHI&`PDO9_x& z)wF{6?TKH#St?u1a5Hh-G9I@RU0PwMaA4Um<%HxL?>OdrTfQ>`ZC5F+!nlX6H!2U)xMDOFK<~e+9D1$+rk!tdhS-#eEWKQwW#8vUCpZ z%_X^WNN+BaJH2PWIXs2<&i=h=kLwKXllDlS_G#S1g@HaAK`S4l?~Z_b9l2rt2=gV( zdeG1wn4bDwR??PmQPkp1=T5k>6ZXg6E8rO!``0?2v!;NX(Tmqx9Zy@+EM^CN@z0K} z)&&;gn7SzbwPQ2BJtDWn_Z=I#&-+bl$CL0qBT+lNg;u#Je$eqKPt)5LpLDE4n#H^= z&UTa|&0^jbjU7jN+oA_;QG{pe{#-KhOa! zMwT|-7P~u^0se^G7SH30+iekl;z9X~O&$05=I~g@!rmO#bj;`F_O?S&$9=u&=69s` zNjHn9E9_TH)V3?N3&R83g}~N&b&OE8taF?6g1m_s?**OBxM#4R^OmqcCnq@RWYUjdp7NL*W>oR03{BcZdja=0;_im~CfowdU*I;tP6f;%#Lb4^`?hl`B+07g3)7nL%f=

W?+c*~czXRzx4_dTvOHKw9ip7par|FNR_vZDTwR68g&i)ILF`sa-=u6Qz+ zaFp3GCU(%(w@6h6UVi;|@u_OFsLI${XSAe+u`>=hvhhmKPP>H?cwWkH)Cj%)C8))qG;6ZRXjRIiH8BzajO0H;<%f#8FP3b4BZcRU4qbVvFbF|A@vt@>hM#M2+KuG_j?PT+|dxdpi!q*e*( zmxGDEo%ns6^-Grd%gh~h69Uyb$mig7DoYGsk$)-VpDWC=xTNb&47WsP z-LPGo8};69EXY7!cdI`j>xItH-7Jlj0dvbF>v0&N2eYI^@OPf!d3JHmaHL*KIH2`p z93r}qo=-n-6fU{yuj6n?-CriOvE6l~{~Bxpw_z8@%8^q2fIN$02Qu{#u~IaAx)sbU z!d@*+8S-xo33iah$nD;PY5`uvkMLXZA?ix>L84f+#xsDQ}5~ zw}i)bm%yZdAj!7dzci#iOqwd25wgZ4pC>T%bLUPH8#)QW&K}oJf|GXPmTA@D^r{HD ztv{}_WJdm)#wqgzOQkD6joP$bK6g^Mub=DtJ1N87zgmAFgysz)?(F!+^m7>x`Ibtq z_V`o74C*T_8?}L94&_0`micsoDMZDkDf$NNu~Dy{vz^z%A1BOWFWzl2xcEJQ zhO1XWx6^|M;s(}R6D`XXS-+D~#{>JQHJ)~I*LAx-hD!TwJKuHRBfs^U%%PrE#i^QECjs!?}$IhT#EMc*thRj4+GL zB>Vz?av2f!4?LuSvSY^xMy!-PAE&-#RGC125P>b+Ni+fvQ=Boucg?z39LeEvB(Bxw z%%=4Kifp>UHH#1AeBaET?}x=!1wGu;;Q36Ww%SIrg+r}?6uixoS(QXT7pkY}w6(dL z3S{$H@jV&ek5(=-y=7k)D7H=bbxfPzzIYyMDCEhPbqjL4b+C zu#Vgf15zHhaI_=cY)z$)9SnR&Z-)(S5A%?Idolptt9Q}W>9jV3t{+RQ#?jUsx-FY_ zXVJZxbXFRD=5G4pSN-34%A?x<(G;8Zx~W`M@UBj+xS>|vL)Yx6A5WXgl>mt;R}@SH zO{nK&@8W2~iFnJ9d?{O9h0$w#fy@h!lOpEra2;03Ji-b!NM=EL7BO2 zeFNdH9D>seD4g9(Mw;V^u6j4xE;Pl7@|t17g>z5Y4kMVa13niBG*ltVEO{Sfb6}7B zK&qOEK4I|KIh>VCgC@nDdWn&*1v0~)RE5VKiZ?K1Gq}9X$#gha!ERI@uL?XtfLuxnxg7Xme?U#Z`qoGr}Dff2+d^Rb;%-G}|lT zH)u=3Lk(m836M1jJlTUGb^(03)fO7Y97NI{^}N}z*$J_oykAD4{O8~oUP$H$6)|9I+-kHm>ja6SdvynM$;iv1XvjamakM#wCv zNXYbvs6B|HMminr1k_=NI{`fNn8FIPfGJplsCc6AlF7F`q9rA#ekL0oyLMPyklG~M zO4=!Q<(SfCqn5=OnD^NxU93GKJlkN+EQ=aWJ%n#;+L&duO`?ag^-R5!zwQun8JG`2 zwVPIuQDn1(E~5<02llUr-zO}KvPnt}jN6e;9LKVGo?Iq2Fzv%{@DyZV_6@(yU4}Xj z+tQ;P>Cu>tFvuVNvX$f;sdv*diA_>wU@mi-)yNST>$dx8m5#2~()D?C))d?WXj}O! zrt&`;$}5@jKRe2wX7Ld46Lo@5c*?i9IwofJR66_7rN%hjKe@V(NM}7DFnqgUfYHQ>1~;AT+@l0K}^D2{X$r z&+!IJqE}Ybt(rzxPo-ys8fWN|W6ETl5j+_Lw8K(9!F=D7lXJ~Hc#0bho8y?R2Qyl@ zWF?ZYCamhTJrru))C!oeVk^)JySNT5{3NpmwKi1@OF^)0dzhHaub||0HyhLJQ0tYt zmIzZss8_*h%rzu%>TX!_j4s0hPV3$}lQ^`b=@&R7%sc3U8$uIB-#2zb!-UTdjQ1!w zMb(1Y3dsGB8xOi1|_;m zi_xr`m|c;UX8H#deezS_;TE2^i{#-*5ONrPVAO3#sGS<6qFq!lLWtGNwvWx7?cj`q&_ z3Mx6!XCokV{Ffgsb-=y5gs`@dl7G@qO){i|qCqV$?68Snnw#*1^ETEKcww{2ocNP4-_EtKjf01h54)7Fq;7LvH;A9L6`vu!1m4hYNHno=O1Q4 z*?78Qj0dAF z$vd>(Sk^)|cqr3IWws;9Ht|<;6T+!2o!=SDTm*0IH#FDzU1Jv|UegfoI$(j~=)wIl zq6;&-A0Cpd{G1lcn-NA7!-7ywlMVxHgyVv_89CFcXV6*GX;lH8_DIdt;GUMT91i&d zM4W?{U(DzW2=R1_^s8~brhM3|=`2Fpkrk&~A|teE?FNlBM3c-XK1A)$wk=GWo^W2@ zDqU4bPs}cO_K?72<7lJ>70F)X*Q{vlgphj3*a2N@Qw#%NmXPo`rxO`NF~f2J^D*3G zqm4hYd0Y6->Bi4a5Sq_AlSY9MXc>)_{^wUT;y`uZCe^*Ev~)#zikbXAGWO_2_mW}v ztQpJEFRGS}JwibO5$N0Po;@_&Gen(Ck&)07?3pLa;aMNXHnlkOh>}X$dDpcQeAj!? zwz4vKUi%%rbKEsu*dxX>|jisCN)7w9TPAb8;m| z_X~SV=%a@xoH55&&!LZgAiO%4KKfy5ZhW9NGygGhg(%vtu07_AZGH#lB(c@=Nbihq zM&(4`gXr->MYFg_=>7J>^X(-@~ zt)EX@4!ZWI#o3NYjmc~+)&;c1W-$|qA|?sOfXLz&g5G{HhyzIU7ZF&XGoBGS}|G-h^Dem@0{A=nIT4P@eIy& zZSn887qrC>^ZK;K5Ai#-#j^zDtI(`PfP#Y1`MJheJF7uuk~9$S#=x5%!B21_D5a_H zz>R>4ykI!ZZTz4!+-_U*R-8c$*N8`48!Paw6aT) zGDoDj($w`!Np7Tr&%xPN@=k;Y)jyTuVMaM^aBp?&pjQ&o_}B%0pTrn@etY*lU6JJ=#7vR2Fw^sRlG+c>Q^0{Sv z{t%y6Rl$W9ma4VUD;t!htnqn+id-Ci2N;Y?0$dl+Lc{g{Dv+O3Yfmq1ZVLKetmgd6 z=mKCgV)8tWMNdUKV~nu?q=swe7pQJz;qs^1Nj-ojP&414jhe?tEQO+Z+G1_=b-u?P zKREdPkT&K5ADxA%woe<|7wgqZ&9TOhiG)NOhmvM}$@5{Iv37o?W~Vd8`_V6`zvR`h z0u^bL`dt^eI24t!yeo@p90m^=DQ%)p{ZhvU&q$%3CpNU)B4hbQfPu?cD5vAR->3({F#}mH=&2;{!=WA~)~*K+ z+l<%`h64=^V*`5x3?yUi>uc&|W5?(*ABB`4bw?pn$qO;@LS+-6bs`Ik)a0%JIaG2? zEnkb6#g)1chg!CFGOuGZhkBU$17?7SC-Cxw&e*Ec(ZCN3DyXC`F7aK*<9c{}EMquy z!J4)4c+ab_is3AUdJ69tpwz$uhL48_hIFAmUC72~p+3h$bduI)gF_v?WLmi81*JzF zqn+7(`a_4RDL4-xr;I~I9F`=J#aC@eMGz6B z!3}&h!eFDbDffoMo!bHUfsbBtPk3jxms&=M7_mQ@PyRk*r0)V?9OPti%b1%W}32q>k;Gzt0F;isQD&cs8PnQbNhPYgJ{m~_jw(Q ziAD!|PJzGwt7YBov0*fCD^)GE!DJZIQ(_G3G@!zHhKIz>&#pa?QS`nt?`>tum~hvD z=+=EzCP|2VT4P!tzf*EO_VY$D{CN#t8yL9uqat)I;<0=t1&<3>^AOIgKi?yHwwQL8(>O|d%jo{{ zu4mfUH@)7lqvk87JnG^j!*CIfX4W$BO^vY=$pJy}X5-2>o!Y2fP8;}{93E>Jc0r+Z z3zR)j%s(vdfuE0EuODcpB!$gI!;XnaaPLos>#SZz2hF703T0y|rS+^EPg5H4;R&m{ zU-3Kl>BL#AZp1_)?WZ5)>6jQM@UUexb4|1=&Yw`r%n3@X+2mM$=hL2S(DZ@x*f(Ae<@zPeK=p%)AS+( zGnHjAl6tIA)cHMa8*8O9b|r|{>t z+T-B#FF~kTz{^*1GQ`x27#sNW3uet?wUDfTfS}|+A`zko`i?Gm)d%pOh)|dZ?+|v7 zFU*7Z?;acPV5SB{DI*B&Y{uL)h2r3>LyNJDL!Cx5)e#h@lDbs^$njbN8_ z)S5S>&N)xMNp;>kH!;+!88tTv8HztH-L&-svYU`eh`Lj5`s-KGuZryjhn999u+Mj< zbuZ|i+?gv&6xb{V>Q!$+ysbdcxS7zHm9!xky8-02+@KDGDoq;fZnn?wUXGIKow>D_ z!4(DjsURL6uMtEVw^VTl%*qIFG;0+N{?}B2jW4HS_J{*ort5CO1C=Aa$eJ!~*MiN` z(|ub$<>Mz{9S-q@y5xEeorkZkFS9BXqezHYD(rB03vv2H)kN2D2LzlD0ecr_zljL7 zi8Qp-I2QFgwWyvHA0AQ6iE54t@QgC>1U8;rHZS_O0Xq6CfKtx;9Xvs8q33v&?B__I z#n4?i@CD)RQnkI$(0YWh;>BlG(w4#GQ+IbKXugi9*vvaG53?P+j(eg_7cakgvQQ@w z46-lXizRT1w7TTypK)9kYw9^kd7Pu9hqAZBLNB3{E!1J6QyG3S`XU#{MZ|z`q?6FJ zyb*na3wQED+$x4QDT=x;-Jn^Wcd!>bL%tZN<8M@PJ3EdV=3Q*iel#iEC z^6*bA@8ix^^S|+@obrbdx8`JQDe$hTa576)VV0O}JaWvTRx0kd@%r(v@TybS0|y>n z0>Qyq>wrJ2A~E)GWD7cvYQt`i@af1C5iBSpBm67CKfVq4uV!o8Y5=vC?dk0`WeXM7 z7ViAak6$W0Ei^F=bO!}a{QlVRwdLZ>%*9l^VR{12cklFs*6&<{e_x;3x*CxtcFX0C z=|a=-D~a)2oxG4S9P6`m^E)>2%eLwACExn%UzYv+Ue%}EB82le8&&s1RH;*22Y1z= zc&|j)b;A{mvIwq#x|N_os?HJreqCcquRjZ;uK@^FCWJ&{LFX13wN>wP>pqUE`z)&T zx)zTAKuv*;!MH$ytElr?xbB1lY~rzSI_fFyd$z}~biqt@?%6~B+Dl%G!8=`$;=z&H z5)P-7KJYT}?#4UTydfalzld!IeieqL`of*f{v|E!A&flKHZ51GM~E{%^dgIwZY!>c zDz1p0AuXy%#<9;LdC0;~U?0{OGSp8O5eUg#oOH zV+YR;kx$8&G2bih34WR=%Ojssu98pVFB87XgS*fQ4$-sU`oROJh)tjbKmUso+IG~! zz3mlf<5t`=gv^g#gqusKosmG0p|%~y!-BJyNhKS;mFGw*O3r=P$Ca;@obKnAJTycY zR2TwO;d&o1F1bW%N%?l;H~xxb2~yiKq$wBu9T)u-eT?MmCbOU-{j)Ep^y= z2pF)oc{6g-1Zg?J`jIwKU3-MkH!QPbBEKXSEd1)12vE241eBOCPXo3twzL{dBmibe zU0_P9K~~kvbkyePD#jHoQ(uKJc68P&bagdtD3_&yvKoPbm!{sbz6KE7%Y`=Ec7y`= zXt^f6)T8AzUTYB)Xsb7n*5~U-uWG7ZW<>=w~jOq^VKRI2;v zvWd$n{umC0O7@oY~r(X=$#8_8ckWa2G|*%Q&cq$c+(rY_Z* zy(y&V_3F~;nWUWm=6Am;Cz*NhX7e#pZWAe&ICITAW0ljnr9Vd5MODt~1MkjkD4md* zc~8_N{}kcPgO7!*9MT?Wektr&bKW16uZkV2BDaw(_&ZZC>@x=c-`WG5f%bH&*+Z)0 zNv|$=Yx(gmrXjmV_kzE9S^@7yOmH4m*U(vWMyWQ_Y0uQCgJ~6N>0e^F+AZ`9!E~EQ zTTACLmQ>JJ%&t6kj(^K)L}6t{>uuES-ABbE|t)|&B`t$)=Jc_%X`yeQ18|43M&w?D!O)_ z?W91rV47WLP&YZOe?<8poU69b%jV9XUN9kdOxmbmnraITpo}ra9wl6En=5Bz*ESf` zjdljbFb$n$_G0~@ql-P}`ygSZkJnSnD_ZCxHR{4pL*vSvBTQ{Ol zgoSNNelTMaj(s#?W}OrP!i-5M-S#K;To+_*p-%`3Vhf(J9Z@2=;H$ve#(n^!raFRo z^wS*UP`}yOWM?R8K_z7V)_U5hW5Mn!BZYim*i2$|0RS_ABxOw_W$nJkhQ^z~fXzdi zurq)mfCs!0R0JR*XeE8#6&qJ93P&@^W0~VlM~rp1IzlG+GR)(e5qu zbSN)D0t|lc&oEU7=gW{0#SSGA0uWfZU_)tgg$A%)?3DEl8mC^{pII%$^li#vO3kC@ zW?MKF_k~;kLicW^vzPPw6LvQF>$lL_SLmx|XoNgHwD@VmvMAp!PBm2fz6D}^cO8P_ z>wxdmAKw}kAjjRA@d09dWaB>b7TwF2y0_8Q+v&D9>8pcMYXc3rb)<)Vax*pkn zu}0K&qbbcZuJz&rlp^#gjrFgzUF_MxX&mcJ(EJp7^v#gmvAA?x9BUUNES_UrE1-5f z-5SINM$fT}qq5MmgPnTaQJw?nY|LM5<>Sftr&O8Bqw!!!sWz0y;6ayS(3QvHVJKz& zP`MNjzLX8Va-ulnP5Gm@oVZl&HB z8?)I~uEv9j*q5A&L*JRJ`X=1&gRm4c0_vz3oSiixQ=mEVO21M?R{`Q3OZX0{fWXW~J}n04hu zW07GjOnLV39Gs`ltGo6R&oD}_8&%qU59|tgoZ?sx6U!?C%*t!iowIDQys8bZ&6|n3 z{=`S?m}iizOfAR%G4F|Iv)c?Ch`e#gFlvQzvFpjyQ55gFoK53LF|qurH(cAc)@5GH zWJrOe!B++OgZ}JT&e|PA;{=%#T$!2I@~``gW4X$dXF@K5h{Ie~AqF5bkElt9R$J*T z8=VW63P?9t{F`ED$zB(jEah8cri zGahjd?UVCdQsN&2R|dE@hn~~qYJ(JJqvoJdMPTnmJd5fbWcdxtutD3B%^YnG<0=uEd>A1 zP7vAoDNl=1vaw(T_aR6OcGA?WtX(t}KZ8$=F$v!76ZGpP4Rz104~P-ASlf2fRBhnp zLTswO`z`_)B}~=LkL_m03850ns^{9$vPLbBUiU@ofhg-td63G*@nZXE7Jz$*yQK~5 z-nX~9*G@xTUY3?RwAYW=gKM_ta`<_rb#0-`GGP49s$d(#deD(a-!FcYbM(0ggVkR( zC$s1YSJfOfQqG;VpHJC2^PoH@eOeQY1x-4hY&vYB9>V3bYc{E?r!Dm9+zWbNgtYh# z&K_vECqRi?Yn;eN3#;0u-uh>mb2j3)Q;B3maGRMu$y@voCxpwP6h0j_)k)^9WqU&_E!U@Tqvlwg{LYxXgSeGNuk4NrI)yB~gJm<5nVB>9^*$$;ibb|y z20R4@#GMg`!5P-`&Kfzrth40$Q}MG|FJF$7XjB-;Z+(dDI*t_WND4Hdd&!pMVD23$ z4XzSuWfN~#3D+3?Y{rzyBN<0>jQ})~k~s|Gh<fQtXaz3gmb z^ieV@Z1mMKchu~}#8oZe0O{OHTVtTIjuE%*Z|K|<-fXf;Q-xHriT5sMO+(#`;H-I0XW&U? zyCY=JMclC#WBzR|igC1237S}*OiXp&Q;`_5lj2Yj7w-WwFd-NwH8)GCTrJxmaQuy< zABc+@Z^6}oo2$y&OWOsd&E!Ps6E8U0GqB+zAHI7knAM(8?%<*5*47QJhlBGAMPV+R z)2W&{?dThw0C*zV?@_(Bm1dYMjCP)m#4=|c-r$W&ABhKZnQwiVXkk$4hSdEm4`e3~ z(ti129_W{Q0wu`K1O4cZGi=aR?2VN8>^FXv{$TOcM%M#JweWcxZxX#rCEtOgJ=e;#iiJBhNs}noSDpY(|?f(h&HT&?QJZ!xA0%1 z6jQP@8;DG~j?fSN*_6VryBJeTTz(Ai+3en9ocHT}Jz=NMUkx~8(%{nrInjn;Z$sNI zx^nMpPKouG1g9ibJVUZ)D19+xTm6$O=C(&o5x^W_%^rbaD&l*F@Zn%bK#g0|BB&(q zlc!w}%jcZG=bwg!yvl__ie~mUn)X)P_U`iRt@SMA+ZGB;3qzQNp+hqvOd#!Ly-!=; zrP~~|_HqJHHqS91)<3h~quZw$7dJgxQ!syVF3HLEp9V(6ujDu7!kinO{x%GqK zB(Hy4M$wrMygs;tYZOv3U>d;)rv_&Viv6(u*lCeR{J3ws+vVBzgC8F^rDn4R{!T@E7iTORQAa zc}*Pa!C+Mn1*+;jKP~zZbqsV*wXhXj$nX7v&~c7rN~)1;_o^_`V*Y|-^!#)S-@E4O&cvbwhYw00luJ)Y@#Q|x(zF;1a@fpWrc%;PK{nkh@uZvb(BVed!>! zzQ?N$s(YG&IKP88;bz!jK2^BnB)&T}mTKW9xq#ZXq<=)N zrpIhMKqCN~mNgu*Ph%ZcBR&JCo*e~)#)x@RwGqDj$(UDaHWa~i{3q_vpJi` zue97+nG;o7Di{QJAxD|5BN)~tuZA^sUY;P2O$p5JYEJz=+Ac~J>y9PL%0dj{7aii~ zWqm@~J3==Z<-XA}N+>%m$a2wUNaX8Y7aGkCv(fXX#jAMId4h8Z<8KKQo8kWil2Ytc zT=4W&hA}&-hmi+#(&)NYLEg5gfp@r;c4a%y7{coHCk+-Ys48B}akDZkTgGvK=X~3f zaRQ>%E^R=Pd{}t)3CR?(^F6yZAaI3r8T`4&CBe2HUdGLhz9no@JtjtbiOpzF@1j{y zpdWmlN8L5JVSEi2-v$TA<0FEyRkN;1O{p8&4$*LxQ&+zl?b=d}?gKPI@~+hZD=6no zGM^y z&SL`VRS!R6)jqP;?4ezwx?iv!!Nt%nZVGjXUnKKlOMGaVu)34b=NHt}w?DphXJ`^2 z-53Ib-Z+01X+mNSeN5aWva4+c&ow4!3L`bkDa~dP)p#^PpxFk_U41T;W?HKR6NNoS zZe31PRgSXyBRW@T49m3O^umE*a zNm{UUU;(`I7GVLK)u%*l$LLPJA$hH>yA&y~%2qpbYA1uEOiV3EeY5w`^Mu_gL<~7k zSh?f8>>mG8VQJC$+OJACjQ=5(w=d|srl3&OM~=!SV+Gt>A55SOEkikOJDPiVWu8N4(RtM2Na+kLe$JXr!) zQy8IHF41fbGgw5M5_lEcCS~=~_ochN^qGIqwis^ji?V^{XL_2;k2Nnzlu&|k{LD!f zJI@&#Kp^8;ntf!cd|F=KwTcbr*>+*ex$Y>HsAtI=r)=dNmxzFK*%JZ~HXdHYn5Pt> zi-lSLq;aLp`jn;wAcTX}Zpnc>;EgM@KcoAEms`&8Sr*4#?>_l^VbkI1)2n{X6*f%Ns~2&6EzF&!G=ybHzkbIET5uzVG^i~gnKm2*&2kz z`(ppLIP`)dz8rtu0ni!&n^@AV00wR+QHgi<6}ZrID9A4KCuvzZ)W|SchoSMBlkO&S zBG-eM&R@{fIPb&p-iJrKS_Lk+Brc3LJsxg7MdN?d%k`&eTQpZ!pe!y>X%a-;mvr-^ zzX`z>h~G2+MPF>t6@+;UM7n}h*}@3jd|}&{H2$~edJEDdhcpS|?wh*#an=DECA@ez zLpQbS3ZjY&qD$mr-F%VNM>oy4enp@8gw`!6@GVdAY6$11FWjR^8M2)FJaNtJf6+q= z;^rS2DiL*i!C^ zGDrFu>xJ9d+-u|D);|z4m38uGg6Ej>*uWXC=gj^-PU}s; zO=)Q48VJV4cOx(8nIU-&6;cGkVe_0uW5C`SsgC5^=D?H;b{N>`RX#FxRTpXNCAqsl zuI+++OK;CVEU+Ny3y&ff2o@>6^|E~Uwzq|m=Tsc|rZFUFXq`N#Xc*gp{REt@ zNn36u; zCTDPP^^YI$Dra(GyaHZ1V}W*U8Fc-(pZT7~J-O|oJL;V}_@x>Wb39`1dHSKQ>KoRJ z_5HmzF~9xH?!?K1AGlo2E=zNC%2BcNOlNgp?}hs7R-?OWfx75*)z;KRu;(W)`B)tI zQguLm-P-PUo@sBx#dVfYa@w*dT7K|EBs4zHf0#*)9{j~s=YIq;lVj@_G=p;W9a9dR zQ&nA2mtL9bo58JJ?Yia~ybE1k%|>;C^K1_{=7*o-P25

    ^UEr43WpY!@B-hv^{> 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 literal 0 HcmV?d00001 diff --git a/package/kernel/cryptodev-linux/Makefile b/package/kernel/cryptodev-linux/Makefile index 0b794a3cd..d04aaeace 100644 --- a/package/kernel/cryptodev-linux/Makefile +++ b/package/kernel/cryptodev-linux/Makefile @@ -11,7 +11,7 @@ include $(INCLUDE_DIR)/kernel.mk PKG_NAME:=cryptodev-linux PKG_VERSION:=1.13 -PKG_RELEASE:=1 +PKG_RELEASE:=2 PKG_SOURCE_URL:=https://codeload.github.com/$(PKG_NAME)/$(PKG_NAME)/tar.gz/$(PKG_NAME)-$(PKG_VERSION)? PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz diff --git a/package/kernel/cryptodev-linux/patches/0005-fix-build-for-linux-5.10.220+.patch b/package/kernel/cryptodev-linux/patches/0005-fix-build-for-linux-5.10.220+.patch new file mode 100644 index 000000000..3d2565317 --- /dev/null +++ b/package/kernel/cryptodev-linux/patches/0005-fix-build-for-linux-5.10.220+.patch @@ -0,0 +1,11 @@ +--- a/ioctl.c ++++ b/ioctl.c +@@ -933,7 +933,7 @@ + if (unlikely(ret)) { + #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 17, 0)) + sys_close(fd); +-#elif (LINUX_VERSION_CODE < KERNEL_VERSION(5, 11, 0)) ++#elif (LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 220)) + ksys_close(fd); + #else + close_fd(fd); diff --git a/package/kernel/mac80211/Makefile b/package/kernel/mac80211/Makefile index 7a808afee..e2d4aeff5 100644 --- a/package/kernel/mac80211/Makefile +++ b/package/kernel/mac80211/Makefile @@ -1,5 +1,5 @@ # -# Copyright (C) 2007-2015 OpenWrt.org +# Copyright (C) 2007-2023 OpenWrt.org # # This is free software, licensed under the GNU General Public License v2. # See /LICENSE for more information. @@ -10,16 +10,14 @@ include $(INCLUDE_DIR)/kernel.mk PKG_NAME:=mac80211 -PKG_VERSION:=6.9.9 -PKG_RELEASE:=1 -PKG_LICENSE:=GPL-2.0-only -PKG_LICENSE_FILES:=COPYING - +PKG_VERSION:=6.1.24 +PKG_RELEASE:=3 +# PKG_SOURCE_URL:=@KERNEL/linux/kernel/projects/backports/stable/v5.15.58/ PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources/ -PKG_HASH:=3417da091a57c7b1c145d44c1fae9f1e0bac6d0c8ad61b37e57b0a802eeb2837 +PKG_HASH:=5d39aca7e34c33cb9b3e366117b2e86841b7bdd37933679d6b1e61be6b150648 PKG_SOURCE:=backports-$(PKG_VERSION).tar.xz -PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/$(if $(BUILD_VARIANT),$(PKG_NAME)-$(BUILD_VARIANT)/)backports-$(PKG_VERSION) +PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/backports-$(PKG_VERSION) PKG_BUILD_PARALLEL:=1 PKG_MAINTAINER:=Felix Fietkau @@ -50,13 +48,7 @@ define KernelPackage/mac80211/Default MAINTAINER:=Felix Fietkau endef -# config_pacakge: -# 1 = OpenWrt KernelPackage name -# 2 = Optional list of variants for which the module may be selected: -# If empty, the module is only selected with the first variant -# Use $(ALL_VARIANTS) to allow module selection in all variants -config_package=$(if $(and $(CONFIG_PACKAGE_kmod-$(1)),$(call mac80211_variant_check,$(2))),m) -mac80211_variant_check=$(if $(ALL_VARIANTS),$(filter $(BUILD_VARIANT),$(if $(1),$(1),$(firstword $(ALL_VARIANTS)))),y) +config_package=$(if $(CONFIG_PACKAGE_kmod-$(1)),m) config-y:= \ WLAN \ @@ -81,10 +73,10 @@ config-y:= \ WLAN_VENDOR_TI \ WLAN_VENDOR_ZYDAS \ -config-$(call config_package,cfg80211,$(ALL_VARIANTS)) += CFG80211 +config-$(call config_package,cfg80211) += CFG80211 config-$(CONFIG_PACKAGE_CFG80211_TESTMODE) += NL80211_TESTMODE -config-$(call config_package,mac80211,$(ALL_VARIANTS)) += MAC80211 +config-$(call config_package,mac80211) += MAC80211 config-$(CONFIG_PACKAGE_MAC80211_MESH) += MAC80211_MESH include ath.mk @@ -172,7 +164,7 @@ define KernelPackage/mac80211-hwsim $(call KernelPackage/mac80211/Default) TITLE:=mac80211 HW simulation device DEPENDS+= +kmod-mac80211 +@DRIVER_11AX_SUPPORT +@DRIVER_11AC_SUPPORT - FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/virtual/mac80211_hwsim.ko + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/mac80211_hwsim.ko AUTOLOAD:=$(call AutoProbe,mac80211_hwsim) endef @@ -188,7 +180,7 @@ endef define KernelPackage/rsi91x $(call KernelPackage/mac80211/Default) TITLE:=Redpine Signals Inc 91x WLAN driver support - DEPENDS+= +kmod-mac80211 +rs9113-firmware + DEPENDS+= +kmod-mac80211 +rs9113-firmware +@DRIVER_11N_SUPPORT FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rsi/rsi_91x.ko endef @@ -212,7 +204,7 @@ endef define KernelPackage/wlcore $(call KernelPackage/mac80211/Default) TITLE:=TI common driver part - DEPENDS+= +kmod-mmc +kmod-mac80211 + DEPENDS+= +kmod-mmc +kmod-mac80211 +@DRIVER_11N_SUPPORT FILES:= \ $(PKG_BUILD_DIR)/drivers/net/wireless/ti/wlcore/wlcore.ko \ $(PKG_BUILD_DIR)/drivers/net/wireless/ti/wlcore/wlcore_sdio.ko @@ -333,6 +325,7 @@ endif ifeq ($(strip $(CONFIG_EXTERNAL_KERNEL_TREE)),"") ifeq ($(strip $(CONFIG_KERNEL_GIT_CLONE_URI)),"") define Build/Configure + cmp $(PKG_BUILD_DIR)/include/linux/ath9k_platform.h $(LINUX_DIR)/include/linux/ath9k_platform.h cmp $(PKG_BUILD_DIR)/include/linux/ath5k_platform.h $(LINUX_DIR)/include/linux/ath5k_platform.h cmp $(PKG_BUILD_DIR)/include/linux/rt2x00_platform.h $(LINUX_DIR)/include/linux/rt2x00_platform.h endef @@ -391,6 +384,14 @@ define Build/InstallDev endef +define KernelPackage/cfg80211/install + $(INSTALL_DIR) $(1)/lib/wifi $(1)/lib/netifd/wireless + $(INSTALL_DATA) ./files/lib/wifi/mac80211.sh $(1)/lib/wifi + $(INSTALL_BIN) ./files/lib/netifd/wireless/mac80211.sh $(1)/lib/netifd/wireless + $(INSTALL_DIR) $(1)/etc/hotplug.d/ieee80211 + $(INSTALL_DATA) ./files/mac80211.hotplug $(1)/etc/hotplug.d/ieee80211/10-wifi-detect +endef + $(eval $(foreach drv,$(PKG_DRIVERS),$(call KernelPackage,$(drv)))) $(eval $(call KernelPackage,cfg80211)) $(eval $(call KernelPackage,mac80211)) diff --git a/package/kernel/mac80211/ath.mk b/package/kernel/mac80211/ath.mk index 1d4b37d25..6f5d17cef 100644 --- a/package/kernel/mac80211/ath.mk +++ b/package/kernel/mac80211/ath.mk @@ -1,6 +1,7 @@ PKG_DRIVERS += \ - ath ath5k ath6kl ath6kl-sdio ath6kl-usb ath9k ath9k-common ath9k-htc ath10k ath10k-smallbuffers \ - ath11k ath11k-ahb ath11k-pci carl9170 owl-loader ar5523 wil6210 + ath ath5k ath6kl ath6kl-sdio ath6kl-usb ath9k ath9k-common ath9k-htc \ + ath10k ath10k-pci ath10k-sdio ath10k-smallbuffers ath11k ath11k-ahb \ + ath11k-pci ar5523 carl9170 owl-loader wil6210 PKG_CONFIG_DEPENDS += \ CONFIG_PACKAGE_ATH_DEBUG \ @@ -37,7 +38,7 @@ ifdef CONFIG_PACKAGE_MAC80211_TRACING WIL6210_TRACING endif -config-$(call config_package,ath,regular smallbuffers) += ATH_CARDS ATH_COMMON +config-$(call config_package,ath) += ATH_CARDS ATH_COMMON config-$(CONFIG_PACKAGE_ATH_DEBUG) += ATH_DEBUG ATH10K_DEBUG ATH11K_DEBUG ATH9K_STATION_STATISTICS config-$(CONFIG_PACKAGE_ATH_DFS) += ATH9K_DFS_CERTIFIED ATH10K_DFS_CERTIFIED config-$(CONFIG_PACKAGE_ATH_SPECTRAL) += ATH9K_COMMON_SPECTRAL ATH10K_SPECTRAL ATH11K_SPECTRAL @@ -58,13 +59,21 @@ config-$(CONFIG_ATH10K_THERMAL) += ATH10K_THERMAL config-$(CONFIG_ATH11K_THERMAL) += ATH11K_THERMAL config-$(call config_package,ath9k-htc) += ATH9K_HTC -config-$(call config_package,ath10k,regular) += ATH10K ATH10K_PCI -config-$(call config_package,ath10k-smallbuffers,smallbuffers) += ATH10K ATH10K_PCI ATH10K_SMALLBUFFERS +config-$(call config_package,ath10k) += ATH10K +config-$(call config_package,ath10k-pci) += ATH10K_PCI +config-$(call config_package,ath10k-sdio) += ATH10K_SDIO +config-$(call config_package,ath10k-smallbuffers) += ATH10K ATH10K_PCI ATH10K_SMALLBUFFERS + config-$(call config_package,ath11k) += ATH11K config-$(call config_package,ath11k-ahb) += ATH11K_AHB config-$(call config_package,ath11k-pci) += ATH11K_PCI -config-$(call config_package,ath5k) += ATH5K ATH5K_PCI +config-$(call config_package,ath5k) += ATH5K +ifdef CONFIG_TARGET_ath25 + config-y += ATH5K_AHB +else + config-y += ATH5K_PCI +endif config-$(call config_package,ath6kl) += ATH6KL config-$(call config_package,ath6kl-sdio) += ATH6KL_SDIO @@ -128,7 +137,7 @@ endef define KernelPackage/ath $(call KernelPackage/mac80211/Default) TITLE:=Atheros common driver part - DEPENDS+= @PCI_SUPPORT||USB_SUPPORT||TARGET_ath79 +kmod-mac80211 + DEPENDS+= @PCI_SUPPORT||USB_SUPPORT||TARGET_ath79||TARGET_ath25 +kmod-mac80211 FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath.ko MENU:=1 endef @@ -141,7 +150,7 @@ define KernelPackage/ath5k $(call KernelPackage/mac80211/Default) TITLE:=Atheros 5xxx wireless cards support URL:=https://wireless.wiki.kernel.org/en/users/drivers/ath5k - DEPENDS+= @PCI_SUPPORT +kmod-ath + DEPENDS+= @(PCI_SUPPORT||TARGET_ath25) +kmod-ath FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath5k/ath5k.ko AUTOLOAD:=$(call AutoProbe,ath5k) endef @@ -156,7 +165,7 @@ define KernelPackage/ath6kl TITLE:=Atheros FullMAC wireless devices (common code for ath6kl_sdio and ath6kl_usb) URL:=https://wireless.wiki.kernel.org/en/users/drivers/ath6kl HIDDEN:=1 - DEPENDS+= +kmod-ath + DEPENDS+= +kmod-ath +@DRIVER_11N_SUPPORT FILES:= $(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath6kl/ath6kl_core.ko endef @@ -257,20 +266,17 @@ define KernelPackage/ath10k $(call KernelPackage/mac80211/Default) TITLE:=Atheros 802.11ac wireless cards support URL:=https://wireless.wiki.kernel.org/en/users/drivers/ath10k - DEPENDS+= @PCI_SUPPORT +kmod-ath +@DRIVER_11AC_SUPPORT \ + DEPENDS+= +kmod-ath +@DRIVER_11N_SUPPORT +@DRIVER_11AC_SUPPORT \ +ATH10K_THERMAL:kmod-hwmon-core +ATH10K_THERMAL:kmod-thermal FILES:= \ - $(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath10k/ath10k_core.ko \ - $(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath10k/ath10k_pci.ko - AUTOLOAD:=$(call AutoProbe,ath10k_core ath10k_pci) + $(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath10k/ath10k_core.ko + AUTOLOAD:=$(call AutoProbe,ath10k_core) MODPARAMS.ath10k_core:=frame_mode=2 - VARIANT:=regular endef define KernelPackage/ath10k/description This module adds support for wireless adapters based on -Atheros IEEE 802.11ac family of chipsets. For now only -PCI is supported. +Atheros IEEE 802.11ac family of chipsets. endef define KernelPackage/ath10k/config @@ -282,12 +288,42 @@ define KernelPackage/ath10k/config config ATH10K_THERMAL bool "Enable thermal sensors and throttling support" + default y depends on PACKAGE_kmod-ath10k || PACKAGE_kmod-ath10k-smallbuffers endef +define KernelPackage/ath10k-pci + $(call KernelPackage/mac80211/Default) + TITLE:=Atheros 802.11ac PCIE wireless cards support + URL:=https://wireless.wiki.kernel.org/en/users/drivers/ath10k + DEPENDS+= @PCI_SUPPORT kmod-ath10k + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath10k/ath10k_pci.ko + AUTOLOAD:=$(call AutoProbe,ath10k_pci) + VARIANT:=regular +endef + +define KernelPackage/ath10k-pci/description +This module adds support for wireless adapters based on +Atheros IEEE 802.11ac family of chipsets with PCIE bus. +endef + +define KernelPackage/ath10k-sdio + $(call KernelPackage/mac80211/Default) + TITLE:=Atheros 802.11ac SDIO wireless cards support + URL:=https://wireless.wiki.kernel.org/en/users/drivers/ath10k + DEPENDS+= kmod-ath10k +kmod-mmc + FILES:= $(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath10k/ath10k_sdio.ko + AUTOLOAD:=$(call AutoProbe,ath10k_sdio) +endef + +define KernelPackage/ath10k-sdio/description +This module adds support for wireless adapters based on +Atheros IEEE 802.11ac family of chipsets with SDIO bus. +endef + define KernelPackage/ath10k-smallbuffers - $(call KernelPackage/ath10k) + $(call KernelPackage/ath10k-pci) TITLE+= (small buffers for low-RAM devices) VARIANT:=smallbuffers endef @@ -296,10 +332,11 @@ define KernelPackage/ath11k $(call KernelPackage/mac80211/Default) TITLE:=Qualcomm 802.11ax wireless chipset support (common code) URL:=https://wireless.wiki.kernel.org/en/users/drivers/ath11k - DEPENDS+= +kmod-ath +@DRIVER_11AC_SUPPORT +@DRIVER_11AX_SUPPORT @!LINUX_5_15 \ + DEPENDS+= +kmod-ath +@DRIVER_11AC_SUPPORT +@DRIVER_11AX_SUPPORT \ +kmod-crypto-michael-mic +ATH11K_THERMAL:kmod-hwmon-core +ATH11K_THERMAL:kmod-thermal FILES:=$(PKG_BUILD_DIR)/drivers/soc/qcom/qmi_helpers.ko \ $(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath11k/ath11k.ko + MODPARAMS.ath11k:=frame_mode=2 endef define KernelPackage/ath11k/description diff --git a/package/kernel/mac80211/broadcom.mk b/package/kernel/mac80211/broadcom.mk index a6f42cd19..a36f92477 100644 --- a/package/kernel/mac80211/broadcom.mk +++ b/package/kernel/mac80211/broadcom.mk @@ -245,11 +245,11 @@ config PACKAGE_B43_USE_BCMA This allows choosing buses that b43 should support. config PACKAGE_B43_BUSES_BCMA_AND_SSB - depends on !TARGET_bcm47xx_legacy && !TARGET_bcm47xx_mips74k && !TARGET_bcm53xx && !TARGET_bmips + depends on !TARGET_bcm47xx_legacy && !TARGET_bcm47xx_mips74k && !TARGET_bcm53xx bool "BCMA and SSB" config PACKAGE_B43_BUSES_BCMA - depends on !TARGET_bcm47xx_legacy && !TARGET_bmips_bcm6358 && !TARGET_bmips_bcm6368 + depends on !TARGET_bcm47xx_legacy bool "BCMA only" config PACKAGE_B43_BUSES_SSB @@ -416,10 +416,7 @@ define KernelPackage/brcmfmac DEPENDS+= @USB_SUPPORT +kmod-cfg80211 +@DRIVER_11AC_SUPPORT \ +kmod-brcmutil +BRCMFMAC_SDIO:kmod-mmc @!TARGET_uml \ +BRCMFMAC_USB:kmod-usb-core +BRCMFMAC_USB:brcmfmac-firmware-usb - FILES:= \ - $(PKG_BUILD_DIR)/drivers/net/wireless/broadcom/brcm80211/brcmfmac/brcmfmac.ko \ - $(foreach type,bca cyw wcc, \ - $(PKG_BUILD_DIR)/drivers/net/wireless/broadcom/brcm80211/brcmfmac/$(type)/brcmfmac-$(type).ko) + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/broadcom/brcm80211/brcmfmac/brcmfmac.ko AUTOLOAD:=$(call AutoProbe,brcmfmac) endef @@ -433,10 +430,9 @@ define KernelPackage/brcmfmac/config config BRCMFMAC_SDIO bool "Enable SDIO bus interface support" default y if TARGET_bcm27xx - default y if TARGET_imx_cortexa7 - default y if TARGET_starfive - default y if TARGET_rockchip default y if TARGET_sunxi + default y if TARGET_rockchip + default y if TARGET_amlogic default n help Enable support for cards attached to an SDIO bus. diff --git a/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh b/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh new file mode 100644 index 000000000..469d4264a --- /dev/null +++ b/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh @@ -0,0 +1,1244 @@ +#!/bin/sh +. /lib/netifd/netifd-wireless.sh +. /lib/netifd/hostapd.sh +. /lib/functions/system.sh + +init_wireless_driver "$@" + +MP_CONFIG_INT="mesh_retry_timeout mesh_confirm_timeout mesh_holding_timeout mesh_max_peer_links + mesh_max_retries mesh_ttl mesh_element_ttl mesh_hwmp_max_preq_retries + mesh_path_refresh_time mesh_min_discovery_timeout mesh_hwmp_active_path_timeout + mesh_hwmp_preq_min_interval mesh_hwmp_net_diameter_traversal_time mesh_hwmp_rootmode + mesh_hwmp_rann_interval mesh_gate_announcements mesh_sync_offset_max_neighor + mesh_rssi_threshold mesh_hwmp_active_path_to_root_timeout mesh_hwmp_root_interval + mesh_hwmp_confirmation_interval mesh_awake_window mesh_plink_timeout" +MP_CONFIG_BOOL="mesh_auto_open_plinks mesh_fwding" +MP_CONFIG_STRING="mesh_power_mode" + +NEWAPLIST= +OLDAPLIST= +NEWSPLIST= +OLDSPLIST= +NEWUMLIST= +OLDUMLIST= + +drv_mac80211_init_device_config() { + hostapd_common_add_device_config + + config_add_string path phy 'macaddr:macaddr' + config_add_string tx_burst + config_add_string distance + config_add_int beacon_int chanbw frag rts + config_add_int rxantenna txantenna antenna_gain txpower min_tx_power + config_add_boolean noscan ht_coex acs_exclude_dfs background_radar + config_add_array ht_capab + config_add_array channels + config_add_array scan_list + config_add_boolean \ + rxldpc \ + short_gi_80 \ + short_gi_160 \ + tx_stbc_2by1 \ + su_beamformer \ + su_beamformee \ + mu_beamformer \ + mu_beamformee \ + he_su_beamformer \ + he_su_beamformee \ + he_mu_beamformer \ + vht_txop_ps \ + htc_vht \ + rx_antenna_pattern \ + tx_antenna_pattern \ + he_spr_sr_control \ + he_spr_psr_enabled \ + he_bss_color_enabled \ + he_twt_required + config_add_int \ + beamformer_antennas \ + beamformee_antennas \ + vht_max_a_mpdu_len_exp \ + vht_max_mpdu \ + vht_link_adapt \ + vht160 \ + rx_stbc \ + tx_stbc \ + he_bss_color \ + he_spr_non_srg_obss_pd_max_offset + config_add_boolean \ + ldpc \ + greenfield \ + short_gi_20 \ + short_gi_40 \ + max_amsdu \ + dsss_cck_40 +} + +drv_mac80211_init_iface_config() { + hostapd_common_add_bss_config + + config_add_string 'macaddr:macaddr' ifname + + config_add_boolean wds powersave enable + config_add_string wds_bridge + config_add_int maxassoc + config_add_int max_listen_int + config_add_int dtim_period + config_add_int start_disabled + + # mesh + config_add_string mesh_id + config_add_int $MP_CONFIG_INT + config_add_boolean $MP_CONFIG_BOOL + config_add_string $MP_CONFIG_STRING +} + +mac80211_add_capabilities() { + local __var="$1"; shift + local __mask="$1"; shift + local __out= oifs + + oifs="$IFS" + IFS=: + for capab in "$@"; do + set -- $capab + + [ "$(($4))" -gt 0 ] || continue + [ "$(($__mask & $2))" -eq "$((${3:-$2}))" ] || continue + __out="$__out[$1]" + done + IFS="$oifs" + + export -n -- "$__var=$__out" +} + +mac80211_add_he_capabilities() { + local __out= oifs + + oifs="$IFS" + IFS=: + for capab in "$@"; do + set -- $capab + [ "$(($4))" -gt 0 ] || continue + [ "$(((0x$2) & $3))" -gt 0 ] || { + eval "$1=0" + continue + } + append base_cfg "$1=1" "$N" + done + IFS="$oifs" +} + +mac80211_hostapd_setup_base() { + local phy="$1" + + json_select config + + [ "$auto_channel" -gt 0 ] && channel=acs_survey + + [ "$auto_channel" -gt 0 ] && json_get_vars acs_exclude_dfs + [ -n "$acs_exclude_dfs" ] && [ "$acs_exclude_dfs" -gt 0 ] && + append base_cfg "acs_exclude_dfs=1" "$N" + + json_get_vars noscan ht_coex vendor_vht min_tx_power:0 + json_get_values ht_capab_list ht_capab tx_burst + json_get_values channel_list channels + + [ "$auto_channel" = 0 ] && [ -z "$channel_list" ] && \ + channel_list="$channel" + + [ "$min_tx_power" -gt 0 ] && append base_cfg "min_tx_power=$min_tx_power" + + set_default noscan 0 + + [ "$noscan" -gt 0 ] && hostapd_noscan=1 + [ "$tx_burst" = 0 ] && tx_burst= + + chan_ofs=0 + [ "$band" = "6g" ] && chan_ofs=1 + + ieee80211n=1 + ht_capab= + case "$htmode" in + VHT20|HT20|HE20) ;; + HT40*|VHT40|VHT80|VHT160|HE40|HE80|HE160) + case "$hwmode" in + a) + case "$(( (($channel / 4) + $chan_ofs) % 2 ))" in + 1) ht_capab="[HT40+]";; + 0) ht_capab="[HT40-]";; + esac + ;; + *) + case "$htmode" in + HT40+) ht_capab="[HT40+]";; + HT40-) ht_capab="[HT40-]";; + *) + if [ "$channel" -lt 7 ]; then + ht_capab="[HT40+]" + else + ht_capab="[HT40-]" + fi + ;; + esac + ;; + esac + [ "$auto_channel" -gt 0 ] && ht_capab="[HT40+]" + ;; + *) ieee80211n= ;; + esac + + [ -n "$ieee80211n" ] && { + append base_cfg "ieee80211n=1" "$N" + + set_default ht_coex 0 + append base_cfg "ht_coex=$ht_coex" "$N" + + json_get_vars \ + ldpc:1 \ + greenfield:0 \ + short_gi_20:1 \ + short_gi_40:1 \ + tx_stbc:1 \ + rx_stbc:3 \ + max_amsdu:1 \ + dsss_cck_40:1 + + ht_cap_mask=0 + for cap in $(iw phy "$phy" info | grep 'Capabilities:' | cut -d: -f2); do + ht_cap_mask="$(($ht_cap_mask | $cap))" + done + + cap_rx_stbc=$((($ht_cap_mask >> 8) & 3)) + [ "$rx_stbc" -lt "$cap_rx_stbc" ] && cap_rx_stbc="$rx_stbc" + ht_cap_mask="$(( ($ht_cap_mask & ~(0x300)) | ($cap_rx_stbc << 8) ))" + + mac80211_add_capabilities ht_capab_flags $ht_cap_mask \ + LDPC:0x1::$ldpc \ + GF:0x10::$greenfield \ + SHORT-GI-20:0x20::$short_gi_20 \ + SHORT-GI-40:0x40::$short_gi_40 \ + TX-STBC:0x80::$tx_stbc \ + RX-STBC1:0x300:0x100:1 \ + RX-STBC12:0x300:0x200:1 \ + RX-STBC123:0x300:0x300:1 \ + MAX-AMSDU-7935:0x800::$max_amsdu \ + DSSS_CCK-40:0x1000::$dsss_cck_40 + + ht_capab="$ht_capab$ht_capab_flags" + [ -n "$ht_capab" ] && append base_cfg "ht_capab=$ht_capab" "$N" + } + + # 802.11ac + enable_ac=0 + vht_oper_chwidth=0 + vht_center_seg0= + + idx="$channel" + case "$htmode" in + VHT20|HE20) enable_ac=1;; + VHT40|HE40) + case "$(( (($channel / 4) + $chan_ofs) % 2 ))" in + 1) idx=$(($channel + 2));; + 0) idx=$(($channel - 2));; + esac + enable_ac=1 + vht_center_seg0=$idx + ;; + VHT80|HE80) + case "$(( (($channel / 4) + $chan_ofs) % 4 ))" in + 1) idx=$(($channel + 6));; + 2) idx=$(($channel + 2));; + 3) idx=$(($channel - 2));; + 0) idx=$(($channel - 6));; + esac + enable_ac=1 + vht_oper_chwidth=1 + vht_center_seg0=$idx + ;; + VHT160|HE160) + if [ "$band" = "6g" ]; then + case "$channel" in + 1|5|9|13|17|21|25|29) idx=15;; + 33|37|41|45|49|53|57|61) idx=47;; + 65|69|73|77|81|85|89|93) idx=79;; + 97|101|105|109|113|117|121|125) idx=111;; + 129|133|137|141|145|149|153|157) idx=143;; + 161|165|169|173|177|181|185|189) idx=175;; + 193|197|201|205|209|213|217|221) idx=207;; + esac + else + case "$channel" in + 36|40|44|48|52|56|60|64) idx=50;; + 100|104|108|112|116|120|124|128) idx=114;; + esac + fi + enable_ac=1 + vht_oper_chwidth=2 + vht_center_seg0=$idx + ;; + esac + [ "$band" = "5g" ] && { + json_get_vars background_radar:0 + + [ "$background_radar" -eq 1 ] && append base_cfg "enable_background_radar=1" "$N" + } + [ "$band" = "6g" ] && { + op_class= + case "$htmode" in + HE20) op_class=131;; + HE*) op_class=$((132 + $vht_oper_chwidth)) + esac + [ -n "$op_class" ] && append base_cfg "op_class=$op_class" "$N" + } + [ "$hwmode" = "a" ] || enable_ac=0 + + if [ "$enable_ac" != "0" -o "$vendor_vht" = "1" ]; then + json_get_vars \ + rxldpc:1 \ + short_gi_80:1 \ + short_gi_160:1 \ + tx_stbc_2by1:1 \ + su_beamformer:1 \ + su_beamformee:1 \ + mu_beamformer:1 \ + mu_beamformee:1 \ + vht_txop_ps:1 \ + htc_vht:1 \ + beamformee_antennas:4 \ + beamformer_antennas:4 \ + rx_antenna_pattern:1 \ + tx_antenna_pattern:1 \ + vht_max_a_mpdu_len_exp:7 \ + vht_max_mpdu:11454 \ + rx_stbc:4 \ + vht_link_adapt:3 \ + vht160:2 + + set_default tx_burst 2.0 + append base_cfg "ieee80211ac=1" "$N" + vht_cap=0 + for cap in $(iw phy "$phy" info | awk -F "[()]" '/VHT Capabilities/ { print $2 }'); do + vht_cap="$(($vht_cap | $cap))" + done + + append base_cfg "vht_oper_chwidth=$vht_oper_chwidth" "$N" + append base_cfg "vht_oper_centr_freq_seg0_idx=$vht_center_seg0" "$N" + + cap_rx_stbc=$((($vht_cap >> 8) & 7)) + [ "$rx_stbc" -lt "$cap_rx_stbc" ] && cap_rx_stbc="$rx_stbc" + vht_cap="$(( ($vht_cap & ~(0x700)) | ($cap_rx_stbc << 8) ))" + + mac80211_add_capabilities vht_capab $vht_cap \ + RXLDPC:0x10::$rxldpc \ + SHORT-GI-80:0x20::$short_gi_80 \ + SHORT-GI-160:0x40::$short_gi_160 \ + TX-STBC-2BY1:0x80::$tx_stbc_2by1 \ + SU-BEAMFORMER:0x800::$su_beamformer \ + SU-BEAMFORMEE:0x1000::$su_beamformee \ + MU-BEAMFORMER:0x80000::$mu_beamformer \ + MU-BEAMFORMEE:0x100000::$mu_beamformee \ + VHT-TXOP-PS:0x200000::$vht_txop_ps \ + HTC-VHT:0x400000::$htc_vht \ + RX-ANTENNA-PATTERN:0x10000000::$rx_antenna_pattern \ + TX-ANTENNA-PATTERN:0x20000000::$tx_antenna_pattern \ + RX-STBC-1:0x700:0x100:1 \ + RX-STBC-12:0x700:0x200:1 \ + RX-STBC-123:0x700:0x300:1 \ + RX-STBC-1234:0x700:0x400:1 \ + + [ "$(($vht_cap & 0x800))" -gt 0 -a "$su_beamformer" -gt 0 ] && { + cap_ant="$(( ( ($vht_cap >> 16) & 3 ) + 1 ))" + [ "$cap_ant" -gt "$beamformer_antennas" ] && cap_ant="$beamformer_antennas" + [ "$cap_ant" -gt 1 ] && vht_capab="$vht_capab[SOUNDING-DIMENSION-$cap_ant]" + } + + [ "$(($vht_cap & 0x1000))" -gt 0 -a "$su_beamformee" -gt 0 ] && { + cap_ant="$(( ( ($vht_cap >> 13) & 3 ) + 1 ))" + [ "$cap_ant" -gt "$beamformee_antennas" ] && cap_ant="$beamformee_antennas" + [ "$cap_ant" -gt 1 ] && vht_capab="$vht_capab[BF-ANTENNA-$cap_ant]" + } + + # supported Channel widths + vht160_hw=0 + [ "$(($vht_cap & 12))" -eq 4 -a 1 -le "$vht160" ] && \ + vht160_hw=1 + [ "$(($vht_cap & 12))" -eq 8 -a 2 -le "$vht160" ] && \ + vht160_hw=2 + [ "$vht160_hw" = 1 ] && vht_capab="$vht_capab[VHT160]" + [ "$vht160_hw" = 2 ] && vht_capab="$vht_capab[VHT160-80PLUS80]" + + # maximum MPDU length + vht_max_mpdu_hw=3895 + [ "$(($vht_cap & 3))" -ge 1 -a 7991 -le "$vht_max_mpdu" ] && \ + vht_max_mpdu_hw=7991 + [ "$(($vht_cap & 3))" -ge 2 -a 11454 -le "$vht_max_mpdu" ] && \ + vht_max_mpdu_hw=11454 + [ "$vht_max_mpdu_hw" != 3895 ] && \ + vht_capab="$vht_capab[MAX-MPDU-$vht_max_mpdu_hw]" + + # maximum A-MPDU length exponent + vht_max_a_mpdu_len_exp_hw=0 + [ "$(($vht_cap & 58720256))" -ge 8388608 -a 1 -le "$vht_max_a_mpdu_len_exp" ] && \ + vht_max_a_mpdu_len_exp_hw=1 + [ "$(($vht_cap & 58720256))" -ge 16777216 -a 2 -le "$vht_max_a_mpdu_len_exp" ] && \ + vht_max_a_mpdu_len_exp_hw=2 + [ "$(($vht_cap & 58720256))" -ge 25165824 -a 3 -le "$vht_max_a_mpdu_len_exp" ] && \ + vht_max_a_mpdu_len_exp_hw=3 + [ "$(($vht_cap & 58720256))" -ge 33554432 -a 4 -le "$vht_max_a_mpdu_len_exp" ] && \ + vht_max_a_mpdu_len_exp_hw=4 + [ "$(($vht_cap & 58720256))" -ge 41943040 -a 5 -le "$vht_max_a_mpdu_len_exp" ] && \ + vht_max_a_mpdu_len_exp_hw=5 + [ "$(($vht_cap & 58720256))" -ge 50331648 -a 6 -le "$vht_max_a_mpdu_len_exp" ] && \ + vht_max_a_mpdu_len_exp_hw=6 + [ "$(($vht_cap & 58720256))" -ge 58720256 -a 7 -le "$vht_max_a_mpdu_len_exp" ] && \ + vht_max_a_mpdu_len_exp_hw=7 + vht_capab="$vht_capab[MAX-A-MPDU-LEN-EXP$vht_max_a_mpdu_len_exp_hw]" + + # whether or not the STA supports link adaptation using VHT variant + vht_link_adapt_hw=0 + [ "$(($vht_cap & 201326592))" -ge 134217728 -a 2 -le "$vht_link_adapt" ] && \ + vht_link_adapt_hw=2 + [ "$(($vht_cap & 201326592))" -ge 201326592 -a 3 -le "$vht_link_adapt" ] && \ + vht_link_adapt_hw=3 + [ "$vht_link_adapt_hw" != 0 ] && \ + vht_capab="$vht_capab[VHT-LINK-ADAPT-$vht_link_adapt_hw]" + + [ -n "$vht_capab" ] && append base_cfg "vht_capab=$vht_capab" "$N" + fi + + # 802.11ax + enable_ax=0 + case "$htmode" in + HE*) enable_ax=1 ;; + esac + + if [ "$enable_ax" != "0" ]; then + json_get_vars \ + he_su_beamformer:1 \ + he_su_beamformee:1 \ + he_mu_beamformer:1 \ + he_twt_required:0 \ + he_spr_sr_control:3 \ + he_spr_psr_enabled:0 \ + he_spr_non_srg_obss_pd_max_offset:0 \ + he_bss_color:128 \ + he_bss_color_enabled:1 + + he_phy_cap=$(iw phy "$phy" info | sed -n '/HE Iftypes: AP/,$p' | awk -F "[()]" '/HE PHY Capabilities/ { print $2 }' | head -1) + he_phy_cap=${he_phy_cap:2} + he_mac_cap=$(iw phy "$phy" info | sed -n '/HE Iftypes: AP/,$p' | awk -F "[()]" '/HE MAC Capabilities/ { print $2 }' | head -1) + he_mac_cap=${he_mac_cap:2} + + append base_cfg "ieee80211ax=1" "$N" + [ "$hwmode" = "a" ] && { + append base_cfg "he_oper_chwidth=$vht_oper_chwidth" "$N" + append base_cfg "he_oper_centr_freq_seg0_idx=$vht_center_seg0" "$N" + } + + mac80211_add_he_capabilities \ + he_su_beamformer:${he_phy_cap:6:2}:0x80:$he_su_beamformer \ + he_su_beamformee:${he_phy_cap:8:2}:0x1:$he_su_beamformee \ + he_mu_beamformer:${he_phy_cap:8:2}:0x2:$he_mu_beamformer \ + he_spr_psr_enabled:${he_phy_cap:14:2}:0x1:$he_spr_psr_enabled \ + he_twt_required:${he_mac_cap:0:2}:0x6:$he_twt_required + + if [ "$he_bss_color_enabled" -gt 0 ]; then + append base_cfg "he_bss_color=$he_bss_color" "$N" + [ "$he_spr_non_srg_obss_pd_max_offset" -gt 0 ] && { \ + append base_cfg "he_spr_non_srg_obss_pd_max_offset=$he_spr_non_srg_obss_pd_max_offset" "$N" + he_spr_sr_control=$((he_spr_sr_control | (1 << 2))) + } + [ "$he_spr_psr_enabled" -gt 0 ] || he_spr_sr_control=$((he_spr_sr_control | (1 << 0))) + append base_cfg "he_spr_sr_control=$he_spr_sr_control" "$N" + else + append base_cfg "he_bss_color_disabled=1" "$N" + fi + + + append base_cfg "he_default_pe_duration=4" "$N" + append base_cfg "he_rts_threshold=1023" "$N" + append base_cfg "he_mu_edca_qos_info_param_count=0" "$N" + append base_cfg "he_mu_edca_qos_info_q_ack=0" "$N" + append base_cfg "he_mu_edca_qos_info_queue_request=0" "$N" + append base_cfg "he_mu_edca_qos_info_txop_request=0" "$N" + append base_cfg "he_mu_edca_ac_be_aifsn=8" "$N" + append base_cfg "he_mu_edca_ac_be_aci=0" "$N" + append base_cfg "he_mu_edca_ac_be_ecwmin=9" "$N" + append base_cfg "he_mu_edca_ac_be_ecwmax=10" "$N" + append base_cfg "he_mu_edca_ac_be_timer=255" "$N" + append base_cfg "he_mu_edca_ac_bk_aifsn=15" "$N" + append base_cfg "he_mu_edca_ac_bk_aci=1" "$N" + append base_cfg "he_mu_edca_ac_bk_ecwmin=9" "$N" + append base_cfg "he_mu_edca_ac_bk_ecwmax=10" "$N" + append base_cfg "he_mu_edca_ac_bk_timer=255" "$N" + append base_cfg "he_mu_edca_ac_vi_ecwmin=5" "$N" + append base_cfg "he_mu_edca_ac_vi_ecwmax=7" "$N" + append base_cfg "he_mu_edca_ac_vi_aifsn=5" "$N" + append base_cfg "he_mu_edca_ac_vi_aci=2" "$N" + append base_cfg "he_mu_edca_ac_vi_timer=255" "$N" + append base_cfg "he_mu_edca_ac_vo_aifsn=5" "$N" + append base_cfg "he_mu_edca_ac_vo_aci=3" "$N" + append base_cfg "he_mu_edca_ac_vo_ecwmin=5" "$N" + append base_cfg "he_mu_edca_ac_vo_ecwmax=7" "$N" + append base_cfg "he_mu_edca_ac_vo_timer=255" "$N" + fi + + hostapd_prepare_device_config "$hostapd_conf_file" nl80211 + cat >> "$hostapd_conf_file" <> $hostapd_conf_file +} + +mac80211_hostapd_setup_bss() { + local phy="$1" + local ifname="$2" + local macaddr="$3" + local type="$4" + + hostapd_cfg= + append hostapd_cfg "$type=$ifname" "$N" + + hostapd_set_bss_options hostapd_cfg "$phy" "$vif" || return 1 + json_get_vars wds wds_bridge dtim_period max_listen_int start_disabled + + set_default wds 0 + set_default start_disabled 0 + + [ "$wds" -gt 0 ] && { + append hostapd_cfg "wds_sta=1" "$N" + [ -n "$wds_bridge" ] && append hostapd_cfg "wds_bridge=$wds_bridge" "$N" + } + [ "$staidx" -gt 0 -o "$start_disabled" -eq 1 ] && append hostapd_cfg "start_disabled=1" "$N" + + cat >> /var/run/hostapd-$phy.conf </dev/null); do + grep -i -q "$macaddr" "/sys/class/ieee80211/${phy}/macaddress" && return 0 + done + } + return 1 +} + +mac80211_check_ap() { + has_ap=1 +} + +mac80211_iw_interface_add() { + local phy="$1" + local ifname="$2" + local type="$3" + local wdsflag="$4" + local rc + local oldifname + + iw phy "$phy" interface add "$ifname" type "$type" $wdsflag >/dev/null 2>&1 + rc="$?" + + [ "$rc" = 233 ] && { + # Device might have just been deleted, give the kernel some time to finish cleaning it up + sleep 1 + + iw phy "$phy" interface add "$ifname" type "$type" $wdsflag >/dev/null 2>&1 + rc="$?" + } + + [ "$rc" = 233 ] && { + # Keep matching pre-existing interface + [ -d "/sys/class/ieee80211/${phy}/device/net/${ifname}" ] && \ + case "$(iw dev $ifname info | grep "^\ttype" | cut -d' ' -f2- 2>/dev/null)" in + "AP") + [ "$type" = "__ap" ] && rc=0 + ;; + "IBSS") + [ "$type" = "adhoc" ] && rc=0 + ;; + "managed") + [ "$type" = "managed" ] && rc=0 + ;; + "mesh point") + [ "$type" = "mp" ] && rc=0 + ;; + "monitor") + [ "$type" = "monitor" ] && rc=0 + ;; + esac + } + + [ "$rc" = 233 ] && { + iw dev "$ifname" del >/dev/null 2>&1 + [ "$?" = 0 ] && { + sleep 1 + + iw phy "$phy" interface add "$ifname" type "$type" $wdsflag >/dev/null 2>&1 + rc="$?" + } + } + + [ "$rc" != 0 ] && { + # Device might not support virtual interfaces, so the interface never got deleted in the first place. + # Check if the interface already exists, and avoid failing in this case. + [ -d "/sys/class/ieee80211/${phy}/device/net/${ifname}" ] && rc=0 + } + + [ "$rc" != 0 ] && { + # Device doesn't support virtual interfaces and may have existing interface other than ifname. + oldifname="$(basename "/sys/class/ieee80211/${phy}/device/net"/* 2>/dev/null)" + [ "$oldifname" ] && ip link set "$oldifname" name "$ifname" 1>/dev/null 2>&1 + rc="$?" + } + + [ "$rc" != 0 ] && echo "Failed to create interface $ifname" + return $rc +} + +mac80211_prepare_vif() { + json_select config + + json_get_vars ifname mode ssid wds powersave macaddr enable wpa_psk_file vlan_file + + [ -n "$ifname" ] || ifname="wlan${phy#phy}${if_idx:+-$if_idx}" + if_idx=$((${if_idx:-0} + 1)) + + set_default wds 0 + set_default powersave 0 + + json_select .. + + if [ -z "$macaddr" ]; then + macaddr="$(mac80211_generate_mac $phy)" + macidx="$(($macidx + 1))" + elif [ "$macaddr" = 'random' ]; then + macaddr="$(macaddr_random)" + fi + + json_add_object data + json_add_string ifname "$ifname" + json_close_object + + [ "$mode" == "ap" ] && { + [ -z "$wpa_psk_file" ] && hostapd_set_psk "$ifname" + [ -z "$vlan_file" ] && hostapd_set_vlan "$ifname" + } + + json_select config + + # It is far easier to delete and create the desired interface + case "$mode" in + adhoc) + mac80211_iw_interface_add "$phy" "$ifname" adhoc || return + ;; + ap) + # Hostapd will handle recreating the interface and + # subsequent virtual APs belonging to the same PHY + if [ -n "$hostapd_ctrl" ]; then + type=bss + else + type=interface + fi + + mac80211_hostapd_setup_bss "$phy" "$ifname" "$macaddr" "$type" || return + + NEWAPLIST="${NEWAPLIST}$ifname " + [ -n "$hostapd_ctrl" ] || { + ap_ifname="${ifname}" + hostapd_ctrl="${hostapd_ctrl:-/var/run/hostapd/$ifname}" + } + ;; + mesh) + mac80211_iw_interface_add "$phy" "$ifname" mp || return + ;; + monitor) + mac80211_iw_interface_add "$phy" "$ifname" monitor || return + ;; + sta) + local wdsflag= + [ "$enable" = 0 ] || staidx="$(($staidx + 1))" + [ "$wds" -gt 0 ] && wdsflag="4addr on" + mac80211_iw_interface_add "$phy" "$ifname" managed "$wdsflag" || return + if [ "$wds" -gt 0 ]; then + iw "$ifname" set 4addr on + else + iw "$ifname" set 4addr off + fi + [ "$powersave" -gt 0 ] && powersave="on" || powersave="off" + iw "$ifname" set power_save "$powersave" + ;; + esac + + case "$mode" in + monitor|mesh) + [ "$auto_channel" -gt 0 ] || iw dev "$ifname" set channel "$channel" $iw_htmode + ;; + esac + + if [ "$mode" != "ap" ]; then + # ALL ap functionality will be passed to hostapd + # All interfaces must have unique mac addresses + # which can either be explicitly set in the device + # section, or automatically generated + ip link set dev "$ifname" address "$macaddr" + fi + + json_select .. +} + +mac80211_setup_supplicant() { + local enable=$1 + local add_sp=0 + local spobj="$(ubus -S list | grep wpa_supplicant.${ifname})" + + [ "$enable" = 0 ] && { + ubus call wpa_supplicant.${phy} config_remove "{\"iface\":\"$ifname\"}" + ip link set dev "$ifname" down + iw dev "$ifname" del + return 0 + } + + wpa_supplicant_prepare_interface "$ifname" nl80211 || { + iw dev "$ifname" del + return 1 + } + if [ "$mode" = "sta" ]; then + wpa_supplicant_add_network "$ifname" + else + wpa_supplicant_add_network "$ifname" "$freq" "$htmode" "$noscan" + fi + + NEWSPLIST="${NEWSPLIST}$ifname " + + if [ "${NEWAPLIST%% *}" != "${OLDAPLIST%% *}" ]; then + [ "$spobj" ] && ubus call wpa_supplicant config_remove "{\"iface\":\"$ifname\"}" + add_sp=1 + fi + [ -z "$spobj" ] && add_sp=1 + + NEW_MD5_SP=$(test -e "${_config}" && md5sum ${_config}) + OLD_MD5_SP=$(uci -q -P /var/state get wireless._${phy}.md5_${ifname}) + if [ "$add_sp" = "1" ]; then + wpa_supplicant_run "$ifname" "$hostapd_ctrl" + else + [ "${NEW_MD5_SP}" == "${OLD_MD5_SP}" ] || ubus call $spobj reload + fi + uci -q -P /var/state set wireless._${phy}.md5_${ifname}="${NEW_MD5_SP}" + return 0 +} + +mac80211_setup_supplicant_noctl() { + local enable=$1 + local spobj="$(ubus -S list | grep wpa_supplicant.${ifname})" + wpa_supplicant_prepare_interface "$ifname" nl80211 || { + iw dev "$ifname" del + return 1 + } + + wpa_supplicant_add_network "$ifname" "$freq" "$htmode" "$noscan" + + NEWSPLIST="${NEWSPLIST}$ifname " + [ "$enable" = 0 ] && { + ubus call wpa_supplicant config_remove "{\"iface\":\"$ifname\"}" + ip link set dev "$ifname" down + return 0 + } + if [ -z "$spobj" ]; then + wpa_supplicant_run "$ifname" + else + ubus call $spobj reload + fi +} + +mac80211_prepare_iw_htmode() { + case "$htmode" in + VHT20|HT20|HE20) iw_htmode=HT20;; + HT40*|VHT40|VHT160|HE40) + case "$band" in + 2g) + case "$htmode" in + HT40+) iw_htmode="HT40+";; + HT40-) iw_htmode="HT40-";; + *) + if [ "$channel" -lt 7 ]; then + iw_htmode="HT40+" + else + iw_htmode="HT40-" + fi + ;; + esac + ;; + *) + case "$(( ($channel / 4) % 2 ))" in + 1) iw_htmode="HT40+" ;; + 0) iw_htmode="HT40-";; + esac + ;; + esac + [ "$auto_channel" -gt 0 ] && iw_htmode="HT40+" + ;; + VHT80|HE80) + iw_htmode="80MHZ" + ;; + NONE|NOHT) + iw_htmode="NOHT" + ;; + *) iw_htmode="" ;; + esac +} + +mac80211_setup_adhoc() { + local enable=$1 + json_get_vars bssid ssid key mcast_rate + + NEWUMLIST="${NEWUMLIST}$ifname " + + [ "$enable" = 0 ] && { + ip link set dev "$ifname" down + return 0 + } + + keyspec= + [ "$auth_type" = "wep" ] && { + set_default key 1 + case "$key" in + [1234]) + local idx + for idx in 1 2 3 4; do + json_get_var ikey "key$idx" + + [ -n "$ikey" ] && { + ikey="$(($idx - 1)):$(prepare_key_wep "$ikey")" + [ $idx -eq $key ] && ikey="d:$ikey" + append keyspec "$ikey" + } + done + ;; + *) + append keyspec "d:0:$(prepare_key_wep "$key")" + ;; + esac + } + + brstr= + for br in $basic_rate_list; do + wpa_supplicant_add_rate brstr "$br" + done + + mcval= + [ -n "$mcast_rate" ] && wpa_supplicant_add_rate mcval "$mcast_rate" + + iw dev "$ifname" set type ibss + iw dev "$ifname" ibss join "$ssid" $freq $iw_htmode fixed-freq $bssid \ + beacon-interval $beacon_int \ + ${brstr:+basic-rates $brstr} \ + ${mcval:+mcast-rate $mcval} \ + ${keyspec:+keys $keyspec} +} + +mac80211_setup_mesh() { + local enable=$1 + json_get_vars ssid mesh_id mcast_rate + + NEWUMLIST="${NEWUMLIST}$ifname " + + [ "$enable" = 0 ] && { + ip link set dev "$ifname" down + return 0 + } + + mcval= + [ -n "$mcast_rate" ] && wpa_supplicant_add_rate mcval "$mcast_rate" + [ -n "$mesh_id" ] && ssid="$mesh_id" + + iw dev "$ifname" mesh join "$ssid" freq $freq $iw_htmode \ + ${mcval:+mcast-rate $mcval} \ + beacon-interval $beacon_int +} + +mac80211_setup_vif() { + local name="$1" + local failed + local action=up + + json_select data + json_get_vars ifname + json_select .. + + json_select config + json_get_vars mode + json_get_var vif_txpower + json_get_var vif_enable enable 1 + + [ "$vif_enable" = 1 ] || action=down + if [ "$mode" != "ap" ] || [ "$ifname" = "$ap_ifname" ]; then + ip link set dev "$ifname" "$action" || { + wireless_setup_vif_failed IFUP_ERROR + json_select .. + return + } + [ -z "$vif_txpower" ] || iw dev "$ifname" set txpower fixed "${vif_txpower%%.*}00" + fi + + case "$mode" in + mesh) + wireless_vif_parse_encryption + [ -z "$htmode" ] && htmode="NOHT"; + if [ "$wpa" -gt 0 -o "$auto_channel" -gt 0 ] || chan_is_dfs "$phy" "$channel"; then + mac80211_setup_supplicant $vif_enable || failed=1 + else + mac80211_setup_mesh $vif_enable + fi + for var in $MP_CONFIG_INT $MP_CONFIG_BOOL $MP_CONFIG_STRING; do + json_get_var mp_val "$var" + [ -n "$mp_val" ] && iw dev "$ifname" set mesh_param "$var" "$mp_val" + done + ;; + adhoc) + wireless_vif_parse_encryption + if [ "$wpa" -gt 0 -o "$auto_channel" -gt 0 ]; then + mac80211_setup_supplicant_noctl $vif_enable || failed=1 + else + mac80211_setup_adhoc $vif_enable + fi + ;; + sta) + mac80211_setup_supplicant $vif_enable || failed=1 + ;; + esac + + json_select .. + [ -n "$failed" ] || wireless_add_vif "$name" "$ifname" +} + +get_freq() { + local phy="$1" + local channel="$2" + local band="$3" + + case "$band" in + 2g) band="1:";; + 5g) band="2:";; + 60g) band="3:";; + 6g) band="4:";; + esac + + iw "$phy" info | awk -v band="$band" -v channel="[$channel]" ' + +$1 ~ /Band/ { + band_match = band == $2 +} + +band_match && $3 == "MHz" && $4 == channel { + print $2 + exit +} +' +} + + +chan_is_dfs() { + local phy="$1" + local chan="$2" + iw "$phy" info | grep -E -m1 "(\* ${chan:-....} MHz${chan:+|\\[$chan\\]})" | grep -q "MHz.*radar detection" + return $! +} + +mac80211_vap_cleanup() { + local service="$1" + local vaps="$2" + + for wdev in $vaps; do + [ "$service" != "none" ] && ubus call ${service} config_remove "{\"iface\":\"$wdev\"}" + ip link set dev "$wdev" down 2>/dev/null + iw dev "$wdev" del + done +} + +mac80211_interface_cleanup() { + local phy="$1" + local primary_ap=$(uci -q -P /var/state get wireless._${phy}.aplist) + primary_ap=${primary_ap%% *} + + mac80211_vap_cleanup hostapd "${primary_ap}" + mac80211_vap_cleanup wpa_supplicant "$(uci -q -P /var/state get wireless._${phy}.splist)" + mac80211_vap_cleanup none "$(uci -q -P /var/state get wireless._${phy}.umlist)" +} + +mac80211_set_noscan() { + hostapd_noscan=1 +} + +drv_mac80211_cleanup() { + hostapd_common_cleanup +} + +drv_mac80211_setup() { + json_select config + json_get_vars \ + phy macaddr path \ + country chanbw distance \ + txpower antenna_gain \ + rxantenna txantenna \ + frag rts beacon_int:100 htmode + json_get_values basic_rate_list basic_rate + json_get_values scan_list scan_list + json_select .. + + find_phy || { + echo "Could not find PHY for device '$1'" + wireless_set_retry 0 + return 1 + } + + wireless_set_data phy="$phy" + [ -z "$(uci -q -P /var/state show wireless._${phy})" ] && uci -q -P /var/state set wireless._${phy}=phy + + OLDAPLIST=$(uci -q -P /var/state get wireless._${phy}.aplist) + OLDSPLIST=$(uci -q -P /var/state get wireless._${phy}.splist) + OLDUMLIST=$(uci -q -P /var/state get wireless._${phy}.umlist) + + local wdev + local cwdev + local found + + for wdev in $(list_phy_interfaces "$phy"); do + found=0 + for cwdev in $OLDAPLIST $OLDSPLIST $OLDUMLIST; do + if [ "$wdev" = "$cwdev" ]; then + found=1 + break + fi + done + if [ "$found" = "0" ]; then + ip link set dev "$wdev" down + iw dev "$wdev" del + fi + done + + # convert channel to frequency + [ "$auto_channel" -gt 0 ] || freq="$(get_freq "$phy" "$channel" "$band")" + + [ -n "$country" ] && { + iw reg get | grep -q "^country $country:" || { + iw reg set "$country" + sleep 1 + } + } + + hostapd_conf_file="/var/run/hostapd-$phy.conf" + + no_ap=1 + macidx=0 + staidx=0 + + [ -n "$chanbw" ] && { + for file in /sys/kernel/debug/ieee80211/$phy/ath9k*/chanbw /sys/kernel/debug/ieee80211/$phy/ath5k/bwmode; do + [ -f "$file" ] && echo "$chanbw" > "$file" + done + } + + set_default rxantenna 0xffffffff + set_default txantenna 0xffffffff + set_default distance 0 + set_default antenna_gain 0 + + [ "$txantenna" = "all" ] && txantenna=0xffffffff + [ "$rxantenna" = "all" ] && rxantenna=0xffffffff + + iw phy "$phy" set antenna $txantenna $rxantenna >/dev/null 2>&1 + iw phy "$phy" set antenna_gain $antenna_gain >/dev/null 2>&1 + iw phy "$phy" set distance "$distance" >/dev/null 2>&1 + + if [ -n "$txpower" ]; then + iw phy "$phy" set txpower fixed "${txpower%%.*}00" + else + iw phy "$phy" set txpower auto + fi + + [ -n "$frag" ] && iw phy "$phy" set frag "${frag%%.*}" + [ -n "$rts" ] && iw phy "$phy" set rts "${rts%%.*}" + + has_ap= + hostapd_ctrl= + ap_ifname= + hostapd_noscan= + for_each_interface "ap" mac80211_check_ap + + rm -f "$hostapd_conf_file" + + for_each_interface "sta adhoc mesh" mac80211_set_noscan + [ -n "$has_ap" ] && mac80211_hostapd_setup_base "$phy" + + mac80211_prepare_iw_htmode + for_each_interface "sta adhoc mesh monitor" mac80211_prepare_vif + NEWAPLIST= + for_each_interface "ap" mac80211_prepare_vif + NEW_MD5=$(test -e "${hostapd_conf_file}" && md5sum ${hostapd_conf_file}) + OLD_MD5=$(uci -q -P /var/state get wireless._${phy}.md5) + if [ "${NEWAPLIST}" != "${OLDAPLIST}" ]; then + mac80211_vap_cleanup hostapd "${OLDAPLIST}" + fi + [ -n "${NEWAPLIST}" ] && mac80211_iw_interface_add "$phy" "${NEWAPLIST%% *}" __ap + local add_ap=0 + local primary_ap=${NEWAPLIST%% *} + [ -n "$hostapd_ctrl" ] && { + local no_reload=1 + if [ -n "$(ubus list | grep hostapd.$primary_ap)" ]; then + no_reload=0 + [ "${NEW_MD5}" = "${OLD_MD5}" ] || { + ubus call hostapd.$primary_ap reload + no_reload=$? + if [ "$no_reload" != "0" ]; then + mac80211_vap_cleanup hostapd "${OLDAPLIST}" + mac80211_vap_cleanup wpa_supplicant "$(uci -q -P /var/state get wireless._${phy}.splist)" + mac80211_vap_cleanup none "$(uci -q -P /var/state get wireless._${phy}.umlist)" + sleep 2 + mac80211_iw_interface_add "$phy" "${NEWAPLIST%% *}" __ap + for_each_interface "sta adhoc mesh monitor" mac80211_prepare_vif + fi + } + fi + if [ "$no_reload" != "0" ]; then + add_ap=1 + ubus wait_for hostapd + local hostapd_res="$(ubus call hostapd config_add "{\"iface\":\"$primary_ap\", \"config\":\"${hostapd_conf_file}\"}")" + ret="$?" + [ "$ret" != 0 -o -z "$hostapd_res" ] && { + wireless_setup_failed HOSTAPD_START_FAILED + return + } + wireless_add_process "$(jsonfilter -s "$hostapd_res" -l 1 -e @.pid)" "/usr/sbin/hostapd" 1 1 + fi + } + uci -q -P /var/state set wireless._${phy}.aplist="${NEWAPLIST}" + uci -q -P /var/state set wireless._${phy}.md5="${NEW_MD5}" + + [ "${add_ap}" = 1 ] && sleep 1 + for_each_interface "ap" mac80211_setup_vif + + NEWSPLIST= + NEWUMLIST= + + for_each_interface "sta adhoc mesh monitor" mac80211_setup_vif + + uci -q -P /var/state set wireless._${phy}.splist="${NEWSPLIST}" + uci -q -P /var/state set wireless._${phy}.umlist="${NEWUMLIST}" + + local foundvap + local dropvap="" + for oldvap in $OLDSPLIST; do + foundvap=0 + for newvap in $NEWSPLIST; do + [ "$oldvap" = "$newvap" ] && foundvap=1 + done + [ "$foundvap" = "0" ] && dropvap="$dropvap $oldvap" + done + [ -n "$dropvap" ] && mac80211_vap_cleanup wpa_supplicant "$dropvap" + wireless_set_up +} + +_list_phy_interfaces() { + local phy="$1" + if [ -d "/sys/class/ieee80211/${phy}/device/net" ]; then + ls "/sys/class/ieee80211/${phy}/device/net" 2>/dev/null; + else + ls "/sys/class/ieee80211/${phy}/device" 2>/dev/null | grep net: | sed -e 's,net:,,g' + fi +} + +list_phy_interfaces() { + local phy="$1" + + for dev in $(_list_phy_interfaces "$phy"); do + readlink "/sys/class/net/${dev}/phy80211" | grep -q "/${phy}\$" || continue + echo "$dev" + done +} + +drv_mac80211_teardown() { + json_select data + json_get_vars phy + json_select .. + [ -n "$phy" ] || { + echo "Bug: PHY is undefined for device '$1'" + return 1 + } + + mac80211_interface_cleanup "$phy" + uci -q -P /var/state revert wireless._${phy} +} + +add_driver mac80211 diff --git a/package/kernel/mac80211/files/lib/wifi/mac80211.sh b/package/kernel/mac80211/files/lib/wifi/mac80211.sh new file mode 100644 index 000000000..4c5981850 --- /dev/null +++ b/package/kernel/mac80211/files/lib/wifi/mac80211.sh @@ -0,0 +1,191 @@ +#!/bin/sh + +append DRIVERS "mac80211" + +lookup_phy() { + [ -n "$phy" ] && { + [ -d /sys/class/ieee80211/$phy ] && return + } + + local devpath + config_get devpath "$device" path + [ -n "$devpath" ] && { + phy="$(iwinfo nl80211 phyname "path=$devpath")" + [ -n "$phy" ] && return + } + + local macaddr="$(config_get "$device" macaddr | tr 'A-Z' 'a-z')" + [ -n "$macaddr" ] && { + for _phy in /sys/class/ieee80211/*; do + [ -e "$_phy" ] || continue + + [ "$macaddr" = "$(cat ${_phy}/macaddress)" ] || continue + phy="${_phy##*/}" + return + done + } + phy= + return +} + +find_mac80211_phy() { + local device="$1" + + config_get phy "$device" phy + lookup_phy + [ -n "$phy" -a -d "/sys/class/ieee80211/$phy" ] || { + echo "PHY for wifi device $1 not found" + return 1 + } + config_set "$device" phy "$phy" + + config_get macaddr "$device" macaddr + [ -z "$macaddr" ] && { + config_set "$device" macaddr "$(cat /sys/class/ieee80211/${phy}/macaddress)" + } + + return 0 +} + +check_mac80211_device() { + config_get phy "$1" phy + [ -z "$phy" ] && { + find_mac80211_phy "$1" >/dev/null || return 0 + config_get phy "$1" phy + } + [ "$phy" = "$dev" ] && found=1 +} + + +__get_band_defaults() { + local phy="$1" + + ( iw phy "$phy" info; echo ) | awk ' +BEGIN { + bands = "" +} + +($1 == "Band" || $1 == "") && band { + if (channel) { + mode="NOHT" + if (ht) mode="HT20" + if (vht && band != "1:") mode="VHT80" + if (he) mode="HE80" + if (he && band == "1:") mode="HE20" + sub("\\[", "", channel) + sub("\\]", "", channel) + bands = bands band channel ":" mode " " + } + band="" +} + +$1 == "Band" { + band = $2 + channel = "" + vht = "" + ht = "" + he = "" +} + +$0 ~ "Capabilities:" { + ht=1 +} + +$0 ~ "VHT Capabilities" { + vht=1 +} + +$0 ~ "HE Iftypes" { + he=1 +} + +$1 == "*" && $3 == "MHz" && $0 !~ /disabled/ && band && !channel { + channel = $4 +} + +END { + print bands +}' +} + +get_band_defaults() { + local phy="$1" + + for c in $(__get_band_defaults "$phy"); do + local band="${c%%:*}" + c="${c#*:}" + local chan="${c%%:*}" + c="${c#*:}" + local mode="${c%%:*}" + + case "$band" in + 1) band=2g;; + 2) band=5g;; + 3) band=60g;; + 4) band=6g;; + *) band="";; + esac + + [ -n "$band" ] || continue + [ -n "$mode_band" -a "$band" = "6g" ] && return + + mode_band="$band" + channel="$chan" + htmode="$mode" + done +} + +detect_mac80211() { + devidx=0 + config_load wireless + while :; do + config_get type "radio$devidx" type + [ -n "$type" ] || break + devidx=$(($devidx + 1)) + done + + for _dev in /sys/class/ieee80211/*; do + [ -e "$_dev" ] || continue + + dev="${_dev##*/}" + + found=0 + config_foreach check_mac80211_device wifi-device + [ "$found" -gt 0 ] && continue + + mode_band="" + channel="" + htmode="" + ht_capab="" + + get_band_defaults "$dev" + + path="$(iwinfo nl80211 path "$dev")" + if [ -n "$path" ]; then + dev_id="set wireless.radio${devidx}.path='$path'" + else + dev_id="set wireless.radio${devidx}.macaddr=$(cat /sys/class/ieee80211/${dev}/macaddress)" + fi + + uci -q batch <<-EOF + set wireless.radio${devidx}=wifi-device + set wireless.radio${devidx}.type=mac80211 + ${dev_id} + set wireless.radio${devidx}.channel=${channel} + set wireless.radio${devidx}.band=${mode_band} + set wireless.radio${devidx}.htmode=$htmode + set wireless.radio${devidx}.disabled=0 + set wireless.radio${devidx}.country=US + + set wireless.default_radio${devidx}=wifi-iface + set wireless.default_radio${devidx}.device=radio${devidx} + set wireless.default_radio${devidx}.network=lan + set wireless.default_radio${devidx}.mode=ap + set wireless.default_radio${devidx}.ssid=OpenWrt + set wireless.default_radio${devidx}.encryption=none +EOF + uci -q commit wireless + + devidx=$(($devidx + 1)) + done +} diff --git a/package/kernel/mac80211/files/mac80211.hotplug b/package/kernel/mac80211/files/mac80211.hotplug new file mode 100644 index 000000000..b86555266 --- /dev/null +++ b/package/kernel/mac80211/files/mac80211.hotplug @@ -0,0 +1,5 @@ +#!/bin/sh + +[ "${ACTION}" = "add" ] && { + /sbin/wifi config +} diff --git a/package/kernel/mac80211/intel.mk b/package/kernel/mac80211/intel.mk index 63b19a55c..8d374d73e 100644 --- a/package/kernel/mac80211/intel.mk +++ b/package/kernel/mac80211/intel.mk @@ -6,7 +6,7 @@ config-$(CONFIG_PACKAGE_IWLWIFI_DEBUGFS)+= IWLWIFI_DEBUGFS define KernelPackage/iwlwifi $(call KernelPackage/mac80211/Default) - DEPENDS:= +kmod-mac80211 +kmod-ptp @PCI_SUPPORT +@DRIVER_11AC_SUPPORT +@DRIVER_11AX_SUPPORT @!LINUX_5_15 + DEPENDS:= +kmod-mac80211 @PCI_SUPPORT +@DRIVER_11AC_SUPPORT +@DRIVER_11AX_SUPPORT TITLE:=Intel AGN Wireless support FILES:= \ $(PKG_BUILD_DIR)/drivers/net/wireless/intel/iwlwifi/iwlwifi.ko \ diff --git a/package/kernel/mac80211/patches/ath/400-ath_move_debug_code.patch b/package/kernel/mac80211/patches/ath/400-ath_move_debug_code.patch index 23b7340e2..eacc72776 100644 --- a/package/kernel/mac80211/patches/ath/400-ath_move_debug_code.patch +++ b/package/kernel/mac80211/patches/ath/400-ath_move_debug_code.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/ath/Makefile +++ b/drivers/net/wireless/ath/Makefile -@@ -16,10 +16,10 @@ ath-objs := main.o \ +@@ -15,10 +15,10 @@ ath-objs := main.o \ regd.o \ hw.o \ key.o \ @@ -14,7 +14,7 @@ CFLAGS_trace.o := -I$(src) --- a/drivers/net/wireless/ath/ath.h +++ b/drivers/net/wireless/ath/ath.h -@@ -321,14 +321,7 @@ void _ath_dbg(struct ath_common *common, +@@ -317,14 +317,7 @@ void _ath_dbg(struct ath_common *common, #endif /* CPTCFG_ATH_DEBUG */ /** Returns string describing opmode, or NULL if unknown mode. */ diff --git a/package/kernel/mac80211/patches/ath/402-ath_regd_optional.patch b/package/kernel/mac80211/patches/ath/402-ath_regd_optional.patch index 0f6a570cb..fd5493de7 100644 --- a/package/kernel/mac80211/patches/ath/402-ath_regd_optional.patch +++ b/package/kernel/mac80211/patches/ath/402-ath_regd_optional.patch @@ -82,7 +82,7 @@ help --- a/local-symbols +++ b/local-symbols -@@ -94,6 +94,7 @@ ADM8211= +@@ -102,6 +102,7 @@ ADM8211= ATH_COMMON= WLAN_VENDOR_ATH= ATH_DEBUG= diff --git a/package/kernel/mac80211/patches/ath/404-regd_no_assoc_hints.patch b/package/kernel/mac80211/patches/ath/404-regd_no_assoc_hints.patch index 895e2ff8d..8d83921a3 100644 --- a/package/kernel/mac80211/patches/ath/404-regd_no_assoc_hints.patch +++ b/package/kernel/mac80211/patches/ath/404-regd_no_assoc_hints.patch @@ -1,6 +1,6 @@ --- a/net/wireless/reg.c +++ b/net/wireless/reg.c -@@ -3364,6 +3364,8 @@ void regulatory_hint_country_ie(struct w +@@ -3370,6 +3370,8 @@ void regulatory_hint_country_ie(struct w enum environment_cap env = ENVIRON_ANY; struct regulatory_request *request = NULL, *lr; @@ -9,7 +9,7 @@ /* IE len must be evenly divisible by 2 */ if (country_ie_len & 0x01) return; -@@ -3615,6 +3617,7 @@ static bool is_wiphy_all_set_reg_flag(en +@@ -3621,6 +3623,7 @@ static bool is_wiphy_all_set_reg_flag(en void regulatory_hint_disconnect(void) { diff --git a/package/kernel/mac80211/patches/ath/431-add_platform_eeprom_support_to_ath5k.patch b/package/kernel/mac80211/patches/ath/431-add_platform_eeprom_support_to_ath5k.patch index c762aa6d6..136be1989 100644 --- a/package/kernel/mac80211/patches/ath/431-add_platform_eeprom_support_to_ath5k.patch +++ b/package/kernel/mac80211/patches/ath/431-add_platform_eeprom_support_to_ath5k.patch @@ -18,7 +18,7 @@ static bool ath5k_pci_eeprom_read(struct ath_common *common, u32 offset, u16 *data) @@ -79,6 +80,19 @@ ath5k_pci_eeprom_read(struct ath_common - struct ath5k_hw *ah = common->ah; + struct ath5k_hw *ah = (struct ath5k_hw *) common->ah; u32 status, timeout; + struct ath5k_platform_data *pdata = NULL; diff --git a/package/kernel/mac80211/patches/ath10k/080-ath10k_thermal_config.patch b/package/kernel/mac80211/patches/ath10k/080-ath10k_thermal_config.patch index c41bfa888..41ad6006b 100644 --- a/package/kernel/mac80211/patches/ath10k/080-ath10k_thermal_config.patch +++ b/package/kernel/mac80211/patches/ath10k/080-ath10k_thermal_config.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/ath/ath10k/Kconfig +++ b/drivers/net/wireless/ath/ath10k/Kconfig -@@ -88,6 +88,12 @@ config ATH10K_TRACING +@@ -86,6 +86,12 @@ config ATH10K_TRACING help Select this to ath10k use tracing infrastructure. @@ -37,7 +37,7 @@ void ath10k_thermal_event_temperature(struct ath10k *ar, int temperature); --- a/local-symbols +++ b/local-symbols -@@ -153,6 +153,7 @@ ATH10K_SNOC= +@@ -161,6 +161,7 @@ ATH10K_SNOC= ATH10K_DEBUG= ATH10K_DEBUGFS= ATH10K_SPECTRAL= diff --git a/package/kernel/mac80211/patches/ath10k/911-ath10k-disable-caldata-prefetch-for-sdio-bus.patch b/package/kernel/mac80211/patches/ath10k/911-ath10k-disable-caldata-prefetch-for-sdio-bus.patch new file mode 100644 index 000000000..8ca8f3b55 --- /dev/null +++ b/package/kernel/mac80211/patches/ath10k/911-ath10k-disable-caldata-prefetch-for-sdio-bus.patch @@ -0,0 +1,12 @@ +--- a/drivers/net/wireless/ath/ath10k/debug.c ++++ b/drivers/net/wireless/ath/ath10k/debug.c +@@ -1260,6 +1260,9 @@ static int ath10k_debug_cal_data_fetch(s + if (ar->hw_params.cal_data_len == 0) + return -EOPNOTSUPP; + ++ if (ar->hif.bus == ATH10K_BUS_SDIO) ++ return -EINVAL; ++ + hi_addr = host_interest_item_address(HI_ITEM(hi_board_data)); + + ret = ath10k_hif_diag_read(ar, hi_addr, &addr, sizeof(addr)); diff --git a/package/kernel/mac80211/patches/ath10k/921-ath10k_init_devices_synchronously.patch b/package/kernel/mac80211/patches/ath10k/921-ath10k_init_devices_synchronously.patch index 479c74e47..f5e702195 100644 --- a/package/kernel/mac80211/patches/ath10k/921-ath10k_init_devices_synchronously.patch +++ b/package/kernel/mac80211/patches/ath10k/921-ath10k_init_devices_synchronously.patch @@ -14,7 +14,7 @@ Signed-off-by: Sven Eckelmann --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c -@@ -3527,6 +3527,16 @@ int ath10k_core_register(struct ath10k * +@@ -3516,6 +3516,17 @@ int ath10k_core_register(struct ath10k * queue_work(ar->workqueue, &ar->register_work); @@ -26,7 +26,8 @@ Signed-off-by: Sven Eckelmann + * Forcing the work to be done immediately works around this problem + * but may also delay the boot when firmware images cannot be found. + */ -+ flush_workqueue(ar->workqueue); ++ if (ar->hif.bus != ATH10K_BUS_SDIO) ++ flush_workqueue(ar->workqueue); + return 0; } diff --git a/package/kernel/mac80211/patches/ath10k/930-ath10k_add_tpt_led_trigger.patch b/package/kernel/mac80211/patches/ath10k/930-ath10k_add_tpt_led_trigger.patch index c9ad4018c..e8beed17e 100644 --- a/package/kernel/mac80211/patches/ath10k/930-ath10k_add_tpt_led_trigger.patch +++ b/package/kernel/mac80211/patches/ath10k/930-ath10k_add_tpt_led_trigger.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c -@@ -9918,6 +9918,21 @@ static int ath10k_mac_init_rd(struct ath +@@ -9909,6 +9909,21 @@ static int ath10k_mac_init_rd(struct ath return 0; } @@ -22,7 +22,7 @@ int ath10k_mac_register(struct ath10k *ar) { static const u32 cipher_suites[] = { -@@ -10280,6 +10295,12 @@ int ath10k_mac_register(struct ath10k *a +@@ -10267,6 +10282,12 @@ int ath10k_mac_register(struct ath10k *a ar->hw->weight_multiplier = ATH10K_AIRTIME_WEIGHT_MULTIPLIER; diff --git a/package/kernel/mac80211/patches/ath10k/974-wifi-ath10k-add-LED-and-GPIO-controlling-support-for.patch b/package/kernel/mac80211/patches/ath10k/974-ath10k_add-LED-and-GPIO-controlling-support-for-various-chipsets.patch similarity index 67% rename from package/kernel/mac80211/patches/ath10k/974-wifi-ath10k-add-LED-and-GPIO-controlling-support-for.patch rename to package/kernel/mac80211/patches/ath10k/974-ath10k_add-LED-and-GPIO-controlling-support-for-various-chipsets.patch index a9eb38e57..fd5b44811 100644 --- a/package/kernel/mac80211/patches/ath10k/974-wifi-ath10k-add-LED-and-GPIO-controlling-support-for.patch +++ b/package/kernel/mac80211/patches/ath10k/974-ath10k_add-LED-and-GPIO-controlling-support-for-various-chipsets.patch @@ -1,52 +1,103 @@ -From 8e1debd82466a3fe711784ab37e6b54e56011267 Mon Sep 17 00:00:00 2001 -From: Sebastian Gottschall -Date: Mon, 13 May 2024 17:22:25 +0300 -Subject: [PATCH] wifi: ath10k: add LED and GPIO controlling support for - various chipsets +From: Sebastian Gottschall + +Adds LED and GPIO Control support for 988x, 9887, 9888, 99x0, 9984 based +chipsets with on chipset connected led's using WMI Firmware API. The LED +device will get available named as "ath10k-phyX" at sysfs and can be controlled +with various triggers. adds also debugfs interface for gpio control. + +This patch is specific for OpenWRt base, as is use old backported package +with old wireless source. Support for QCA9984 is removed and a simbol +is added to local-simbol file to export the actually compile the code +with the ATH10K_LEDS simbol. -Adds LED and GPIO Control support for 988x, 9887, 9888, 99x0, 9984 -based chipsets with on chipset connected led's using WMI Firmware API. -The LED device will get available named as "ath10k-phyX" at sysfs and -can be controlled with various triggers. -Adds also debugfs interface for gpio control. Signed-off-by: Sebastian Gottschall Reviewed-by: Steve deRosier [kvalo: major reorg and cleanup] Signed-off-by: Kalle Valo -[ansuel: rebase and small cleanup] -Signed-off-by: Christian Marangi -Tested-by: Stefan Lippers-Hollmann -Signed-off-by: Kalle Valo -Link: https://msgid.link/20230611080505.17393-1-ansuelsmth@gmail.com +Signed-off-by: Ansuel Smith --- - drivers/net/wireless/ath/ath10k/Kconfig | 6 ++ - drivers/net/wireless/ath/ath10k/Makefile | 1 + - drivers/net/wireless/ath/ath10k/core.c | 32 ++++++++ - drivers/net/wireless/ath/ath10k/core.h | 8 ++ - drivers/net/wireless/ath/ath10k/hw.h | 1 + - drivers/net/wireless/ath/ath10k/leds.c | 90 +++++++++++++++++++++++ - drivers/net/wireless/ath/ath10k/leds.h | 34 +++++++++ - drivers/net/wireless/ath/ath10k/mac.c | 1 + - drivers/net/wireless/ath/ath10k/wmi-ops.h | 32 ++++++++ - drivers/net/wireless/ath/ath10k/wmi-tlv.c | 2 + - drivers/net/wireless/ath/ath10k/wmi.c | 54 ++++++++++++++ - drivers/net/wireless/ath/ath10k/wmi.h | 35 +++++++++ - 12 files changed, 296 insertions(+) + +v13: + +* only compile tested! + +* fix all checkpatch warnings + +* fix commit log + +* sizeof(struct ath10k_gpiocontrol) -> sizeof(*gpio) + +* unsigned -> unsigned int + +* remove GPIOLIB code, that should be added in a separate patch + +* rename gpio.c to leds.c + +* add leds.h + +* rename some functions: + + ath10k_attach_led() -> ath10k_leds_register() + ath10k_unregister_led() -> ath10k_leds_unregister() + ath10k_reset_led_pin() -> ath10k_leds_start() + +* call ath10k_leds_unregister() before ath10k_thermal_unregister() to preserve ordering + +* call ath10k_leds_start() only from ath10k_core_start() and not from mac.c + +* rename struct ath10k_gpiocontrol as anonymous function under struct + ath10k::leds, no need for memory allocation + +* merge ath10k_add_led() to ath10k_attach_led(), which is it's only caller + +* remove #if IS_ENABLED() checks from most of places, memory savings from those were not worth it + +* Kconfig help text improvement and move it lower in the menu, also don't enable it by default + +* switch to set_brightness_blocking() so that the callback can sleep, + then no need to use ath10k_wmi_cmd_send_nowait() and can take mutex + to access ar->state + +* don't touch ath10k_wmi_pdev_get_temperature() + +* as QCA6174/QCA9377 are not (yet) supported don't add the command to WMI-TLV interface + +* remove debugfs interface, that should be added in another patch + +* cleanup includes + + + drivers/net/wireless/ath/ath10k/Kconfig | 10 +++ + drivers/net/wireless/ath/ath10k/Makefile | 1 + + drivers/net/wireless/ath/ath10k/core.c | 22 +++++++ + drivers/net/wireless/ath/ath10k/core.h | 9 ++- + drivers/net/wireless/ath/ath10k/hw.h | 1 + + drivers/net/wireless/ath/ath10k/leds.c | 103 ++++++++++++++++++++++++++++++ + drivers/net/wireless/ath/ath10k/leds.h | 45 +++++++++++++ + drivers/net/wireless/ath/ath10k/mac.c | 1 + + drivers/net/wireless/ath/ath10k/wmi-ops.h | 32 ++++++++++ + drivers/net/wireless/ath/ath10k/wmi-tlv.c | 2 + + drivers/net/wireless/ath/ath10k/wmi.c | 54 ++++++++++++++++ + drivers/net/wireless/ath/ath10k/wmi.h | 35 ++++++++++ + 12 files changed, 314 insertions(+), 1 deletion(-) create mode 100644 drivers/net/wireless/ath/ath10k/leds.c create mode 100644 drivers/net/wireless/ath/ath10k/leds.h - --- a/drivers/net/wireless/ath/ath10k/Kconfig +++ b/drivers/net/wireless/ath/ath10k/Kconfig -@@ -73,6 +73,12 @@ config ATH10K_DEBUGFS +@@ -71,6 +71,16 @@ config ATH10K_DEBUGFS If unsure, say Y to make it easier to debug problems. +config ATH10K_LEDS -+ bool ++ bool "Atheros ath10k LED support" + depends on ATH10K -+ depends on LEDS_CLASS=y || LEDS_CLASS=MAC80211 ++ select MAC80211_LEDS ++ select LEDS_CLASS ++ select NEW_LEDS + default y ++ ---help--- ++ This option is necessary, if you want LED support for chipset connected led pins. If unsure, say N. + config ATH10K_SPECTRAL bool "Atheros ath10k spectral scan support" @@ -63,7 +114,7 @@ Link: https://msgid.link/20230611080505.17393-1-ansuelsmth@gmail.com ath10k_core-$(CONFIG_DEV_COREDUMP) += coredump.o --- a/local-symbols +++ b/local-symbols -@@ -154,6 +154,7 @@ ATH10K_DEBUG= +@@ -162,6 +162,7 @@ ATH10K_DEBUG= ATH10K_DEBUGFS= ATH10K_SPECTRAL= ATH10K_THERMAL= @@ -73,7 +124,7 @@ Link: https://msgid.link/20230611080505.17393-1-ansuelsmth@gmail.com WCN36XX= --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c -@@ -27,6 +27,7 @@ +@@ -26,6 +26,7 @@ #include "testmode.h" #include "wmi-ops.h" #include "coredump.h" @@ -81,135 +132,47 @@ Link: https://msgid.link/20230611080505.17393-1-ansuelsmth@gmail.com unsigned int ath10k_debug_mask; EXPORT_SYMBOL(ath10k_debug_mask); -@@ -68,6 +69,7 @@ static const struct ath10k_hw_params ath +@@ -65,6 +66,7 @@ static const struct ath10k_hw_params ath + .dev_id = QCA988X_2_0_DEVICE_ID, + .bus = ATH10K_BUS_PCI, .name = "qca988x hw2.0", - .patch_load_addr = QCA988X_HW_2_0_PATCH_LOAD_ADDR, - .uart_pin = 7, + .led_pin = 1, - .cc_wraparound_type = ATH10K_HW_CC_WRAP_SHIFTED_ALL, - .otp_exe_param = 0, - .channel_counters_freq_hz = 88000, -@@ -109,6 +111,7 @@ static const struct ath10k_hw_params ath - .name = "qca988x hw2.0 ubiquiti", .patch_load_addr = QCA988X_HW_2_0_PATCH_LOAD_ADDR, .uart_pin = 7, -+ .led_pin = 0, .cc_wraparound_type = ATH10K_HW_CC_WRAP_SHIFTED_ALL, - .otp_exe_param = 0, - .channel_counters_freq_hz = 88000, -@@ -151,6 +154,7 @@ static const struct ath10k_hw_params ath +@@ -146,6 +148,7 @@ static const struct ath10k_hw_params ath + .dev_id = QCA9887_1_0_DEVICE_ID, + .bus = ATH10K_BUS_PCI, .name = "qca9887 hw1.0", ++ .led_pin = 1, .patch_load_addr = QCA9887_HW_1_0_PATCH_LOAD_ADDR, .uart_pin = 7, -+ .led_pin = 1, .cc_wraparound_type = ATH10K_HW_CC_WRAP_SHIFTED_ALL, - .otp_exe_param = 0, - .channel_counters_freq_hz = 88000, -@@ -193,6 +197,7 @@ static const struct ath10k_hw_params ath - .name = "qca6174 hw3.2 sdio", - .patch_load_addr = QCA6174_HW_3_0_PATCH_LOAD_ADDR, - .uart_pin = 19, -+ .led_pin = 0, - .otp_exe_param = 0, - .channel_counters_freq_hz = 88000, - .max_probe_resp_desc_thres = 0, -@@ -230,6 +235,7 @@ static const struct ath10k_hw_params ath - .name = "qca6164 hw2.1", - .patch_load_addr = QCA6174_HW_2_1_PATCH_LOAD_ADDR, - .uart_pin = 6, -+ .led_pin = 0, - .otp_exe_param = 0, - .channel_counters_freq_hz = 88000, - .max_probe_resp_desc_thres = 0, -@@ -271,6 +277,7 @@ static const struct ath10k_hw_params ath - .name = "qca6174 hw2.1", - .patch_load_addr = QCA6174_HW_2_1_PATCH_LOAD_ADDR, - .uart_pin = 6, -+ .led_pin = 0, - .otp_exe_param = 0, - .channel_counters_freq_hz = 88000, - .max_probe_resp_desc_thres = 0, -@@ -312,6 +319,7 @@ static const struct ath10k_hw_params ath - .name = "qca6174 hw3.0", - .patch_load_addr = QCA6174_HW_3_0_PATCH_LOAD_ADDR, - .uart_pin = 6, -+ .led_pin = 0, - .otp_exe_param = 0, - .channel_counters_freq_hz = 88000, - .max_probe_resp_desc_thres = 0, -@@ -353,6 +361,7 @@ static const struct ath10k_hw_params ath - .name = "qca6174 hw3.2", - .patch_load_addr = QCA6174_HW_3_0_PATCH_LOAD_ADDR, - .uart_pin = 6, -+ .led_pin = 0, - .otp_exe_param = 0, - .channel_counters_freq_hz = 88000, - .max_probe_resp_desc_thres = 0, -@@ -398,6 +407,7 @@ static const struct ath10k_hw_params ath +@@ -387,6 +390,7 @@ static const struct ath10k_hw_params ath + .dev_id = QCA99X0_2_0_DEVICE_ID, + .bus = ATH10K_BUS_PCI, .name = "qca99x0 hw2.0", ++ .led_pin = 17, .patch_load_addr = QCA99X0_HW_2_0_PATCH_LOAD_ADDR, .uart_pin = 7, -+ .led_pin = 17, .otp_exe_param = 0x00000700, - .continuous_frag_desc = true, - .cck_rate_map_rev2 = true, -@@ -445,6 +455,7 @@ static const struct ath10k_hw_params ath +@@ -433,6 +437,7 @@ static const struct ath10k_hw_params ath + .dev_id = QCA9984_1_0_DEVICE_ID, + .bus = ATH10K_BUS_PCI, .name = "qca9984/qca9994 hw1.0", ++ .led_pin = 17, .patch_load_addr = QCA9984_HW_1_0_PATCH_LOAD_ADDR, .uart_pin = 7, -+ .led_pin = 17, .cc_wraparound_type = ATH10K_HW_CC_WRAP_SHIFTED_EACH, - .otp_exe_param = 0x00000700, - .continuous_frag_desc = true, -@@ -499,6 +510,7 @@ static const struct ath10k_hw_params ath +@@ -486,6 +491,7 @@ static const struct ath10k_hw_params ath + .dev_id = QCA9888_2_0_DEVICE_ID, + .bus = ATH10K_BUS_PCI, .name = "qca9888 hw2.0", ++ .led_pin = 17, .patch_load_addr = QCA9888_HW_2_0_PATCH_LOAD_ADDR, .uart_pin = 7, -+ .led_pin = 17, .cc_wraparound_type = ATH10K_HW_CC_WRAP_SHIFTED_EACH, - .otp_exe_param = 0x00000700, - .continuous_frag_desc = true, -@@ -550,6 +562,7 @@ static const struct ath10k_hw_params ath - .name = "qca9377 hw1.0", - .patch_load_addr = QCA9377_HW_1_0_PATCH_LOAD_ADDR, - .uart_pin = 6, -+ .led_pin = 0, - .otp_exe_param = 0, - .channel_counters_freq_hz = 88000, - .max_probe_resp_desc_thres = 0, -@@ -591,6 +604,7 @@ static const struct ath10k_hw_params ath - .name = "qca9377 hw1.1", - .patch_load_addr = QCA9377_HW_1_0_PATCH_LOAD_ADDR, - .uart_pin = 6, -+ .led_pin = 0, - .otp_exe_param = 0, - .channel_counters_freq_hz = 88000, - .max_probe_resp_desc_thres = 0, -@@ -634,6 +648,7 @@ static const struct ath10k_hw_params ath - .name = "qca9377 hw1.1 sdio", - .patch_load_addr = QCA9377_HW_1_0_PATCH_LOAD_ADDR, - .uart_pin = 19, -+ .led_pin = 0, - .otp_exe_param = 0, - .channel_counters_freq_hz = 88000, - .max_probe_resp_desc_thres = 0, -@@ -668,6 +683,7 @@ static const struct ath10k_hw_params ath - .name = "qca4019 hw1.0", - .patch_load_addr = QCA4019_HW_1_0_PATCH_LOAD_ADDR, - .uart_pin = 7, -+ .led_pin = 0, - .cc_wraparound_type = ATH10K_HW_CC_WRAP_SHIFTED_EACH, - .otp_exe_param = 0x0010000, - .continuous_frag_desc = true, -@@ -714,6 +730,7 @@ static const struct ath10k_hw_params ath - .dev_id = 0, - .bus = ATH10K_BUS_SNOC, - .name = "wcn3990 hw1.0", -+ .led_pin = 0, - .continuous_frag_desc = true, - .tx_chain_mask = 0x7, - .rx_chain_mask = 0x7, -@@ -3242,6 +3259,10 @@ int ath10k_core_start(struct ath10k *ar, +@@ -3231,6 +3237,10 @@ int ath10k_core_start(struct ath10k *ar, goto err_hif_stop; } @@ -220,7 +183,7 @@ Link: https://msgid.link/20230611080505.17393-1-ansuelsmth@gmail.com return 0; err_hif_stop: -@@ -3500,9 +3521,18 @@ static void ath10k_core_register_work(st +@@ -3489,9 +3499,18 @@ static void ath10k_core_register_work(st goto err_spectral_destroy; } @@ -239,7 +202,7 @@ Link: https://msgid.link/20230611080505.17393-1-ansuelsmth@gmail.com err_spectral_destroy: ath10k_spectral_destroy(ar); err_debug_destroy: -@@ -3548,6 +3578,8 @@ void ath10k_core_unregister(struct ath10 +@@ -3538,6 +3557,8 @@ void ath10k_core_unregister(struct ath10 if (!test_bit(ATH10K_FLAG_CORE_REGISTERED, &ar->dev_flags)) return; @@ -250,7 +213,7 @@ Link: https://msgid.link/20230611080505.17393-1-ansuelsmth@gmail.com * relayfs debugfs file cleanly. Otherwise the parent debugfs tree --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h -@@ -15,6 +15,7 @@ +@@ -14,6 +14,7 @@ #include #include #include @@ -258,7 +221,7 @@ Link: https://msgid.link/20230611080505.17393-1-ansuelsmth@gmail.com #include "htt.h" #include "htc.h" -@@ -1257,6 +1258,13 @@ struct ath10k { +@@ -1253,6 +1254,13 @@ struct ath10k { } testmode; struct { @@ -274,7 +237,7 @@ Link: https://msgid.link/20230611080505.17393-1-ansuelsmth@gmail.com u32 fw_crash_counter; --- a/drivers/net/wireless/ath/ath10k/hw.h +++ b/drivers/net/wireless/ath/ath10k/hw.h -@@ -521,6 +521,7 @@ struct ath10k_hw_params { +@@ -519,6 +519,7 @@ struct ath10k_hw_params { const char *name; u32 patch_load_addr; int uart_pin; @@ -284,13 +247,24 @@ Link: https://msgid.link/20230611080505.17393-1-ansuelsmth@gmail.com /* Type of hw cycle counter wraparound logic, for more info --- /dev/null +++ b/drivers/net/wireless/ath/ath10k/leds.c -@@ -0,0 +1,90 @@ -+// SPDX-License-Identifier: ISC +@@ -0,0 +1,103 @@ +/* + * Copyright (c) 2005-2011 Atheros Communications Inc. + * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. + * Copyright (c) 2018 Sebastian Gottschall -+ * Copyright (c) 2018 The Linux Foundation. All rights reserved. ++ * Copyright (c) 2018, The Linux Foundation. All rights reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ++ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ++ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include @@ -357,6 +331,8 @@ Link: https://msgid.link/20230611080505.17393-1-ansuelsmth@gmail.com + + ar->leds.cdev.name = ar->leds.label; + ar->leds.cdev.brightness_set_blocking = ath10k_leds_set_brightness_blocking; ++ ++ /* FIXME: this assignment doesn't make sense as it's NULL, remove it? */ + ar->leds.cdev.default_trigger = ar->leds.wifi_led.default_trigger; + + ret = led_classdev_register(wiphy_dev(ar->hw->wiphy), &ar->leds.cdev); @@ -377,15 +353,22 @@ Link: https://msgid.link/20230611080505.17393-1-ansuelsmth@gmail.com + --- /dev/null +++ b/drivers/net/wireless/ath/ath10k/leds.h -@@ -0,0 +1,34 @@ -+/* SPDX-License-Identifier: ISC */ +@@ -0,0 +1,41 @@ +/* -+ * Copyright (c) 2005-2011 Atheros Communications Inc. -+ * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. -+ * Copyright (c) 2018 Sebastian Gottschall -+ * Copyright (c) 2018 The Linux Foundation. All rights reserved. ++ * Copyright (c) 2018, The Linux Foundation. All rights reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ++ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ++ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ -+ +#ifndef _LEDS_H_ +#define _LEDS_H_ + @@ -414,7 +397,7 @@ Link: https://msgid.link/20230611080505.17393-1-ansuelsmth@gmail.com +#endif /* _LEDS_H_ */ --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c -@@ -25,6 +25,7 @@ +@@ -24,6 +24,7 @@ #include "wmi-tlv.h" #include "wmi-ops.h" #include "wow.h" @@ -473,7 +456,7 @@ Link: https://msgid.link/20230611080505.17393-1-ansuelsmth@gmail.com { --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c -@@ -4606,6 +4606,8 @@ static const struct wmi_ops wmi_tlv_ops +@@ -4594,6 +4594,8 @@ static const struct wmi_ops wmi_tlv_ops .gen_echo = ath10k_wmi_tlv_op_gen_echo, .gen_vdev_spectral_conf = ath10k_wmi_tlv_op_gen_vdev_spectral_conf, .gen_vdev_spectral_enable = ath10k_wmi_tlv_op_gen_vdev_spectral_enable, @@ -484,7 +467,7 @@ Link: https://msgid.link/20230611080505.17393-1-ansuelsmth@gmail.com static const struct wmi_peer_flags_map wmi_tlv_peer_flags_map = { --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c -@@ -7493,6 +7493,49 @@ ath10k_wmi_op_gen_peer_set_param(struct +@@ -7472,6 +7472,49 @@ ath10k_wmi_op_gen_peer_set_param(struct return skb; } @@ -534,7 +517,7 @@ Link: https://msgid.link/20230611080505.17393-1-ansuelsmth@gmail.com static struct sk_buff * ath10k_wmi_op_gen_set_psmode(struct ath10k *ar, u32 vdev_id, enum wmi_sta_ps_mode psmode) -@@ -9157,6 +9200,9 @@ static const struct wmi_ops wmi_ops = { +@@ -9160,6 +9203,9 @@ static const struct wmi_ops wmi_ops = { .fw_stats_fill = ath10k_wmi_main_op_fw_stats_fill, .get_vdev_subtype = ath10k_wmi_op_get_vdev_subtype, .gen_echo = ath10k_wmi_op_gen_echo, @@ -544,7 +527,7 @@ Link: https://msgid.link/20230611080505.17393-1-ansuelsmth@gmail.com /* .gen_bcn_tmpl not implemented */ /* .gen_prb_tmpl not implemented */ /* .gen_p2p_go_bcn_ie not implemented */ -@@ -9227,6 +9273,8 @@ static const struct wmi_ops wmi_10_1_ops +@@ -9230,6 +9276,8 @@ static const struct wmi_ops wmi_10_1_ops .fw_stats_fill = ath10k_wmi_10x_op_fw_stats_fill, .get_vdev_subtype = ath10k_wmi_op_get_vdev_subtype, .gen_echo = ath10k_wmi_op_gen_echo, @@ -553,7 +536,7 @@ Link: https://msgid.link/20230611080505.17393-1-ansuelsmth@gmail.com /* .gen_bcn_tmpl not implemented */ /* .gen_prb_tmpl not implemented */ /* .gen_p2p_go_bcn_ie not implemented */ -@@ -9299,6 +9347,8 @@ static const struct wmi_ops wmi_10_2_ops +@@ -9302,6 +9350,8 @@ static const struct wmi_ops wmi_10_2_ops .gen_delba_send = ath10k_wmi_op_gen_delba_send, .fw_stats_fill = ath10k_wmi_10x_op_fw_stats_fill, .get_vdev_subtype = ath10k_wmi_op_get_vdev_subtype, @@ -562,7 +545,7 @@ Link: https://msgid.link/20230611080505.17393-1-ansuelsmth@gmail.com /* .gen_pdev_enable_adaptive_cca not implemented */ }; -@@ -9370,6 +9420,8 @@ static const struct wmi_ops wmi_10_2_4_o +@@ -9373,6 +9423,8 @@ static const struct wmi_ops wmi_10_2_4_o ath10k_wmi_op_gen_pdev_enable_adaptive_cca, .get_vdev_subtype = ath10k_wmi_10_2_4_op_get_vdev_subtype, .gen_bb_timing = ath10k_wmi_10_2_4_op_gen_bb_timing, @@ -571,7 +554,7 @@ Link: https://msgid.link/20230611080505.17393-1-ansuelsmth@gmail.com /* .gen_bcn_tmpl not implemented */ /* .gen_prb_tmpl not implemented */ /* .gen_p2p_go_bcn_ie not implemented */ -@@ -9451,6 +9503,8 @@ static const struct wmi_ops wmi_10_4_ops +@@ -9454,6 +9506,8 @@ static const struct wmi_ops wmi_10_4_ops .gen_pdev_bss_chan_info_req = ath10k_wmi_10_2_op_gen_pdev_bss_chan_info, .gen_echo = ath10k_wmi_op_gen_echo, .gen_pdev_get_tpc_config = ath10k_wmi_10_2_4_op_gen_pdev_get_tpc_config, @@ -582,11 +565,11 @@ Link: https://msgid.link/20230611080505.17393-1-ansuelsmth@gmail.com int ath10k_wmi_attach(struct ath10k *ar) --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h -@@ -3034,6 +3034,41 @@ enum wmi_10_4_feature_mask { +@@ -3030,6 +3030,41 @@ enum wmi_10_4_feature_mask { }; -+/* WMI_GPIO_CPTCFG_CMDID */ ++/* WMI_GPIO_CONFIG_CMDID */ +enum { + WMI_GPIO_PULL_NONE, + WMI_GPIO_PULL_UP, @@ -602,7 +585,7 @@ Link: https://msgid.link/20230611080505.17393-1-ansuelsmth@gmail.com + WMI_GPIO_INTTYPE_LEVEL_HIGH +}; + -+/* WMI_GPIO_CPTCFG_CMDID */ ++/* WMI_GPIO_CONFIG_CMDID */ +struct wmi_gpio_config_cmd { + __le32 gpio_num; /* GPIO number to be setup */ + __le32 input; /* 0 - Output/ 1 - Input */ diff --git a/package/kernel/mac80211/patches/ath10k/975-ath10k-use-tpt-trigger-by-default.patch b/package/kernel/mac80211/patches/ath10k/975-ath10k-use-tpt-trigger-by-default.patch index 5bd9186d1..4c1f9aa81 100644 --- a/package/kernel/mac80211/patches/ath10k/975-ath10k-use-tpt-trigger-by-default.patch +++ b/package/kernel/mac80211/patches/ath10k/975-ath10k-use-tpt-trigger-by-default.patch @@ -16,7 +16,7 @@ Signed-off-by: Mathias Kresin --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h -@@ -1313,6 +1313,10 @@ struct ath10k { +@@ -1309,6 +1309,10 @@ struct ath10k { s32 tx_power_2g_limit; s32 tx_power_5g_limit; @@ -29,10 +29,12 @@ Signed-off-by: Mathias Kresin }; --- a/drivers/net/wireless/ath/ath10k/leds.c +++ b/drivers/net/wireless/ath/ath10k/leds.c -@@ -70,7 +70,7 @@ int ath10k_leds_register(struct ath10k * +@@ -81,9 +81,7 @@ int ath10k_leds_register(struct ath10k * ar->leds.cdev.name = ar->leds.label; ar->leds.cdev.brightness_set_blocking = ath10k_leds_set_brightness_blocking; +- +- /* FIXME: this assignment doesn't make sense as it's NULL, remove it? */ - ar->leds.cdev.default_trigger = ar->leds.wifi_led.default_trigger; + ar->leds.cdev.default_trigger = ar->led_default_trigger; @@ -40,7 +42,7 @@ Signed-off-by: Mathias Kresin if (ret) --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c -@@ -10297,7 +10297,7 @@ int ath10k_mac_register(struct ath10k *a +@@ -10284,7 +10284,7 @@ int ath10k_mac_register(struct ath10k *a ar->hw->weight_multiplier = ATH10K_AIRTIME_WEIGHT_MULTIPLIER; #ifdef CPTCFG_MAC80211_LEDS diff --git a/package/kernel/mac80211/patches/ath10k/981-ath10k-adjust-tx-power-reduction-for-US-regulatory-d.patch b/package/kernel/mac80211/patches/ath10k/981-ath10k-adjust-tx-power-reduction-for-US-regulatory-d.patch index f1770cfbe..3626debf1 100644 --- a/package/kernel/mac80211/patches/ath10k/981-ath10k-adjust-tx-power-reduction-for-US-regulatory-d.patch +++ b/package/kernel/mac80211/patches/ath10k/981-ath10k-adjust-tx-power-reduction-for-US-regulatory-d.patch @@ -28,7 +28,7 @@ Forwarded: no --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c -@@ -1022,6 +1022,40 @@ static inline int ath10k_vdev_setup_sync +@@ -1028,6 +1028,40 @@ static inline int ath10k_vdev_setup_sync return ar->last_wmi_vdev_start_status; } @@ -69,7 +69,7 @@ Forwarded: no static int ath10k_monitor_vdev_start(struct ath10k *ar, int vdev_id) { struct cfg80211_chan_def *chandef = NULL; -@@ -1054,7 +1088,8 @@ static int ath10k_monitor_vdev_start(str +@@ -1060,7 +1094,8 @@ static int ath10k_monitor_vdev_start(str arg.channel.min_power = 0; arg.channel.max_power = channel->max_power * 2; arg.channel.max_reg_power = channel->max_reg_power * 2; @@ -79,7 +79,7 @@ Forwarded: no reinit_completion(&ar->vdev_setup_done); reinit_completion(&ar->vdev_delete_done); -@@ -1500,7 +1535,8 @@ static int ath10k_vdev_start_restart(str +@@ -1506,7 +1541,8 @@ static int ath10k_vdev_start_restart(str arg.channel.min_power = 0; arg.channel.max_power = chandef->chan->max_power * 2; arg.channel.max_reg_power = chandef->chan->max_reg_power * 2; @@ -89,7 +89,7 @@ Forwarded: no if (arvif->vdev_type == WMI_VDEV_TYPE_AP) { arg.ssid = arvif->u.ap.ssid; -@@ -3431,7 +3467,8 @@ static int ath10k_update_channel_list(st +@@ -3437,7 +3473,8 @@ static int ath10k_update_channel_list(st ch->min_power = 0; ch->max_power = channel->max_power * 2; ch->max_reg_power = channel->max_reg_power * 2; diff --git a/package/kernel/mac80211/patches/ath10k/984-ath10k-Try-to-get-mac-address-from-dts.patch b/package/kernel/mac80211/patches/ath10k/984-ath10k-Try-to-get-mac-address-from-dts.patch index 5d70df15a..084e28a2d 100644 --- a/package/kernel/mac80211/patches/ath10k/984-ath10k-Try-to-get-mac-address-from-dts.patch +++ b/package/kernel/mac80211/patches/ath10k/984-ath10k-Try-to-get-mac-address-from-dts.patch @@ -18,7 +18,7 @@ Signed-off-by: Ansuel Smith --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c -@@ -9,6 +9,7 @@ +@@ -8,6 +8,7 @@ #include #include #include @@ -26,7 +26,7 @@ Signed-off-by: Ansuel Smith #include #include #include -@@ -3429,6 +3430,8 @@ static int ath10k_core_probe_fw(struct a +@@ -3407,6 +3408,8 @@ static int ath10k_core_probe_fw(struct a device_get_mac_address(ar->dev, ar->mac_addr); diff --git a/package/kernel/mac80211/patches/ath10k/985-ath10k-allow-vht-on-2g.patch b/package/kernel/mac80211/patches/ath10k/985-ath10k-allow-vht-on-2g.patch new file mode 100644 index 000000000..3fb26bff9 --- /dev/null +++ b/package/kernel/mac80211/patches/ath10k/985-ath10k-allow-vht-on-2g.patch @@ -0,0 +1,10 @@ +--- a/drivers/net/wireless/ath/ath10k/mac.c ++++ b/drivers/net/wireless/ath/ath10k/mac.c +@@ -5034,6 +5034,7 @@ static void ath10k_mac_setup_ht_vht_cap( + if (ar->phy_capability & WHAL_WLAN_11G_CAPABILITY) { + band = &ar->mac.sbands[NL80211_BAND_2GHZ]; + band->ht_cap = ht_cap; ++ band->vht_cap = vht_cap; + } + if (ar->phy_capability & WHAL_WLAN_11A_CAPABILITY) { + band = &ar->mac.sbands[NL80211_BAND_5GHZ]; diff --git a/package/kernel/mac80211/patches/ath10k/988-ath10k-always-use-mac80211-loss-detection.patch b/package/kernel/mac80211/patches/ath10k/988-ath10k-always-use-mac80211-loss-detection.patch index b9cdae7e1..f4b1ded15 100644 --- a/package/kernel/mac80211/patches/ath10k/988-ath10k-always-use-mac80211-loss-detection.patch +++ b/package/kernel/mac80211/patches/ath10k/988-ath10k-always-use-mac80211-loss-detection.patch @@ -18,7 +18,7 @@ Signed-off-by: David Bauer --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c -@@ -10089,7 +10089,6 @@ int ath10k_mac_register(struct ath10k *a +@@ -10081,7 +10081,6 @@ int ath10k_mac_register(struct ath10k *a ieee80211_hw_set(ar->hw, CHANCTX_STA_CSA); ieee80211_hw_set(ar->hw, QUEUE_CONTROL); ieee80211_hw_set(ar->hw, SUPPORTS_TX_FRAG); diff --git a/package/kernel/mac80211/patches/ath10k/990-ath10k-small-buffers.patch b/package/kernel/mac80211/patches/ath10k/990-ath10k-small-buffers.patch index 755982a7d..2f560c70a 100644 --- a/package/kernel/mac80211/patches/ath10k/990-ath10k-small-buffers.patch +++ b/package/kernel/mac80211/patches/ath10k/990-ath10k-small-buffers.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/ath/ath10k/htt.h +++ b/drivers/net/wireless/ath/ath10k/htt.h -@@ -236,7 +236,11 @@ enum htt_rx_ring_flags { +@@ -235,7 +235,11 @@ enum htt_rx_ring_flags { }; #define HTT_RX_RING_SIZE_MIN 128 @@ -14,7 +14,7 @@ #define HTT_RX_RING_FILL_LEVEL_DUAL_MAC (HTT_RX_RING_SIZE - 1) --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c -@@ -132,7 +132,11 @@ static const struct ce_attr pci_host_ce_ +@@ -131,7 +131,11 @@ static const struct ce_attr pci_host_ce_ .flags = CE_ATTR_FLAGS, .src_nentries = 0, .src_sz_max = 2048, @@ -26,7 +26,7 @@ .recv_cb = ath10k_pci_htt_htc_rx_cb, }, -@@ -141,7 +145,11 @@ static const struct ce_attr pci_host_ce_ +@@ -140,7 +144,11 @@ static const struct ce_attr pci_host_ce_ .flags = CE_ATTR_FLAGS, .src_nentries = 0, .src_sz_max = 2048, @@ -38,7 +38,7 @@ .recv_cb = ath10k_pci_htc_rx_cb, }, -@@ -168,7 +176,11 @@ static const struct ce_attr pci_host_ce_ +@@ -167,7 +175,11 @@ static const struct ce_attr pci_host_ce_ .flags = CE_ATTR_FLAGS, .src_nentries = 0, .src_sz_max = 512, @@ -50,7 +50,7 @@ .recv_cb = ath10k_pci_htt_rx_cb, }, -@@ -193,7 +205,11 @@ static const struct ce_attr pci_host_ce_ +@@ -192,7 +204,11 @@ static const struct ce_attr pci_host_ce_ .flags = CE_ATTR_FLAGS, .src_nentries = 0, .src_sz_max = 2048, diff --git a/package/kernel/mac80211/patches/ath11k/0001-wifi-ath11k-stop-tx-queues-immediately-upon-firmware.patch b/package/kernel/mac80211/patches/ath11k/0001-wifi-ath11k-stop-tx-queues-immediately-upon-firmware.patch new file mode 100644 index 000000000..d0dc04feb --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0001-wifi-ath11k-stop-tx-queues-immediately-upon-firmware.patch @@ -0,0 +1,78 @@ +From 81e60b2dfb2744ab6642c4aa62534b4f711fdc5d Mon Sep 17 00:00:00 2001 +From: Aditya Kumar Singh +Date: Tue, 27 Sep 2022 09:18:54 +0300 +Subject: [PATCH] wifi: ath11k: stop tx queues immediately upon firmware exit + +Currently, recovery flag is set immediately upon firmware +exit but tx queues are stopped once firmware arrives back +and is ready which is during ath11k_core_restart. Once +ieee80211 hw restart is completed, tx queues are resumed. +If during the time delta between firmware exit and firmware +ready, mac80211 send packets, currently ath11k will drop it +since recovery flag will be set. But warning prints will +come - + "ath11k c000000.wifi: failed to transmit frame -108" + +If more tx packets are there, this could lead to flooding +of above print. + +However, actually tx queues should be stopped immediately +when firmware leaves. This will prevent packets to get +dropped when firmware is recovering. + +Add fix to stop tx queues immediately after firmware exit. + +Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.5.0.1-01100-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Aditya Kumar Singh +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20220923170235.18873-1-quic_adisi@quicinc.com +--- + drivers/net/wireless/ath/ath11k/core.c | 5 +---- + drivers/net/wireless/ath/ath11k/core.h | 1 + + drivers/net/wireless/ath/ath11k/qmi.c | 3 +++ + 3 files changed, 5 insertions(+), 4 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/core.c ++++ b/drivers/net/wireless/ath/ath11k/core.c +@@ -1641,7 +1641,7 @@ static void ath11k_update_11d(struct wor + } + } + +-static void ath11k_core_pre_reconfigure_recovery(struct ath11k_base *ab) ++void ath11k_core_pre_reconfigure_recovery(struct ath11k_base *ab) + { + struct ath11k *ar; + struct ath11k_pdev *pdev; +@@ -1730,9 +1730,6 @@ static void ath11k_core_restart(struct w + struct ath11k_base *ab = container_of(work, struct ath11k_base, restart_work); + int ret; + +- if (!ab->is_reset) +- ath11k_core_pre_reconfigure_recovery(ab); +- + ret = ath11k_core_reconfigure_on_crash(ab); + if (ret) { + ath11k_err(ab, "failed to reconfigure driver on crash recovery\n"); +--- a/drivers/net/wireless/ath/ath11k/core.h ++++ b/drivers/net/wireless/ath/ath11k/core.h +@@ -1158,6 +1158,7 @@ int ath11k_core_check_smbios(struct ath1 + void ath11k_core_halt(struct ath11k *ar); + int ath11k_core_resume(struct ath11k_base *ab); + int ath11k_core_suspend(struct ath11k_base *ab); ++void ath11k_core_pre_reconfigure_recovery(struct ath11k_base *ab); + + const struct firmware *ath11k_core_firmware_request(struct ath11k_base *ab, + const char *filename); +--- a/drivers/net/wireless/ath/ath11k/qmi.c ++++ b/drivers/net/wireless/ath/ath11k/qmi.c +@@ -3164,6 +3164,9 @@ static void ath11k_qmi_driver_event_work + case ATH11K_QMI_EVENT_SERVER_EXIT: + set_bit(ATH11K_FLAG_CRASH_FLUSH, &ab->dev_flags); + set_bit(ATH11K_FLAG_RECOVERY, &ab->dev_flags); ++ ++ if (!ab->is_reset) ++ ath11k_core_pre_reconfigure_recovery(ab); + break; + case ATH11K_QMI_EVENT_REQUEST_MEM: + ret = ath11k_qmi_event_mem_request(qmi); diff --git a/package/kernel/mac80211/patches/ath11k/0002-wifi-ath11k-Don-t-exit-on-wakeup-failure.patch b/package/kernel/mac80211/patches/ath11k/0002-wifi-ath11k-Don-t-exit-on-wakeup-failure.patch new file mode 100644 index 000000000..47385e045 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0002-wifi-ath11k-Don-t-exit-on-wakeup-failure.patch @@ -0,0 +1,45 @@ +From 45d2e268369b0c768d5a644f319758bcfd370521 Mon Sep 17 00:00:00 2001 +From: Baochen Qiang +Date: Wed, 28 Sep 2022 09:51:40 +0800 +Subject: [PATCH] wifi: ath11k: Don't exit on wakeup failure + +Currently, ath11k_pcic_read() returns an error if wakeup() +fails, this makes firmware crash debug quite hard because we can +get nothing. + +Change to go ahead on wakeup failure, in that case we still may +get something valid to check. There should be no mislead due +to incorrect content because we are aware of the failure with the +log printed. + +Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-01720.1-QCAHSPSWPL_V1_V2_SILICONZ_LITE-1 + +Signed-off-by: Baochen Qiang +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20220928015140.5431-1-quic_bqiang@quicinc.com +--- + drivers/net/wireless/ath/ath11k/pcic.c | 13 ++++++++++--- + 1 file changed, 10 insertions(+), 3 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/pcic.c ++++ b/drivers/net/wireless/ath/ath11k/pcic.c +@@ -218,9 +218,16 @@ int ath11k_pcic_read(struct ath11k_base + if (wakeup_required && ab->pci.ops->wakeup) { + ret = ab->pci.ops->wakeup(ab); + if (ret) { +- ath11k_warn(ab, "failed to wakeup for read from 0x%x: %d\n", +- start, ret); +- return ret; ++ ath11k_warn(ab, ++ "wakeup failed, data may be invalid: %d", ++ ret); ++ /* Even though wakeup() failed, continue processing rather ++ * than returning because some parts of the data may still ++ * be valid and useful in some cases, e.g. could give us ++ * some clues on firmware crash. ++ * Mislead due to invalid data could be avoided because we ++ * are aware of the wakeup failure. ++ */ + } + } + diff --git a/package/kernel/mac80211/patches/ath11k/0005-wifi-ath11k-Fix-spelling-mistake-chnange-change.patch b/package/kernel/mac80211/patches/ath11k/0005-wifi-ath11k-Fix-spelling-mistake-chnange-change.patch new file mode 100644 index 000000000..4b52252ef --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0005-wifi-ath11k-Fix-spelling-mistake-chnange-change.patch @@ -0,0 +1,25 @@ +From a797f479bf3e02c6d179c2e6aeace7f9b22b0acd Mon Sep 17 00:00:00 2001 +From: Colin Ian King +Date: Wed, 28 Sep 2022 15:38:34 +0100 +Subject: [PATCH] wifi: ath11k: Fix spelling mistake "chnange" -> "change" + +There is a spelling mistake in an ath11k_dbg debug message. Fix it. + +Signed-off-by: Colin Ian King +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20220928143834.35189-1-colin.i.king@gmail.com +--- + drivers/net/wireless/ath/ath11k/wmi.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/wireless/ath/ath11k/wmi.c ++++ b/drivers/net/wireless/ath/ath11k/wmi.c +@@ -6829,7 +6829,7 @@ static void ath11k_wmi_event_peer_sta_ps + } + + ath11k_dbg(ab, ATH11K_DBG_WMI, +- "peer sta ps chnange ev addr %pM state %u sup_bitmap %x ps_valid %u ts %u\n", ++ "peer sta ps change ev addr %pM state %u sup_bitmap %x ps_valid %u ts %u\n", + ev->peer_macaddr.addr, ev->peer_ps_state, + ev->ps_supported_bitmap, ev->peer_ps_valid, + ev->peer_ps_timestamp); diff --git a/package/kernel/mac80211/patches/ath11k/0007-wifi-ath11k-suppress-add-interface-error.patch b/package/kernel/mac80211/patches/ath11k/0007-wifi-ath11k-suppress-add-interface-error.patch new file mode 100644 index 000000000..fbef0abb8 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0007-wifi-ath11k-suppress-add-interface-error.patch @@ -0,0 +1,52 @@ +From 638b26652b0438563a76ec90014c8cba34db982b Mon Sep 17 00:00:00 2001 +From: Karthikeyan Periyasamy +Date: Thu, 6 Oct 2022 06:28:42 +0530 +Subject: [PATCH 7/9] wifi: ath11k: suppress add interface error + +In the VIF (other than monitor type) creation request, we should not +throw the error code when the monitor VIF creation fails, since the +actual VIF creation succeeds. If we throw the error code from driver +then the actual VIF creation get fail. So suppress the monitor VIF +creation error by throwing warning message instead of error code. + +Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.6.0.1-00760-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Karthikeyan Periyasamy +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20221006005842.8599-1-quic_periyasa@quicinc.com +--- + drivers/net/wireless/ath/ath11k/mac.c | 9 +++------ + 1 file changed, 3 insertions(+), 6 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -6421,18 +6421,16 @@ static int ath11k_mac_op_add_interface(s + + ath11k_dp_vdev_tx_attach(ar, arvif); + ++ ath11k_debugfs_add_interface(arvif); ++ + if (vif->type != NL80211_IFTYPE_MONITOR && + test_bit(ATH11K_FLAG_MONITOR_CONF_ENABLED, &ar->monitor_flags)) { + ret = ath11k_mac_monitor_vdev_create(ar); +- if (ret) { ++ if (ret) + ath11k_warn(ar->ab, "failed to create monitor vdev during add interface: %d", + ret); +- goto err_peer_del; +- } + } + +- ath11k_debugfs_add_interface(arvif); +- + mutex_unlock(&ar->conf_mutex); + + return 0; +@@ -6457,7 +6455,6 @@ err_vdev_del: + spin_unlock_bh(&ar->data_lock); + + err: +- ath11k_debugfs_remove_interface(arvif); + mutex_unlock(&ar->conf_mutex); + + return ret; diff --git a/package/kernel/mac80211/patches/ath11k/0008-wifi-ath11k-add-support-to-configure-channel-dwell-t.patch b/package/kernel/mac80211/patches/ath11k/0008-wifi-ath11k-add-support-to-configure-channel-dwell-t.patch new file mode 100644 index 000000000..d0b19fe59 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0008-wifi-ath11k-add-support-to-configure-channel-dwell-t.patch @@ -0,0 +1,102 @@ +From c362daa213cdeb0a9e7c2ed84849544c24505720 Mon Sep 17 00:00:00 2001 +From: Manikanta Pubbisetty +Date: Fri, 7 Oct 2022 10:41:30 +0530 +Subject: [PATCH 8/9] wifi: ath11k: add support to configure channel dwell time + +Add support to configure channel dwell time during scan. +Dwell time help to stay on the channel for a specified duration +during scan and aid userspace in finding WiFi networks. Very +useful in passive scans where longer dwell times are needed +to find the WiFi networks. + +Configure channel dwell time from duration of the scan request +received from mac80211 when the duration is non-zero. When the +scan request does not have duration value, use the default ones, +the current implementation. + +Advertise corresponding feature flag NL80211_EXT_FEATURE_SET_SCAN_DWELL +to enable the feature. + +Change is applicable for all ath11k hardware. + +Tested-on: WCN6750 hw1.0 AHB WLAN.MSL.1.0.1-00887-QCAMSLSWPLZ-1 + +Signed-off-by: Manikanta Pubbisetty +Reviewed-by: Jeff Johnson +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20221007051130.6067-1-quic_mpubbise@quicinc.com +--- + drivers/net/wireless/ath/ath11k/mac.c | 33 +++++++++++++++++++++++---- + 1 file changed, 29 insertions(+), 4 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -241,7 +241,10 @@ const struct htt_rx_ring_tlv_filter ath1 + #define ath11k_a_rates (ath11k_legacy_rates + 4) + #define ath11k_a_rates_size (ARRAY_SIZE(ath11k_legacy_rates) - 4) + +-#define ATH11K_MAC_SCAN_TIMEOUT_MSECS 200 /* in msecs */ ++#define ATH11K_MAC_SCAN_CMD_EVT_OVERHEAD 200 /* in msecs */ ++ ++/* Overhead due to the processing of channel switch events from FW */ ++#define ATH11K_SCAN_CHANNEL_SWITCH_WMI_EVT_OVERHEAD 10 /* in msecs */ + + static const u32 ath11k_smps_map[] = { + [WLAN_HT_CAP_SM_PS_STATIC] = WMI_PEER_SMPS_STATIC, +@@ -3612,6 +3615,7 @@ static int ath11k_mac_op_hw_scan(struct + struct scan_req_params arg; + int ret = 0; + int i; ++ u32 scan_timeout; + + mutex_lock(&ar->conf_mutex); + +@@ -3681,6 +3685,26 @@ static int ath11k_mac_op_hw_scan(struct + ether_addr_copy(arg.mac_mask.addr, req->mac_addr_mask); + } + ++ /* if duration is set, default dwell times will be overwritten */ ++ if (req->duration) { ++ arg.dwell_time_active = req->duration; ++ arg.dwell_time_active_2g = req->duration; ++ arg.dwell_time_active_6g = req->duration; ++ arg.dwell_time_passive = req->duration; ++ arg.dwell_time_passive_6g = req->duration; ++ arg.burst_duration = req->duration; ++ ++ scan_timeout = min_t(u32, arg.max_rest_time * ++ (arg.num_chan - 1) + (req->duration + ++ ATH11K_SCAN_CHANNEL_SWITCH_WMI_EVT_OVERHEAD) * ++ arg.num_chan, arg.max_scan_time); ++ } else { ++ scan_timeout = arg.max_scan_time; ++ } ++ ++ /* Add a margin to account for event/command processing */ ++ scan_timeout += ATH11K_MAC_SCAN_CMD_EVT_OVERHEAD; ++ + ret = ath11k_start_scan(ar, &arg); + if (ret) { + ath11k_warn(ar->ab, "failed to start hw scan: %d\n", ret); +@@ -3689,10 +3713,8 @@ static int ath11k_mac_op_hw_scan(struct + spin_unlock_bh(&ar->data_lock); + } + +- /* Add a 200ms margin to account for event/command processing */ + ieee80211_queue_delayed_work(ar->hw, &ar->scan.timeout, +- msecs_to_jiffies(arg.max_scan_time + +- ATH11K_MAC_SCAN_TIMEOUT_MSECS)); ++ msecs_to_jiffies(scan_timeout)); + + exit: + kfree(arg.chan_list); +@@ -9060,6 +9082,9 @@ static int __ath11k_mac_register(struct + NL80211_EXT_FEATURE_UNSOL_BCAST_PROBE_RESP); + } + ++ wiphy_ext_feature_set(ar->hw->wiphy, ++ NL80211_EXT_FEATURE_SET_SCAN_DWELL); ++ + ath11k_reg_init(ar); + + if (!test_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags)) { diff --git a/package/kernel/mac80211/patches/ath11k/0010-wifi-ath11k-Fix-firmware-crash-on-vdev-delete-race-c.patch b/package/kernel/mac80211/patches/ath11k/0010-wifi-ath11k-Fix-firmware-crash-on-vdev-delete-race-c.patch new file mode 100644 index 000000000..7275af06e --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0010-wifi-ath11k-Fix-firmware-crash-on-vdev-delete-race-c.patch @@ -0,0 +1,116 @@ +From 3811fa1f231f1a3e29759efef4992116604aab8b Mon Sep 17 00:00:00 2001 +From: Sowmiya Sree Elavalagan +Date: Tue, 11 Oct 2022 15:23:46 +0530 +Subject: [PATCH] wifi: ath11k: Fix firmware crash on vdev delete race + condition + +Current code does not wait for vdev delete completion on vdev create +failures and tries to send another vdev create followed by vdev set +param to firmware with same vdev id. This causes firmware crash. +Fix this crash by waiting for vdev delete completion on vdev +create failures. + +Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.6.0.1-00905-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Sowmiya Sree Elavalagan +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20221011095346.3901-1-quic_ssreeela@quicinc.com +--- + drivers/net/wireless/ath/ath11k/mac.c | 60 +++++++++++++++++---------- + 1 file changed, 37 insertions(+), 23 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -6233,6 +6233,40 @@ void ath11k_mac_11d_scan_stop_all(struct + } + } + ++static int ath11k_mac_vdev_delete(struct ath11k *ar, struct ath11k_vif *arvif) ++{ ++ unsigned long time_left; ++ struct ieee80211_vif *vif = arvif->vif; ++ int ret = 0; ++ ++ lockdep_assert_held(&ar->conf_mutex); ++ ++ reinit_completion(&ar->vdev_delete_done); ++ ++ ret = ath11k_wmi_vdev_delete(ar, arvif->vdev_id); ++ if (ret) { ++ ath11k_warn(ar->ab, "failed to delete WMI vdev %d: %d\n", ++ arvif->vdev_id, ret); ++ return ret; ++ } ++ ++ time_left = wait_for_completion_timeout(&ar->vdev_delete_done, ++ ATH11K_VDEV_DELETE_TIMEOUT_HZ); ++ if (time_left == 0) { ++ ath11k_warn(ar->ab, "Timeout in receiving vdev delete response\n"); ++ return -ETIMEDOUT; ++ } ++ ++ ar->ab->free_vdev_map |= 1LL << (arvif->vdev_id); ++ ar->allocated_vdev_map &= ~(1LL << arvif->vdev_id); ++ ar->num_created_vdevs--; ++ ++ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "vdev %pM deleted, vdev_id %d\n", ++ vif->addr, arvif->vdev_id); ++ ++ return ret; ++} ++ + static int ath11k_mac_op_add_interface(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) + { +@@ -6468,10 +6502,7 @@ err_peer_del: + } + + err_vdev_del: +- ath11k_wmi_vdev_delete(ar, arvif->vdev_id); +- ar->num_created_vdevs--; +- ar->allocated_vdev_map &= ~(1LL << arvif->vdev_id); +- ab->free_vdev_map |= 1LL << arvif->vdev_id; ++ ath11k_mac_vdev_delete(ar, arvif); + spin_lock_bh(&ar->data_lock); + list_del(&arvif->list); + spin_unlock_bh(&ar->data_lock); +@@ -6499,7 +6530,6 @@ static void ath11k_mac_op_remove_interfa + struct ath11k *ar = hw->priv; + struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif); + struct ath11k_base *ab = ar->ab; +- unsigned long time_left; + int ret; + int i; + +@@ -6520,29 +6550,13 @@ static void ath11k_mac_op_remove_interfa + arvif->vdev_id, ret); + } + +- reinit_completion(&ar->vdev_delete_done); +- +- ret = ath11k_wmi_vdev_delete(ar, arvif->vdev_id); ++ ret = ath11k_mac_vdev_delete(ar, arvif); + if (ret) { +- ath11k_warn(ab, "failed to delete WMI vdev %d: %d\n", ++ ath11k_warn(ab, "failed to delete vdev %d: %d\n", + arvif->vdev_id, ret); + goto err_vdev_del; + } + +- time_left = wait_for_completion_timeout(&ar->vdev_delete_done, +- ATH11K_VDEV_DELETE_TIMEOUT_HZ); +- if (time_left == 0) { +- ath11k_warn(ab, "Timeout in receiving vdev delete response\n"); +- goto err_vdev_del; +- } +- +- ab->free_vdev_map |= 1LL << (arvif->vdev_id); +- ar->allocated_vdev_map &= ~(1LL << arvif->vdev_id); +- ar->num_created_vdevs--; +- +- ath11k_dbg(ab, ATH11K_DBG_MAC, "vdev %pM deleted, vdev_id %d\n", +- vif->addr, arvif->vdev_id); +- + if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) { + clear_bit(ATH11K_FLAG_MONITOR_VDEV_CREATED, &ar->monitor_flags); + ar->monitor_vdev_id = -1; diff --git a/package/kernel/mac80211/patches/ath11k/0011-wifi-ath11k-fix-monitor-vdev-creation-with-firmware-.patch b/package/kernel/mac80211/patches/ath11k/0011-wifi-ath11k-fix-monitor-vdev-creation-with-firmware-.patch new file mode 100644 index 000000000..2f066d0a5 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0011-wifi-ath11k-fix-monitor-vdev-creation-with-firmware-.patch @@ -0,0 +1,40 @@ +From f3ca72b0327101a074a871539e61775d43908ca4 Mon Sep 17 00:00:00 2001 +From: Nagarajan Maran +Date: Fri, 14 Oct 2022 21:20:54 +0530 +Subject: [PATCH] wifi: ath11k: fix monitor vdev creation with firmware + recovery + +During firmware recovery, the monitor interface is not +getting created in the driver and firmware since +the respective flags are not updated properly. + +So after firmware recovery is successful, when monitor +interface is brought down manually, firmware assertion +is observed, since we are trying to bring down the +interface which is not yet created in the firmware. + +Fix this by updating the monitor flags properly per +phy#, during firmware recovery. + +Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Nagarajan Maran +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20221014155054.11471-1-quic_nmaran@quicinc.com +--- + drivers/net/wireless/ath/ath11k/core.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/net/wireless/ath/ath11k/core.c ++++ b/drivers/net/wireless/ath/ath11k/core.c +@@ -1677,6 +1677,10 @@ void ath11k_core_pre_reconfigure_recover + ath11k_mac_tx_mgmt_pending_free, ar); + idr_destroy(&ar->txmgmt_idr); + wake_up(&ar->txmgmt_empty_waitq); ++ ++ ar->monitor_vdev_id = -1; ++ clear_bit(ATH11K_FLAG_MONITOR_STARTED, &ar->monitor_flags); ++ clear_bit(ATH11K_FLAG_MONITOR_VDEV_CREATED, &ar->monitor_flags); + } + + wake_up(&ab->wmi_ab.tx_credits_wq); diff --git a/package/kernel/mac80211/patches/ath11k/0012-wifi-ath11k-Fix-qmi_msg_handler-data-structure-initi.patch b/package/kernel/mac80211/patches/ath11k/0012-wifi-ath11k-Fix-qmi_msg_handler-data-structure-initi.patch new file mode 100644 index 000000000..fccfa4385 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0012-wifi-ath11k-Fix-qmi_msg_handler-data-structure-initi.patch @@ -0,0 +1,33 @@ +From ed3725e15a154ebebf44e0c34806c57525483f92 Mon Sep 17 00:00:00 2001 +From: Rahul Bhattacharjee +Date: Fri, 21 Oct 2022 14:31:26 +0530 +Subject: [PATCH] wifi: ath11k: Fix qmi_msg_handler data structure + initialization + +qmi_msg_handler is required to be null terminated by QMI module. +There might be a case where a handler for a msg id is not present in the +handlers array which can lead to infinite loop while searching the handler +and therefore out of bound access in qmi_invoke_handler(). +Hence update the initialization in qmi_msg_handler data structure. + +Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.5.0.1-01100-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Rahul Bhattacharjee +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20221021090126.28626-1-quic_rbhattac@quicinc.com +--- + drivers/net/wireless/ath/ath11k/qmi.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/net/wireless/ath/ath11k/qmi.c ++++ b/drivers/net/wireless/ath/ath11k/qmi.c +@@ -1702,6 +1702,9 @@ static struct qmi_elem_info qmi_wlfw_fw_ + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + }, ++ ++ /* end of list */ ++ {}, + }; + + static int ath11k_qmi_host_cap_send(struct ath11k_base *ab) diff --git a/package/kernel/mac80211/patches/ath11k/0013-wifi-ath11k-synchronize-ath11k_mac_he_gi_to_nl80211_.patch b/package/kernel/mac80211/patches/ath11k/0013-wifi-ath11k-synchronize-ath11k_mac_he_gi_to_nl80211_.patch new file mode 100644 index 000000000..1e89b4d4f --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0013-wifi-ath11k-synchronize-ath11k_mac_he_gi_to_nl80211_.patch @@ -0,0 +1,42 @@ +From dd1c2322694522f674c874f5fa02ac5ae39135dd Mon Sep 17 00:00:00 2001 +From: "Jiri Slaby (SUSE)" +Date: Mon, 31 Oct 2022 12:43:41 +0100 +Subject: [PATCH] wifi: ath11k: synchronize + ath11k_mac_he_gi_to_nl80211_he_gi()'s return type + +ath11k_mac_he_gi_to_nl80211_he_gi() generates a valid warning with gcc-13: + drivers/net/wireless/ath/ath11k/mac.c:321:20: error: conflicting types for 'ath11k_mac_he_gi_to_nl80211_he_gi' due to enum/integer mismatch; have 'enum nl80211_he_gi(u8)' + drivers/net/wireless/ath/ath11k/mac.h:166:5: note: previous declaration of 'ath11k_mac_he_gi_to_nl80211_he_gi' with type 'u32(u8)' + +I.e. the type of the return value ath11k_mac_he_gi_to_nl80211_he_gi() in +the declaration is u32, while the definition spells enum nl80211_he_gi. +Synchronize them to the latter. + +Cc: Martin Liska +Cc: Kalle Valo +Cc: "David S. Miller" +Cc: Eric Dumazet +Cc: Jakub Kicinski +Cc: Paolo Abeni +Cc: ath11k@lists.infradead.org +Cc: linux-wireless@vger.kernel.org +Cc: netdev@vger.kernel.org +Signed-off-by: Jiri Slaby (SUSE) +Reviewed-by: Jeff Johnson +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20221031114341.10377-1-jirislaby@kernel.org +--- + drivers/net/wireless/ath/ath11k/mac.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/wireless/ath/ath11k/mac.h ++++ b/drivers/net/wireless/ath/ath11k/mac.h +@@ -163,7 +163,7 @@ void ath11k_mac_drain_tx(struct ath11k * + void ath11k_mac_peer_cleanup_all(struct ath11k *ar); + int ath11k_mac_tx_mgmt_pending_free(int buf_id, void *skb, void *ctx); + u8 ath11k_mac_bw_to_mac80211_bw(u8 bw); +-u32 ath11k_mac_he_gi_to_nl80211_he_gi(u8 sgi); ++enum nl80211_he_gi ath11k_mac_he_gi_to_nl80211_he_gi(u8 sgi); + enum nl80211_he_ru_alloc ath11k_mac_phy_he_ru_to_nl80211_he_ru_alloc(u16 ru_phy); + enum nl80211_he_ru_alloc ath11k_mac_he_ru_tones_to_nl80211_he_ru_alloc(u16 ru_tones); + enum ath11k_supported_bw ath11k_mac_mac80211_bw_to_ath11k_bw(enum rate_info_bw bw); diff --git a/package/kernel/mac80211/patches/ath11k/0016-wifi-ath11k-Make-QMI-message-rules-const.patch b/package/kernel/mac80211/patches/ath11k/0016-wifi-ath11k-Make-QMI-message-rules-const.patch new file mode 100644 index 000000000..1f48df73f --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0016-wifi-ath11k-Make-QMI-message-rules-const.patch @@ -0,0 +1,341 @@ +From 93c1592889fca46d09d833455628bab05516cdbf Mon Sep 17 00:00:00 2001 +From: Jeff Johnson +Date: Wed, 14 Sep 2022 17:23:03 -0700 +Subject: [PATCH] wifi: ath11k: Make QMI message rules const + +Commit ff6d365898d4 ("soc: qcom: qmi: use const for struct +qmi_elem_info") allows QMI message encoding/decoding rules to be +const, so do that for ath11k. + +Compile tested only. + +Signed-off-by: Jeff Johnson +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20220915002303.12206-1-quic_jjohnson@quicinc.com +--- + drivers/net/wireless/ath/ath11k/qmi.c | 72 +++++++++++++-------------- + 1 file changed, 36 insertions(+), 36 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/qmi.c ++++ b/drivers/net/wireless/ath/ath11k/qmi.c +@@ -29,7 +29,7 @@ module_param_named(cold_boot_cal, ath11k + MODULE_PARM_DESC(cold_boot_cal, + "Decrease the channel switch time but increase the driver load time (Default: true)"); + +-static struct qmi_elem_info qmi_wlanfw_host_cap_req_msg_v01_ei[] = { ++static const struct qmi_elem_info qmi_wlanfw_host_cap_req_msg_v01_ei[] = { + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, +@@ -280,7 +280,7 @@ static struct qmi_elem_info qmi_wlanfw_h + }, + }; + +-static struct qmi_elem_info qmi_wlanfw_host_cap_resp_msg_v01_ei[] = { ++static const struct qmi_elem_info qmi_wlanfw_host_cap_resp_msg_v01_ei[] = { + { + .data_type = QMI_STRUCT, + .elem_len = 1, +@@ -297,7 +297,7 @@ static struct qmi_elem_info qmi_wlanfw_h + }, + }; + +-static struct qmi_elem_info qmi_wlanfw_ind_register_req_msg_v01_ei[] = { ++static const struct qmi_elem_info qmi_wlanfw_ind_register_req_msg_v01_ei[] = { + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, +@@ -522,7 +522,7 @@ static struct qmi_elem_info qmi_wlanfw_i + }, + }; + +-static struct qmi_elem_info qmi_wlanfw_ind_register_resp_msg_v01_ei[] = { ++static const struct qmi_elem_info qmi_wlanfw_ind_register_resp_msg_v01_ei[] = { + { + .data_type = QMI_STRUCT, + .elem_len = 1, +@@ -558,7 +558,7 @@ static struct qmi_elem_info qmi_wlanfw_i + }, + }; + +-static struct qmi_elem_info qmi_wlanfw_mem_cfg_s_v01_ei[] = { ++static const struct qmi_elem_info qmi_wlanfw_mem_cfg_s_v01_ei[] = { + { + .data_type = QMI_UNSIGNED_8_BYTE, + .elem_len = 1, +@@ -590,7 +590,7 @@ static struct qmi_elem_info qmi_wlanfw_m + }, + }; + +-static struct qmi_elem_info qmi_wlanfw_mem_seg_s_v01_ei[] = { ++static const struct qmi_elem_info qmi_wlanfw_mem_seg_s_v01_ei[] = { + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, +@@ -632,7 +632,7 @@ static struct qmi_elem_info qmi_wlanfw_m + }, + }; + +-static struct qmi_elem_info qmi_wlanfw_request_mem_ind_msg_v01_ei[] = { ++static const struct qmi_elem_info qmi_wlanfw_request_mem_ind_msg_v01_ei[] = { + { + .data_type = QMI_DATA_LEN, + .elem_len = 1, +@@ -659,7 +659,7 @@ static struct qmi_elem_info qmi_wlanfw_r + }, + }; + +-static struct qmi_elem_info qmi_wlanfw_mem_seg_resp_s_v01_ei[] = { ++static const struct qmi_elem_info qmi_wlanfw_mem_seg_resp_s_v01_ei[] = { + { + .data_type = QMI_UNSIGNED_8_BYTE, + .elem_len = 1, +@@ -699,7 +699,7 @@ static struct qmi_elem_info qmi_wlanfw_m + }, + }; + +-static struct qmi_elem_info qmi_wlanfw_respond_mem_req_msg_v01_ei[] = { ++static const struct qmi_elem_info qmi_wlanfw_respond_mem_req_msg_v01_ei[] = { + { + .data_type = QMI_DATA_LEN, + .elem_len = 1, +@@ -726,7 +726,7 @@ static struct qmi_elem_info qmi_wlanfw_r + }, + }; + +-static struct qmi_elem_info qmi_wlanfw_respond_mem_resp_msg_v01_ei[] = { ++static const struct qmi_elem_info qmi_wlanfw_respond_mem_resp_msg_v01_ei[] = { + { + .data_type = QMI_STRUCT, + .elem_len = 1, +@@ -744,7 +744,7 @@ static struct qmi_elem_info qmi_wlanfw_r + }, + }; + +-static struct qmi_elem_info qmi_wlanfw_cap_req_msg_v01_ei[] = { ++static const struct qmi_elem_info qmi_wlanfw_cap_req_msg_v01_ei[] = { + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, +@@ -752,7 +752,7 @@ static struct qmi_elem_info qmi_wlanfw_c + }, + }; + +-static struct qmi_elem_info qmi_wlanfw_device_info_req_msg_v01_ei[] = { ++static const struct qmi_elem_info qmi_wlanfw_device_info_req_msg_v01_ei[] = { + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, +@@ -760,7 +760,7 @@ static struct qmi_elem_info qmi_wlanfw_d + }, + }; + +-static struct qmi_elem_info qmi_wlfw_device_info_resp_msg_v01_ei[] = { ++static const struct qmi_elem_info qmi_wlfw_device_info_resp_msg_v01_ei[] = { + { + .data_type = QMI_STRUCT, + .elem_len = 1, +@@ -814,7 +814,7 @@ static struct qmi_elem_info qmi_wlfw_dev + }, + }; + +-static struct qmi_elem_info qmi_wlanfw_rf_chip_info_s_v01_ei[] = { ++static const struct qmi_elem_info qmi_wlanfw_rf_chip_info_s_v01_ei[] = { + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, +@@ -840,7 +840,7 @@ static struct qmi_elem_info qmi_wlanfw_r + }, + }; + +-static struct qmi_elem_info qmi_wlanfw_rf_board_info_s_v01_ei[] = { ++static const struct qmi_elem_info qmi_wlanfw_rf_board_info_s_v01_ei[] = { + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, +@@ -857,7 +857,7 @@ static struct qmi_elem_info qmi_wlanfw_r + }, + }; + +-static struct qmi_elem_info qmi_wlanfw_soc_info_s_v01_ei[] = { ++static const struct qmi_elem_info qmi_wlanfw_soc_info_s_v01_ei[] = { + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, +@@ -873,7 +873,7 @@ static struct qmi_elem_info qmi_wlanfw_s + }, + }; + +-static struct qmi_elem_info qmi_wlanfw_fw_version_info_s_v01_ei[] = { ++static const struct qmi_elem_info qmi_wlanfw_fw_version_info_s_v01_ei[] = { + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, +@@ -899,7 +899,7 @@ static struct qmi_elem_info qmi_wlanfw_f + }, + }; + +-static struct qmi_elem_info qmi_wlanfw_cap_resp_msg_v01_ei[] = { ++static const struct qmi_elem_info qmi_wlanfw_cap_resp_msg_v01_ei[] = { + { + .data_type = QMI_STRUCT, + .elem_len = 1, +@@ -1100,7 +1100,7 @@ static struct qmi_elem_info qmi_wlanfw_c + }, + }; + +-static struct qmi_elem_info qmi_wlanfw_bdf_download_req_msg_v01_ei[] = { ++static const struct qmi_elem_info qmi_wlanfw_bdf_download_req_msg_v01_ei[] = { + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, +@@ -1235,7 +1235,7 @@ static struct qmi_elem_info qmi_wlanfw_b + }, + }; + +-static struct qmi_elem_info qmi_wlanfw_bdf_download_resp_msg_v01_ei[] = { ++static const struct qmi_elem_info qmi_wlanfw_bdf_download_resp_msg_v01_ei[] = { + { + .data_type = QMI_STRUCT, + .elem_len = 1, +@@ -1253,7 +1253,7 @@ static struct qmi_elem_info qmi_wlanfw_b + }, + }; + +-static struct qmi_elem_info qmi_wlanfw_m3_info_req_msg_v01_ei[] = { ++static const struct qmi_elem_info qmi_wlanfw_m3_info_req_msg_v01_ei[] = { + { + .data_type = QMI_UNSIGNED_8_BYTE, + .elem_len = 1, +@@ -1277,7 +1277,7 @@ static struct qmi_elem_info qmi_wlanfw_m + }, + }; + +-static struct qmi_elem_info qmi_wlanfw_m3_info_resp_msg_v01_ei[] = { ++static const struct qmi_elem_info qmi_wlanfw_m3_info_resp_msg_v01_ei[] = { + { + .data_type = QMI_STRUCT, + .elem_len = 1, +@@ -1294,7 +1294,7 @@ static struct qmi_elem_info qmi_wlanfw_m + }, + }; + +-static struct qmi_elem_info qmi_wlanfw_ce_tgt_pipe_cfg_s_v01_ei[] = { ++static const struct qmi_elem_info qmi_wlanfw_ce_tgt_pipe_cfg_s_v01_ei[] = { + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, +@@ -1347,7 +1347,7 @@ static struct qmi_elem_info qmi_wlanfw_c + }, + }; + +-static struct qmi_elem_info qmi_wlanfw_ce_svc_pipe_cfg_s_v01_ei[] = { ++static const struct qmi_elem_info qmi_wlanfw_ce_svc_pipe_cfg_s_v01_ei[] = { + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, +@@ -1382,7 +1382,7 @@ static struct qmi_elem_info qmi_wlanfw_c + }, + }; + +-static struct qmi_elem_info qmi_wlanfw_shadow_reg_cfg_s_v01_ei[] = { ++static const struct qmi_elem_info qmi_wlanfw_shadow_reg_cfg_s_v01_ei[] = { + { + .data_type = QMI_UNSIGNED_2_BYTE, + .elem_len = 1, +@@ -1406,7 +1406,7 @@ static struct qmi_elem_info qmi_wlanfw_s + }, + }; + +-static struct qmi_elem_info qmi_wlanfw_shadow_reg_v2_cfg_s_v01_ei[] = { ++static const struct qmi_elem_info qmi_wlanfw_shadow_reg_v2_cfg_s_v01_ei[] = { + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, +@@ -1423,7 +1423,7 @@ static struct qmi_elem_info qmi_wlanfw_s + }, + }; + +-static struct qmi_elem_info qmi_wlanfw_wlan_mode_req_msg_v01_ei[] = { ++static const struct qmi_elem_info qmi_wlanfw_wlan_mode_req_msg_v01_ei[] = { + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, +@@ -1458,7 +1458,7 @@ static struct qmi_elem_info qmi_wlanfw_w + }, + }; + +-static struct qmi_elem_info qmi_wlanfw_wlan_mode_resp_msg_v01_ei[] = { ++static const struct qmi_elem_info qmi_wlanfw_wlan_mode_resp_msg_v01_ei[] = { + { + .data_type = QMI_STRUCT, + .elem_len = 1, +@@ -1476,7 +1476,7 @@ static struct qmi_elem_info qmi_wlanfw_w + }, + }; + +-static struct qmi_elem_info qmi_wlanfw_wlan_cfg_req_msg_v01_ei[] = { ++static const struct qmi_elem_info qmi_wlanfw_wlan_cfg_req_msg_v01_ei[] = { + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, +@@ -1615,7 +1615,7 @@ static struct qmi_elem_info qmi_wlanfw_w + }, + }; + +-static struct qmi_elem_info qmi_wlanfw_wlan_cfg_resp_msg_v01_ei[] = { ++static const struct qmi_elem_info qmi_wlanfw_wlan_cfg_resp_msg_v01_ei[] = { + { + .data_type = QMI_STRUCT, + .elem_len = 1, +@@ -1632,28 +1632,28 @@ static struct qmi_elem_info qmi_wlanfw_w + }, + }; + +-static struct qmi_elem_info qmi_wlanfw_mem_ready_ind_msg_v01_ei[] = { ++static const struct qmi_elem_info qmi_wlanfw_mem_ready_ind_msg_v01_ei[] = { + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + }, + }; + +-static struct qmi_elem_info qmi_wlanfw_fw_ready_ind_msg_v01_ei[] = { ++static const struct qmi_elem_info qmi_wlanfw_fw_ready_ind_msg_v01_ei[] = { + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + }, + }; + +-static struct qmi_elem_info qmi_wlanfw_cold_boot_cal_done_ind_msg_v01_ei[] = { ++static const struct qmi_elem_info qmi_wlanfw_cold_boot_cal_done_ind_msg_v01_ei[] = { + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + }, + }; + +-static struct qmi_elem_info qmi_wlanfw_wlan_ini_req_msg_v01_ei[] = { ++static const struct qmi_elem_info qmi_wlanfw_wlan_ini_req_msg_v01_ei[] = { + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, +@@ -1679,7 +1679,7 @@ static struct qmi_elem_info qmi_wlanfw_w + }, + }; + +-static struct qmi_elem_info qmi_wlanfw_wlan_ini_resp_msg_v01_ei[] = { ++static const struct qmi_elem_info qmi_wlanfw_wlan_ini_resp_msg_v01_ei[] = { + { + .data_type = QMI_STRUCT, + .elem_len = 1, +@@ -1697,7 +1697,7 @@ static struct qmi_elem_info qmi_wlanfw_w + }, + }; + +-static struct qmi_elem_info qmi_wlfw_fw_init_done_ind_msg_v01_ei[] = { ++static const struct qmi_elem_info qmi_wlfw_fw_init_done_ind_msg_v01_ei[] = { + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, diff --git a/package/kernel/mac80211/patches/ath11k/0017-wifi-ath11k-Trigger-sta-disconnect-on-hardware-resta.patch b/package/kernel/mac80211/patches/ath11k/0017-wifi-ath11k-Trigger-sta-disconnect-on-hardware-resta.patch new file mode 100644 index 000000000..f95e5027b --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0017-wifi-ath11k-Trigger-sta-disconnect-on-hardware-resta.patch @@ -0,0 +1,119 @@ +From a018750a2cceaf4427c4ee3d9ce3e83a171d5bd6 Mon Sep 17 00:00:00 2001 +From: Youghandhar Chintala +Date: Fri, 4 Nov 2022 14:24:03 +0530 +Subject: [PATCH] wifi: ath11k: Trigger sta disconnect on hardware restart + +Currently after the hardware restart triggered from the driver, the +station interface connection remains intact, since a disconnect trigger +is not sent to userspace. This can lead to a problem in targets where +the wifi mac sequence is added by the firmware. + +After the target restart, its wifi mac sequence number gets reset to +zero. Hence AP to which our device is connected will receive frames with +a wifi mac sequence number jump to the past, thereby resulting in the +AP dropping all these frames, until the frame arrives with a wifi mac +sequence number which AP was expecting. + +To avoid such frame drops, its better to trigger a station disconnect +upon target hardware restart which can be done with API +ieee80211_reconfig_disconnect exposed to mac80211. + +The other targets are not affected by this change, since the hardware +params flag is not set. + +Reported-by: kernel test robot + +Tested-on: WCN6750 hw1.0 AHB WLAN.MSL.1.0.1-00887-QCAMSLSWPLZ-1 + +Signed-off-by: Youghandhar Chintala +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20221104085403.11025-1-quic_youghand@quicinc.com +--- + drivers/net/wireless/ath/ath11k/core.c | 6 ++++++ + drivers/net/wireless/ath/ath11k/hw.h | 1 + + drivers/net/wireless/ath/ath11k/mac.c | 7 +++++++ + 3 files changed, 14 insertions(+) + +--- a/drivers/net/wireless/ath/ath11k/core.c ++++ b/drivers/net/wireless/ath/ath11k/core.c +@@ -195,6 +195,7 @@ static const struct ath11k_hw_params ath + .tcl_ring_retry = true, + .tx_ring_size = DP_TCL_DATA_RING_SIZE, + .smp2p_wow_exit = false, ++ .support_fw_mac_sequence = false, + }, + { + .name = "qca6390 hw2.0", +@@ -277,6 +278,7 @@ static const struct ath11k_hw_params ath + .tcl_ring_retry = true, + .tx_ring_size = DP_TCL_DATA_RING_SIZE, + .smp2p_wow_exit = false, ++ .support_fw_mac_sequence = true, + }, + { + .name = "qcn9074 hw1.0", +@@ -356,6 +358,7 @@ static const struct ath11k_hw_params ath + .tcl_ring_retry = true, + .tx_ring_size = DP_TCL_DATA_RING_SIZE, + .smp2p_wow_exit = false, ++ .support_fw_mac_sequence = false, + }, + { + .name = "wcn6855 hw2.0", +@@ -438,6 +441,7 @@ static const struct ath11k_hw_params ath + .tcl_ring_retry = true, + .tx_ring_size = DP_TCL_DATA_RING_SIZE, + .smp2p_wow_exit = false, ++ .support_fw_mac_sequence = true, + }, + { + .name = "wcn6855 hw2.1", +@@ -519,6 +523,7 @@ static const struct ath11k_hw_params ath + .tcl_ring_retry = true, + .tx_ring_size = DP_TCL_DATA_RING_SIZE, + .smp2p_wow_exit = false, ++ .support_fw_mac_sequence = true, + }, + { + .name = "wcn6750 hw1.0", +@@ -597,6 +602,7 @@ static const struct ath11k_hw_params ath + .tcl_ring_retry = false, + .tx_ring_size = DP_TCL_DATA_RING_SIZE_WCN6750, + .smp2p_wow_exit = true, ++ .support_fw_mac_sequence = true, + }, + }; + +--- a/drivers/net/wireless/ath/ath11k/hw.h ++++ b/drivers/net/wireless/ath/ath11k/hw.h +@@ -219,6 +219,7 @@ struct ath11k_hw_params { + bool tcl_ring_retry; + u32 tx_ring_size; + bool smp2p_wow_exit; ++ bool support_fw_mac_sequence; + }; + + struct ath11k_hw_ops { +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -8010,6 +8010,7 @@ ath11k_mac_op_reconfig_complete(struct i + struct ath11k *ar = hw->priv; + struct ath11k_base *ab = ar->ab; + int recovery_count; ++ struct ath11k_vif *arvif; + + if (reconfig_type != IEEE80211_RECONFIG_TYPE_RESTART) + return; +@@ -8045,6 +8046,12 @@ ath11k_mac_op_reconfig_complete(struct i + ath11k_dbg(ab, ATH11K_DBG_BOOT, "reset success\n"); + } + } ++ if (ar->ab->hw_params.support_fw_mac_sequence) { ++ list_for_each_entry(arvif, &ar->arvifs, list) { ++ if (arvif->is_up && arvif->vdev_type == WMI_VDEV_TYPE_STA) ++ ieee80211_hw_restart_disconnect(arvif->vif); ++ } ++ } + } + + mutex_unlock(&ar->conf_mutex); diff --git a/package/kernel/mac80211/patches/ath11k/0018-wifi-ath11k-Fix-race-condition-with-struct-htt_ppdu_.patch b/package/kernel/mac80211/patches/ath11k/0018-wifi-ath11k-Fix-race-condition-with-struct-htt_ppdu_.patch new file mode 100644 index 000000000..cef61ee34 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0018-wifi-ath11k-Fix-race-condition-with-struct-htt_ppdu_.patch @@ -0,0 +1,103 @@ +From e44de90453bb2b46a523df78c39eb896bab35dcd Mon Sep 17 00:00:00 2001 +From: Govindaraj Saminathan +Date: Tue, 29 Nov 2022 13:04:02 +0200 +Subject: [PATCH] wifi: ath11k: Fix race condition with struct + htt_ppdu_stats_info + +A crash happens when running the traffic with multiple clients: + +Crash Signature : Unable to handle kernel paging request at +virtual address ffffffd700970918 During the crash, PC points to +"ieee80211_tx_rate_update+0x30/0x68 [mac80211]" +LR points to "ath11k_dp_htt_htc_t2h_msg_handler+0x5a8/0x8a0 [ath11k]". + +Struct ppdu_stats_info is allocated and accessed from event callback via copy +engine tasklet, this has a problem when freeing it from ath11k_mac_op_stop(). + +Use data_lock during entire ath11k_dp_htt_get_ppdu_desc() call to protect +struct htt_ppdu_stats_info access and to avoid race condition when accessing it +from ath11k_mac_op_stop(). + +Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Govindaraj Saminathan +Co-developed-by: Karthikeyan Kathirvel +Signed-off-by: Karthikeyan Kathirvel +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20221124071104.22506-1-quic_kathirve@quicinc.com +--- + drivers/net/wireless/ath/ath11k/dp_rx.c | 22 +++++++++++----------- + 1 file changed, 11 insertions(+), 11 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath11k/dp_rx.c +@@ -1535,13 +1535,12 @@ struct htt_ppdu_stats_info *ath11k_dp_ht + { + struct htt_ppdu_stats_info *ppdu_info; + +- spin_lock_bh(&ar->data_lock); ++ lockdep_assert_held(&ar->data_lock); ++ + if (!list_empty(&ar->ppdu_stats_info)) { + list_for_each_entry(ppdu_info, &ar->ppdu_stats_info, list) { +- if (ppdu_info->ppdu_id == ppdu_id) { +- spin_unlock_bh(&ar->data_lock); ++ if (ppdu_info->ppdu_id == ppdu_id) + return ppdu_info; +- } + } + + if (ar->ppdu_stat_list_depth > HTT_PPDU_DESC_MAX_DEPTH) { +@@ -1553,16 +1552,13 @@ struct htt_ppdu_stats_info *ath11k_dp_ht + kfree(ppdu_info); + } + } +- spin_unlock_bh(&ar->data_lock); + + ppdu_info = kzalloc(sizeof(*ppdu_info), GFP_ATOMIC); + if (!ppdu_info) + return NULL; + +- spin_lock_bh(&ar->data_lock); + list_add_tail(&ppdu_info->list, &ar->ppdu_stats_info); + ar->ppdu_stat_list_depth++; +- spin_unlock_bh(&ar->data_lock); + + return ppdu_info; + } +@@ -1586,16 +1582,17 @@ static int ath11k_htt_pull_ppdu_stats(st + ar = ath11k_mac_get_ar_by_pdev_id(ab, pdev_id); + if (!ar) { + ret = -EINVAL; +- goto exit; ++ goto out; + } + + if (ath11k_debugfs_is_pktlog_lite_mode_enabled(ar)) + trace_ath11k_htt_ppdu_stats(ar, skb->data, len); + ++ spin_lock_bh(&ar->data_lock); + ppdu_info = ath11k_dp_htt_get_ppdu_desc(ar, ppdu_id); + if (!ppdu_info) { + ret = -EINVAL; +- goto exit; ++ goto out_unlock_data; + } + + ppdu_info->ppdu_id = ppdu_id; +@@ -1604,10 +1601,13 @@ static int ath11k_htt_pull_ppdu_stats(st + (void *)ppdu_info); + if (ret) { + ath11k_warn(ab, "Failed to parse tlv %d\n", ret); +- goto exit; ++ goto out_unlock_data; + } + +-exit: ++out_unlock_data: ++ spin_unlock_bh(&ar->data_lock); ++ ++out: + rcu_read_unlock(); + + return ret; diff --git a/package/kernel/mac80211/patches/ath11k/0019-wifi-ath11k-update-hw-params-for-IPQ5018.patch b/package/kernel/mac80211/patches/ath11k/0019-wifi-ath11k-update-hw-params-for-IPQ5018.patch new file mode 100644 index 000000000..25d39ddb0 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0019-wifi-ath11k-update-hw-params-for-IPQ5018.patch @@ -0,0 +1,125 @@ +From 8dfe875aa24aec68baf6702018633c84c2c1feca Mon Sep 17 00:00:00 2001 +From: Sriram R +Date: Fri, 2 Dec 2022 23:37:13 +0200 +Subject: [PATCH] wifi: ath11k: update hw params for IPQ5018 + +Add new compatible string for IPQ5018 and add +required hw params for IPQ5018. The hw descriptors size and +datapath ops are similar to QCN9074, hence reuse the same. + +Tested-on: IPQ5018 hw1.0 AHB WLAN.HK.2.6.0.1-00861-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Sriram R +Co-developed-by: Karthikeyan Kathirvel +Signed-off-by: Karthikeyan Kathirvel +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20221122132152.17771-3-quic_kathirve@quicinc.com +--- + drivers/net/wireless/ath/ath11k/core.c | 71 ++++++++++++++++++++++++++ + drivers/net/wireless/ath/ath11k/core.h | 8 +++ + 2 files changed, 79 insertions(+) + +--- a/drivers/net/wireless/ath/ath11k/core.c ++++ b/drivers/net/wireless/ath/ath11k/core.c +@@ -604,6 +604,77 @@ static const struct ath11k_hw_params ath + .smp2p_wow_exit = true, + .support_fw_mac_sequence = true, + }, ++ { ++ .hw_rev = ATH11K_HW_IPQ5018_HW10, ++ .name = "ipq5018 hw1.0", ++ .fw = { ++ .dir = "IPQ5018/hw1.0", ++ .board_size = 256 * 1024, ++ .cal_offset = 128 * 1024, ++ }, ++ .max_radios = MAX_RADIOS_5018, ++ .bdf_addr = 0x4BA00000, ++ /* hal_desc_sz and hw ops are similar to qcn9074 */ ++ .hal_desc_sz = sizeof(struct hal_rx_desc_qcn9074), ++ .qmi_service_ins_id = ATH11K_QMI_WLFW_SERVICE_INS_ID_V01_IPQ8074, ++ .ring_mask = &ath11k_hw_ring_mask_ipq8074, ++ .credit_flow = false, ++ .max_tx_ring = 1, ++ .spectral = { ++ .fft_sz = 2, ++ .fft_pad_sz = 0, ++ .summary_pad_sz = 16, ++ .fft_hdr_len = 24, ++ .max_fft_bins = 1024, ++ }, ++ .internal_sleep_clock = false, ++ .host_ce_config = ath11k_host_ce_config_qcn9074, ++ .ce_count = CE_CNT_5018, ++ .rxdma1_enable = true, ++ .num_rxmda_per_pdev = RXDMA_PER_PDEV_5018, ++ .rx_mac_buf_ring = false, ++ .vdev_start_delay = false, ++ .htt_peer_map_v2 = true, ++ .interface_modes = BIT(NL80211_IFTYPE_STATION) | ++ BIT(NL80211_IFTYPE_AP) | ++ BIT(NL80211_IFTYPE_MESH_POINT), ++ .supports_monitor = false, ++ .supports_sta_ps = false, ++ .supports_shadow_regs = false, ++ .fw_mem_mode = 0, ++ .num_vdevs = 16 + 1, ++ .num_peers = 512, ++ .supports_regdb = false, ++ .idle_ps = false, ++ .supports_suspend = false, ++ .hal_params = &ath11k_hw_hal_params_ipq8074, ++ .single_pdev_only = false, ++ .cold_boot_calib = true, ++ .fix_l1ss = true, ++ .supports_dynamic_smps_6ghz = false, ++ .alloc_cacheable_memory = true, ++ .supports_rssi_stats = false, ++ .fw_wmi_diag_event = false, ++ .current_cc_support = false, ++ .dbr_debug_support = true, ++ .global_reset = false, ++ .bios_sar_capa = NULL, ++ .m3_fw_support = false, ++ .fixed_bdf_addr = true, ++ .fixed_mem_region = true, ++ .static_window_map = false, ++ .hybrid_bus_type = false, ++ .fixed_fw_mem = false, ++ .support_off_channel_tx = false, ++ .supports_multi_bssid = false, ++ ++ .sram_dump = {}, ++ ++ .tcl_ring_retry = true, ++ .tx_ring_size = DP_TCL_DATA_RING_SIZE, ++ .smp2p_wow_exit = false, ++ .support_fw_mac_sequence = false, ++ }, + }; + + static inline struct ath11k_pdev *ath11k_core_get_single_pdev(struct ath11k_base *ab) +--- a/drivers/net/wireless/ath/ath11k/core.h ++++ b/drivers/net/wireless/ath/ath11k/core.h +@@ -142,6 +142,7 @@ enum ath11k_hw_rev { + ATH11K_HW_WCN6855_HW20, + ATH11K_HW_WCN6855_HW21, + ATH11K_HW_WCN6750_HW10, ++ ATH11K_HW_IPQ5018_HW10, + }; + + enum ath11k_firmware_mode { +@@ -230,6 +231,13 @@ struct ath11k_he { + + #define MAX_RADIOS 3 + ++/* ipq5018 hw param macros */ ++#define MAX_RADIOS_5018 1 ++#define CE_CNT_5018 6 ++#define TARGET_CE_CNT_5018 9 ++#define SVC_CE_MAP_LEN_5018 17 ++#define RXDMA_PER_PDEV_5018 1 ++ + enum { + WMI_HOST_TP_SCALE_MAX = 0, + WMI_HOST_TP_SCALE_50 = 1, diff --git a/package/kernel/mac80211/patches/ath11k/0020-wifi-ath11k-update-ce-configurations-for-IPQ5018.patch b/package/kernel/mac80211/patches/ath11k/0020-wifi-ath11k-update-ce-configurations-for-IPQ5018.patch new file mode 100644 index 000000000..95643a95f --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0020-wifi-ath11k-update-ce-configurations-for-IPQ5018.patch @@ -0,0 +1,246 @@ +From 26af7aabd2d8225c6b2056234626ba5099610871 Mon Sep 17 00:00:00 2001 +From: Sriram R +Date: Fri, 2 Dec 2022 23:37:14 +0200 +Subject: [PATCH] wifi: ath11k: update ce configurations for IPQ5018 + +IPQ5018 is a single pdev device. Update host +and target CE configurations accordingly. + +Tested-on: IPQ5018 hw1.0 AHB WLAN.HK.2.6.0.1-00861-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Sriram R +Co-developed-by: Karthikeyan Kathirvel +Signed-off-by: Karthikeyan Kathirvel +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20221122132152.17771-4-quic_kathirve@quicinc.com +--- + drivers/net/wireless/ath/ath11k/core.c | 4 + + drivers/net/wireless/ath/ath11k/core.h | 3 + + drivers/net/wireless/ath/ath11k/hw.c | 191 +++++++++++++++++++++++++ + 3 files changed, 198 insertions(+) + +--- a/drivers/net/wireless/ath/ath11k/core.c ++++ b/drivers/net/wireless/ath/ath11k/core.c +@@ -630,6 +630,10 @@ static const struct ath11k_hw_params ath + .internal_sleep_clock = false, + .host_ce_config = ath11k_host_ce_config_qcn9074, + .ce_count = CE_CNT_5018, ++ .target_ce_config = ath11k_target_ce_config_wlan_ipq5018, ++ .target_ce_count = TARGET_CE_CNT_5018, ++ .svc_to_ce_map = ath11k_target_service_to_ce_map_wlan_ipq5018, ++ .svc_to_ce_map_len = SVC_CE_MAP_LEN_5018, + .rxdma1_enable = true, + .num_rxmda_per_pdev = RXDMA_PER_PDEV_5018, + .rx_mac_buf_ring = false, +--- a/drivers/net/wireless/ath/ath11k/core.h ++++ b/drivers/net/wireless/ath/ath11k/core.h +@@ -1145,6 +1145,9 @@ extern const struct service_to_pipe ath1 + extern const struct ce_pipe_config ath11k_target_ce_config_wlan_qca6390[]; + extern const struct service_to_pipe ath11k_target_service_to_ce_map_wlan_qca6390[]; + ++extern const struct ce_pipe_config ath11k_target_ce_config_wlan_ipq5018[]; ++extern const struct service_to_pipe ath11k_target_service_to_ce_map_wlan_ipq5018[]; ++ + extern const struct ce_pipe_config ath11k_target_ce_config_wlan_qcn9074[]; + extern const struct service_to_pipe ath11k_target_service_to_ce_map_wlan_qcn9074[]; + int ath11k_core_qmi_firmware_ready(struct ath11k_base *ab); +--- a/drivers/net/wireless/ath/ath11k/hw.c ++++ b/drivers/net/wireless/ath/ath11k/hw.c +@@ -1972,6 +1972,197 @@ const struct ath11k_hw_ring_mask ath11k_ + }, + }; + ++/* Target firmware's Copy Engine configuration for IPQ5018 */ ++const struct ce_pipe_config ath11k_target_ce_config_wlan_ipq5018[] = { ++ /* CE0: host->target HTC control and raw streams */ ++ { ++ .pipenum = __cpu_to_le32(0), ++ .pipedir = __cpu_to_le32(PIPEDIR_OUT), ++ .nentries = __cpu_to_le32(32), ++ .nbytes_max = __cpu_to_le32(2048), ++ .flags = __cpu_to_le32(CE_ATTR_FLAGS), ++ .reserved = __cpu_to_le32(0), ++ }, ++ ++ /* CE1: target->host HTT + HTC control */ ++ { ++ .pipenum = __cpu_to_le32(1), ++ .pipedir = __cpu_to_le32(PIPEDIR_IN), ++ .nentries = __cpu_to_le32(32), ++ .nbytes_max = __cpu_to_le32(2048), ++ .flags = __cpu_to_le32(CE_ATTR_FLAGS), ++ .reserved = __cpu_to_le32(0), ++ }, ++ ++ /* CE2: target->host WMI */ ++ { ++ .pipenum = __cpu_to_le32(2), ++ .pipedir = __cpu_to_le32(PIPEDIR_IN), ++ .nentries = __cpu_to_le32(32), ++ .nbytes_max = __cpu_to_le32(2048), ++ .flags = __cpu_to_le32(CE_ATTR_FLAGS), ++ .reserved = __cpu_to_le32(0), ++ }, ++ ++ /* CE3: host->target WMI */ ++ { ++ .pipenum = __cpu_to_le32(3), ++ .pipedir = __cpu_to_le32(PIPEDIR_OUT), ++ .nentries = __cpu_to_le32(32), ++ .nbytes_max = __cpu_to_le32(2048), ++ .flags = __cpu_to_le32(CE_ATTR_FLAGS), ++ .reserved = __cpu_to_le32(0), ++ }, ++ ++ /* CE4: host->target HTT */ ++ { ++ .pipenum = __cpu_to_le32(4), ++ .pipedir = __cpu_to_le32(PIPEDIR_OUT), ++ .nentries = __cpu_to_le32(256), ++ .nbytes_max = __cpu_to_le32(256), ++ .flags = __cpu_to_le32(CE_ATTR_FLAGS | CE_ATTR_DIS_INTR), ++ .reserved = __cpu_to_le32(0), ++ }, ++ ++ /* CE5: target->host Pktlog */ ++ { ++ .pipenum = __cpu_to_le32(5), ++ .pipedir = __cpu_to_le32(PIPEDIR_IN), ++ .nentries = __cpu_to_le32(32), ++ .nbytes_max = __cpu_to_le32(2048), ++ .flags = __cpu_to_le32(CE_ATTR_FLAGS), ++ .reserved = __cpu_to_le32(0), ++ }, ++ ++ /* CE6: Reserved for target autonomous hif_memcpy */ ++ { ++ .pipenum = __cpu_to_le32(6), ++ .pipedir = __cpu_to_le32(PIPEDIR_INOUT), ++ .nentries = __cpu_to_le32(32), ++ .nbytes_max = __cpu_to_le32(16384), ++ .flags = __cpu_to_le32(CE_ATTR_FLAGS), ++ .reserved = __cpu_to_le32(0), ++ }, ++ ++ /* CE7 used only by Host */ ++ { ++ .pipenum = __cpu_to_le32(7), ++ .pipedir = __cpu_to_le32(PIPEDIR_OUT), ++ .nentries = __cpu_to_le32(32), ++ .nbytes_max = __cpu_to_le32(2048), ++ .flags = __cpu_to_le32(0x2000), ++ .reserved = __cpu_to_le32(0), ++ }, ++ ++ /* CE8 target->host used only by IPA */ ++ { ++ .pipenum = __cpu_to_le32(8), ++ .pipedir = __cpu_to_le32(PIPEDIR_INOUT), ++ .nentries = __cpu_to_le32(32), ++ .nbytes_max = __cpu_to_le32(16384), ++ .flags = __cpu_to_le32(CE_ATTR_FLAGS), ++ .reserved = __cpu_to_le32(0), ++ }, ++}; ++ ++/* Map from service/endpoint to Copy Engine for IPQ5018. ++ * This table is derived from the CE TABLE, above. ++ * It is passed to the Target at startup for use by firmware. ++ */ ++const struct service_to_pipe ath11k_target_service_to_ce_map_wlan_ipq5018[] = { ++ { ++ .service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_VO), ++ .pipedir = __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */ ++ .pipenum = __cpu_to_le32(3), ++ }, ++ { ++ .service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_VO), ++ .pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */ ++ .pipenum = __cpu_to_le32(2), ++ }, ++ { ++ .service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_BK), ++ .pipedir = __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */ ++ .pipenum = __cpu_to_le32(3), ++ }, ++ { ++ .service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_BK), ++ .pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */ ++ .pipenum = __cpu_to_le32(2), ++ }, ++ { ++ .service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_BE), ++ .pipedir = __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */ ++ .pipenum = __cpu_to_le32(3), ++ }, ++ { ++ .service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_BE), ++ .pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */ ++ .pipenum = __cpu_to_le32(2), ++ }, ++ { ++ .service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_VI), ++ .pipedir = __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */ ++ .pipenum = __cpu_to_le32(3), ++ }, ++ { ++ .service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_VI), ++ .pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */ ++ .pipenum = __cpu_to_le32(2), ++ }, ++ { ++ .service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_CONTROL), ++ .pipedir = __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */ ++ .pipenum = __cpu_to_le32(3), ++ }, ++ { ++ .service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_CONTROL), ++ .pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */ ++ .pipenum = __cpu_to_le32(2), ++ }, ++ ++ { ++ .service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_RSVD_CTRL), ++ .pipedir = __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */ ++ .pipenum = __cpu_to_le32(0), ++ }, ++ { ++ .service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_RSVD_CTRL), ++ .pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */ ++ .pipenum = __cpu_to_le32(1), ++ }, ++ ++ { ++ .service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_TEST_RAW_STREAMS), ++ .pipedir = __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */ ++ .pipenum = __cpu_to_le32(0), ++ }, ++ { ++ .service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_TEST_RAW_STREAMS), ++ .pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */ ++ .pipenum = __cpu_to_le32(1), ++ }, ++ { ++ .service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_HTT_DATA_MSG), ++ .pipedir = __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */ ++ .pipenum = __cpu_to_le32(4), ++ }, ++ { ++ .service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_HTT_DATA_MSG), ++ .pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */ ++ .pipenum = __cpu_to_le32(1), ++ }, ++ { ++ .service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_PKT_LOG), ++ .pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */ ++ .pipenum = __cpu_to_le32(5), ++ }, ++ ++ /* (Additions here) */ ++ ++ { /* terminator entry */ } ++}; ++ + const struct ath11k_hw_regs ipq8074_regs = { + /* SW2TCL(x) R0 ring configuration address */ + .hal_tcl1_ring_base_lsb = 0x00000510, diff --git a/package/kernel/mac80211/patches/ath11k/0021-wifi-ath11k-remap-ce-register-space-for-IPQ5018.patch b/package/kernel/mac80211/patches/ath11k/0021-wifi-ath11k-remap-ce-register-space-for-IPQ5018.patch new file mode 100644 index 000000000..d07a258ac --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0021-wifi-ath11k-remap-ce-register-space-for-IPQ5018.patch @@ -0,0 +1,351 @@ +From b42b3678c91f3ca6e0888bf5a15c1e8678fd5f2d Mon Sep 17 00:00:00 2001 +From: Sriram R +Date: Fri, 2 Dec 2022 23:37:14 +0200 +Subject: [PATCH] wifi: ath11k: remap ce register space for IPQ5018 + +In IPQ5018 ce register space is moved out of wcss unlike +ipq8074 or ipq6018 and the space is not contiguous, +hence remap the CE registers to a new space to access them. + +Register read/write is modified to check if the register to be written +falls in the CE register space and corresponding register is written. +Also adjust the interrupt register address to ce irq enable/disable. + +Tested-on: IPQ5018 hw1.0 AHB WLAN.HK.2.6.0.1-00861-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Sriram R +Co-developed-by: Karthikeyan Kathirvel +Signed-off-by: Karthikeyan Kathirvel +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20221122132152.17771-5-quic_kathirve@quicinc.com +--- + drivers/net/wireless/ath/ath11k/ahb.c | 44 ++++++++++++++++++++++---- + drivers/net/wireless/ath/ath11k/ce.h | 16 ++++++++++ + drivers/net/wireless/ath/ath11k/core.c | 8 +++++ + drivers/net/wireless/ath/ath11k/core.h | 1 + + drivers/net/wireless/ath/ath11k/hal.c | 17 ++++++---- + drivers/net/wireless/ath/ath11k/hal.h | 5 +++ + drivers/net/wireless/ath/ath11k/hw.c | 17 ++++++++++ + drivers/net/wireless/ath/ath11k/hw.h | 9 ++++++ + drivers/net/wireless/ath/ath11k/pci.c | 2 ++ + 9 files changed, 107 insertions(+), 12 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/ahb.c ++++ b/drivers/net/wireless/ath/ath11k/ahb.c +@@ -267,30 +267,42 @@ static void ath11k_ahb_clearbit32(struct + static void ath11k_ahb_ce_irq_enable(struct ath11k_base *ab, u16 ce_id) + { + const struct ce_attr *ce_attr; ++ const struct ce_ie_addr *ce_ie_addr = ab->hw_params.ce_ie_addr; ++ u32 ie1_reg_addr, ie2_reg_addr, ie3_reg_addr; ++ ++ ie1_reg_addr = ce_ie_addr->ie1_reg_addr + ATH11K_CE_OFFSET(ab); ++ ie2_reg_addr = ce_ie_addr->ie2_reg_addr + ATH11K_CE_OFFSET(ab); ++ ie3_reg_addr = ce_ie_addr->ie3_reg_addr + ATH11K_CE_OFFSET(ab); + + ce_attr = &ab->hw_params.host_ce_config[ce_id]; + if (ce_attr->src_nentries) +- ath11k_ahb_setbit32(ab, ce_id, CE_HOST_IE_ADDRESS); ++ ath11k_ahb_setbit32(ab, ce_id, ie1_reg_addr); + + if (ce_attr->dest_nentries) { +- ath11k_ahb_setbit32(ab, ce_id, CE_HOST_IE_2_ADDRESS); ++ ath11k_ahb_setbit32(ab, ce_id, ie2_reg_addr); + ath11k_ahb_setbit32(ab, ce_id + CE_HOST_IE_3_SHIFT, +- CE_HOST_IE_3_ADDRESS); ++ ie3_reg_addr); + } + } + + static void ath11k_ahb_ce_irq_disable(struct ath11k_base *ab, u16 ce_id) + { + const struct ce_attr *ce_attr; ++ const struct ce_ie_addr *ce_ie_addr = ab->hw_params.ce_ie_addr; ++ u32 ie1_reg_addr, ie2_reg_addr, ie3_reg_addr; ++ ++ ie1_reg_addr = ce_ie_addr->ie1_reg_addr + ATH11K_CE_OFFSET(ab); ++ ie2_reg_addr = ce_ie_addr->ie2_reg_addr + ATH11K_CE_OFFSET(ab); ++ ie3_reg_addr = ce_ie_addr->ie3_reg_addr + ATH11K_CE_OFFSET(ab); + + ce_attr = &ab->hw_params.host_ce_config[ce_id]; + if (ce_attr->src_nentries) +- ath11k_ahb_clearbit32(ab, ce_id, CE_HOST_IE_ADDRESS); ++ ath11k_ahb_clearbit32(ab, ce_id, ie1_reg_addr); + + if (ce_attr->dest_nentries) { +- ath11k_ahb_clearbit32(ab, ce_id, CE_HOST_IE_2_ADDRESS); ++ ath11k_ahb_clearbit32(ab, ce_id, ie2_reg_addr); + ath11k_ahb_clearbit32(ab, ce_id + CE_HOST_IE_3_SHIFT, +- CE_HOST_IE_3_ADDRESS); ++ ie3_reg_addr); + } + } + +@@ -1142,10 +1154,26 @@ static int ath11k_ahb_probe(struct platf + goto err_core_free; + } + ++ ab->mem_ce = ab->mem; ++ + ret = ath11k_core_pre_init(ab); + if (ret) + goto err_core_free; + ++ if (ab->hw_params.ce_remap) { ++ const struct ce_remap *ce_remap = ab->hw_params.ce_remap; ++ /* ce register space is moved out of wcss unlike ipq8074 or ipq6018 ++ * and the space is not contiguous, hence remapping the CE registers ++ * to a new space for accessing them. ++ */ ++ ab->mem_ce = ioremap(ce_remap->base, ce_remap->size); ++ if (IS_ERR(ab->mem_ce)) { ++ dev_err(&pdev->dev, "ce ioremap error\n"); ++ ret = -ENOMEM; ++ goto err_core_free; ++ } ++ } ++ + ret = ath11k_ahb_setup_resources(ab); + if (ret) + goto err_core_free; +@@ -1236,6 +1264,10 @@ static void ath11k_ahb_free_resources(st + ath11k_ahb_release_smp2p_handle(ab); + ath11k_ahb_fw_resource_deinit(ab); + ath11k_ce_free_pipes(ab); ++ ++ if (ab->hw_params.ce_remap) ++ iounmap(ab->mem_ce); ++ + ath11k_core_free(ab); + platform_set_drvdata(pdev, NULL); + } +--- a/drivers/net/wireless/ath/ath11k/ce.h ++++ b/drivers/net/wireless/ath/ath11k/ce.h +@@ -49,6 +49,11 @@ void ath11k_ce_byte_swap(void *mem, u32 + #define CE_HOST_IE_2_ADDRESS 0x00A18040 + #define CE_HOST_IE_3_ADDRESS CE_HOST_IE_ADDRESS + ++/* CE IE registers are different for IPQ5018 */ ++#define CE_HOST_IPQ5018_IE_ADDRESS 0x0841804C ++#define CE_HOST_IPQ5018_IE_2_ADDRESS 0x08418050 ++#define CE_HOST_IPQ5018_IE_3_ADDRESS CE_HOST_IPQ5018_IE_ADDRESS ++ + #define CE_HOST_IE_3_SHIFT 0xC + + #define CE_RING_IDX_INCR(nentries_mask, idx) (((idx) + 1) & (nentries_mask)) +@@ -84,6 +89,17 @@ struct ce_pipe_config { + __le32 reserved; + }; + ++struct ce_ie_addr { ++ u32 ie1_reg_addr; ++ u32 ie2_reg_addr; ++ u32 ie3_reg_addr; ++}; ++ ++struct ce_remap { ++ u32 base; ++ u32 size; ++}; ++ + struct ce_attr { + /* CE_ATTR_* values */ + unsigned int flags; +--- a/drivers/net/wireless/ath/ath11k/core.c ++++ b/drivers/net/wireless/ath/ath11k/core.c +@@ -54,6 +54,7 @@ static const struct ath11k_hw_params ath + .target_ce_count = 11, + .svc_to_ce_map = ath11k_target_service_to_ce_map_wlan_ipq8074, + .svc_to_ce_map_len = 21, ++ .ce_ie_addr = &ath11k_ce_ie_addr_ipq8074, + .single_pdev_only = false, + .rxdma1_enable = true, + .num_rxmda_per_pdev = 1, +@@ -137,6 +138,7 @@ static const struct ath11k_hw_params ath + .target_ce_count = 11, + .svc_to_ce_map = ath11k_target_service_to_ce_map_wlan_ipq6018, + .svc_to_ce_map_len = 19, ++ .ce_ie_addr = &ath11k_ce_ie_addr_ipq8074, + .single_pdev_only = false, + .rxdma1_enable = true, + .num_rxmda_per_pdev = 1, +@@ -218,6 +220,7 @@ static const struct ath11k_hw_params ath + .target_ce_count = 9, + .svc_to_ce_map = ath11k_target_service_to_ce_map_wlan_qca6390, + .svc_to_ce_map_len = 14, ++ .ce_ie_addr = &ath11k_ce_ie_addr_ipq8074, + .single_pdev_only = true, + .rxdma1_enable = false, + .num_rxmda_per_pdev = 2, +@@ -301,6 +304,7 @@ static const struct ath11k_hw_params ath + .target_ce_count = 9, + .svc_to_ce_map = ath11k_target_service_to_ce_map_wlan_qcn9074, + .svc_to_ce_map_len = 18, ++ .ce_ie_addr = &ath11k_ce_ie_addr_ipq8074, + .rxdma1_enable = true, + .num_rxmda_per_pdev = 1, + .rx_mac_buf_ring = false, +@@ -381,6 +385,7 @@ static const struct ath11k_hw_params ath + .target_ce_count = 9, + .svc_to_ce_map = ath11k_target_service_to_ce_map_wlan_qca6390, + .svc_to_ce_map_len = 14, ++ .ce_ie_addr = &ath11k_ce_ie_addr_ipq8074, + .single_pdev_only = true, + .rxdma1_enable = false, + .num_rxmda_per_pdev = 2, +@@ -546,6 +551,7 @@ static const struct ath11k_hw_params ath + .target_ce_count = 9, + .svc_to_ce_map = ath11k_target_service_to_ce_map_wlan_qca6390, + .svc_to_ce_map_len = 14, ++ .ce_ie_addr = &ath11k_ce_ie_addr_ipq8074, + .single_pdev_only = true, + .rxdma1_enable = false, + .num_rxmda_per_pdev = 1, +@@ -634,6 +640,8 @@ static const struct ath11k_hw_params ath + .target_ce_count = TARGET_CE_CNT_5018, + .svc_to_ce_map = ath11k_target_service_to_ce_map_wlan_ipq5018, + .svc_to_ce_map_len = SVC_CE_MAP_LEN_5018, ++ .ce_ie_addr = &ath11k_ce_ie_addr_ipq5018, ++ .ce_remap = &ath11k_ce_remap_ipq5018, + .rxdma1_enable = true, + .num_rxmda_per_pdev = RXDMA_PER_PDEV_5018, + .rx_mac_buf_ring = false, +--- a/drivers/net/wireless/ath/ath11k/core.h ++++ b/drivers/net/wireless/ath/ath11k/core.h +@@ -851,6 +851,7 @@ struct ath11k_base { + struct ath11k_dp dp; + + void __iomem *mem; ++ void __iomem *mem_ce; + unsigned long mem_len; + + struct { +--- a/drivers/net/wireless/ath/ath11k/hal.c ++++ b/drivers/net/wireless/ath/ath11k/hal.c +@@ -1220,16 +1220,20 @@ static int ath11k_hal_srng_create_config + s->reg_start[1] = HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL_STATUS_RING_HP; + + s = &hal->srng_config[HAL_CE_SRC]; +- s->reg_start[0] = HAL_SEQ_WCSS_UMAC_CE0_SRC_REG(ab) + HAL_CE_DST_RING_BASE_LSB; +- s->reg_start[1] = HAL_SEQ_WCSS_UMAC_CE0_SRC_REG(ab) + HAL_CE_DST_RING_HP; ++ s->reg_start[0] = HAL_SEQ_WCSS_UMAC_CE0_SRC_REG(ab) + HAL_CE_DST_RING_BASE_LSB + ++ ATH11K_CE_OFFSET(ab); ++ s->reg_start[1] = HAL_SEQ_WCSS_UMAC_CE0_SRC_REG(ab) + HAL_CE_DST_RING_HP + ++ ATH11K_CE_OFFSET(ab); + s->reg_size[0] = HAL_SEQ_WCSS_UMAC_CE1_SRC_REG(ab) - + HAL_SEQ_WCSS_UMAC_CE0_SRC_REG(ab); + s->reg_size[1] = HAL_SEQ_WCSS_UMAC_CE1_SRC_REG(ab) - + HAL_SEQ_WCSS_UMAC_CE0_SRC_REG(ab); + + s = &hal->srng_config[HAL_CE_DST]; +- s->reg_start[0] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab) + HAL_CE_DST_RING_BASE_LSB; +- s->reg_start[1] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab) + HAL_CE_DST_RING_HP; ++ s->reg_start[0] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab) + HAL_CE_DST_RING_BASE_LSB + ++ ATH11K_CE_OFFSET(ab); ++ s->reg_start[1] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab) + HAL_CE_DST_RING_HP + ++ ATH11K_CE_OFFSET(ab); + s->reg_size[0] = HAL_SEQ_WCSS_UMAC_CE1_DST_REG(ab) - + HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab); + s->reg_size[1] = HAL_SEQ_WCSS_UMAC_CE1_DST_REG(ab) - +@@ -1237,8 +1241,9 @@ static int ath11k_hal_srng_create_config + + s = &hal->srng_config[HAL_CE_DST_STATUS]; + s->reg_start[0] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab) + +- HAL_CE_DST_STATUS_RING_BASE_LSB; +- s->reg_start[1] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab) + HAL_CE_DST_STATUS_RING_HP; ++ HAL_CE_DST_STATUS_RING_BASE_LSB + ATH11K_CE_OFFSET(ab); ++ s->reg_start[1] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab) + HAL_CE_DST_STATUS_RING_HP + ++ ATH11K_CE_OFFSET(ab); + s->reg_size[0] = HAL_SEQ_WCSS_UMAC_CE1_DST_REG(ab) - + HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab); + s->reg_size[1] = HAL_SEQ_WCSS_UMAC_CE1_DST_REG(ab) - +--- a/drivers/net/wireless/ath/ath11k/hal.h ++++ b/drivers/net/wireless/ath/ath11k/hal.h +@@ -321,6 +321,10 @@ struct ath11k_base; + #define HAL_WBM2SW_RELEASE_RING_BASE_MSB_RING_SIZE 0x000fffff + #define HAL_RXDMA_RING_MAX_SIZE 0x0000ffff + ++/* IPQ5018 ce registers */ ++#define HAL_IPQ5018_CE_WFSS_REG_BASE 0x08400000 ++#define HAL_IPQ5018_CE_SIZE 0x200000 ++ + /* Add any other errors here and return them in + * ath11k_hal_rx_desc_get_err(). + */ +@@ -519,6 +523,7 @@ enum hal_srng_dir { + #define HAL_SRNG_FLAGS_MSI_INTR 0x00020000 + #define HAL_SRNG_FLAGS_CACHED 0x20000000 + #define HAL_SRNG_FLAGS_LMAC_RING 0x80000000 ++#define HAL_SRNG_FLAGS_REMAP_CE_RING 0x10000000 + + #define HAL_SRNG_TLV_HDR_TAG GENMASK(9, 1) + #define HAL_SRNG_TLV_HDR_LEN GENMASK(25, 10) +--- a/drivers/net/wireless/ath/ath11k/hw.c ++++ b/drivers/net/wireless/ath/ath11k/hw.c +@@ -2163,6 +2163,23 @@ const struct service_to_pipe ath11k_targ + { /* terminator entry */ } + }; + ++const struct ce_ie_addr ath11k_ce_ie_addr_ipq8074 = { ++ .ie1_reg_addr = CE_HOST_IE_ADDRESS, ++ .ie2_reg_addr = CE_HOST_IE_2_ADDRESS, ++ .ie3_reg_addr = CE_HOST_IE_3_ADDRESS, ++}; ++ ++const struct ce_ie_addr ath11k_ce_ie_addr_ipq5018 = { ++ .ie1_reg_addr = CE_HOST_IPQ5018_IE_ADDRESS - HAL_IPQ5018_CE_WFSS_REG_BASE, ++ .ie2_reg_addr = CE_HOST_IPQ5018_IE_2_ADDRESS - HAL_IPQ5018_CE_WFSS_REG_BASE, ++ .ie3_reg_addr = CE_HOST_IPQ5018_IE_3_ADDRESS - HAL_IPQ5018_CE_WFSS_REG_BASE, ++}; ++ ++const struct ce_remap ath11k_ce_remap_ipq5018 = { ++ .base = HAL_IPQ5018_CE_WFSS_REG_BASE, ++ .size = HAL_IPQ5018_CE_SIZE, ++}; ++ + const struct ath11k_hw_regs ipq8074_regs = { + /* SW2TCL(x) R0 ring configuration address */ + .hal_tcl1_ring_base_lsb = 0x00000510, +--- a/drivers/net/wireless/ath/ath11k/hw.h ++++ b/drivers/net/wireless/ath/ath11k/hw.h +@@ -80,6 +80,8 @@ + #define ATH11K_M3_FILE "m3.bin" + #define ATH11K_REGDB_FILE_NAME "regdb.bin" + ++#define ATH11K_CE_OFFSET(ab) (ab->mem_ce - ab->mem) ++ + enum ath11k_hw_rate_cck { + ATH11K_HW_RATE_CCK_LP_11M = 0, + ATH11K_HW_RATE_CCK_LP_5_5M, +@@ -158,6 +160,8 @@ struct ath11k_hw_params { + u32 target_ce_count; + const struct service_to_pipe *svc_to_ce_map; + u32 svc_to_ce_map_len; ++ const struct ce_ie_addr *ce_ie_addr; ++ const struct ce_remap *ce_remap; + + bool single_pdev_only; + +@@ -277,6 +281,11 @@ extern const struct ath11k_hw_ring_mask + extern const struct ath11k_hw_ring_mask ath11k_hw_ring_mask_qcn9074; + extern const struct ath11k_hw_ring_mask ath11k_hw_ring_mask_wcn6750; + ++extern const struct ce_ie_addr ath11k_ce_ie_addr_ipq8074; ++extern const struct ce_ie_addr ath11k_ce_ie_addr_ipq5018; ++ ++extern const struct ce_remap ath11k_ce_remap_ipq5018; ++ + extern const struct ath11k_hw_hal_params ath11k_hw_hal_params_ipq8074; + extern const struct ath11k_hw_hal_params ath11k_hw_hal_params_qca6390; + extern const struct ath11k_hw_hal_params ath11k_hw_hal_params_wcn6750; +--- a/drivers/net/wireless/ath/ath11k/pci.c ++++ b/drivers/net/wireless/ath/ath11k/pci.c +@@ -543,6 +543,8 @@ static int ath11k_pci_claim(struct ath11 + goto clear_master; + } + ++ ab->mem_ce = ab->mem; ++ + ath11k_dbg(ab, ATH11K_DBG_BOOT, "boot pci_mem 0x%pK\n", ab->mem); + return 0; + diff --git a/package/kernel/mac80211/patches/ath11k/0022-wifi-ath11k-update-hal-srng-regs-for-IPQ5018.patch b/package/kernel/mac80211/patches/ath11k/0022-wifi-ath11k-update-hal-srng-regs-for-IPQ5018.patch new file mode 100644 index 000000000..35ea20a3c --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0022-wifi-ath11k-update-hal-srng-regs-for-IPQ5018.patch @@ -0,0 +1,130 @@ +From 711b80acbdfb9667a9cf8374e13320a6e624ce73 Mon Sep 17 00:00:00 2001 +From: Sriram R +Date: Fri, 2 Dec 2022 23:37:14 +0200 +Subject: [PATCH] wifi: ath11k: update hal srng regs for IPQ5018 + +IPQ5018 hal srng register address & offsets are not +similar to IPQ8074/IPQ6018/QCN9074, hence define a +new set of srng register group data for IPQ5018. + +Tested-on: IPQ5018 hw1.0 AHB WLAN.HK.2.6.0.1-00861-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Sriram R +Co-developed-by: Karthikeyan Kathirvel +Signed-off-by: Karthikeyan Kathirvel +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20221122132152.17771-6-quic_kathirve@quicinc.com +--- + drivers/net/wireless/ath/ath11k/core.c | 1 + + drivers/net/wireless/ath/ath11k/hw.c | 79 ++++++++++++++++++++++++++ + drivers/net/wireless/ath/ath11k/hw.h | 1 + + 3 files changed, 81 insertions(+) + +--- a/drivers/net/wireless/ath/ath11k/core.c ++++ b/drivers/net/wireless/ath/ath11k/core.c +@@ -634,6 +634,7 @@ static const struct ath11k_hw_params ath + .max_fft_bins = 1024, + }, + .internal_sleep_clock = false, ++ .regs = &ipq5018_regs, + .host_ce_config = ath11k_host_ce_config_qcn9074, + .ce_count = CE_CNT_5018, + .target_ce_config = ath11k_target_ce_config_wlan_ipq5018, +--- a/drivers/net/wireless/ath/ath11k/hw.c ++++ b/drivers/net/wireless/ath/ath11k/hw.c +@@ -2645,6 +2645,85 @@ static const struct ath11k_hw_tcl2wbm_rb + }, + }; + ++const struct ath11k_hw_regs ipq5018_regs = { ++ /* SW2TCL(x) R0 ring configuration address */ ++ .hal_tcl1_ring_base_lsb = 0x00000694, ++ .hal_tcl1_ring_base_msb = 0x00000698, ++ .hal_tcl1_ring_id = 0x0000069c, ++ .hal_tcl1_ring_misc = 0x000006a4, ++ .hal_tcl1_ring_tp_addr_lsb = 0x000006b0, ++ .hal_tcl1_ring_tp_addr_msb = 0x000006b4, ++ .hal_tcl1_ring_consumer_int_setup_ix0 = 0x000006c4, ++ .hal_tcl1_ring_consumer_int_setup_ix1 = 0x000006c8, ++ .hal_tcl1_ring_msi1_base_lsb = 0x000006dc, ++ .hal_tcl1_ring_msi1_base_msb = 0x000006e0, ++ .hal_tcl1_ring_msi1_data = 0x000006e4, ++ .hal_tcl2_ring_base_lsb = 0x000006ec, ++ .hal_tcl_ring_base_lsb = 0x0000079c, ++ ++ /* TCL STATUS ring address */ ++ .hal_tcl_status_ring_base_lsb = 0x000008a4, ++ ++ /* REO2SW(x) R0 ring configuration address */ ++ .hal_reo1_ring_base_lsb = 0x000001ec, ++ .hal_reo1_ring_base_msb = 0x000001f0, ++ .hal_reo1_ring_id = 0x000001f4, ++ .hal_reo1_ring_misc = 0x000001fc, ++ .hal_reo1_ring_hp_addr_lsb = 0x00000200, ++ .hal_reo1_ring_hp_addr_msb = 0x00000204, ++ .hal_reo1_ring_producer_int_setup = 0x00000210, ++ .hal_reo1_ring_msi1_base_lsb = 0x00000234, ++ .hal_reo1_ring_msi1_base_msb = 0x00000238, ++ .hal_reo1_ring_msi1_data = 0x0000023c, ++ .hal_reo2_ring_base_lsb = 0x00000244, ++ .hal_reo1_aging_thresh_ix_0 = 0x00000564, ++ .hal_reo1_aging_thresh_ix_1 = 0x00000568, ++ .hal_reo1_aging_thresh_ix_2 = 0x0000056c, ++ .hal_reo1_aging_thresh_ix_3 = 0x00000570, ++ ++ /* REO2SW(x) R2 ring pointers (head/tail) address */ ++ .hal_reo1_ring_hp = 0x00003028, ++ .hal_reo1_ring_tp = 0x0000302c, ++ .hal_reo2_ring_hp = 0x00003030, ++ ++ /* REO2TCL R0 ring configuration address */ ++ .hal_reo_tcl_ring_base_lsb = 0x000003fc, ++ .hal_reo_tcl_ring_hp = 0x00003058, ++ ++ /* SW2REO ring address */ ++ .hal_sw2reo_ring_base_lsb = 0x0000013c, ++ .hal_sw2reo_ring_hp = 0x00003018, ++ ++ /* REO CMD ring address */ ++ .hal_reo_cmd_ring_base_lsb = 0x000000e4, ++ .hal_reo_cmd_ring_hp = 0x00003010, ++ ++ /* REO status address */ ++ .hal_reo_status_ring_base_lsb = 0x00000504, ++ .hal_reo_status_hp = 0x00003070, ++ ++ /* WCSS relative address */ ++ .hal_seq_wcss_umac_ce0_src_reg = 0x08400000 ++ - HAL_IPQ5018_CE_WFSS_REG_BASE, ++ .hal_seq_wcss_umac_ce0_dst_reg = 0x08401000 ++ - HAL_IPQ5018_CE_WFSS_REG_BASE, ++ .hal_seq_wcss_umac_ce1_src_reg = 0x08402000 ++ - HAL_IPQ5018_CE_WFSS_REG_BASE, ++ .hal_seq_wcss_umac_ce1_dst_reg = 0x08403000 ++ - HAL_IPQ5018_CE_WFSS_REG_BASE, ++ ++ /* WBM Idle address */ ++ .hal_wbm_idle_link_ring_base_lsb = 0x00000874, ++ .hal_wbm_idle_link_ring_misc = 0x00000884, ++ ++ /* SW2WBM release address */ ++ .hal_wbm_release_ring_base_lsb = 0x000001ec, ++ ++ /* WBM2SW release address */ ++ .hal_wbm0_release_ring_base_lsb = 0x00000924, ++ .hal_wbm1_release_ring_base_lsb = 0x0000097c, ++}; ++ + const struct ath11k_hw_hal_params ath11k_hw_hal_params_ipq8074 = { + .rx_buf_rbm = HAL_RX_BUF_RBM_SW3_BM, + .tcl2wbm_rbm_map = ath11k_hw_tcl2wbm_rbm_map_ipq8074, +--- a/drivers/net/wireless/ath/ath11k/hw.h ++++ b/drivers/net/wireless/ath/ath11k/hw.h +@@ -415,6 +415,7 @@ extern const struct ath11k_hw_regs qca63 + extern const struct ath11k_hw_regs qcn9074_regs; + extern const struct ath11k_hw_regs wcn6855_regs; + extern const struct ath11k_hw_regs wcn6750_regs; ++extern const struct ath11k_hw_regs ipq5018_regs; + + static inline const char *ath11k_bd_ie_type_str(enum ath11k_bd_ie_type type) + { diff --git a/package/kernel/mac80211/patches/ath11k/0023-wifi-ath11k-initialize-hw_ops-for-IPQ5018.patch b/package/kernel/mac80211/patches/ath11k/0023-wifi-ath11k-initialize-hw_ops-for-IPQ5018.patch new file mode 100644 index 000000000..5ef701a44 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0023-wifi-ath11k-initialize-hw_ops-for-IPQ5018.patch @@ -0,0 +1,90 @@ +From ba60f2793d3a37a00da14bb56a26558a902d2831 Mon Sep 17 00:00:00 2001 +From: Sriram R +Date: Fri, 2 Dec 2022 23:37:14 +0200 +Subject: [PATCH] wifi: ath11k: initialize hw_ops for IPQ5018 + +The ipq5018_ops is initialized for IPQ5018. This is different from +other platforms. + +Tested-on: IPQ5018 hw1.0 AHB WLAN.HK.2.6.0.1-00861-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Sriram R +Co-developed-by: Karthikeyan Kathirvel +Signed-off-by: Karthikeyan Kathirvel +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20221122132152.17771-7-quic_kathirve@quicinc.com +--- + drivers/net/wireless/ath/ath11k/core.c | 1 + + drivers/net/wireless/ath/ath11k/hw.c | 40 ++++++++++++++++++++++++++ + drivers/net/wireless/ath/ath11k/hw.h | 1 + + 3 files changed, 42 insertions(+) + +--- a/drivers/net/wireless/ath/ath11k/core.c ++++ b/drivers/net/wireless/ath/ath11k/core.c +@@ -635,6 +635,7 @@ static const struct ath11k_hw_params ath + }, + .internal_sleep_clock = false, + .regs = &ipq5018_regs, ++ .hw_ops = &ipq5018_ops, + .host_ce_config = ath11k_host_ce_config_qcn9074, + .ce_count = CE_CNT_5018, + .target_ce_config = ath11k_target_ce_config_wlan_ipq5018, +--- a/drivers/net/wireless/ath/ath11k/hw.c ++++ b/drivers/net/wireless/ath/ath11k/hw.c +@@ -1084,6 +1084,46 @@ const struct ath11k_hw_ops wcn6750_ops = + .get_ring_selector = ath11k_hw_wcn6750_get_tcl_ring_selector, + }; + ++/* IPQ5018 hw ops is similar to QCN9074 except for the dest ring remap */ ++const struct ath11k_hw_ops ipq5018_ops = { ++ .get_hw_mac_from_pdev_id = ath11k_hw_ipq6018_mac_from_pdev_id, ++ .wmi_init_config = ath11k_init_wmi_config_ipq8074, ++ .mac_id_to_pdev_id = ath11k_hw_mac_id_to_pdev_id_ipq8074, ++ .mac_id_to_srng_id = ath11k_hw_mac_id_to_srng_id_ipq8074, ++ .tx_mesh_enable = ath11k_hw_qcn9074_tx_mesh_enable, ++ .rx_desc_get_first_msdu = ath11k_hw_qcn9074_rx_desc_get_first_msdu, ++ .rx_desc_get_last_msdu = ath11k_hw_qcn9074_rx_desc_get_last_msdu, ++ .rx_desc_get_l3_pad_bytes = ath11k_hw_qcn9074_rx_desc_get_l3_pad_bytes, ++ .rx_desc_get_hdr_status = ath11k_hw_qcn9074_rx_desc_get_hdr_status, ++ .rx_desc_encrypt_valid = ath11k_hw_qcn9074_rx_desc_encrypt_valid, ++ .rx_desc_get_encrypt_type = ath11k_hw_qcn9074_rx_desc_get_encrypt_type, ++ .rx_desc_get_decap_type = ath11k_hw_qcn9074_rx_desc_get_decap_type, ++ .rx_desc_get_mesh_ctl = ath11k_hw_qcn9074_rx_desc_get_mesh_ctl, ++ .rx_desc_get_ldpc_support = ath11k_hw_qcn9074_rx_desc_get_ldpc_support, ++ .rx_desc_get_mpdu_seq_ctl_vld = ath11k_hw_qcn9074_rx_desc_get_mpdu_seq_ctl_vld, ++ .rx_desc_get_mpdu_fc_valid = ath11k_hw_qcn9074_rx_desc_get_mpdu_fc_valid, ++ .rx_desc_get_mpdu_start_seq_no = ath11k_hw_qcn9074_rx_desc_get_mpdu_start_seq_no, ++ .rx_desc_get_msdu_len = ath11k_hw_qcn9074_rx_desc_get_msdu_len, ++ .rx_desc_get_msdu_sgi = ath11k_hw_qcn9074_rx_desc_get_msdu_sgi, ++ .rx_desc_get_msdu_rate_mcs = ath11k_hw_qcn9074_rx_desc_get_msdu_rate_mcs, ++ .rx_desc_get_msdu_rx_bw = ath11k_hw_qcn9074_rx_desc_get_msdu_rx_bw, ++ .rx_desc_get_msdu_freq = ath11k_hw_qcn9074_rx_desc_get_msdu_freq, ++ .rx_desc_get_msdu_pkt_type = ath11k_hw_qcn9074_rx_desc_get_msdu_pkt_type, ++ .rx_desc_get_msdu_nss = ath11k_hw_qcn9074_rx_desc_get_msdu_nss, ++ .rx_desc_get_mpdu_tid = ath11k_hw_qcn9074_rx_desc_get_mpdu_tid, ++ .rx_desc_get_mpdu_peer_id = ath11k_hw_qcn9074_rx_desc_get_mpdu_peer_id, ++ .rx_desc_copy_attn_end_tlv = ath11k_hw_qcn9074_rx_desc_copy_attn_end, ++ .rx_desc_get_mpdu_start_tag = ath11k_hw_qcn9074_rx_desc_get_mpdu_start_tag, ++ .rx_desc_get_mpdu_ppdu_id = ath11k_hw_qcn9074_rx_desc_get_mpdu_ppdu_id, ++ .rx_desc_set_msdu_len = ath11k_hw_qcn9074_rx_desc_set_msdu_len, ++ .rx_desc_get_attention = ath11k_hw_qcn9074_rx_desc_get_attention, ++ .rx_desc_get_msdu_payload = ath11k_hw_qcn9074_rx_desc_get_msdu_payload, ++ .mpdu_info_get_peerid = ath11k_hw_ipq8074_mpdu_info_get_peerid, ++ .rx_desc_mac_addr2_valid = ath11k_hw_ipq9074_rx_desc_mac_addr2_valid, ++ .rx_desc_mpdu_start_addr2 = ath11k_hw_ipq9074_rx_desc_mpdu_start_addr2, ++ ++}; ++ + #define ATH11K_TX_RING_MASK_0 BIT(0) + #define ATH11K_TX_RING_MASK_1 BIT(1) + #define ATH11K_TX_RING_MASK_2 BIT(2) +--- a/drivers/net/wireless/ath/ath11k/hw.h ++++ b/drivers/net/wireless/ath/ath11k/hw.h +@@ -275,6 +275,7 @@ extern const struct ath11k_hw_ops qca639 + extern const struct ath11k_hw_ops qcn9074_ops; + extern const struct ath11k_hw_ops wcn6855_ops; + extern const struct ath11k_hw_ops wcn6750_ops; ++extern const struct ath11k_hw_ops ipq5018_ops; + + extern const struct ath11k_hw_ring_mask ath11k_hw_ring_mask_ipq8074; + extern const struct ath11k_hw_ring_mask ath11k_hw_ring_mask_qca6390; diff --git a/package/kernel/mac80211/patches/ath11k/0024-wifi-ath11k-add-new-hw-ops-for-IPQ5018-to-get-rx-des.patch b/package/kernel/mac80211/patches/ath11k/0024-wifi-ath11k-add-new-hw-ops-for-IPQ5018-to-get-rx-des.patch new file mode 100644 index 000000000..64531f13f --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0024-wifi-ath11k-add-new-hw-ops-for-IPQ5018-to-get-rx-des.patch @@ -0,0 +1,84 @@ +From 69968f88f1770d61cae0febef805fd00d66cf6a1 Mon Sep 17 00:00:00 2001 +From: Sriram R +Date: Fri, 2 Dec 2022 23:37:15 +0200 +Subject: [PATCH] wifi: ath11k: add new hw ops for IPQ5018 to get rx dest ring + hashmap + +The Destination ring control register is different +for IPQ5018 when compared to IPQ8074/IPQ6018/QCN9074. +Hence create a new hw ops to fetch the hash ring map +for different device variants. ipq5018 hw ops +is similar to qcn9074 except for this change, so reuse +all the qcn9074 ops for ipq5018. + +Tested-on: IPQ5018 hw1.0 AHB WLAN.HK.2.6.0.1-00861-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Sriram R +Co-developed-by: Karthikeyan Kathirvel +Signed-off-by: Karthikeyan Kathirvel +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20221122132152.17771-8-quic_kathirve@quicinc.com +--- + drivers/net/wireless/ath/ath11k/hw.c | 44 ++++++++++++++++++++++++++++ + 1 file changed, 44 insertions(+) + +--- a/drivers/net/wireless/ath/ath11k/hw.c ++++ b/drivers/net/wireless/ath/ath11k/hw.c +@@ -791,6 +791,49 @@ static void ath11k_hw_wcn6855_reo_setup( + ring_hash_map); + } + ++static void ath11k_hw_ipq5018_reo_setup(struct ath11k_base *ab) ++{ ++ u32 reo_base = HAL_SEQ_WCSS_UMAC_REO_REG; ++ u32 val; ++ ++ /* Each hash entry uses three bits to map to a particular ring. */ ++ u32 ring_hash_map = HAL_HASH_ROUTING_RING_SW1 << 0 | ++ HAL_HASH_ROUTING_RING_SW2 << 4 | ++ HAL_HASH_ROUTING_RING_SW3 << 8 | ++ HAL_HASH_ROUTING_RING_SW4 << 12 | ++ HAL_HASH_ROUTING_RING_SW1 << 16 | ++ HAL_HASH_ROUTING_RING_SW2 << 20 | ++ HAL_HASH_ROUTING_RING_SW3 << 24 | ++ HAL_HASH_ROUTING_RING_SW4 << 28; ++ ++ val = ath11k_hif_read32(ab, reo_base + HAL_REO1_GEN_ENABLE); ++ ++ val &= ~HAL_REO1_GEN_ENABLE_FRAG_DST_RING; ++ val |= FIELD_PREP(HAL_REO1_GEN_ENABLE_FRAG_DST_RING, ++ HAL_SRNG_RING_ID_REO2SW1) | ++ FIELD_PREP(HAL_REO1_GEN_ENABLE_AGING_LIST_ENABLE, 1) | ++ FIELD_PREP(HAL_REO1_GEN_ENABLE_AGING_FLUSH_ENABLE, 1); ++ ath11k_hif_write32(ab, reo_base + HAL_REO1_GEN_ENABLE, val); ++ ++ ath11k_hif_write32(ab, reo_base + HAL_REO1_AGING_THRESH_IX_0(ab), ++ HAL_DEFAULT_REO_TIMEOUT_USEC); ++ ath11k_hif_write32(ab, reo_base + HAL_REO1_AGING_THRESH_IX_1(ab), ++ HAL_DEFAULT_REO_TIMEOUT_USEC); ++ ath11k_hif_write32(ab, reo_base + HAL_REO1_AGING_THRESH_IX_2(ab), ++ HAL_DEFAULT_REO_TIMEOUT_USEC); ++ ath11k_hif_write32(ab, reo_base + HAL_REO1_AGING_THRESH_IX_3(ab), ++ HAL_DEFAULT_REO_TIMEOUT_USEC); ++ ++ ath11k_hif_write32(ab, reo_base + HAL_REO1_DEST_RING_CTRL_IX_0, ++ ring_hash_map); ++ ath11k_hif_write32(ab, reo_base + HAL_REO1_DEST_RING_CTRL_IX_1, ++ ring_hash_map); ++ ath11k_hif_write32(ab, reo_base + HAL_REO1_DEST_RING_CTRL_IX_2, ++ ring_hash_map); ++ ath11k_hif_write32(ab, reo_base + HAL_REO1_DEST_RING_CTRL_IX_3, ++ ring_hash_map); ++} ++ + static u16 ath11k_hw_ipq8074_mpdu_info_get_peerid(u8 *tlv_data) + { + u16 peer_id = 0; +@@ -1117,6 +1160,7 @@ const struct ath11k_hw_ops ipq5018_ops = + .rx_desc_get_mpdu_ppdu_id = ath11k_hw_qcn9074_rx_desc_get_mpdu_ppdu_id, + .rx_desc_set_msdu_len = ath11k_hw_qcn9074_rx_desc_set_msdu_len, + .rx_desc_get_attention = ath11k_hw_qcn9074_rx_desc_get_attention, ++ .reo_setup = ath11k_hw_ipq5018_reo_setup, + .rx_desc_get_msdu_payload = ath11k_hw_qcn9074_rx_desc_get_msdu_payload, + .mpdu_info_get_peerid = ath11k_hw_ipq8074_mpdu_info_get_peerid, + .rx_desc_mac_addr2_valid = ath11k_hw_ipq9074_rx_desc_mac_addr2_valid, diff --git a/package/kernel/mac80211/patches/ath11k/0025-wifi-ath11k-add-ipq5018-device-support.patch b/package/kernel/mac80211/patches/ath11k/0025-wifi-ath11k-add-ipq5018-device-support.patch new file mode 100644 index 000000000..5b930e8d4 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0025-wifi-ath11k-add-ipq5018-device-support.patch @@ -0,0 +1,31 @@ +From 25edca7bb18a2a40cc7e54c6f522e9b3c917e2c5 Mon Sep 17 00:00:00 2001 +From: Sriram R +Date: Fri, 2 Dec 2022 23:37:15 +0200 +Subject: [PATCH] wifi: ath11k: add ipq5018 device support + +ipq5018 is a ahb 2ghz device, enable the compatible support for +ipq5018 in ahb. + +Tested-on: IPQ5018 hw1.0 AHB WLAN.HK.2.6.0.1-00861-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Sriram R +Co-developed-by: Karthikeyan Kathirvel +Signed-off-by: Karthikeyan Kathirvel +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20221122132152.17771-9-quic_kathirve@quicinc.com +--- + drivers/net/wireless/ath/ath11k/ahb.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/net/wireless/ath/ath11k/ahb.c ++++ b/drivers/net/wireless/ath/ath11k/ahb.c +@@ -32,6 +32,9 @@ static const struct of_device_id ath11k_ + { .compatible = "qcom,wcn6750-wifi", + .data = (void *)ATH11K_HW_WCN6750_HW10, + }, ++ { .compatible = "qcom,ipq5018-wifi", ++ .data = (void *)ATH11K_HW_IPQ5018_HW10, ++ }, + { } + }; + diff --git a/package/kernel/mac80211/patches/ath11k/0026-wifi-ath11k-Fix-scan-request-param-frame-size-warnin.patch b/package/kernel/mac80211/patches/ath11k/0026-wifi-ath11k-Fix-scan-request-param-frame-size-warnin.patch new file mode 100644 index 000000000..50c14e7b9 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0026-wifi-ath11k-Fix-scan-request-param-frame-size-warnin.patch @@ -0,0 +1,161 @@ +From d45daa6d1a8da080f1b516c570a8428a7b9225e4 Mon Sep 17 00:00:00 2001 +From: Karthikeyan Kathirvel +Date: Tue, 6 Dec 2022 00:51:25 +0530 +Subject: [PATCH] wifi: ath11k: Fix scan request param frame size warning + +Following warning was observed + +drivers/net/wireless/ath/ath11k/mac.c:2351:1: warning: the frame +size of 1184 bytes is larger than 1024 bytes [-Wframe-larger-than=] + +A local variable is declared with a size larger than 1024 bytes +this causing a compilation warning. Change the local variable to +heap memory to fix the warning. + +Tested-on: IPQ8074 AHB WLAN.HK.2.7.0.1-01701-QCAHKSWPL_SILICONZ-1 v2 + +Signed-off-by: Karthikeyan Kathirvel +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20221205192125.13533-1-quic_kathirve@quicinc.com +--- + drivers/net/wireless/ath/ath11k/mac.c | 83 +++++++++++++++------------ + 1 file changed, 45 insertions(+), 38 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -3612,7 +3612,7 @@ static int ath11k_mac_op_hw_scan(struct + struct ath11k *ar = hw->priv; + struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif); + struct cfg80211_scan_request *req = &hw_req->req; +- struct scan_req_params arg; ++ struct scan_req_params *arg = NULL; + int ret = 0; + int i; + u32 scan_timeout; +@@ -3640,72 +3640,78 @@ static int ath11k_mac_op_hw_scan(struct + if (ret) + goto exit; + +- memset(&arg, 0, sizeof(arg)); +- ath11k_wmi_start_scan_init(ar, &arg); +- arg.vdev_id = arvif->vdev_id; +- arg.scan_id = ATH11K_SCAN_ID; ++ arg = kzalloc(sizeof(*arg), GFP_KERNEL); ++ ++ if (!arg) { ++ ret = -ENOMEM; ++ goto exit; ++ } ++ ++ ath11k_wmi_start_scan_init(ar, arg); ++ arg->vdev_id = arvif->vdev_id; ++ arg->scan_id = ATH11K_SCAN_ID; + + if (req->ie_len) { +- arg.extraie.ptr = kmemdup(req->ie, req->ie_len, GFP_KERNEL); +- if (!arg.extraie.ptr) { ++ arg->extraie.ptr = kmemdup(req->ie, req->ie_len, GFP_KERNEL); ++ if (!arg->extraie.ptr) { + ret = -ENOMEM; + goto exit; + } +- arg.extraie.len = req->ie_len; ++ arg->extraie.len = req->ie_len; + } + + if (req->n_ssids) { +- arg.num_ssids = req->n_ssids; +- for (i = 0; i < arg.num_ssids; i++) { +- arg.ssid[i].length = req->ssids[i].ssid_len; +- memcpy(&arg.ssid[i].ssid, req->ssids[i].ssid, ++ arg->num_ssids = req->n_ssids; ++ for (i = 0; i < arg->num_ssids; i++) { ++ arg->ssid[i].length = req->ssids[i].ssid_len; ++ memcpy(&arg->ssid[i].ssid, req->ssids[i].ssid, + req->ssids[i].ssid_len); + } + } else { +- arg.scan_flags |= WMI_SCAN_FLAG_PASSIVE; ++ arg->scan_flags |= WMI_SCAN_FLAG_PASSIVE; + } + + if (req->n_channels) { +- arg.num_chan = req->n_channels; +- arg.chan_list = kcalloc(arg.num_chan, sizeof(*arg.chan_list), +- GFP_KERNEL); ++ arg->num_chan = req->n_channels; ++ arg->chan_list = kcalloc(arg->num_chan, sizeof(*arg->chan_list), ++ GFP_KERNEL); + +- if (!arg.chan_list) { ++ if (!arg->chan_list) { + ret = -ENOMEM; + goto exit; + } + +- for (i = 0; i < arg.num_chan; i++) +- arg.chan_list[i] = req->channels[i]->center_freq; ++ for (i = 0; i < arg->num_chan; i++) ++ arg->chan_list[i] = req->channels[i]->center_freq; + } + + if (req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) { +- arg.scan_f_add_spoofed_mac_in_probe = 1; +- ether_addr_copy(arg.mac_addr.addr, req->mac_addr); +- ether_addr_copy(arg.mac_mask.addr, req->mac_addr_mask); ++ arg->scan_f_add_spoofed_mac_in_probe = 1; ++ ether_addr_copy(arg->mac_addr.addr, req->mac_addr); ++ ether_addr_copy(arg->mac_mask.addr, req->mac_addr_mask); + } + + /* if duration is set, default dwell times will be overwritten */ + if (req->duration) { +- arg.dwell_time_active = req->duration; +- arg.dwell_time_active_2g = req->duration; +- arg.dwell_time_active_6g = req->duration; +- arg.dwell_time_passive = req->duration; +- arg.dwell_time_passive_6g = req->duration; +- arg.burst_duration = req->duration; ++ arg->dwell_time_active = req->duration; ++ arg->dwell_time_active_2g = req->duration; ++ arg->dwell_time_active_6g = req->duration; ++ arg->dwell_time_passive = req->duration; ++ arg->dwell_time_passive_6g = req->duration; ++ arg->burst_duration = req->duration; + +- scan_timeout = min_t(u32, arg.max_rest_time * +- (arg.num_chan - 1) + (req->duration + ++ scan_timeout = min_t(u32, arg->max_rest_time * ++ (arg->num_chan - 1) + (req->duration + + ATH11K_SCAN_CHANNEL_SWITCH_WMI_EVT_OVERHEAD) * +- arg.num_chan, arg.max_scan_time); ++ arg->num_chan, arg->max_scan_time); + } else { +- scan_timeout = arg.max_scan_time; ++ scan_timeout = arg->max_scan_time; + } + + /* Add a margin to account for event/command processing */ + scan_timeout += ATH11K_MAC_SCAN_CMD_EVT_OVERHEAD; + +- ret = ath11k_start_scan(ar, &arg); ++ ret = ath11k_start_scan(ar, arg); + if (ret) { + ath11k_warn(ar->ab, "failed to start hw scan: %d\n", ret); + spin_lock_bh(&ar->data_lock); +@@ -3717,10 +3723,11 @@ static int ath11k_mac_op_hw_scan(struct + msecs_to_jiffies(scan_timeout)); + + exit: +- kfree(arg.chan_list); +- +- if (req->ie_len) +- kfree(arg.extraie.ptr); ++ if (arg) { ++ kfree(arg->chan_list); ++ kfree(arg->extraie.ptr); ++ kfree(arg); ++ } + + mutex_unlock(&ar->conf_mutex); + diff --git a/package/kernel/mac80211/patches/ath11k/0029-wifi-ath11k-Add-support-to-configure-FTM-responder-r.patch b/package/kernel/mac80211/patches/ath11k/0029-wifi-ath11k-Add-support-to-configure-FTM-responder-r.patch new file mode 100644 index 000000000..f652d689b --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0029-wifi-ath11k-Add-support-to-configure-FTM-responder-r.patch @@ -0,0 +1,169 @@ +From a27c6a5853eb9d4f293b99be73a6891fe88263c7 Mon Sep 17 00:00:00 2001 +From: Sowmiya Sree Elavalagan +Date: Tue, 10 Jan 2023 15:30:57 +0200 +Subject: [PATCH] wifi: ath11k: Add support to configure FTM responder role + +Fine Timing Measurement(FTM) support is used to measure round trip +time between two nodes. + +Enable FTM responder feature using hw_params on supported device. +Since FTM functionality is offloaded to firmware, adding the +interface allows user space to enable or disable FTM responder. +Also add support for advertising the same in extended capabilities. + +QCA6390, WCN6855 and WCN6750 do not support this feature. + +Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 +Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Sowmiya Sree Elavalagan +Signed-off-by: Raj Kumar Bhagat +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20221220044435.10506-1-quic_rajkbhag@quicinc.com +--- + drivers/net/wireless/ath/ath11k/core.c | 8 ++++++++ + drivers/net/wireless/ath/ath11k/core.h | 1 + + drivers/net/wireless/ath/ath11k/hw.h | 1 + + drivers/net/wireless/ath/ath11k/mac.c | 20 +++++++++++++++++++- + drivers/net/wireless/ath/ath11k/wmi.h | 1 + + 5 files changed, 30 insertions(+), 1 deletion(-) + +--- a/drivers/net/wireless/ath/ath11k/core.c ++++ b/drivers/net/wireless/ath/ath11k/core.c +@@ -116,6 +116,7 @@ static const struct ath11k_hw_params ath + .tcl_ring_retry = true, + .tx_ring_size = DP_TCL_DATA_RING_SIZE, + .smp2p_wow_exit = false, ++ .ftm_responder = true, + }, + { + .hw_rev = ATH11K_HW_IPQ6018_HW10, +@@ -198,6 +199,7 @@ static const struct ath11k_hw_params ath + .tx_ring_size = DP_TCL_DATA_RING_SIZE, + .smp2p_wow_exit = false, + .support_fw_mac_sequence = false, ++ .ftm_responder = true, + }, + { + .name = "qca6390 hw2.0", +@@ -282,6 +284,7 @@ static const struct ath11k_hw_params ath + .tx_ring_size = DP_TCL_DATA_RING_SIZE, + .smp2p_wow_exit = false, + .support_fw_mac_sequence = true, ++ .ftm_responder = false, + }, + { + .name = "qcn9074 hw1.0", +@@ -363,6 +366,7 @@ static const struct ath11k_hw_params ath + .tx_ring_size = DP_TCL_DATA_RING_SIZE, + .smp2p_wow_exit = false, + .support_fw_mac_sequence = false, ++ .ftm_responder = true, + }, + { + .name = "wcn6855 hw2.0", +@@ -447,6 +451,7 @@ static const struct ath11k_hw_params ath + .tx_ring_size = DP_TCL_DATA_RING_SIZE, + .smp2p_wow_exit = false, + .support_fw_mac_sequence = true, ++ .ftm_responder = false, + }, + { + .name = "wcn6855 hw2.1", +@@ -529,6 +534,7 @@ static const struct ath11k_hw_params ath + .tx_ring_size = DP_TCL_DATA_RING_SIZE, + .smp2p_wow_exit = false, + .support_fw_mac_sequence = true, ++ .ftm_responder = false, + }, + { + .name = "wcn6750 hw1.0", +@@ -609,6 +615,7 @@ static const struct ath11k_hw_params ath + .tx_ring_size = DP_TCL_DATA_RING_SIZE_WCN6750, + .smp2p_wow_exit = true, + .support_fw_mac_sequence = true, ++ .ftm_responder = false, + }, + { + .hw_rev = ATH11K_HW_IPQ5018_HW10, +@@ -688,6 +695,7 @@ static const struct ath11k_hw_params ath + .tx_ring_size = DP_TCL_DATA_RING_SIZE, + .smp2p_wow_exit = false, + .support_fw_mac_sequence = false, ++ .ftm_responder = true, + }, + }; + +--- a/drivers/net/wireless/ath/ath11k/core.h ++++ b/drivers/net/wireless/ath/ath11k/core.h +@@ -346,6 +346,7 @@ struct ath11k_vif { + + bool is_started; + bool is_up; ++ bool ftm_responder; + bool spectral_enabled; + bool ps; + u32 aid; +--- a/drivers/net/wireless/ath/ath11k/hw.h ++++ b/drivers/net/wireless/ath/ath11k/hw.h +@@ -224,6 +224,7 @@ struct ath11k_hw_params { + u32 tx_ring_size; + bool smp2p_wow_exit; + bool support_fw_mac_sequence; ++ bool ftm_responder; + }; + + struct ath11k_hw_ops { +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -3110,7 +3110,7 @@ static void ath11k_mac_op_bss_info_chang + u16 bitrate; + int ret = 0; + u8 rateidx; +- u32 rate; ++ u32 rate, param; + u32 ipv4_cnt; + + mutex_lock(&ar->conf_mutex); +@@ -3412,6 +3412,20 @@ static void ath11k_mac_op_bss_info_chang + } + } + ++ if (changed & BSS_CHANGED_FTM_RESPONDER && ++ arvif->ftm_responder != info->ftm_responder && ++ ar->ab->hw_params.ftm_responder && ++ (vif->type == NL80211_IFTYPE_AP || ++ vif->type == NL80211_IFTYPE_MESH_POINT)) { ++ arvif->ftm_responder = info->ftm_responder; ++ param = WMI_VDEV_PARAM_ENABLE_DISABLE_RTT_RESPONDER_ROLE; ++ ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, param, ++ arvif->ftm_responder); ++ if (ret) ++ ath11k_warn(ar->ab, "Failed to set ftm responder %i: %d\n", ++ arvif->vdev_id, ret); ++ } ++ + if (changed & BSS_CHANGED_FILS_DISCOVERY || + changed & BSS_CHANGED_UNSOL_BCAST_PROBE_RESP) + ath11k_mac_fils_discovery(arvif, info); +@@ -9113,6 +9127,10 @@ static int __ath11k_mac_register(struct + wiphy_ext_feature_set(ar->hw->wiphy, + NL80211_EXT_FEATURE_SET_SCAN_DWELL); + ++ if (ab->hw_params.ftm_responder) ++ wiphy_ext_feature_set(ar->hw->wiphy, ++ NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER); ++ + ath11k_reg_init(ar); + + if (!test_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags)) { +--- a/drivers/net/wireless/ath/ath11k/wmi.h ++++ b/drivers/net/wireless/ath/ath11k/wmi.h +@@ -1073,6 +1073,7 @@ enum wmi_tlv_vdev_param { + WMI_VDEV_PARAM_ENABLE_BCAST_PROBE_RESPONSE, + WMI_VDEV_PARAM_FILS_MAX_CHANNEL_GUARD_TIME, + WMI_VDEV_PARAM_HE_LTF = 0x74, ++ WMI_VDEV_PARAM_ENABLE_DISABLE_RTT_RESPONDER_ROLE = 0x7d, + WMI_VDEV_PARAM_BA_MODE = 0x7e, + WMI_VDEV_PARAM_AUTORATE_MISC_CFG = 0x80, + WMI_VDEV_PARAM_SET_HE_SOUNDING_MODE = 0x87, diff --git a/package/kernel/mac80211/patches/ath11k/0030-wifi-ath11k-add-channel-177-into-5-GHz-channel-list.patch b/package/kernel/mac80211/patches/ath11k/0030-wifi-ath11k-add-channel-177-into-5-GHz-channel-list.patch new file mode 100644 index 000000000..d0ed9c54b --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0030-wifi-ath11k-add-channel-177-into-5-GHz-channel-list.patch @@ -0,0 +1,41 @@ +From e5e94d10c85653609a2893c8d0ef24a27471b68f Mon Sep 17 00:00:00 2001 +From: Wen Gong +Date: Tue, 10 Jan 2023 15:30:58 +0200 +Subject: [PATCH] wifi: ath11k: add channel 177 into 5 GHz channel list + +Add support for the 5 GHz channel 177 with center frequency 5885 MHz and +operating class 125 per IEEE Std 802.11ax-2021, Table E-4. + +Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3 + +Signed-off-by: Wen Gong +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20221220101912.30816-1-quic_wgong@quicinc.com +--- + drivers/net/wireless/ath/ath11k/core.h | 4 ++-- + drivers/net/wireless/ath/ath11k/mac.c | 1 + + 2 files changed, 3 insertions(+), 2 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/core.h ++++ b/drivers/net/wireless/ath/ath11k/core.h +@@ -521,8 +521,8 @@ struct ath11k_sta { + #define ATH11K_MIN_5G_FREQ 4150 + #define ATH11K_MIN_6G_FREQ 5925 + #define ATH11K_MAX_6G_FREQ 7115 +-#define ATH11K_NUM_CHANS 101 +-#define ATH11K_MAX_5G_CHAN 173 ++#define ATH11K_NUM_CHANS 102 ++#define ATH11K_MAX_5G_CHAN 177 + + enum ath11k_state { + ATH11K_STATE_OFF, +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -96,6 +96,7 @@ static const struct ieee80211_channel at + CHAN5G(165, 5825, 0), + CHAN5G(169, 5845, 0), + CHAN5G(173, 5865, 0), ++ CHAN5G(177, 5885, 0), + }; + + static const struct ieee80211_channel ath11k_6ghz_channels[] = { diff --git a/package/kernel/mac80211/patches/ath11k/0031-wifi-ath11k-fix-ce-memory-mapping-for-ahb-devices.patch b/package/kernel/mac80211/patches/ath11k/0031-wifi-ath11k-fix-ce-memory-mapping-for-ahb-devices.patch new file mode 100644 index 000000000..278679997 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0031-wifi-ath11k-fix-ce-memory-mapping-for-ahb-devices.patch @@ -0,0 +1,114 @@ +From 53a998c4d7284debd77734d01e1466e59a1d03b2 Mon Sep 17 00:00:00 2001 +From: Raj Kumar Bhagat +Date: Fri, 13 Jan 2023 12:02:09 +0530 +Subject: [PATCH] wifi: ath11k: fix ce memory mapping for ahb devices + +Currently ath11k_ahb module is not loaded successfully and the wifi +interface is not created. Kernel trace is seen while loading the +ath11k_ahb module. The issue is seen in all ath11k AHB devices except +in IPQ5018. + +This happens because in ath11k_ahb_probe(), ab->mem_ce is initialized +with the value of ab->mem. However, at this instant ab->mem is not +yet set. + +Later, during write to a particular memory via ath11k_ahb_write32() +this ab->mem_ce is used with particular offset. Since ab->mem_ce is +not set properly this possibly leads to memory conflict to handle +kernel paging request and the below trace is seen. + +[ 93.035047] Unable to handle kernel paging request at virtual address ffff800100a00000 +[ 93.035083] Mem abort info: +[ 93.041869] ESR = 0x0000000096000045 +[ 93.044561] EC = 0x25: DABT (current EL), IL = 32 bits +[ 93.048377] SET = 0, FnV = 0 +[ 93.053840] EA = 0, S1PTW = 0 +[ 93.056704] FSC = 0x05: level 1 translation fault +[ 93.059745] Data abort info: +[ 93.064603] ISV = 0, ISS = 0x00000045 +[ 93.067729] CM = 0, WnR = 1 +[ 93.071287] swapper pgtable: 4k pages, 48-bit VAs, pgdp=0000000042219000 +[ 93.074409] [ffff800100a00000] pgd=100000007ffff003, p4d=100000007ffff003, pud=0000000000000000 +[ 93.081195] Internal error: Oops: 0000000096000045 [#1] PREEMPT SMP +[ 93.089598] Modules linked in: ath11k_ahb ath11k_pci ath11k qmi_helpers +[ 93.095851] CPU: 2 PID: 66 Comm: kworker/u8:3 Not tainted 6.1.0-rc8-wt-ath-658126-g58e4b9df840c-dirty #2 +[ 93.102454] Hardware name: Qualcomm Technologies, Inc. IPQ8074/AP-HK14 (DT) +[ 93.112171] Workqueue: ath11k_qmi_driver_event ath11k_qmi_driver_event_work [ath11k] +[ 93.118856] pstate: 40000005 (nZcv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--) +[ 93.126838] pc : ath11k_ahb_write32+0xc/0x18 [ath11k_ahb] +[ 93.133520] lr : ath11k_hal_srng_setup+0x860/0x8f0 [ath11k] +[ 93.139075] sp : ffff80000aaebb70 +[ 93.144452] x29: ffff80000aaebb70 x28: 0000000000000020 x27: ffff80000aaebc50 +[ 93.147934] x26: ffff000004923750 x25: ffff000004921200 x24: ffff000004928000 +[ 93.155051] x23: 0000000000000020 x22: ffff000004930000 x21: ffff000004923200 +[ 93.162170] x20: ffff000004920000 x19: 00000000eea00000 x18: ffff0000049200f0 +[ 93.169288] x17: 0000000000000000 x16: 0000000000000000 x15: 000000000000025e +[ 93.176405] x14: ffff000003c414f0 x13: 0000000000000000 x12: 0000000000000008 +[ 93.183524] x11: ffff000003c41488 x10: 0000000000000040 x9 : 0000000000000000 +[ 93.190641] x8 : ffff80000a9dd100 x7 : 0000000000000000 x6 : 000000000000003f +[ 93.197759] x5 : ffff800100a00400 x4 : ffff8000031f4018 x3 : 0000000000000004 +[ 93.204877] x2 : 0000000047b62000 x1 : ffff800100a00000 x0 : ffff800012000000 +[ 93.211996] Call trace: +[ 93.219104] ath11k_ahb_write32+0xc/0x18 [ath11k_ahb] +[ 93.221366] ath11k_ce_init_ring+0x184/0x278 [ath11k] +[ 93.226576] ath11k_ce_init_pipes+0x4c/0x1a0 [ath11k] +[ 93.231610] ath11k_core_qmi_firmware_ready+0x3c/0x568 [ath11k] +[ 93.236646] ath11k_qmi_driver_event_work+0x168/0x4f8 [ath11k] +[ 93.242376] process_one_work+0x144/0x350 +[ 93.248275] worker_thread+0x120/0x430 +[ 93.252352] kthread+0xf4/0x110 +[ 93.255997] ret_from_fork+0x10/0x20 +[ 93.259043] Code: d503201f f94e1c00 8b214001 d50332bf (b9000022) +[ 93.262863] ---[ end trace 0000000000000000 ]--- + +However, for the device IPQ5018 ath11k_hw_params .ce_remap is +defined. This parameter is used to recalculate ab->mem_ce and hence, +this issue is not seen in IPQ5018. + +Hence, fix this by initializing ab->mem_ce after ab->mem is set. +ab->mem is set inside the ath11k_ahb_setup_resources() therefore +initialize ab->mem_ce after ath11k_ahb_setup_resources(). + +Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 + +Fixes: b42b3678c91f ("wifi: ath11k: remap ce register space for IPQ5018") + +Signed-off-by: Raj Kumar Bhagat +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20230113063209.7256-1-quic_rajkbhag@quicinc.com +--- + drivers/net/wireless/ath/ath11k/ahb.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/ahb.c ++++ b/drivers/net/wireless/ath/ath11k/ahb.c +@@ -1157,12 +1157,16 @@ static int ath11k_ahb_probe(struct platf + goto err_core_free; + } + +- ab->mem_ce = ab->mem; +- + ret = ath11k_core_pre_init(ab); + if (ret) + goto err_core_free; + ++ ret = ath11k_ahb_setup_resources(ab); ++ if (ret) ++ goto err_core_free; ++ ++ ab->mem_ce = ab->mem; ++ + if (ab->hw_params.ce_remap) { + const struct ce_remap *ce_remap = ab->hw_params.ce_remap; + /* ce register space is moved out of wcss unlike ipq8074 or ipq6018 +@@ -1177,10 +1181,6 @@ static int ath11k_ahb_probe(struct platf + } + } + +- ret = ath11k_ahb_setup_resources(ab); +- if (ret) +- goto err_core_free; +- + ret = ath11k_ahb_fw_resources_init(ab); + if (ret) + goto err_core_free; diff --git a/package/kernel/mac80211/patches/ath11k/0033-wifi-ath11k-Set-ext-passive-scan-flag-to-adjust-pass.patch b/package/kernel/mac80211/patches/ath11k/0033-wifi-ath11k-Set-ext-passive-scan-flag-to-adjust-pass.patch new file mode 100644 index 000000000..79b79e105 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0033-wifi-ath11k-Set-ext-passive-scan-flag-to-adjust-pass.patch @@ -0,0 +1,73 @@ +From cf8f3d4deb02a8fdc806c46d4112b69868544697 Mon Sep 17 00:00:00 2001 +From: Tamizh Chelvam Raja +Date: Wed, 15 Feb 2023 20:31:36 +0200 +Subject: [PATCH] wifi: ath11k: Set ext passive scan flag to adjust passive + scan start time + +Set the WMI_SCAN_FLAG_EXT_PASSIVE_SCAN_START_TIME_ENHANCE flag +while sending the scan command. If this flag is enabled when the +incoming scan request comes with a strict start time and its duration +overlaps with next TBTT, then target adjust the start time accordingly +for passive scan. Target supporting this feature will advertise +WMI_TLV_SERVICE_PASSIVE_SCAN_START_TIME_ENHANCE. + +Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.4.0.1-01467-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Tamizh Chelvam Raja +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20221222131720.11368-1-quic_tamizhr@quicinc.com +--- + drivers/net/wireless/ath/ath11k/wmi.c | 8 ++++++++ + drivers/net/wireless/ath/ath11k/wmi.h | 3 +++ + 2 files changed, 11 insertions(+) + +--- a/drivers/net/wireless/ath/ath11k/wmi.c ++++ b/drivers/net/wireless/ath/ath11k/wmi.c +@@ -2068,6 +2068,12 @@ void ath11k_wmi_start_scan_init(struct a + WMI_SCAN_EVENT_FOREIGN_CHAN | + WMI_SCAN_EVENT_DEQUEUED; + arg->scan_flags |= WMI_SCAN_CHAN_STAT_EVENT; ++ ++ if (test_bit(WMI_TLV_SERVICE_PASSIVE_SCAN_START_TIME_ENHANCE, ++ ar->ab->wmi_ab.svc_map)) ++ arg->scan_ctrl_flags_ext |= ++ WMI_SCAN_FLAG_EXT_PASSIVE_SCAN_START_TIME_ENHANCE; ++ + arg->num_bssid = 1; + + /* fill bssid_list[0] with 0xff, otherwise bssid and RA will be +@@ -2149,6 +2155,8 @@ ath11k_wmi_copy_scan_event_cntrl_flags(s + /* for adaptive scan mode using 3 bits (21 - 23 bits) */ + WMI_SCAN_SET_DWELL_MODE(cmd->scan_ctrl_flags, + param->adaptive_dwell_time_mode); ++ ++ cmd->scan_ctrl_flags_ext = param->scan_ctrl_flags_ext; + } + + int ath11k_wmi_send_scan_start_cmd(struct ath11k *ar, +--- a/drivers/net/wireless/ath/ath11k/wmi.h ++++ b/drivers/net/wireless/ath/ath11k/wmi.h +@@ -2093,6 +2093,7 @@ enum wmi_tlv_service { + WMI_TLV_SERVICE_EXT2_MSG = 220, + WMI_TLV_SERVICE_PEER_POWER_SAVE_DURATION_SUPPORT = 246, + WMI_TLV_SERVICE_SRG_SRP_SPATIAL_REUSE_SUPPORT = 249, ++ WMI_TLV_SERVICE_PASSIVE_SCAN_START_TIME_ENHANCE = 263, + + /* The second 128 bits */ + WMI_MAX_EXT_SERVICE = 256, +@@ -3223,6 +3224,7 @@ struct wmi_start_scan_cmd { + + #define WMI_SCAN_DWELL_MODE_MASK 0x00E00000 + #define WMI_SCAN_DWELL_MODE_SHIFT 21 ++#define WMI_SCAN_FLAG_EXT_PASSIVE_SCAN_START_TIME_ENHANCE 0x00000800 + + enum { + WMI_SCAN_DWELL_MODE_DEFAULT = 0, +@@ -3270,6 +3272,7 @@ struct scan_req_params { + }; + u32 scan_events; + }; ++ u32 scan_ctrl_flags_ext; + u32 dwell_time_active; + u32 dwell_time_active_2g; + u32 dwell_time_passive; diff --git a/package/kernel/mac80211/patches/ath11k/0034-wifi-ath11k-fix-return-value-check-in-ath11k_ahb_pro.patch b/package/kernel/mac80211/patches/ath11k/0034-wifi-ath11k-fix-return-value-check-in-ath11k_ahb_pro.patch new file mode 100644 index 000000000..59132913b --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0034-wifi-ath11k-fix-return-value-check-in-ath11k_ahb_pro.patch @@ -0,0 +1,27 @@ +From 342fcde9d91460f01f65707e16368a1571271a3a Mon Sep 17 00:00:00 2001 +From: Yang Yingliang +Date: Fri, 17 Feb 2023 11:00:31 +0800 +Subject: [PATCH] wifi: ath11k: fix return value check in ath11k_ahb_probe() + +ioremap() returns NULL pointer not PTR_ERR() when it fails, +so replace the IS_ERR() check with NULL pointer check. + +Fixes: b42b3678c91f ("wifi: ath11k: remap ce register space for IPQ5018") +Signed-off-by: Yang Yingliang +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20230217030031.4021289-1-yangyingliang@huawei.com +--- + drivers/net/wireless/ath/ath11k/ahb.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/wireless/ath/ath11k/ahb.c ++++ b/drivers/net/wireless/ath/ath11k/ahb.c +@@ -1174,7 +1174,7 @@ static int ath11k_ahb_probe(struct platf + * to a new space for accessing them. + */ + ab->mem_ce = ioremap(ce_remap->base, ce_remap->size); +- if (IS_ERR(ab->mem_ce)) { ++ if (!ab->mem_ce) { + dev_err(&pdev->dev, "ce ioremap error\n"); + ret = -ENOMEM; + goto err_core_free; diff --git a/package/kernel/mac80211/patches/ath11k/0035-wifi-ath11k-Use-platform_get_irq-to-get-the-interrup.patch b/package/kernel/mac80211/patches/ath11k/0035-wifi-ath11k-Use-platform_get_irq-to-get-the-interrup.patch new file mode 100644 index 000000000..93a9da8fc --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0035-wifi-ath11k-Use-platform_get_irq-to-get-the-interrup.patch @@ -0,0 +1,50 @@ +From f117276638b7600b981b3fe28550823cfbe1ef23 Mon Sep 17 00:00:00 2001 +From: Douglas Anderson +Date: Wed, 1 Feb 2023 08:54:42 -0800 +Subject: [PATCH] wifi: ath11k: Use platform_get_irq() to get the interrupt + +As of commit a1a2b7125e10 ("of/platform: Drop static setup of IRQ +resource from DT core"), we need to use platform_get_irq() instead of +platform_get_resource() to get our IRQs because +platform_get_resource() simply won't get them anymore. + +This was already fixed in several other Atheros WiFi drivers, +apparently in response to Zeal Robot reports. An example of another +fix is commit 9503a1fc123d ("ath9k: Use platform_get_irq() to get the +interrupt"). ath11k seems to have been missed in this effort, though. + +Without this change, WiFi wasn't coming up on my Qualcomm sc7280-based +hardware. Specifically, "platform_get_resource(pdev, IORESOURCE_IRQ, +i)" was failing even for i=0. + +Tested-on: WCN6750 hw1.0 AHB WLAN.MSL.1.0.1-00887-QCAMSLSWPLZ-1 + +Fixes: a1a2b7125e10 ("of/platform: Drop static setup of IRQ resource from DT core") +Fixes: 00402f49d26f ("ath11k: Add support for WCN6750 device") +Signed-off-by: Douglas Anderson +Tested-by: Jun Yu +Reviewed-by: Lad Prabhakar +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20230201084131.v2.1.I69cf3d56c97098287fe3a70084ee515098390b70@changeid +--- + drivers/net/wireless/ath/ath11k/ahb.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/ahb.c ++++ b/drivers/net/wireless/ath/ath11k/ahb.c +@@ -874,11 +874,11 @@ static int ath11k_ahb_setup_msi_resource + ab->pci.msi.ep_base_data = int_prop + 32; + + for (i = 0; i < ab->pci.msi.config->total_vectors; i++) { +- res = platform_get_resource(pdev, IORESOURCE_IRQ, i); +- if (!res) +- return -ENODEV; ++ ret = platform_get_irq(pdev, i); ++ if (ret < 0) ++ return ret; + +- ab->pci.msi.irqs[i] = res->start; ++ ab->pci.msi.irqs[i] = ret; + } + + set_bit(ATH11K_FLAG_MULTI_MSI_VECTORS, &ab->dev_flags); diff --git a/package/kernel/mac80211/patches/ath11k/0036-wifi-ath11k-fix-SAC-bug-on-peer-addition-with-sta-ba.patch b/package/kernel/mac80211/patches/ath11k/0036-wifi-ath11k-fix-SAC-bug-on-peer-addition-with-sta-ba.patch new file mode 100644 index 000000000..b37f070ba --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0036-wifi-ath11k-fix-SAC-bug-on-peer-addition-with-sta-ba.patch @@ -0,0 +1,53 @@ +From 60b7d62ba8cdbd073997bff0f1cdae8d844002c0 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Thu, 9 Feb 2023 23:26:22 +0100 +Subject: [PATCH] wifi: ath11k: fix SAC bug on peer addition with sta band + migration + +Fix sleep in atomic context warning detected by Smatch static checker +analyzer. + +Following the locking pattern for peer_rhash_add lock tbl_mtx_lock mutex +always even if sta is not transitioning to another band. +This is peer_add function and a more secure locking should not cause +performance regression. + +Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.5.0.1-01208-QCAHKSWPL_SILICONZ-1 + +Fixes: d673cb6fe6c0 ("wifi: ath11k: fix peer addition/deletion error on sta band migration") +Reported-by: Dan Carpenter +Signed-off-by: Christian Marangi +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20230209222622.1751-1-ansuelsmth@gmail.com +--- + drivers/net/wireless/ath/ath11k/peer.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/peer.c ++++ b/drivers/net/wireless/ath/ath11k/peer.c +@@ -382,22 +382,23 @@ int ath11k_peer_create(struct ath11k *ar + return -ENOBUFS; + } + ++ mutex_lock(&ar->ab->tbl_mtx_lock); + spin_lock_bh(&ar->ab->base_lock); + peer = ath11k_peer_find_by_addr(ar->ab, param->peer_addr); + if (peer) { + if (peer->vdev_id == param->vdev_id) { + spin_unlock_bh(&ar->ab->base_lock); ++ mutex_unlock(&ar->ab->tbl_mtx_lock); + return -EINVAL; + } + + /* Assume sta is transitioning to another band. + * Remove here the peer from rhash. + */ +- mutex_lock(&ar->ab->tbl_mtx_lock); + ath11k_peer_rhash_delete(ar->ab, peer); +- mutex_unlock(&ar->ab->tbl_mtx_lock); + } + spin_unlock_bh(&ar->ab->base_lock); ++ mutex_unlock(&ar->ab->tbl_mtx_lock); + + ret = ath11k_wmi_send_peer_create_cmd(ar, param); + if (ret) { diff --git a/package/kernel/mac80211/patches/ath11k/0037-wifi-ath11k-allow-system-suspend-to-survive-ath11k.patch b/package/kernel/mac80211/patches/ath11k/0037-wifi-ath11k-allow-system-suspend-to-survive-ath11k.patch new file mode 100644 index 000000000..fa680954e --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0037-wifi-ath11k-allow-system-suspend-to-survive-ath11k.patch @@ -0,0 +1,43 @@ +From 7c15430822e71e90203d87e6d0cfe83fa058b0dc Mon Sep 17 00:00:00 2001 +From: Len Brown +Date: Wed, 1 Feb 2023 12:32:01 -0600 +Subject: [PATCH] wifi: ath11k: allow system suspend to survive ath11k + +When ath11k runs into internal errors upon suspend, +it returns an error code to pci_pm_suspend, which +aborts the entire system suspend. + +The driver should not abort system suspend, but should +keep its internal errors to itself, and allow the system +to suspend. Otherwise, a user can suspend a laptop +by closing the lid and sealing it into a case, assuming +that is will suspend, rather than heating up and draining +the battery when in transit. + +In practice, the ath11k device seems to have plenty of transient +errors, and subsequent suspend cycles after this failure +often succeed. + +https://bugzilla.kernel.org/show_bug.cgi?id=216968 + +Fixes: d1b0c33850d29 ("ath11k: implement suspend for QCA6390 PCI devices") + +Signed-off-by: Len Brown +Cc: stable@vger.kernel.org +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20230201183201.14431-1-len.brown@intel.com +--- + drivers/net/wireless/ath/ath11k/pci.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/wireless/ath/ath11k/pci.c ++++ b/drivers/net/wireless/ath/ath11k/pci.c +@@ -998,7 +998,7 @@ static __maybe_unused int ath11k_pci_pm_ + if (ret) + ath11k_warn(ab, "failed to resume core: %d\n", ret); + +- return ret; ++ return 0; + } + + static SIMPLE_DEV_PM_OPS(ath11k_pci_pm_ops, diff --git a/package/kernel/mac80211/patches/ath11k/0038-wifi-ath11k-modify-accessor-macros-to-match-index-si.patch b/package/kernel/mac80211/patches/ath11k/0038-wifi-ath11k-modify-accessor-macros-to-match-index-si.patch new file mode 100644 index 000000000..42bf170a0 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0038-wifi-ath11k-modify-accessor-macros-to-match-index-si.patch @@ -0,0 +1,61 @@ +From a96f10422e74cde27c100b321b127ec32ae75747 Mon Sep 17 00:00:00 2001 +From: Muna Sinada +Date: Fri, 24 Feb 2023 12:28:03 +0200 +Subject: [PATCH] wifi: ath11k: modify accessor macros to match index size + +HE PHY is only 11 bytes, therefore it should be using byte indexes +instead of dword. Change corresponding macros to reflect this. + +Signed-off-by: Muna Sinada +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/1666128501-12364-2-git-send-email-quic_msinada@quicinc.com +--- + drivers/net/wireless/ath/ath11k/wmi.h | 24 +++++++++++++----------- + 1 file changed, 13 insertions(+), 11 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/wmi.h ++++ b/drivers/net/wireless/ath/ath11k/wmi.h +@@ -2859,30 +2859,32 @@ struct rx_reorder_queue_remove_params { + #define WMI_VDEV_PARAM_TXBF_SU_TX_BFER BIT(2) + #define WMI_VDEV_PARAM_TXBF_MU_TX_BFER BIT(3) + +-#define HECAP_PHYDWORD_0 0 +-#define HECAP_PHYDWORD_1 1 +-#define HECAP_PHYDWORD_2 2 ++#define HE_PHYCAP_BYTE_0 0 ++#define HE_PHYCAP_BYTE_1 1 ++#define HE_PHYCAP_BYTE_2 2 ++#define HE_PHYCAP_BYTE_3 3 ++#define HE_PHYCAP_BYTE_4 4 + +-#define HECAP_PHY_SU_BFER BIT(31) ++#define HECAP_PHY_SU_BFER BIT(7) + #define HECAP_PHY_SU_BFEE BIT(0) + #define HECAP_PHY_MU_BFER BIT(1) +-#define HECAP_PHY_UL_MUMIMO BIT(22) +-#define HECAP_PHY_UL_MUOFDMA BIT(23) ++#define HECAP_PHY_UL_MUMIMO BIT(6) ++#define HECAP_PHY_UL_MUOFDMA BIT(7) + + #define HECAP_PHY_SUBFMR_GET(hecap_phy) \ +- FIELD_GET(HECAP_PHY_SU_BFER, hecap_phy[HECAP_PHYDWORD_0]) ++ FIELD_GET(HECAP_PHY_SU_BFER, hecap_phy[HE_PHYCAP_BYTE_3]) + + #define HECAP_PHY_SUBFME_GET(hecap_phy) \ +- FIELD_GET(HECAP_PHY_SU_BFEE, hecap_phy[HECAP_PHYDWORD_1]) ++ FIELD_GET(HECAP_PHY_SU_BFEE, hecap_phy[HE_PHYCAP_BYTE_4]) + + #define HECAP_PHY_MUBFMR_GET(hecap_phy) \ +- FIELD_GET(HECAP_PHY_MU_BFER, hecap_phy[HECAP_PHYDWORD_1]) ++ FIELD_GET(HECAP_PHY_MU_BFER, hecap_phy[HE_PHYCAP_BYTE_4]) + + #define HECAP_PHY_ULMUMIMO_GET(hecap_phy) \ +- FIELD_GET(HECAP_PHY_UL_MUMIMO, hecap_phy[HECAP_PHYDWORD_0]) ++ FIELD_GET(HECAP_PHY_UL_MUMIMO, hecap_phy[HE_PHYCAP_BYTE_2]) + + #define HECAP_PHY_ULOFDMA_GET(hecap_phy) \ +- FIELD_GET(HECAP_PHY_UL_MUOFDMA, hecap_phy[HECAP_PHYDWORD_0]) ++ FIELD_GET(HECAP_PHY_UL_MUOFDMA, hecap_phy[HE_PHYCAP_BYTE_2]) + + #define HE_MODE_SU_TX_BFEE BIT(0) + #define HE_MODE_SU_TX_BFER BIT(1) diff --git a/package/kernel/mac80211/patches/ath11k/0039-wifi-ath11k-push-MU-MIMO-params-from-hostapd-to-hard.patch b/package/kernel/mac80211/patches/ath11k/0039-wifi-ath11k-push-MU-MIMO-params-from-hostapd-to-hard.patch new file mode 100644 index 000000000..298ce1a61 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0039-wifi-ath11k-push-MU-MIMO-params-from-hostapd-to-hard.patch @@ -0,0 +1,300 @@ +From 38dfe775d0abf511341f37c1cb77b919a3ad410b Mon Sep 17 00:00:00 2001 +From: Muna Sinada +Date: Fri, 24 Feb 2023 12:28:04 +0200 +Subject: [PATCH] wifi: ath11k: push MU-MIMO params from hostapd to hardware + +In the previous behaviour only HE IE in management frames are changed +regarding MU-MIMO configurations and not in hardware. Adding push of +MU-MIMO configurations to the hardware as well. + +Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.4.0.1-00356-QCAHKSWPL_SILICONZ-1 + +Co-developed-by: Anilkumar Kolli +Signed-off-by: Anilkumar Kolli +Signed-off-by: Muna Sinada +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/1666128501-12364-3-git-send-email-quic_msinada@quicinc.com +--- + drivers/net/wireless/ath/ath11k/mac.c | 200 ++++++++++++++++---------- + drivers/net/wireless/ath/ath11k/wmi.h | 3 + + 2 files changed, 130 insertions(+), 73 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -2699,6 +2699,117 @@ static int ath11k_setup_peer_smps(struct + ath11k_smps_map[smps]); + } + ++static bool ath11k_mac_set_he_txbf_conf(struct ath11k_vif *arvif) ++{ ++ struct ath11k *ar = arvif->ar; ++ u32 param, value; ++ int ret; ++ ++ if (!arvif->vif->bss_conf.he_support) ++ return true; ++ ++ param = WMI_VDEV_PARAM_SET_HEMU_MODE; ++ value = 0; ++ if (arvif->vif->bss_conf.he_su_beamformer) { ++ value |= FIELD_PREP(HE_MODE_SU_TX_BFER, HE_SU_BFER_ENABLE); ++ if (arvif->vif->bss_conf.he_mu_beamformer && ++ arvif->vdev_type == WMI_VDEV_TYPE_AP) ++ value |= FIELD_PREP(HE_MODE_MU_TX_BFER, HE_MU_BFER_ENABLE); ++ } ++ ++ if (arvif->vif->type != NL80211_IFTYPE_MESH_POINT) { ++ value |= FIELD_PREP(HE_MODE_DL_OFDMA, HE_DL_MUOFDMA_ENABLE) | ++ FIELD_PREP(HE_MODE_UL_OFDMA, HE_UL_MUOFDMA_ENABLE); ++ ++ if (arvif->vif->bss_conf.he_full_ul_mumimo) ++ value |= FIELD_PREP(HE_MODE_UL_MUMIMO, HE_UL_MUMIMO_ENABLE); ++ ++ if (arvif->vif->bss_conf.he_su_beamformee) ++ value |= FIELD_PREP(HE_MODE_SU_TX_BFEE, HE_SU_BFEE_ENABLE); ++ } ++ ++ ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, param, value); ++ if (ret) { ++ ath11k_warn(ar->ab, "failed to set vdev %d HE MU mode: %d\n", ++ arvif->vdev_id, ret); ++ return false; ++ } ++ ++ param = WMI_VDEV_PARAM_SET_HE_SOUNDING_MODE; ++ value = FIELD_PREP(HE_VHT_SOUNDING_MODE, HE_VHT_SOUNDING_MODE_ENABLE) | ++ FIELD_PREP(HE_TRIG_NONTRIG_SOUNDING_MODE, ++ HE_TRIG_NONTRIG_SOUNDING_MODE_ENABLE); ++ ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, ++ param, value); ++ if (ret) { ++ ath11k_warn(ar->ab, "failed to set vdev %d sounding mode: %d\n", ++ arvif->vdev_id, ret); ++ return false; ++ } ++ return true; ++} ++ ++static bool ath11k_mac_vif_recalc_sta_he_txbf(struct ath11k *ar, ++ struct ieee80211_vif *vif, ++ struct ieee80211_sta_he_cap *he_cap) ++{ ++ struct ath11k_vif *arvif = (void *)vif->drv_priv; ++ struct ieee80211_he_cap_elem he_cap_elem = {0}; ++ struct ieee80211_sta_he_cap *cap_band = NULL; ++ struct cfg80211_chan_def def; ++ u32 param = WMI_VDEV_PARAM_SET_HEMU_MODE; ++ u32 hemode = 0; ++ int ret; ++ ++ if (!vif->bss_conf.he_support) ++ return true; ++ ++ if (vif->type != NL80211_IFTYPE_STATION) ++ return false; ++ ++ if (WARN_ON(ath11k_mac_vif_chan(vif, &def))) ++ return false; ++ ++ if (def.chan->band == NL80211_BAND_2GHZ) ++ cap_band = &ar->mac.iftype[NL80211_BAND_2GHZ][vif->type].he_cap; ++ else ++ cap_band = &ar->mac.iftype[NL80211_BAND_5GHZ][vif->type].he_cap; ++ ++ memcpy(&he_cap_elem, &cap_band->he_cap_elem, sizeof(he_cap_elem)); ++ ++ if (HECAP_PHY_SUBFME_GET(he_cap_elem.phy_cap_info)) { ++ if (HECAP_PHY_SUBFMR_GET(he_cap->he_cap_elem.phy_cap_info)) ++ hemode |= FIELD_PREP(HE_MODE_SU_TX_BFEE, HE_SU_BFEE_ENABLE); ++ if (HECAP_PHY_MUBFMR_GET(he_cap->he_cap_elem.phy_cap_info)) ++ hemode |= FIELD_PREP(HE_MODE_MU_TX_BFEE, HE_MU_BFEE_ENABLE); ++ } ++ ++ if (vif->type != NL80211_IFTYPE_MESH_POINT) { ++ hemode |= FIELD_PREP(HE_MODE_DL_OFDMA, HE_DL_MUOFDMA_ENABLE) | ++ FIELD_PREP(HE_MODE_UL_OFDMA, HE_UL_MUOFDMA_ENABLE); ++ ++ if (HECAP_PHY_ULMUMIMO_GET(he_cap_elem.phy_cap_info)) ++ if (HECAP_PHY_ULMUMIMO_GET(he_cap->he_cap_elem.phy_cap_info)) ++ hemode |= FIELD_PREP(HE_MODE_UL_MUMIMO, ++ HE_UL_MUMIMO_ENABLE); ++ ++ if (FIELD_GET(HE_MODE_MU_TX_BFEE, hemode)) ++ hemode |= FIELD_PREP(HE_MODE_SU_TX_BFEE, HE_SU_BFEE_ENABLE); ++ ++ if (FIELD_GET(HE_MODE_MU_TX_BFER, hemode)) ++ hemode |= FIELD_PREP(HE_MODE_SU_TX_BFER, HE_SU_BFER_ENABLE); ++ } ++ ++ ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, param, hemode); ++ if (ret) { ++ ath11k_warn(ar->ab, "failed to submit vdev param txbf 0x%x: %d\n", ++ hemode, ret); ++ return false; ++ } ++ ++ return true; ++} ++ + static void ath11k_bss_assoc(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *bss_conf) +@@ -2709,6 +2820,7 @@ static void ath11k_bss_assoc(struct ieee + struct ieee80211_sta *ap_sta; + struct ath11k_peer *peer; + bool is_auth = false; ++ struct ieee80211_sta_he_cap he_cap; + int ret; + + lockdep_assert_held(&ar->conf_mutex); +@@ -2726,6 +2838,9 @@ static void ath11k_bss_assoc(struct ieee + return; + } + ++ /* he_cap here is updated at assoc success for sta mode only */ ++ he_cap = ap_sta->deflink.he_cap; ++ + ath11k_peer_assoc_prepare(ar, vif, ap_sta, &peer_arg, false); + + rcu_read_unlock(); +@@ -2753,6 +2868,12 @@ static void ath11k_bss_assoc(struct ieee + return; + } + ++ if (!ath11k_mac_vif_recalc_sta_he_txbf(ar, vif, &he_cap)) { ++ ath11k_warn(ar->ab, "failed to recalc he txbf for vdev %i on bss %pM\n", ++ arvif->vdev_id, bss_conf->bssid); ++ return; ++ } ++ + WARN_ON(arvif->is_up); + + arvif->aid = vif->cfg.aid; +@@ -3202,6 +3323,8 @@ static void ath11k_mac_op_bss_info_chang + ether_addr_copy(arvif->bssid, info->bssid); + + if (changed & BSS_CHANGED_BEACON_ENABLED) { ++ if (info->enable_beacon) ++ ath11k_mac_set_he_txbf_conf(arvif); + ath11k_control_beaconing(arvif, info); + + if (arvif->is_up && vif->bss_conf.he_support && +@@ -5392,6 +5515,10 @@ static int ath11k_mac_copy_he_cap(struct + + he_cap_elem->mac_cap_info[1] &= + IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_MASK; ++ he_cap_elem->phy_cap_info[0] &= ++ ~IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G; ++ he_cap_elem->phy_cap_info[0] &= ++ ~IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G; + + he_cap_elem->phy_cap_info[5] &= + ~IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_MASK; +@@ -6026,69 +6153,6 @@ ath11k_mac_setup_vdev_create_params(stru + } + } + +-static u32 +-ath11k_mac_prepare_he_mode(struct ath11k_pdev *pdev, u32 viftype) +-{ +- struct ath11k_pdev_cap *pdev_cap = &pdev->cap; +- struct ath11k_band_cap *cap_band = NULL; +- u32 *hecap_phy_ptr = NULL; +- u32 hemode = 0; +- +- if (pdev->cap.supported_bands & WMI_HOST_WLAN_2G_CAP) +- cap_band = &pdev_cap->band[NL80211_BAND_2GHZ]; +- else +- cap_band = &pdev_cap->band[NL80211_BAND_5GHZ]; +- +- hecap_phy_ptr = &cap_band->he_cap_phy_info[0]; +- +- hemode = FIELD_PREP(HE_MODE_SU_TX_BFEE, HE_SU_BFEE_ENABLE) | +- FIELD_PREP(HE_MODE_SU_TX_BFER, HECAP_PHY_SUBFMR_GET(hecap_phy_ptr)) | +- FIELD_PREP(HE_MODE_UL_MUMIMO, HECAP_PHY_ULMUMIMO_GET(hecap_phy_ptr)); +- +- /* TODO WDS and other modes */ +- if (viftype == NL80211_IFTYPE_AP) { +- hemode |= FIELD_PREP(HE_MODE_MU_TX_BFER, +- HECAP_PHY_MUBFMR_GET(hecap_phy_ptr)) | +- FIELD_PREP(HE_MODE_DL_OFDMA, HE_DL_MUOFDMA_ENABLE) | +- FIELD_PREP(HE_MODE_UL_OFDMA, HE_UL_MUOFDMA_ENABLE); +- } else { +- hemode |= FIELD_PREP(HE_MODE_MU_TX_BFEE, HE_MU_BFEE_ENABLE); +- } +- +- return hemode; +-} +- +-static int ath11k_set_he_mu_sounding_mode(struct ath11k *ar, +- struct ath11k_vif *arvif) +-{ +- u32 param_id, param_value; +- struct ath11k_base *ab = ar->ab; +- int ret = 0; +- +- param_id = WMI_VDEV_PARAM_SET_HEMU_MODE; +- param_value = ath11k_mac_prepare_he_mode(ar->pdev, arvif->vif->type); +- ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, +- param_id, param_value); +- if (ret) { +- ath11k_warn(ab, "failed to set vdev %d HE MU mode: %d param_value %x\n", +- arvif->vdev_id, ret, param_value); +- return ret; +- } +- param_id = WMI_VDEV_PARAM_SET_HE_SOUNDING_MODE; +- param_value = +- FIELD_PREP(HE_VHT_SOUNDING_MODE, HE_VHT_SOUNDING_MODE_ENABLE) | +- FIELD_PREP(HE_TRIG_NONTRIG_SOUNDING_MODE, +- HE_TRIG_NONTRIG_SOUNDING_MODE_ENABLE); +- ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, +- param_id, param_value); +- if (ret) { +- ath11k_warn(ab, "failed to set vdev %d HE MU mode: %d\n", +- arvif->vdev_id, ret); +- return ret; +- } +- return ret; +-} +- + static void ath11k_mac_op_update_vif_offload(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) + { +@@ -6757,7 +6821,6 @@ ath11k_mac_vdev_start_restart(struct ath + struct ath11k_base *ab = ar->ab; + struct wmi_vdev_start_req_arg arg = {}; + const struct cfg80211_chan_def *chandef = &ctx->def; +- int he_support = arvif->vif->bss_conf.he_support; + int ret = 0; + + lockdep_assert_held(&ar->conf_mutex); +@@ -6798,15 +6861,6 @@ ath11k_mac_vdev_start_restart(struct ath + spin_lock_bh(&ab->base_lock); + arg.regdomain = ar->ab->dfs_region; + spin_unlock_bh(&ab->base_lock); +- +- if (he_support) { +- ret = ath11k_set_he_mu_sounding_mode(ar, arvif); +- if (ret) { +- ath11k_warn(ar->ab, "failed to set he mode vdev %i\n", +- arg.vdev_id); +- return ret; +- } +- } + } + + arg.channel.passive |= !!(chandef->chan->flags & IEEE80211_CHAN_NO_IR); +--- a/drivers/net/wireless/ath/ath11k/wmi.h ++++ b/drivers/net/wireless/ath/ath11k/wmi.h +@@ -2897,8 +2897,11 @@ struct rx_reorder_queue_remove_params { + #define HE_DL_MUOFDMA_ENABLE 1 + #define HE_UL_MUOFDMA_ENABLE 1 + #define HE_DL_MUMIMO_ENABLE 1 ++#define HE_UL_MUMIMO_ENABLE 1 + #define HE_MU_BFEE_ENABLE 1 + #define HE_SU_BFEE_ENABLE 1 ++#define HE_MU_BFER_ENABLE 1 ++#define HE_SU_BFER_ENABLE 1 + + #define HE_VHT_SOUNDING_MODE_ENABLE 1 + #define HE_SU_MU_SOUNDING_MODE_ENABLE 1 diff --git a/package/kernel/mac80211/patches/ath11k/0040-wifi-ath11k-move-HE-MCS-mapper-to-a-separate-functio.patch b/package/kernel/mac80211/patches/ath11k/0040-wifi-ath11k-move-HE-MCS-mapper-to-a-separate-functio.patch new file mode 100644 index 000000000..6bc9880e1 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0040-wifi-ath11k-move-HE-MCS-mapper-to-a-separate-functio.patch @@ -0,0 +1,67 @@ +From 8077c1bbbc28e527fb29143c46f32c6a9d6cadf0 Mon Sep 17 00:00:00 2001 +From: Muna Sinada +Date: Fri, 24 Feb 2023 12:28:04 +0200 +Subject: [PATCH] wifi: ath11k: move HE MCS mapper to a separate function + +Move HE MCS mapper to a separate function and call new function +in ath11k_mac_copy_he_cap(). + +Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.4.0.1-00356-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Muna Sinada +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/1666128501-12364-4-git-send-email-quic_msinada@quicinc.com +--- + drivers/net/wireless/ath/ath11k/mac.c | 34 +++++++++++++++++---------- + 1 file changed, 22 insertions(+), 12 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -5483,6 +5483,27 @@ static __le16 ath11k_mac_setup_he_6ghz_c + return cpu_to_le16(bcap->he_6ghz_capa); + } + ++static void ath11k_mac_set_hemcsmap(struct ath11k *ar, ++ struct ath11k_pdev_cap *cap, ++ struct ieee80211_sta_he_cap *he_cap, ++ int band) ++{ ++ struct ath11k_band_cap *band_cap = &cap->band[band]; ++ ++ he_cap->he_mcs_nss_supp.rx_mcs_80 = ++ cpu_to_le16(band_cap->he_mcs & 0xffff); ++ he_cap->he_mcs_nss_supp.tx_mcs_80 = ++ cpu_to_le16(band_cap->he_mcs & 0xffff); ++ he_cap->he_mcs_nss_supp.rx_mcs_160 = ++ cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff); ++ he_cap->he_mcs_nss_supp.tx_mcs_160 = ++ cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff); ++ he_cap->he_mcs_nss_supp.rx_mcs_80p80 = ++ cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff); ++ he_cap->he_mcs_nss_supp.tx_mcs_80p80 = ++ cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff); ++} ++ + static int ath11k_mac_copy_he_cap(struct ath11k *ar, + struct ath11k_pdev_cap *cap, + struct ieee80211_sband_iftype_data *data, +@@ -5544,18 +5565,7 @@ static int ath11k_mac_copy_he_cap(struct + break; + } + +- he_cap->he_mcs_nss_supp.rx_mcs_80 = +- cpu_to_le16(band_cap->he_mcs & 0xffff); +- he_cap->he_mcs_nss_supp.tx_mcs_80 = +- cpu_to_le16(band_cap->he_mcs & 0xffff); +- he_cap->he_mcs_nss_supp.rx_mcs_160 = +- cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff); +- he_cap->he_mcs_nss_supp.tx_mcs_160 = +- cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff); +- he_cap->he_mcs_nss_supp.rx_mcs_80p80 = +- cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff); +- he_cap->he_mcs_nss_supp.tx_mcs_80p80 = +- cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff); ++ ath11k_mac_set_hemcsmap(ar, cap, he_cap, band); + + memset(he_cap->ppe_thres, 0, sizeof(he_cap->ppe_thres)); + if (he_cap_elem->phy_cap_info[6] & diff --git a/package/kernel/mac80211/patches/ath11k/0041-wifi-ath11k-generate-rx-and-tx-mcs-maps-for-supporte.patch b/package/kernel/mac80211/patches/ath11k/0041-wifi-ath11k-generate-rx-and-tx-mcs-maps-for-supporte.patch new file mode 100644 index 000000000..5cb7801b2 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0041-wifi-ath11k-generate-rx-and-tx-mcs-maps-for-supporte.patch @@ -0,0 +1,64 @@ +From ebf82988f844dd98e6b007cffcc5e95986056995 Mon Sep 17 00:00:00 2001 +From: Muna Sinada +Date: Fri, 24 Feb 2023 12:28:04 +0200 +Subject: [PATCH] wifi: ath11k: generate rx and tx mcs maps for supported HE + mcs + +Generate rx and tx mcs maps in ath11k_mac_set_hemcsmap() and set them +in supported mcs/nss for HE capabilities. + +Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.4.0.1-00356-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Muna Sinada +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/1666128501-12364-5-git-send-email-quic_msinada@quicinc.com +--- + drivers/net/wireless/ath/ath11k/mac.c | 30 ++++++++++++++++++++------- + 1 file changed, 23 insertions(+), 7 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -5488,20 +5488,36 @@ static void ath11k_mac_set_hemcsmap(stru + struct ieee80211_sta_he_cap *he_cap, + int band) + { +- struct ath11k_band_cap *band_cap = &cap->band[band]; ++ u16 txmcs_map, rxmcs_map; ++ u32 i; + ++ rxmcs_map = 0; ++ txmcs_map = 0; ++ for (i = 0; i < 8; i++) { ++ if (i < ar->num_tx_chains && ++ (ar->cfg_tx_chainmask >> cap->tx_chain_mask_shift) & BIT(i)) ++ txmcs_map |= IEEE80211_HE_MCS_SUPPORT_0_11 << (i * 2); ++ else ++ txmcs_map |= IEEE80211_HE_MCS_NOT_SUPPORTED << (i * 2); ++ ++ if (i < ar->num_rx_chains && ++ (ar->cfg_rx_chainmask >> cap->tx_chain_mask_shift) & BIT(i)) ++ rxmcs_map |= IEEE80211_HE_MCS_SUPPORT_0_11 << (i * 2); ++ else ++ rxmcs_map |= IEEE80211_HE_MCS_NOT_SUPPORTED << (i * 2); ++ } + he_cap->he_mcs_nss_supp.rx_mcs_80 = +- cpu_to_le16(band_cap->he_mcs & 0xffff); ++ cpu_to_le16(rxmcs_map & 0xffff); + he_cap->he_mcs_nss_supp.tx_mcs_80 = +- cpu_to_le16(band_cap->he_mcs & 0xffff); ++ cpu_to_le16(txmcs_map & 0xffff); + he_cap->he_mcs_nss_supp.rx_mcs_160 = +- cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff); ++ cpu_to_le16(rxmcs_map & 0xffff); + he_cap->he_mcs_nss_supp.tx_mcs_160 = +- cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff); ++ cpu_to_le16(txmcs_map & 0xffff); + he_cap->he_mcs_nss_supp.rx_mcs_80p80 = +- cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff); ++ cpu_to_le16(rxmcs_map & 0xffff); + he_cap->he_mcs_nss_supp.tx_mcs_80p80 = +- cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff); ++ cpu_to_le16(txmcs_map & 0xffff); + } + + static int ath11k_mac_copy_he_cap(struct ath11k *ar, diff --git a/package/kernel/mac80211/patches/ath11k/0042-wifi-ath11k-Add-tx-ack-signal-support-for-management.patch b/package/kernel/mac80211/patches/ath11k/0042-wifi-ath11k-Add-tx-ack-signal-support-for-management.patch new file mode 100644 index 000000000..8d4165731 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0042-wifi-ath11k-Add-tx-ack-signal-support-for-management.patch @@ -0,0 +1,150 @@ +From 01c6c9fccbd51c1d9eab0f5794b0271b026178df Mon Sep 17 00:00:00 2001 +From: Abinaya Kalaiselvan +Date: Mon, 19 Dec 2022 11:08:44 +0530 +Subject: [PATCH] wifi: ath11k: Add tx ack signal support for management + packets + +Add support to notify tx ack signal values for management +packets to userspace through nl80211 interface. + +Advertise NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT flag +to enable this feature and it will be used for data +packets as well. + +Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Abinaya Kalaiselvan +Signed-off-by: Maharaja Kennadyrajan +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20221219053844.4084486-1-quic_mkenna@quicinc.com +--- + drivers/net/wireless/ath/ath11k/hw.c | 1 + + drivers/net/wireless/ath/ath11k/mac.c | 5 +++++ + drivers/net/wireless/ath/ath11k/wmi.c | 27 ++++++++++++++++----------- + drivers/net/wireless/ath/ath11k/wmi.h | 3 +++ + 4 files changed, 25 insertions(+), 11 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/hw.c ++++ b/drivers/net/wireless/ath/ath11k/hw.c +@@ -201,6 +201,7 @@ static void ath11k_init_wmi_config_ipq80 + config->twt_ap_pdev_count = ab->num_radios; + config->twt_ap_sta_count = 1000; + config->flag1 |= WMI_RSRC_CFG_FLAG1_BSS_CHANNEL_INFO_64; ++ config->flag1 |= WMI_RSRC_CFG_FLAG1_ACK_RSSI; + } + + static int ath11k_hw_mac_id_to_pdev_id_ipq8074(struct ath11k_hw_params *hw, +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -9174,6 +9174,11 @@ static int __ath11k_mac_register(struct + goto err_free_if_combs; + } + ++ if (test_bit(WMI_TLV_SERVICE_TX_DATA_MGMT_ACK_RSSI, ++ ar->ab->wmi_ab.svc_map)) ++ wiphy_ext_feature_set(ar->hw->wiphy, ++ NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT); ++ + ar->hw->queues = ATH11K_HW_MAX_QUEUES; + ar->hw->wiphy->tx_queue_len = ATH11K_QUEUE_LEN; + ar->hw->offchannel_tx_hw_queue = ATH11K_HW_MAX_QUEUES - 1; +--- a/drivers/net/wireless/ath/ath11k/wmi.c ++++ b/drivers/net/wireless/ath/ath11k/wmi.c +@@ -5229,8 +5229,8 @@ static int ath11k_pull_mgmt_rx_params_tl + return 0; + } + +-static int wmi_process_mgmt_tx_comp(struct ath11k *ar, u32 desc_id, +- u32 status) ++static int wmi_process_mgmt_tx_comp(struct ath11k *ar, ++ struct wmi_mgmt_tx_compl_event *tx_compl_param) + { + struct sk_buff *msdu; + struct ieee80211_tx_info *info; +@@ -5238,24 +5238,29 @@ static int wmi_process_mgmt_tx_comp(stru + int num_mgmt; + + spin_lock_bh(&ar->txmgmt_idr_lock); +- msdu = idr_find(&ar->txmgmt_idr, desc_id); ++ msdu = idr_find(&ar->txmgmt_idr, tx_compl_param->desc_id); + + if (!msdu) { + ath11k_warn(ar->ab, "received mgmt tx compl for invalid msdu_id: %d\n", +- desc_id); ++ tx_compl_param->desc_id); + spin_unlock_bh(&ar->txmgmt_idr_lock); + return -ENOENT; + } + +- idr_remove(&ar->txmgmt_idr, desc_id); ++ idr_remove(&ar->txmgmt_idr, tx_compl_param->desc_id); + spin_unlock_bh(&ar->txmgmt_idr_lock); + + skb_cb = ATH11K_SKB_CB(msdu); + dma_unmap_single(ar->ab->dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE); + + info = IEEE80211_SKB_CB(msdu); +- if ((!(info->flags & IEEE80211_TX_CTL_NO_ACK)) && !status) ++ if ((!(info->flags & IEEE80211_TX_CTL_NO_ACK)) && ++ !tx_compl_param->status) { + info->flags |= IEEE80211_TX_STAT_ACK; ++ if (test_bit(WMI_TLV_SERVICE_TX_DATA_MGMT_ACK_RSSI, ++ ar->ab->wmi_ab.svc_map)) ++ info->status.ack_signal = tx_compl_param->ack_rssi; ++ } + + ieee80211_tx_status_irqsafe(ar->hw, msdu); + +@@ -5267,7 +5272,7 @@ static int wmi_process_mgmt_tx_comp(stru + + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, + "wmi mgmt tx comp pending %d desc id %d\n", +- num_mgmt, desc_id); ++ num_mgmt, tx_compl_param->desc_id); + + if (!num_mgmt) + wake_up(&ar->txmgmt_empty_waitq); +@@ -5300,6 +5305,7 @@ static int ath11k_pull_mgmt_tx_compl_par + param->pdev_id = ev->pdev_id; + param->desc_id = ev->desc_id; + param->status = ev->status; ++ param->ack_rssi = ev->ack_rssi; + + kfree(tb); + return 0; +@@ -7070,13 +7076,12 @@ static void ath11k_mgmt_tx_compl_event(s + goto exit; + } + +- wmi_process_mgmt_tx_comp(ar, tx_compl_param.desc_id, +- tx_compl_param.status); ++ wmi_process_mgmt_tx_comp(ar, &tx_compl_param); + + ath11k_dbg(ab, ATH11K_DBG_MGMT, +- "mgmt tx compl ev pdev_id %d, desc_id %d, status %d", ++ "mgmt tx compl ev pdev_id %d, desc_id %d, status %d ack_rssi %d", + tx_compl_param.pdev_id, tx_compl_param.desc_id, +- tx_compl_param.status); ++ tx_compl_param.status, tx_compl_param.ack_rssi); + + exit: + rcu_read_unlock(); +--- a/drivers/net/wireless/ath/ath11k/wmi.h ++++ b/drivers/net/wireless/ath/ath11k/wmi.h +@@ -2311,6 +2311,7 @@ struct wmi_init_cmd { + } __packed; + + #define WMI_RSRC_CFG_FLAG1_BSS_CHANNEL_INFO_64 BIT(5) ++#define WMI_RSRC_CFG_FLAG1_ACK_RSSI BIT(18) + + struct wmi_resource_config { + u32 tlv_header; +@@ -4550,6 +4551,8 @@ struct wmi_mgmt_tx_compl_event { + u32 desc_id; + u32 status; + u32 pdev_id; ++ u32 ppdu_id; ++ u32 ack_rssi; + } __packed; + + struct wmi_scan_event { diff --git a/package/kernel/mac80211/patches/ath11k/0043-wifi-ath11k-use-proper-regulatory-reference-for-band.patch b/package/kernel/mac80211/patches/ath11k/0043-wifi-ath11k-use-proper-regulatory-reference-for-band.patch new file mode 100644 index 000000000..5bc195528 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0043-wifi-ath11k-use-proper-regulatory-reference-for-band.patch @@ -0,0 +1,216 @@ +From 25e289e1f52e1f4fb1d07622c6a24f8d8a8e420d Mon Sep 17 00:00:00 2001 +From: Aditya Kumar Singh +Date: Wed, 1 Mar 2023 16:20:58 +0200 +Subject: [PATCH] wifi: ath11k: use proper regulatory reference for bands + +Currently, during regulatory event, 2 GHz/5 GHz is referred +to as 2G/5G including variable names. However, there is no +such entity as 2G or 5G. + +Re-name such occurences to its proper name. No functional changes. + +Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 +Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 +Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.5.0.1-01100-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Aditya Kumar Singh +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20230110121024.14051-2-quic_adisi@quicinc.com +--- + drivers/net/wireless/ath/ath11k/reg.c | 20 ++++----- + drivers/net/wireless/ath/ath11k/wmi.c | 58 ++++++++++++++------------- + drivers/net/wireless/ath/ath11k/wmi.h | 28 ++++++------- + 3 files changed, 54 insertions(+), 52 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/reg.c ++++ b/drivers/net/wireless/ath/ath11k/reg.c +@@ -619,7 +619,7 @@ ath11k_reg_build_regd(struct ath11k_base + u32 flags; + char alpha2[3]; + +- num_rules = reg_info->num_5g_reg_rules + reg_info->num_2g_reg_rules; ++ num_rules = reg_info->num_5ghz_reg_rules + reg_info->num_2ghz_reg_rules; + + if (!num_rules) + goto ret; +@@ -644,20 +644,20 @@ ath11k_reg_build_regd(struct ath11k_base + alpha2, ath11k_reg_get_regdom_str(tmp_regd->dfs_region), + reg_info->dfs_region, num_rules); + /* Update reg_rules[] below. Firmware is expected to +- * send these rules in order(2G rules first and then 5G) ++ * send these rules in order(2 GHz rules first and then 5 GHz) + */ + for (; i < num_rules; i++) { +- if (reg_info->num_2g_reg_rules && +- (i < reg_info->num_2g_reg_rules)) { +- reg_rule = reg_info->reg_rules_2g_ptr + i; ++ if (reg_info->num_2ghz_reg_rules && ++ (i < reg_info->num_2ghz_reg_rules)) { ++ reg_rule = reg_info->reg_rules_2ghz_ptr + i; + max_bw = min_t(u16, reg_rule->max_bw, +- reg_info->max_bw_2g); ++ reg_info->max_bw_2ghz); + flags = 0; +- } else if (reg_info->num_5g_reg_rules && +- (j < reg_info->num_5g_reg_rules)) { +- reg_rule = reg_info->reg_rules_5g_ptr + j++; ++ } else if (reg_info->num_5ghz_reg_rules && ++ (j < reg_info->num_5ghz_reg_rules)) { ++ reg_rule = reg_info->reg_rules_5ghz_ptr + j++; + max_bw = min_t(u16, reg_rule->max_bw, +- reg_info->max_bw_5g); ++ reg_info->max_bw_5ghz); + + /* FW doesn't pass NL80211_RRF_AUTO_BW flag for + * BW Auto correction, we can enable this by default +--- a/drivers/net/wireless/ath/ath11k/wmi.c ++++ b/drivers/net/wireless/ath/ath11k/wmi.c +@@ -4959,7 +4959,7 @@ static int ath11k_pull_reg_chan_list_upd + const void **tb; + const struct wmi_reg_chan_list_cc_event *chan_list_event_hdr; + struct wmi_regulatory_rule_struct *wmi_reg_rule; +- u32 num_2g_reg_rules, num_5g_reg_rules; ++ u32 num_2ghz_reg_rules, num_5ghz_reg_rules; + int ret; + + ath11k_dbg(ab, ATH11K_DBG_WMI, "processing regulatory channel list\n"); +@@ -4978,10 +4978,10 @@ static int ath11k_pull_reg_chan_list_upd + return -EPROTO; + } + +- reg_info->num_2g_reg_rules = chan_list_event_hdr->num_2g_reg_rules; +- reg_info->num_5g_reg_rules = chan_list_event_hdr->num_5g_reg_rules; ++ reg_info->num_2ghz_reg_rules = chan_list_event_hdr->num_2ghz_reg_rules; ++ reg_info->num_5ghz_reg_rules = chan_list_event_hdr->num_5ghz_reg_rules; + +- if (!(reg_info->num_2g_reg_rules + reg_info->num_5g_reg_rules)) { ++ if (!(reg_info->num_2ghz_reg_rules + reg_info->num_5ghz_reg_rules)) { + ath11k_warn(ab, "No regulatory rules available in the event info\n"); + kfree(tb); + return -EINVAL; +@@ -5008,46 +5008,48 @@ static int ath11k_pull_reg_chan_list_upd + else if (chan_list_event_hdr->status_code == WMI_REG_SET_CC_STATUS_FAIL) + reg_info->status_code = REG_SET_CC_STATUS_FAIL; + +- reg_info->min_bw_2g = chan_list_event_hdr->min_bw_2g; +- reg_info->max_bw_2g = chan_list_event_hdr->max_bw_2g; +- reg_info->min_bw_5g = chan_list_event_hdr->min_bw_5g; +- reg_info->max_bw_5g = chan_list_event_hdr->max_bw_5g; ++ reg_info->min_bw_2ghz = chan_list_event_hdr->min_bw_2ghz; ++ reg_info->max_bw_2ghz = chan_list_event_hdr->max_bw_2ghz; ++ reg_info->min_bw_5ghz = chan_list_event_hdr->min_bw_5ghz; ++ reg_info->max_bw_5ghz = chan_list_event_hdr->max_bw_5ghz; + +- num_2g_reg_rules = reg_info->num_2g_reg_rules; +- num_5g_reg_rules = reg_info->num_5g_reg_rules; ++ num_2ghz_reg_rules = reg_info->num_2ghz_reg_rules; ++ num_5ghz_reg_rules = reg_info->num_5ghz_reg_rules; + + ath11k_dbg(ab, ATH11K_DBG_WMI, +- "%s:cc %s dsf %d BW: min_2g %d max_2g %d min_5g %d max_5g %d", ++ "%s:cc %s dsf %d BW: min_2ghz %d max_2ghz %d min_5ghz %d max_5ghz %d", + __func__, reg_info->alpha2, reg_info->dfs_region, +- reg_info->min_bw_2g, reg_info->max_bw_2g, +- reg_info->min_bw_5g, reg_info->max_bw_5g); ++ reg_info->min_bw_2ghz, reg_info->max_bw_2ghz, ++ reg_info->min_bw_5ghz, reg_info->max_bw_5ghz); + + ath11k_dbg(ab, ATH11K_DBG_WMI, +- "%s: num_2g_reg_rules %d num_5g_reg_rules %d", __func__, +- num_2g_reg_rules, num_5g_reg_rules); ++ "%s: num_2ghz_reg_rules %d num_5ghz_reg_rules %d", __func__, ++ num_2ghz_reg_rules, num_5ghz_reg_rules); + + wmi_reg_rule = + (struct wmi_regulatory_rule_struct *)((u8 *)chan_list_event_hdr + + sizeof(*chan_list_event_hdr) + + sizeof(struct wmi_tlv)); + +- if (num_2g_reg_rules) { +- reg_info->reg_rules_2g_ptr = create_reg_rules_from_wmi(num_2g_reg_rules, +- wmi_reg_rule); +- if (!reg_info->reg_rules_2g_ptr) { ++ if (num_2ghz_reg_rules) { ++ reg_info->reg_rules_2ghz_ptr = ++ create_reg_rules_from_wmi(num_2ghz_reg_rules, ++ wmi_reg_rule); ++ if (!reg_info->reg_rules_2ghz_ptr) { + kfree(tb); +- ath11k_warn(ab, "Unable to Allocate memory for 2g rules\n"); ++ ath11k_warn(ab, "Unable to Allocate memory for 2 GHz rules\n"); + return -ENOMEM; + } + } + +- if (num_5g_reg_rules) { +- wmi_reg_rule += num_2g_reg_rules; +- reg_info->reg_rules_5g_ptr = create_reg_rules_from_wmi(num_5g_reg_rules, +- wmi_reg_rule); +- if (!reg_info->reg_rules_5g_ptr) { ++ if (num_5ghz_reg_rules) { ++ wmi_reg_rule += num_2ghz_reg_rules; ++ reg_info->reg_rules_5ghz_ptr = ++ create_reg_rules_from_wmi(num_5ghz_reg_rules, ++ wmi_reg_rule); ++ if (!reg_info->reg_rules_5ghz_ptr) { + kfree(tb); +- ath11k_warn(ab, "Unable to Allocate memory for 5g rules\n"); ++ ath11k_warn(ab, "Unable to Allocate memory for 5 GHz rules\n"); + return -ENOMEM; + } + } +@@ -6619,8 +6621,8 @@ fallback: + WARN_ON(1); + mem_free: + if (reg_info) { +- kfree(reg_info->reg_rules_2g_ptr); +- kfree(reg_info->reg_rules_5g_ptr); ++ kfree(reg_info->reg_rules_2ghz_ptr); ++ kfree(reg_info->reg_rules_5ghz_ptr); + kfree(reg_info); + } + return ret; +--- a/drivers/net/wireless/ath/ath11k/wmi.h ++++ b/drivers/net/wireless/ath/ath11k/wmi.h +@@ -4129,14 +4129,14 @@ struct cur_regulatory_info { + u8 alpha2[REG_ALPHA2_LEN + 1]; + u32 dfs_region; + u32 phybitmap; +- u32 min_bw_2g; +- u32 max_bw_2g; +- u32 min_bw_5g; +- u32 max_bw_5g; +- u32 num_2g_reg_rules; +- u32 num_5g_reg_rules; +- struct cur_reg_rule *reg_rules_2g_ptr; +- struct cur_reg_rule *reg_rules_5g_ptr; ++ u32 min_bw_2ghz; ++ u32 max_bw_2ghz; ++ u32 min_bw_5ghz; ++ u32 max_bw_5ghz; ++ u32 num_2ghz_reg_rules; ++ u32 num_5ghz_reg_rules; ++ struct cur_reg_rule *reg_rules_2ghz_ptr; ++ struct cur_reg_rule *reg_rules_5ghz_ptr; + }; + + struct wmi_reg_chan_list_cc_event { +@@ -4148,12 +4148,12 @@ struct wmi_reg_chan_list_cc_event { + u32 domain_code; + u32 dfs_region; + u32 phybitmap; +- u32 min_bw_2g; +- u32 max_bw_2g; +- u32 min_bw_5g; +- u32 max_bw_5g; +- u32 num_2g_reg_rules; +- u32 num_5g_reg_rules; ++ u32 min_bw_2ghz; ++ u32 max_bw_2ghz; ++ u32 min_bw_5ghz; ++ u32 max_bw_5ghz; ++ u32 num_2ghz_reg_rules; ++ u32 num_5ghz_reg_rules; + } __packed; + + struct wmi_regulatory_rule_struct { diff --git a/package/kernel/mac80211/patches/ath11k/0044-wifi-ath11k-add-support-to-parse-new-WMI-event-for-6.patch b/package/kernel/mac80211/patches/ath11k/0044-wifi-ath11k-add-support-to-parse-new-WMI-event-for-6.patch new file mode 100644 index 000000000..e165c09dc --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0044-wifi-ath11k-add-support-to-parse-new-WMI-event-for-6.patch @@ -0,0 +1,844 @@ +From 91fa00fa69224aae5afb720c5e68b22e4c4f7333 Mon Sep 17 00:00:00 2001 +From: Aditya Kumar Singh +Date: Wed, 1 Mar 2023 16:20:59 +0200 +Subject: [PATCH] wifi: ath11k: add support to parse new WMI event for 6 GHz + +In order to support different power levels of 6 GHz AP and client, +new WMI event for regulatory - WMI_REG_CHAN_LIST_CC_EXT_EVENTID is +added in firmware. This event provides new parameters required for +6 GHz regulatory rules. + +Add support for parsing 2.4 GHz, 5 GHz and 6 GHz reg rules and other +parameters from WMI_REG_CHAN_LIST_CC_EXT_EVENTID. + +Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 +Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 +Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.5.0.1-01100-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Lavanya Suresh +Signed-off-by: Wen Gong +Signed-off-by: Aditya Kumar Singh +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20230110121024.14051-3-quic_adisi@quicinc.com +--- + drivers/net/wireless/ath/ath11k/reg.c | 37 ++- + drivers/net/wireless/ath/ath11k/wmi.c | 418 +++++++++++++++++++++++++- + drivers/net/wireless/ath/ath11k/wmi.h | 163 +++++++++- + 3 files changed, 584 insertions(+), 34 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/reg.c ++++ b/drivers/net/wireless/ath/ath11k/reg.c +@@ -613,7 +613,7 @@ ath11k_reg_build_regd(struct ath11k_base + { + struct ieee80211_regdomain *tmp_regd, *default_regd, *new_regd = NULL; + struct cur_reg_rule *reg_rule; +- u8 i = 0, j = 0; ++ u8 i = 0, j = 0, k = 0; + u8 num_rules; + u16 max_bw; + u32 flags; +@@ -621,6 +621,12 @@ ath11k_reg_build_regd(struct ath11k_base + + num_rules = reg_info->num_5ghz_reg_rules + reg_info->num_2ghz_reg_rules; + ++ /* FIXME: Currently taking reg rules for 6 GHz only from Indoor AP mode list. ++ * This can be updated after complete 6 GHz regulatory support is added. ++ */ ++ if (reg_info->is_ext_reg_event) ++ num_rules += reg_info->num_6ghz_rules_ap[WMI_REG_INDOOR_AP]; ++ + if (!num_rules) + goto ret; + +@@ -666,6 +672,14 @@ ath11k_reg_build_regd(struct ath11k_base + * per other BW rule flags we pass from here + */ + flags = NL80211_RRF_AUTO_BW; ++ } else if (reg_info->is_ext_reg_event && ++ reg_info->num_6ghz_rules_ap[WMI_REG_INDOOR_AP] && ++ (k < reg_info->num_6ghz_rules_ap[WMI_REG_INDOOR_AP])) { ++ reg_rule = reg_info->reg_rules_6ghz_ap_ptr[WMI_REG_INDOOR_AP] + ++ k++; ++ max_bw = min_t(u16, reg_rule->max_bw, ++ reg_info->max_bw_6ghz_ap[WMI_REG_INDOOR_AP]); ++ flags = NL80211_RRF_AUTO_BW; + } else { + break; + } +@@ -693,12 +707,21 @@ ath11k_reg_build_regd(struct ath11k_base + continue; + } + +- ath11k_dbg(ab, ATH11K_DBG_REG, +- "\t%d. (%d - %d @ %d) (%d, %d) (%d ms) (FLAGS %d)\n", +- i + 1, reg_rule->start_freq, reg_rule->end_freq, +- max_bw, reg_rule->ant_gain, reg_rule->reg_power, +- tmp_regd->reg_rules[i].dfs_cac_ms, +- flags); ++ if (reg_info->is_ext_reg_event) { ++ ath11k_dbg(ab, ATH11K_DBG_REG, ++ "\t%d. (%d - %d @ %d) (%d, %d) (%d ms) (FLAGS %d) (%d, %d)\n", ++ i + 1, reg_rule->start_freq, reg_rule->end_freq, ++ max_bw, reg_rule->ant_gain, reg_rule->reg_power, ++ tmp_regd->reg_rules[i].dfs_cac_ms, flags, ++ reg_rule->psd_flag, reg_rule->psd_eirp); ++ } else { ++ ath11k_dbg(ab, ATH11K_DBG_REG, ++ "\t%d. (%d - %d @ %d) (%d, %d) (%d ms) (FLAGS %d)\n", ++ i + 1, reg_rule->start_freq, reg_rule->end_freq, ++ max_bw, reg_rule->ant_gain, reg_rule->reg_power, ++ tmp_regd->reg_rules[i].dfs_cac_ms, ++ flags); ++ } + } + + tmp_regd->n_reg_rules = i; +--- a/drivers/net/wireless/ath/ath11k/wmi.c ++++ b/drivers/net/wireless/ath/ath11k/wmi.c +@@ -105,6 +105,8 @@ static const struct wmi_tlv_policy wmi_t + = { .min_len = sizeof(struct wmi_vdev_stopped_event) }, + [WMI_TAG_REG_CHAN_LIST_CC_EVENT] + = { .min_len = sizeof(struct wmi_reg_chan_list_cc_event) }, ++ [WMI_TAG_REG_CHAN_LIST_CC_EXT_EVENT] ++ = { .min_len = sizeof(struct wmi_reg_chan_list_cc_ext_event) }, + [WMI_TAG_MGMT_RX_HDR] + = { .min_len = sizeof(struct wmi_mgmt_rx_hdr) }, + [WMI_TAG_MGMT_TX_COMPL_EVENT] +@@ -3974,6 +3976,10 @@ ath11k_wmi_copy_resource_config(struct w + wmi_cfg->sched_params = tg_cfg->sched_params; + wmi_cfg->twt_ap_pdev_count = tg_cfg->twt_ap_pdev_count; + wmi_cfg->twt_ap_sta_count = tg_cfg->twt_ap_sta_count; ++ wmi_cfg->host_service_flags &= ++ ~(1 << WMI_CFG_HOST_SERVICE_FLAG_REG_CC_EXT); ++ wmi_cfg->host_service_flags |= (tg_cfg->is_reg_cc_ext_event_supported << ++ WMI_CFG_HOST_SERVICE_FLAG_REG_CC_EXT); + } + + static int ath11k_init_cmd_send(struct ath11k_pdev_wmi *wmi, +@@ -4192,6 +4198,10 @@ int ath11k_wmi_cmd_init(struct ath11k_ba + + ab->hw_params.hw_ops->wmi_init_config(ab, &config); + ++ if (test_bit(WMI_TLV_SERVICE_REG_CC_EXT_EVENT_SUPPORT, ++ ab->wmi_ab.svc_map)) ++ config.is_reg_cc_ext_event_supported = 1; ++ + memcpy(&wmi_sc->wlan_resource_config, &config, sizeof(config)); + + init_param.res_cfg = &wmi_sc->wlan_resource_config; +@@ -4995,18 +5005,11 @@ static int ath11k_pull_reg_chan_list_upd + reg_info->phy_id = chan_list_event_hdr->phy_id; + reg_info->ctry_code = chan_list_event_hdr->country_id; + reg_info->reg_dmn_pair = chan_list_event_hdr->domain_code; +- if (chan_list_event_hdr->status_code == WMI_REG_SET_CC_STATUS_PASS) +- reg_info->status_code = REG_SET_CC_STATUS_PASS; +- else if (chan_list_event_hdr->status_code == WMI_REG_CURRENT_ALPHA2_NOT_FOUND) +- reg_info->status_code = REG_CURRENT_ALPHA2_NOT_FOUND; +- else if (chan_list_event_hdr->status_code == WMI_REG_INIT_ALPHA2_NOT_FOUND) +- reg_info->status_code = REG_INIT_ALPHA2_NOT_FOUND; +- else if (chan_list_event_hdr->status_code == WMI_REG_SET_CC_CHANGE_NOT_ALLOWED) +- reg_info->status_code = REG_SET_CC_CHANGE_NOT_ALLOWED; +- else if (chan_list_event_hdr->status_code == WMI_REG_SET_CC_STATUS_NO_MEMORY) +- reg_info->status_code = REG_SET_CC_STATUS_NO_MEMORY; +- else if (chan_list_event_hdr->status_code == WMI_REG_SET_CC_STATUS_FAIL) +- reg_info->status_code = REG_SET_CC_STATUS_FAIL; ++ ++ reg_info->status_code = ++ ath11k_wmi_cc_setting_code_to_reg(chan_list_event_hdr->status_code); ++ ++ reg_info->is_ext_reg_event = false; + + reg_info->min_bw_2ghz = chan_list_event_hdr->min_bw_2ghz; + reg_info->max_bw_2ghz = chan_list_event_hdr->max_bw_2ghz; +@@ -5060,6 +5063,372 @@ static int ath11k_pull_reg_chan_list_upd + return 0; + } + ++static struct cur_reg_rule ++*create_ext_reg_rules_from_wmi(u32 num_reg_rules, ++ struct wmi_regulatory_ext_rule *wmi_reg_rule) ++{ ++ struct cur_reg_rule *reg_rule_ptr; ++ u32 count; ++ ++ reg_rule_ptr = kcalloc(num_reg_rules, sizeof(*reg_rule_ptr), GFP_ATOMIC); ++ ++ if (!reg_rule_ptr) ++ return NULL; ++ ++ for (count = 0; count < num_reg_rules; count++) { ++ reg_rule_ptr[count].start_freq = ++ u32_get_bits(wmi_reg_rule[count].freq_info, ++ REG_RULE_START_FREQ); ++ reg_rule_ptr[count].end_freq = ++ u32_get_bits(wmi_reg_rule[count].freq_info, ++ REG_RULE_END_FREQ); ++ reg_rule_ptr[count].max_bw = ++ u32_get_bits(wmi_reg_rule[count].bw_pwr_info, ++ REG_RULE_MAX_BW); ++ reg_rule_ptr[count].reg_power = ++ u32_get_bits(wmi_reg_rule[count].bw_pwr_info, ++ REG_RULE_REG_PWR); ++ reg_rule_ptr[count].ant_gain = ++ u32_get_bits(wmi_reg_rule[count].bw_pwr_info, ++ REG_RULE_ANT_GAIN); ++ reg_rule_ptr[count].flags = ++ u32_get_bits(wmi_reg_rule[count].flag_info, ++ REG_RULE_FLAGS); ++ reg_rule_ptr[count].psd_flag = ++ u32_get_bits(wmi_reg_rule[count].psd_power_info, ++ REG_RULE_PSD_INFO); ++ reg_rule_ptr[count].psd_eirp = ++ u32_get_bits(wmi_reg_rule[count].psd_power_info, ++ REG_RULE_PSD_EIRP); ++ } ++ ++ return reg_rule_ptr; ++} ++ ++static u8 ++ath11k_invalid_5ghz_reg_ext_rules_from_wmi(u32 num_reg_rules, ++ const struct wmi_regulatory_ext_rule *rule) ++{ ++ u8 num_invalid_5ghz_rules = 0; ++ u32 count, start_freq; ++ ++ for (count = 0; count < num_reg_rules; count++) { ++ start_freq = u32_get_bits(rule[count].freq_info, ++ REG_RULE_START_FREQ); ++ ++ if (start_freq >= ATH11K_MIN_6G_FREQ) ++ num_invalid_5ghz_rules++; ++ } ++ ++ return num_invalid_5ghz_rules; ++} ++ ++static int ath11k_pull_reg_chan_list_ext_update_ev(struct ath11k_base *ab, ++ struct sk_buff *skb, ++ struct cur_regulatory_info *reg_info) ++{ ++ const void **tb; ++ const struct wmi_reg_chan_list_cc_ext_event *ext_chan_list_event_hdr; ++ struct wmi_regulatory_ext_rule *ext_wmi_reg_rule; ++ u32 num_2ghz_reg_rules, num_5ghz_reg_rules; ++ u32 num_6ghz_reg_rules_ap[WMI_REG_CURRENT_MAX_AP_TYPE]; ++ u32 num_6ghz_client[WMI_REG_CURRENT_MAX_AP_TYPE][WMI_REG_MAX_CLIENT_TYPE]; ++ u32 total_reg_rules = 0; ++ int ret, i, j, num_invalid_5ghz_ext_rules = 0; ++ ++ ath11k_dbg(ab, ATH11K_DBG_WMI, "processing regulatory ext channel list\n"); ++ ++ tb = ath11k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC); ++ if (IS_ERR(tb)) { ++ ret = PTR_ERR(tb); ++ ath11k_warn(ab, "failed to parse tlv: %d\n", ret); ++ return ret; ++ } ++ ++ ext_chan_list_event_hdr = tb[WMI_TAG_REG_CHAN_LIST_CC_EXT_EVENT]; ++ if (!ext_chan_list_event_hdr) { ++ ath11k_warn(ab, "failed to fetch reg chan list ext update ev\n"); ++ kfree(tb); ++ return -EPROTO; ++ } ++ ++ reg_info->num_2ghz_reg_rules = ++ ext_chan_list_event_hdr->num_2ghz_reg_rules; ++ reg_info->num_5ghz_reg_rules = ++ ext_chan_list_event_hdr->num_5ghz_reg_rules; ++ reg_info->num_6ghz_rules_ap[WMI_REG_INDOOR_AP] = ++ ext_chan_list_event_hdr->num_6ghz_reg_rules_ap_lpi; ++ reg_info->num_6ghz_rules_ap[WMI_REG_STANDARD_POWER_AP] = ++ ext_chan_list_event_hdr->num_6ghz_reg_rules_ap_sp; ++ reg_info->num_6ghz_rules_ap[WMI_REG_VERY_LOW_POWER_AP] = ++ ext_chan_list_event_hdr->num_6ghz_reg_rules_ap_vlp; ++ ++ for (i = 0; i < WMI_REG_MAX_CLIENT_TYPE; i++) { ++ reg_info->num_6ghz_rules_client[WMI_REG_INDOOR_AP][i] = ++ ext_chan_list_event_hdr->num_6ghz_reg_rules_client_lpi[i]; ++ reg_info->num_6ghz_rules_client[WMI_REG_STANDARD_POWER_AP][i] = ++ ext_chan_list_event_hdr->num_6ghz_reg_rules_client_sp[i]; ++ reg_info->num_6ghz_rules_client[WMI_REG_VERY_LOW_POWER_AP][i] = ++ ext_chan_list_event_hdr->num_6ghz_reg_rules_client_vlp[i]; ++ } ++ ++ num_2ghz_reg_rules = reg_info->num_2ghz_reg_rules; ++ num_5ghz_reg_rules = reg_info->num_5ghz_reg_rules; ++ ++ total_reg_rules += num_2ghz_reg_rules; ++ total_reg_rules += num_5ghz_reg_rules; ++ ++ if ((num_2ghz_reg_rules > MAX_REG_RULES) || ++ (num_5ghz_reg_rules > MAX_REG_RULES)) { ++ ath11k_warn(ab, "Num reg rules for 2.4 GHz/5 GHz exceeds max limit (num_2ghz_reg_rules: %d num_5ghz_reg_rules: %d max_rules: %d)\n", ++ num_2ghz_reg_rules, num_5ghz_reg_rules, MAX_REG_RULES); ++ kfree(tb); ++ return -EINVAL; ++ } ++ ++ for (i = 0; i < WMI_REG_CURRENT_MAX_AP_TYPE; i++) { ++ num_6ghz_reg_rules_ap[i] = reg_info->num_6ghz_rules_ap[i]; ++ ++ if (num_6ghz_reg_rules_ap[i] > MAX_6GHZ_REG_RULES) { ++ ath11k_warn(ab, "Num 6 GHz reg rules for AP mode(%d) exceeds max limit (num_6ghz_reg_rules_ap: %d, max_rules: %d)\n", ++ i, num_6ghz_reg_rules_ap[i], MAX_6GHZ_REG_RULES); ++ kfree(tb); ++ return -EINVAL; ++ } ++ ++ total_reg_rules += num_6ghz_reg_rules_ap[i]; ++ } ++ ++ for (i = 0; i < WMI_REG_MAX_CLIENT_TYPE; i++) { ++ num_6ghz_client[WMI_REG_INDOOR_AP][i] = ++ reg_info->num_6ghz_rules_client[WMI_REG_INDOOR_AP][i]; ++ total_reg_rules += num_6ghz_client[WMI_REG_INDOOR_AP][i]; ++ ++ num_6ghz_client[WMI_REG_STANDARD_POWER_AP][i] = ++ reg_info->num_6ghz_rules_client[WMI_REG_STANDARD_POWER_AP][i]; ++ total_reg_rules += num_6ghz_client[WMI_REG_STANDARD_POWER_AP][i]; ++ ++ num_6ghz_client[WMI_REG_VERY_LOW_POWER_AP][i] = ++ reg_info->num_6ghz_rules_client[WMI_REG_VERY_LOW_POWER_AP][i]; ++ total_reg_rules += num_6ghz_client[WMI_REG_VERY_LOW_POWER_AP][i]; ++ ++ if ((num_6ghz_client[WMI_REG_INDOOR_AP][i] > MAX_6GHZ_REG_RULES) || ++ (num_6ghz_client[WMI_REG_STANDARD_POWER_AP][i] > ++ MAX_6GHZ_REG_RULES) || ++ (num_6ghz_client[WMI_REG_VERY_LOW_POWER_AP][i] > ++ MAX_6GHZ_REG_RULES)) { ++ ath11k_warn(ab, ++ "Num 6 GHz client reg rules exceeds max limit, for client(type: %d)\n", ++ i); ++ kfree(tb); ++ return -EINVAL; ++ } ++ } ++ ++ if (!total_reg_rules) { ++ ath11k_warn(ab, "No reg rules available\n"); ++ kfree(tb); ++ return -EINVAL; ++ } ++ ++ memcpy(reg_info->alpha2, &ext_chan_list_event_hdr->alpha2, ++ REG_ALPHA2_LEN); ++ ++ reg_info->dfs_region = ext_chan_list_event_hdr->dfs_region; ++ reg_info->phybitmap = ext_chan_list_event_hdr->phybitmap; ++ reg_info->num_phy = ext_chan_list_event_hdr->num_phy; ++ reg_info->phy_id = ext_chan_list_event_hdr->phy_id; ++ reg_info->ctry_code = ext_chan_list_event_hdr->country_id; ++ reg_info->reg_dmn_pair = ext_chan_list_event_hdr->domain_code; ++ ++ reg_info->status_code = ++ ath11k_wmi_cc_setting_code_to_reg(ext_chan_list_event_hdr->status_code); ++ ++ reg_info->is_ext_reg_event = true; ++ ++ reg_info->min_bw_2ghz = ext_chan_list_event_hdr->min_bw_2ghz; ++ reg_info->max_bw_2ghz = ext_chan_list_event_hdr->max_bw_2ghz; ++ reg_info->min_bw_5ghz = ext_chan_list_event_hdr->min_bw_5ghz; ++ reg_info->max_bw_5ghz = ext_chan_list_event_hdr->max_bw_5ghz; ++ ++ reg_info->min_bw_6ghz_ap[WMI_REG_INDOOR_AP] = ++ ext_chan_list_event_hdr->min_bw_6ghz_ap_lpi; ++ reg_info->max_bw_6ghz_ap[WMI_REG_INDOOR_AP] = ++ ext_chan_list_event_hdr->max_bw_6ghz_ap_lpi; ++ reg_info->min_bw_6ghz_ap[WMI_REG_STANDARD_POWER_AP] = ++ ext_chan_list_event_hdr->min_bw_6ghz_ap_sp; ++ reg_info->max_bw_6ghz_ap[WMI_REG_STANDARD_POWER_AP] = ++ ext_chan_list_event_hdr->max_bw_6ghz_ap_sp; ++ reg_info->min_bw_6ghz_ap[WMI_REG_VERY_LOW_POWER_AP] = ++ ext_chan_list_event_hdr->min_bw_6ghz_ap_vlp; ++ reg_info->max_bw_6ghz_ap[WMI_REG_VERY_LOW_POWER_AP] = ++ ext_chan_list_event_hdr->max_bw_6ghz_ap_vlp; ++ ++ for (i = 0; i < WMI_REG_MAX_CLIENT_TYPE; i++) { ++ reg_info->min_bw_6ghz_client[WMI_REG_INDOOR_AP][i] = ++ ext_chan_list_event_hdr->min_bw_6ghz_client_lpi[i]; ++ reg_info->max_bw_6ghz_client[WMI_REG_INDOOR_AP][i] = ++ ext_chan_list_event_hdr->max_bw_6ghz_client_lpi[i]; ++ reg_info->min_bw_6ghz_client[WMI_REG_STANDARD_POWER_AP][i] = ++ ext_chan_list_event_hdr->min_bw_6ghz_client_sp[i]; ++ reg_info->max_bw_6ghz_client[WMI_REG_STANDARD_POWER_AP][i] = ++ ext_chan_list_event_hdr->max_bw_6ghz_client_sp[i]; ++ reg_info->min_bw_6ghz_client[WMI_REG_VERY_LOW_POWER_AP][i] = ++ ext_chan_list_event_hdr->min_bw_6ghz_client_vlp[i]; ++ reg_info->max_bw_6ghz_client[WMI_REG_VERY_LOW_POWER_AP][i] = ++ ext_chan_list_event_hdr->max_bw_6ghz_client_vlp[i]; ++ } ++ ++ ath11k_dbg(ab, ATH11K_DBG_WMI, ++ "%s:cc_ext %s dsf %d BW: min_2ghz %d max_2ghz %d min_5ghz %d max_5ghz %d", ++ __func__, reg_info->alpha2, reg_info->dfs_region, ++ reg_info->min_bw_2ghz, reg_info->max_bw_2ghz, ++ reg_info->min_bw_5ghz, reg_info->max_bw_5ghz); ++ ++ ath11k_dbg(ab, ATH11K_DBG_WMI, ++ "num_2ghz_reg_rules %d num_5ghz_reg_rules %d", ++ num_2ghz_reg_rules, num_5ghz_reg_rules); ++ ++ ath11k_dbg(ab, ATH11K_DBG_WMI, ++ "num_6ghz_reg_rules_ap_lpi: %d num_6ghz_reg_rules_ap_sp: %d num_6ghz_reg_rules_ap_vlp: %d", ++ num_6ghz_reg_rules_ap[WMI_REG_INDOOR_AP], ++ num_6ghz_reg_rules_ap[WMI_REG_STANDARD_POWER_AP], ++ num_6ghz_reg_rules_ap[WMI_REG_VERY_LOW_POWER_AP]); ++ ++ j = WMI_REG_DEFAULT_CLIENT; ++ ath11k_dbg(ab, ATH11K_DBG_WMI, ++ "6 GHz Regular client: num_6ghz_reg_rules_lpi: %d num_6ghz_reg_rules_sp: %d num_6ghz_reg_rules_vlp: %d", ++ num_6ghz_client[WMI_REG_INDOOR_AP][j], ++ num_6ghz_client[WMI_REG_STANDARD_POWER_AP][j], ++ num_6ghz_client[WMI_REG_VERY_LOW_POWER_AP][j]); ++ ++ j = WMI_REG_SUBORDINATE_CLIENT; ++ ath11k_dbg(ab, ATH11K_DBG_WMI, ++ "6 GHz Subordinate client: num_6ghz_reg_rules_lpi: %d num_6ghz_reg_rules_sp: %d num_6ghz_reg_rules_vlp: %d", ++ num_6ghz_client[WMI_REG_INDOOR_AP][j], ++ num_6ghz_client[WMI_REG_STANDARD_POWER_AP][j], ++ num_6ghz_client[WMI_REG_VERY_LOW_POWER_AP][j]); ++ ++ ext_wmi_reg_rule = ++ (struct wmi_regulatory_ext_rule *)((u8 *)ext_chan_list_event_hdr ++ + sizeof(*ext_chan_list_event_hdr) ++ + sizeof(struct wmi_tlv)); ++ if (num_2ghz_reg_rules) { ++ reg_info->reg_rules_2ghz_ptr = ++ create_ext_reg_rules_from_wmi(num_2ghz_reg_rules, ++ ext_wmi_reg_rule); ++ ++ if (!reg_info->reg_rules_2ghz_ptr) { ++ kfree(tb); ++ ath11k_warn(ab, "Unable to Allocate memory for 2 GHz rules\n"); ++ return -ENOMEM; ++ } ++ } ++ ++ ext_wmi_reg_rule += num_2ghz_reg_rules; ++ ++ /* Firmware might include 6 GHz reg rule in 5 GHz rule list ++ * for few countries along with separate 6 GHz rule. ++ * Having same 6 GHz reg rule in 5 GHz and 6 GHz rules list ++ * causes intersect check to be true, and same rules will be ++ * shown multiple times in iw cmd. ++ * Hence, avoid parsing 6 GHz rule from 5 GHz reg rule list ++ */ ++ num_invalid_5ghz_ext_rules = ++ ath11k_invalid_5ghz_reg_ext_rules_from_wmi(num_5ghz_reg_rules, ++ ext_wmi_reg_rule); ++ ++ if (num_invalid_5ghz_ext_rules) { ++ ath11k_dbg(ab, ATH11K_DBG_WMI, ++ "CC: %s 5 GHz reg rules number %d from fw, %d number of invalid 5 GHz rules", ++ reg_info->alpha2, reg_info->num_5ghz_reg_rules, ++ num_invalid_5ghz_ext_rules); ++ ++ num_5ghz_reg_rules = num_5ghz_reg_rules - num_invalid_5ghz_ext_rules; ++ reg_info->num_5ghz_reg_rules = num_5ghz_reg_rules; ++ } ++ ++ if (num_5ghz_reg_rules) { ++ reg_info->reg_rules_5ghz_ptr = ++ create_ext_reg_rules_from_wmi(num_5ghz_reg_rules, ++ ext_wmi_reg_rule); ++ ++ if (!reg_info->reg_rules_5ghz_ptr) { ++ kfree(tb); ++ ath11k_warn(ab, "Unable to Allocate memory for 5 GHz rules\n"); ++ return -ENOMEM; ++ } ++ } ++ ++ /* We have adjusted the number of 5 GHz reg rules above. But still those ++ * many rules needs to be adjusted in ext_wmi_reg_rule. ++ * ++ * NOTE: num_invalid_5ghz_ext_rules will be 0 for rest other cases. ++ */ ++ ext_wmi_reg_rule += (num_5ghz_reg_rules + num_invalid_5ghz_ext_rules); ++ ++ for (i = 0; i < WMI_REG_CURRENT_MAX_AP_TYPE; i++) { ++ reg_info->reg_rules_6ghz_ap_ptr[i] = ++ create_ext_reg_rules_from_wmi(num_6ghz_reg_rules_ap[i], ++ ext_wmi_reg_rule); ++ ++ if (!reg_info->reg_rules_6ghz_ap_ptr[i]) { ++ kfree(tb); ++ ath11k_warn(ab, "Unable to Allocate memory for 6 GHz AP rules\n"); ++ return -ENOMEM; ++ } ++ ++ ext_wmi_reg_rule += num_6ghz_reg_rules_ap[i]; ++ } ++ ++ for (j = 0; j < WMI_REG_CURRENT_MAX_AP_TYPE; j++) { ++ for (i = 0; i < WMI_REG_MAX_CLIENT_TYPE; i++) { ++ reg_info->reg_rules_6ghz_client_ptr[j][i] = ++ create_ext_reg_rules_from_wmi(num_6ghz_client[j][i], ++ ext_wmi_reg_rule); ++ ++ if (!reg_info->reg_rules_6ghz_client_ptr[j][i]) { ++ kfree(tb); ++ ath11k_warn(ab, "Unable to Allocate memory for 6 GHz client rules\n"); ++ return -ENOMEM; ++ } ++ ++ ext_wmi_reg_rule += num_6ghz_client[j][i]; ++ } ++ } ++ ++ reg_info->client_type = ext_chan_list_event_hdr->client_type; ++ reg_info->rnr_tpe_usable = ext_chan_list_event_hdr->rnr_tpe_usable; ++ reg_info->unspecified_ap_usable = ++ ext_chan_list_event_hdr->unspecified_ap_usable; ++ reg_info->domain_code_6ghz_ap[WMI_REG_INDOOR_AP] = ++ ext_chan_list_event_hdr->domain_code_6ghz_ap_lpi; ++ reg_info->domain_code_6ghz_ap[WMI_REG_STANDARD_POWER_AP] = ++ ext_chan_list_event_hdr->domain_code_6ghz_ap_sp; ++ reg_info->domain_code_6ghz_ap[WMI_REG_VERY_LOW_POWER_AP] = ++ ext_chan_list_event_hdr->domain_code_6ghz_ap_vlp; ++ ++ for (i = 0; i < WMI_REG_MAX_CLIENT_TYPE; i++) { ++ reg_info->domain_code_6ghz_client[WMI_REG_INDOOR_AP][i] = ++ ext_chan_list_event_hdr->domain_code_6ghz_client_lpi[i]; ++ reg_info->domain_code_6ghz_client[WMI_REG_STANDARD_POWER_AP][i] = ++ ext_chan_list_event_hdr->domain_code_6ghz_client_sp[i]; ++ reg_info->domain_code_6ghz_client[WMI_REG_VERY_LOW_POWER_AP][i] = ++ ext_chan_list_event_hdr->domain_code_6ghz_client_vlp[i]; ++ } ++ ++ reg_info->domain_code_6ghz_super_id = ++ ext_chan_list_event_hdr->domain_code_6ghz_super_id; ++ ++ ath11k_dbg(ab, ATH11K_DBG_WMI, "6 GHz client_type: %d domain_code_6ghz_super_id: %d", ++ reg_info->client_type, reg_info->domain_code_6ghz_super_id); ++ ++ ath11k_dbg(ab, ATH11K_DBG_WMI, "processed regulatory ext channel list\n"); ++ ++ kfree(tb); ++ return 0; ++} ++ + static int ath11k_pull_peer_del_resp_ev(struct ath11k_base *ab, struct sk_buff *skb, + struct wmi_peer_delete_resp_event *peer_del_resp) + { +@@ -6507,12 +6876,14 @@ static bool ath11k_reg_is_world_alpha(ch + return false; + } + +-static int ath11k_reg_chan_list_event(struct ath11k_base *ab, struct sk_buff *skb) ++static int ath11k_reg_chan_list_event(struct ath11k_base *ab, ++ struct sk_buff *skb, ++ enum wmi_reg_chan_list_cmd_type id) + { + struct cur_regulatory_info *reg_info = NULL; + struct ieee80211_regdomain *regd = NULL; + bool intersect = false; +- int ret = 0, pdev_idx; ++ int ret = 0, pdev_idx, i, j; + struct ath11k *ar; + + reg_info = kzalloc(sizeof(*reg_info), GFP_ATOMIC); +@@ -6521,7 +6892,11 @@ static int ath11k_reg_chan_list_event(st + goto fallback; + } + +- ret = ath11k_pull_reg_chan_list_update_ev(ab, skb, reg_info); ++ if (id == WMI_REG_CHAN_LIST_CC_ID) ++ ret = ath11k_pull_reg_chan_list_update_ev(ab, skb, reg_info); ++ else ++ ret = ath11k_pull_reg_chan_list_ext_update_ev(ab, skb, reg_info); ++ + if (ret) { + ath11k_warn(ab, "failed to extract regulatory info from received event\n"); + goto fallback; +@@ -6623,6 +6998,14 @@ mem_free: + if (reg_info) { + kfree(reg_info->reg_rules_2ghz_ptr); + kfree(reg_info->reg_rules_5ghz_ptr); ++ if (reg_info->is_ext_reg_event) { ++ for (i = 0; i < WMI_REG_CURRENT_MAX_AP_TYPE; i++) ++ kfree(reg_info->reg_rules_6ghz_ap_ptr[i]); ++ ++ for (j = 0; j < WMI_REG_CURRENT_MAX_AP_TYPE; j++) ++ for (i = 0; i < WMI_REG_MAX_CLIENT_TYPE; i++) ++ kfree(reg_info->reg_rules_6ghz_client_ptr[j][i]); ++ } + kfree(reg_info); + } + return ret; +@@ -8054,7 +8437,10 @@ static void ath11k_wmi_tlv_op_rx(struct + ath11k_service_ready_ext2_event(ab, skb); + break; + case WMI_REG_CHAN_LIST_CC_EVENTID: +- ath11k_reg_chan_list_event(ab, skb); ++ ath11k_reg_chan_list_event(ab, skb, WMI_REG_CHAN_LIST_CC_ID); ++ break; ++ case WMI_REG_CHAN_LIST_CC_EXT_EVENTID: ++ ath11k_reg_chan_list_event(ab, skb, WMI_REG_CHAN_LIST_CC_EXT_ID); + break; + case WMI_READY_EVENTID: + ath11k_ready_event(ab, skb); +--- a/drivers/net/wireless/ath/ath11k/wmi.h ++++ b/drivers/net/wireless/ath/ath11k/wmi.h +@@ -797,6 +797,7 @@ enum wmi_tlv_event_id { + WMI_RMC_NEW_LEADER_EVENTID = WMI_TLV_CMD(WMI_GRP_RMC), + WMI_REG_CHAN_LIST_CC_EVENTID = WMI_TLV_CMD(WMI_GRP_REGULATORY), + WMI_11D_NEW_COUNTRY_EVENTID, ++ WMI_REG_CHAN_LIST_CC_EXT_EVENTID, + WMI_NDI_CAP_RSP_EVENTID = WMI_TLV_CMD(WMI_GRP_PROTOTYPE), + WMI_NDP_INITIATOR_RSP_EVENTID, + WMI_NDP_RESPONDER_RSP_EVENTID, +@@ -1865,6 +1866,8 @@ enum wmi_tlv_tag { + WMI_TAG_PDEV_SRG_OBSS_BSSID_ENABLE_BITMAP_CMD, + WMI_TAG_PDEV_NON_SRG_OBSS_COLOR_ENABLE_BITMAP_CMD, + WMI_TAG_PDEV_NON_SRG_OBSS_BSSID_ENABLE_BITMAP_CMD, ++ WMI_TAG_REGULATORY_RULE_EXT_STRUCT = 0x3A9, ++ WMI_TAG_REG_CHAN_LIST_CC_EXT_EVENT, + WMI_TAG_PDEV_SET_BIOS_SAR_TABLE_CMD = 0x3D8, + WMI_TAG_PDEV_SET_BIOS_GEO_TABLE_CMD, + WMI_TAG_MAX +@@ -2097,6 +2100,7 @@ enum wmi_tlv_service { + + /* The second 128 bits */ + WMI_MAX_EXT_SERVICE = 256, ++ WMI_TLV_SERVICE_REG_CC_EXT_EVENT_SUPPORT = 281, + WMI_TLV_SERVICE_BIOS_SAR_SUPPORT = 326, + + /* The third 128 bits */ +@@ -2313,6 +2317,8 @@ struct wmi_init_cmd { + #define WMI_RSRC_CFG_FLAG1_BSS_CHANNEL_INFO_64 BIT(5) + #define WMI_RSRC_CFG_FLAG1_ACK_RSSI BIT(18) + ++#define WMI_CFG_HOST_SERVICE_FLAG_REG_CC_EXT 4 ++ + struct wmi_resource_config { + u32 tlv_header; + u32 num_vdevs; +@@ -2372,6 +2378,15 @@ struct wmi_resource_config { + u32 sched_params; + u32 twt_ap_pdev_count; + u32 twt_ap_sta_count; ++ u32 max_nlo_ssids; ++ u32 num_pkt_filters; ++ u32 num_max_sta_vdevs; ++ u32 max_bssid_indicator; ++ u32 ul_resp_config; ++ u32 msdu_flow_override_config0; ++ u32 msdu_flow_override_config1; ++ u32 flags2; ++ u32 host_service_flags; + } __packed; + + struct wmi_service_ready_event { +@@ -2854,6 +2869,8 @@ struct rx_reorder_queue_remove_params { + #define REG_RULE_MAX_BW 0x0000ffff + #define REG_RULE_REG_PWR 0x00ff0000 + #define REG_RULE_ANT_GAIN 0xff000000 ++#define REG_RULE_PSD_INFO BIT(0) ++#define REG_RULE_PSD_EIRP 0xff0000 + + #define WMI_VDEV_PARAM_TXBF_SU_TX_BFEE BIT(0) + #define WMI_VDEV_PARAM_TXBF_MU_TX_BFEE BIT(1) +@@ -4049,6 +4066,7 @@ struct wmi_he_rate_set { + + #define MAX_REG_RULES 10 + #define REG_ALPHA2_LEN 2 ++#define MAX_6GHZ_REG_RULES 5 + + enum wmi_start_event_param { + WMI_VDEV_START_RESP_EVENT = 0, +@@ -4079,16 +4097,6 @@ enum wmi_vdev_start_resp_status_code { + WMI_VDEV_START_RESPONSE_INVALID_REGDOMAIN = 4, + }; + +-; +-enum cc_setting_code { +- REG_SET_CC_STATUS_PASS = 0, +- REG_CURRENT_ALPHA2_NOT_FOUND = 1, +- REG_INIT_ALPHA2_NOT_FOUND = 2, +- REG_SET_CC_CHANGE_NOT_ALLOWED = 3, +- REG_SET_CC_STATUS_NO_MEMORY = 4, +- REG_SET_CC_STATUS_FAIL = 5, +-}; +- + /* Regaulatory Rule Flags Passed by FW */ + #define REGULATORY_CHAN_DISABLED BIT(0) + #define REGULATORY_CHAN_NO_IR BIT(1) +@@ -4102,13 +4110,72 @@ enum cc_setting_code { + #define REGULATORY_CHAN_NO_20MHZ BIT(11) + #define REGULATORY_CHAN_NO_10MHZ BIT(12) + +-enum { ++enum wmi_reg_chan_list_cmd_type { ++ WMI_REG_CHAN_LIST_CC_ID = 0, ++ WMI_REG_CHAN_LIST_CC_EXT_ID = 1, ++}; ++ ++enum wmi_reg_cc_setting_code { + WMI_REG_SET_CC_STATUS_PASS = 0, + WMI_REG_CURRENT_ALPHA2_NOT_FOUND = 1, + WMI_REG_INIT_ALPHA2_NOT_FOUND = 2, + WMI_REG_SET_CC_CHANGE_NOT_ALLOWED = 3, + WMI_REG_SET_CC_STATUS_NO_MEMORY = 4, + WMI_REG_SET_CC_STATUS_FAIL = 5, ++ ++ /* add new setting code above, update in ++ * @enum cc_setting_code as well. ++ * Also handle it in ath11k_wmi_cc_setting_code_to_reg() ++ */ ++}; ++ ++enum cc_setting_code { ++ REG_SET_CC_STATUS_PASS = 0, ++ REG_CURRENT_ALPHA2_NOT_FOUND = 1, ++ REG_INIT_ALPHA2_NOT_FOUND = 2, ++ REG_SET_CC_CHANGE_NOT_ALLOWED = 3, ++ REG_SET_CC_STATUS_NO_MEMORY = 4, ++ REG_SET_CC_STATUS_FAIL = 5, ++ ++ /* add new setting code above, update in ++ * @enum wmi_reg_cc_setting_code as well. ++ */ ++}; ++ ++static inline enum cc_setting_code ++ath11k_wmi_cc_setting_code_to_reg(enum wmi_reg_cc_setting_code status_code) ++{ ++ switch (status_code) { ++ case WMI_REG_SET_CC_STATUS_PASS: ++ return REG_SET_CC_STATUS_PASS; ++ case WMI_REG_CURRENT_ALPHA2_NOT_FOUND: ++ return REG_CURRENT_ALPHA2_NOT_FOUND; ++ case WMI_REG_INIT_ALPHA2_NOT_FOUND: ++ return REG_INIT_ALPHA2_NOT_FOUND; ++ case WMI_REG_SET_CC_CHANGE_NOT_ALLOWED: ++ return REG_SET_CC_CHANGE_NOT_ALLOWED; ++ case WMI_REG_SET_CC_STATUS_NO_MEMORY: ++ return REG_SET_CC_STATUS_NO_MEMORY; ++ case WMI_REG_SET_CC_STATUS_FAIL: ++ return REG_SET_CC_STATUS_FAIL; ++ } ++ ++ return REG_SET_CC_STATUS_FAIL; ++} ++ ++enum wmi_reg_6ghz_ap_type { ++ WMI_REG_INDOOR_AP = 0, ++ WMI_REG_STANDARD_POWER_AP = 1, ++ WMI_REG_VERY_LOW_POWER_AP = 2, ++ ++ WMI_REG_CURRENT_MAX_AP_TYPE, ++ WMI_REG_MAX_AP_TYPE = 7, ++}; ++ ++enum wmi_reg_6ghz_client_type { ++ WMI_REG_DEFAULT_CLIENT = 0, ++ WMI_REG_SUBORDINATE_CLIENT = 1, ++ WMI_REG_MAX_CLIENT_TYPE = 2, + }; + + struct cur_reg_rule { +@@ -4118,6 +4185,8 @@ struct cur_reg_rule { + u8 reg_power; + u8 ant_gain; + u16 flags; ++ bool psd_flag; ++ s8 psd_eirp; + }; + + struct cur_regulatory_info { +@@ -4137,6 +4206,22 @@ struct cur_regulatory_info { + u32 num_5ghz_reg_rules; + struct cur_reg_rule *reg_rules_2ghz_ptr; + struct cur_reg_rule *reg_rules_5ghz_ptr; ++ bool is_ext_reg_event; ++ enum wmi_reg_6ghz_client_type client_type; ++ bool rnr_tpe_usable; ++ bool unspecified_ap_usable; ++ u8 domain_code_6ghz_ap[WMI_REG_CURRENT_MAX_AP_TYPE]; ++ u8 domain_code_6ghz_client[WMI_REG_CURRENT_MAX_AP_TYPE][WMI_REG_MAX_CLIENT_TYPE]; ++ u32 domain_code_6ghz_super_id; ++ u32 min_bw_6ghz_ap[WMI_REG_CURRENT_MAX_AP_TYPE]; ++ u32 max_bw_6ghz_ap[WMI_REG_CURRENT_MAX_AP_TYPE]; ++ u32 min_bw_6ghz_client[WMI_REG_CURRENT_MAX_AP_TYPE][WMI_REG_MAX_CLIENT_TYPE]; ++ u32 max_bw_6ghz_client[WMI_REG_CURRENT_MAX_AP_TYPE][WMI_REG_MAX_CLIENT_TYPE]; ++ u32 num_6ghz_rules_ap[WMI_REG_CURRENT_MAX_AP_TYPE]; ++ u32 num_6ghz_rules_client[WMI_REG_CURRENT_MAX_AP_TYPE][WMI_REG_MAX_CLIENT_TYPE]; ++ struct cur_reg_rule *reg_rules_6ghz_ap_ptr[WMI_REG_CURRENT_MAX_AP_TYPE]; ++ struct cur_reg_rule *reg_rules_6ghz_client_ptr ++ [WMI_REG_CURRENT_MAX_AP_TYPE][WMI_REG_MAX_CLIENT_TYPE]; + }; + + struct wmi_reg_chan_list_cc_event { +@@ -4163,6 +4248,61 @@ struct wmi_regulatory_rule_struct { + u32 flag_info; + }; + ++#define WMI_REG_CLIENT_MAX 4 ++ ++struct wmi_reg_chan_list_cc_ext_event { ++ u32 status_code; ++ u32 phy_id; ++ u32 alpha2; ++ u32 num_phy; ++ u32 country_id; ++ u32 domain_code; ++ u32 dfs_region; ++ u32 phybitmap; ++ u32 min_bw_2ghz; ++ u32 max_bw_2ghz; ++ u32 min_bw_5ghz; ++ u32 max_bw_5ghz; ++ u32 num_2ghz_reg_rules; ++ u32 num_5ghz_reg_rules; ++ u32 client_type; ++ u32 rnr_tpe_usable; ++ u32 unspecified_ap_usable; ++ u32 domain_code_6ghz_ap_lpi; ++ u32 domain_code_6ghz_ap_sp; ++ u32 domain_code_6ghz_ap_vlp; ++ u32 domain_code_6ghz_client_lpi[WMI_REG_CLIENT_MAX]; ++ u32 domain_code_6ghz_client_sp[WMI_REG_CLIENT_MAX]; ++ u32 domain_code_6ghz_client_vlp[WMI_REG_CLIENT_MAX]; ++ u32 domain_code_6ghz_super_id; ++ u32 min_bw_6ghz_ap_sp; ++ u32 max_bw_6ghz_ap_sp; ++ u32 min_bw_6ghz_ap_lpi; ++ u32 max_bw_6ghz_ap_lpi; ++ u32 min_bw_6ghz_ap_vlp; ++ u32 max_bw_6ghz_ap_vlp; ++ u32 min_bw_6ghz_client_sp[WMI_REG_CLIENT_MAX]; ++ u32 max_bw_6ghz_client_sp[WMI_REG_CLIENT_MAX]; ++ u32 min_bw_6ghz_client_lpi[WMI_REG_CLIENT_MAX]; ++ u32 max_bw_6ghz_client_lpi[WMI_REG_CLIENT_MAX]; ++ u32 min_bw_6ghz_client_vlp[WMI_REG_CLIENT_MAX]; ++ u32 max_bw_6ghz_client_vlp[WMI_REG_CLIENT_MAX]; ++ u32 num_6ghz_reg_rules_ap_sp; ++ u32 num_6ghz_reg_rules_ap_lpi; ++ u32 num_6ghz_reg_rules_ap_vlp; ++ u32 num_6ghz_reg_rules_client_sp[WMI_REG_CLIENT_MAX]; ++ u32 num_6ghz_reg_rules_client_lpi[WMI_REG_CLIENT_MAX]; ++ u32 num_6ghz_reg_rules_client_vlp[WMI_REG_CLIENT_MAX]; ++} __packed; ++ ++struct wmi_regulatory_ext_rule { ++ u32 tlv_header; ++ u32 freq_info; ++ u32 bw_pwr_info; ++ u32 flag_info; ++ u32 psd_power_info; ++} __packed; ++ + struct wmi_vdev_delete_resp_event { + u32 vdev_id; + } __packed; +@@ -5358,6 +5498,7 @@ struct target_resource_config { + u32 sched_params; + u32 twt_ap_pdev_count; + u32 twt_ap_sta_count; ++ u8 is_reg_cc_ext_event_supported; + }; + + enum wmi_debug_log_param { diff --git a/package/kernel/mac80211/patches/ath11k/0045-wifi-ath11k-add-debug-prints-in-regulatory-WMI-event.patch b/package/kernel/mac80211/patches/ath11k/0045-wifi-ath11k-add-debug-prints-in-regulatory-WMI-event.patch new file mode 100644 index 000000000..b88e51928 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0045-wifi-ath11k-add-debug-prints-in-regulatory-WMI-event.patch @@ -0,0 +1,567 @@ +From e238e62ba8868a784e485eb94451c87cd1b85cee Mon Sep 17 00:00:00 2001 +From: Aditya Kumar Singh +Date: Wed, 1 Mar 2023 16:20:59 +0200 +Subject: [PATCH] wifi: ath11k: add debug prints in regulatory WMI event + processing + +Add some more debug prints in processing regulatory WMI event in order to +increase more debuggability. + +Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 +Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 +Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.5.0.1-01100-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Aditya Kumar Singh +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20230110121024.14051-4-quic_adisi@quicinc.com +--- + drivers/net/wireless/ath/ath11k/reg.c | 2 +- + drivers/net/wireless/ath/ath11k/wmi.c | 207 ++++++++++++++++++-------- + drivers/net/wireless/ath/ath11k/wmi.h | 142 ++++++++++++++++++ + 3 files changed, 291 insertions(+), 60 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/reg.c ++++ b/drivers/net/wireless/ath/ath11k/reg.c +@@ -646,7 +646,7 @@ ath11k_reg_build_regd(struct ath11k_base + tmp_regd->dfs_region = ath11k_map_fw_dfs_region(reg_info->dfs_region); + + ath11k_dbg(ab, ATH11K_DBG_REG, +- "\r\nCountry %s, CFG Regdomain %s FW Regdomain %d, num_reg_rules %d\n", ++ "Country %s, CFG Regdomain %s FW Regdomain %d, num_reg_rules %d\n", + alpha2, ath11k_reg_get_regdom_str(tmp_regd->dfs_region), + reg_info->dfs_region, num_rules); + /* Update reg_rules[] below. Firmware is expected to +--- a/drivers/net/wireless/ath/ath11k/wmi.c ++++ b/drivers/net/wireless/ath/ath11k/wmi.c +@@ -4925,6 +4925,26 @@ static int ath11k_pull_vdev_start_resp_t + return 0; + } + ++static void ath11k_print_reg_rule(struct ath11k_base *ab, const char *band, ++ u32 num_reg_rules, ++ struct cur_reg_rule *reg_rule_ptr) ++{ ++ struct cur_reg_rule *reg_rule = reg_rule_ptr; ++ u32 count; ++ ++ ath11k_dbg(ab, ATH11K_DBG_WMI, "number of reg rules in %s band: %d\n", ++ band, num_reg_rules); ++ ++ for (count = 0; count < num_reg_rules; count++) { ++ ath11k_dbg(ab, ATH11K_DBG_WMI, ++ "reg rule %d: (%d - %d @ %d) (%d, %d) (FLAGS %d)\n", ++ count + 1, reg_rule->start_freq, reg_rule->end_freq, ++ reg_rule->max_bw, reg_rule->ant_gain, ++ reg_rule->reg_power, reg_rule->flags); ++ reg_rule++; ++ } ++} ++ + static struct cur_reg_rule + *create_reg_rules_from_wmi(u32 num_reg_rules, + struct wmi_regulatory_rule_struct *wmi_reg_rule) +@@ -5006,6 +5026,10 @@ static int ath11k_pull_reg_chan_list_upd + reg_info->ctry_code = chan_list_event_hdr->country_id; + reg_info->reg_dmn_pair = chan_list_event_hdr->domain_code; + ++ ath11k_dbg(ab, ATH11K_DBG_WMI, ++ "status_code %s", ++ ath11k_cc_status_to_str(reg_info->status_code)); ++ + reg_info->status_code = + ath11k_wmi_cc_setting_code_to_reg(chan_list_event_hdr->status_code); + +@@ -5020,13 +5044,13 @@ static int ath11k_pull_reg_chan_list_upd + num_5ghz_reg_rules = reg_info->num_5ghz_reg_rules; + + ath11k_dbg(ab, ATH11K_DBG_WMI, +- "%s:cc %s dsf %d BW: min_2ghz %d max_2ghz %d min_5ghz %d max_5ghz %d", +- __func__, reg_info->alpha2, reg_info->dfs_region, ++ "cc %s dsf %d BW: min_2ghz %d max_2ghz %d min_5ghz %d max_5ghz %d", ++ reg_info->alpha2, reg_info->dfs_region, + reg_info->min_bw_2ghz, reg_info->max_bw_2ghz, + reg_info->min_bw_5ghz, reg_info->max_bw_5ghz); + + ath11k_dbg(ab, ATH11K_DBG_WMI, +- "%s: num_2ghz_reg_rules %d num_5ghz_reg_rules %d", __func__, ++ "num_2ghz_reg_rules %d num_5ghz_reg_rules %d", + num_2ghz_reg_rules, num_5ghz_reg_rules); + + wmi_reg_rule = +@@ -5043,6 +5067,10 @@ static int ath11k_pull_reg_chan_list_upd + ath11k_warn(ab, "Unable to Allocate memory for 2 GHz rules\n"); + return -ENOMEM; + } ++ ++ ath11k_print_reg_rule(ab, "2 GHz", ++ num_2ghz_reg_rules, ++ reg_info->reg_rules_2ghz_ptr); + } + + if (num_5ghz_reg_rules) { +@@ -5055,6 +5083,10 @@ static int ath11k_pull_reg_chan_list_upd + ath11k_warn(ab, "Unable to Allocate memory for 5 GHz rules\n"); + return -ENOMEM; + } ++ ++ ath11k_print_reg_rule(ab, "5 GHz", ++ num_5ghz_reg_rules, ++ reg_info->reg_rules_5ghz_ptr); + } + + ath11k_dbg(ab, ATH11K_DBG_WMI, "processed regulatory channel list\n"); +@@ -5128,7 +5160,7 @@ static int ath11k_pull_reg_chan_list_ext + struct cur_regulatory_info *reg_info) + { + const void **tb; +- const struct wmi_reg_chan_list_cc_ext_event *ext_chan_list_event_hdr; ++ const struct wmi_reg_chan_list_cc_ext_event *ev; + struct wmi_regulatory_ext_rule *ext_wmi_reg_rule; + u32 num_2ghz_reg_rules, num_5ghz_reg_rules; + u32 num_6ghz_reg_rules_ap[WMI_REG_CURRENT_MAX_AP_TYPE]; +@@ -5145,31 +5177,29 @@ static int ath11k_pull_reg_chan_list_ext + return ret; + } + +- ext_chan_list_event_hdr = tb[WMI_TAG_REG_CHAN_LIST_CC_EXT_EVENT]; +- if (!ext_chan_list_event_hdr) { ++ ev = tb[WMI_TAG_REG_CHAN_LIST_CC_EXT_EVENT]; ++ if (!ev) { + ath11k_warn(ab, "failed to fetch reg chan list ext update ev\n"); + kfree(tb); + return -EPROTO; + } + +- reg_info->num_2ghz_reg_rules = +- ext_chan_list_event_hdr->num_2ghz_reg_rules; +- reg_info->num_5ghz_reg_rules = +- ext_chan_list_event_hdr->num_5ghz_reg_rules; ++ reg_info->num_2ghz_reg_rules = ev->num_2ghz_reg_rules; ++ reg_info->num_5ghz_reg_rules = ev->num_5ghz_reg_rules; + reg_info->num_6ghz_rules_ap[WMI_REG_INDOOR_AP] = +- ext_chan_list_event_hdr->num_6ghz_reg_rules_ap_lpi; ++ ev->num_6ghz_reg_rules_ap_lpi; + reg_info->num_6ghz_rules_ap[WMI_REG_STANDARD_POWER_AP] = +- ext_chan_list_event_hdr->num_6ghz_reg_rules_ap_sp; ++ ev->num_6ghz_reg_rules_ap_sp; + reg_info->num_6ghz_rules_ap[WMI_REG_VERY_LOW_POWER_AP] = +- ext_chan_list_event_hdr->num_6ghz_reg_rules_ap_vlp; ++ ev->num_6ghz_reg_rules_ap_vlp; + + for (i = 0; i < WMI_REG_MAX_CLIENT_TYPE; i++) { + reg_info->num_6ghz_rules_client[WMI_REG_INDOOR_AP][i] = +- ext_chan_list_event_hdr->num_6ghz_reg_rules_client_lpi[i]; ++ ev->num_6ghz_reg_rules_client_lpi[i]; + reg_info->num_6ghz_rules_client[WMI_REG_STANDARD_POWER_AP][i] = +- ext_chan_list_event_hdr->num_6ghz_reg_rules_client_sp[i]; ++ ev->num_6ghz_reg_rules_client_sp[i]; + reg_info->num_6ghz_rules_client[WMI_REG_VERY_LOW_POWER_AP][i] = +- ext_chan_list_event_hdr->num_6ghz_reg_rules_client_vlp[i]; ++ ev->num_6ghz_reg_rules_client_vlp[i]; + } + + num_2ghz_reg_rules = reg_info->num_2ghz_reg_rules; +@@ -5231,57 +5261,79 @@ static int ath11k_pull_reg_chan_list_ext + return -EINVAL; + } + +- memcpy(reg_info->alpha2, &ext_chan_list_event_hdr->alpha2, +- REG_ALPHA2_LEN); ++ memcpy(reg_info->alpha2, &ev->alpha2, REG_ALPHA2_LEN); ++ ++ reg_info->dfs_region = ev->dfs_region; ++ reg_info->phybitmap = ev->phybitmap; ++ reg_info->num_phy = ev->num_phy; ++ reg_info->phy_id = ev->phy_id; ++ reg_info->ctry_code = ev->country_id; ++ reg_info->reg_dmn_pair = ev->domain_code; + +- reg_info->dfs_region = ext_chan_list_event_hdr->dfs_region; +- reg_info->phybitmap = ext_chan_list_event_hdr->phybitmap; +- reg_info->num_phy = ext_chan_list_event_hdr->num_phy; +- reg_info->phy_id = ext_chan_list_event_hdr->phy_id; +- reg_info->ctry_code = ext_chan_list_event_hdr->country_id; +- reg_info->reg_dmn_pair = ext_chan_list_event_hdr->domain_code; ++ ath11k_dbg(ab, ATH11K_DBG_WMI, ++ "status_code %s", ++ ath11k_cc_status_to_str(reg_info->status_code)); + + reg_info->status_code = +- ath11k_wmi_cc_setting_code_to_reg(ext_chan_list_event_hdr->status_code); ++ ath11k_wmi_cc_setting_code_to_reg(ev->status_code); + + reg_info->is_ext_reg_event = true; + +- reg_info->min_bw_2ghz = ext_chan_list_event_hdr->min_bw_2ghz; +- reg_info->max_bw_2ghz = ext_chan_list_event_hdr->max_bw_2ghz; +- reg_info->min_bw_5ghz = ext_chan_list_event_hdr->min_bw_5ghz; +- reg_info->max_bw_5ghz = ext_chan_list_event_hdr->max_bw_5ghz; ++ reg_info->min_bw_2ghz = ev->min_bw_2ghz; ++ reg_info->max_bw_2ghz = ev->max_bw_2ghz; ++ reg_info->min_bw_5ghz = ev->min_bw_5ghz; ++ reg_info->max_bw_5ghz = ev->max_bw_5ghz; + + reg_info->min_bw_6ghz_ap[WMI_REG_INDOOR_AP] = +- ext_chan_list_event_hdr->min_bw_6ghz_ap_lpi; ++ ev->min_bw_6ghz_ap_lpi; + reg_info->max_bw_6ghz_ap[WMI_REG_INDOOR_AP] = +- ext_chan_list_event_hdr->max_bw_6ghz_ap_lpi; ++ ev->max_bw_6ghz_ap_lpi; + reg_info->min_bw_6ghz_ap[WMI_REG_STANDARD_POWER_AP] = +- ext_chan_list_event_hdr->min_bw_6ghz_ap_sp; ++ ev->min_bw_6ghz_ap_sp; + reg_info->max_bw_6ghz_ap[WMI_REG_STANDARD_POWER_AP] = +- ext_chan_list_event_hdr->max_bw_6ghz_ap_sp; ++ ev->max_bw_6ghz_ap_sp; + reg_info->min_bw_6ghz_ap[WMI_REG_VERY_LOW_POWER_AP] = +- ext_chan_list_event_hdr->min_bw_6ghz_ap_vlp; ++ ev->min_bw_6ghz_ap_vlp; + reg_info->max_bw_6ghz_ap[WMI_REG_VERY_LOW_POWER_AP] = +- ext_chan_list_event_hdr->max_bw_6ghz_ap_vlp; ++ ev->max_bw_6ghz_ap_vlp; ++ ++ ath11k_dbg(ab, ATH11K_DBG_WMI, ++ "6 GHz AP BW: LPI (%d - %d), SP (%d - %d), VLP (%d - %d)\n", ++ reg_info->min_bw_6ghz_ap[WMI_REG_INDOOR_AP], ++ reg_info->max_bw_6ghz_ap[WMI_REG_INDOOR_AP], ++ reg_info->min_bw_6ghz_ap[WMI_REG_STANDARD_POWER_AP], ++ reg_info->max_bw_6ghz_ap[WMI_REG_STANDARD_POWER_AP], ++ reg_info->min_bw_6ghz_ap[WMI_REG_VERY_LOW_POWER_AP], ++ reg_info->max_bw_6ghz_ap[WMI_REG_VERY_LOW_POWER_AP]); + + for (i = 0; i < WMI_REG_MAX_CLIENT_TYPE; i++) { + reg_info->min_bw_6ghz_client[WMI_REG_INDOOR_AP][i] = +- ext_chan_list_event_hdr->min_bw_6ghz_client_lpi[i]; ++ ev->min_bw_6ghz_client_lpi[i]; + reg_info->max_bw_6ghz_client[WMI_REG_INDOOR_AP][i] = +- ext_chan_list_event_hdr->max_bw_6ghz_client_lpi[i]; ++ ev->max_bw_6ghz_client_lpi[i]; + reg_info->min_bw_6ghz_client[WMI_REG_STANDARD_POWER_AP][i] = +- ext_chan_list_event_hdr->min_bw_6ghz_client_sp[i]; ++ ev->min_bw_6ghz_client_sp[i]; + reg_info->max_bw_6ghz_client[WMI_REG_STANDARD_POWER_AP][i] = +- ext_chan_list_event_hdr->max_bw_6ghz_client_sp[i]; ++ ev->max_bw_6ghz_client_sp[i]; + reg_info->min_bw_6ghz_client[WMI_REG_VERY_LOW_POWER_AP][i] = +- ext_chan_list_event_hdr->min_bw_6ghz_client_vlp[i]; ++ ev->min_bw_6ghz_client_vlp[i]; + reg_info->max_bw_6ghz_client[WMI_REG_VERY_LOW_POWER_AP][i] = +- ext_chan_list_event_hdr->max_bw_6ghz_client_vlp[i]; ++ ev->max_bw_6ghz_client_vlp[i]; ++ ++ ath11k_dbg(ab, ATH11K_DBG_WMI, ++ "6 GHz %s BW: LPI (%d - %d), SP (%d - %d), VLP (%d - %d)\n", ++ ath11k_6ghz_client_type_to_str(i), ++ reg_info->min_bw_6ghz_client[WMI_REG_INDOOR_AP][i], ++ reg_info->max_bw_6ghz_client[WMI_REG_INDOOR_AP][i], ++ reg_info->min_bw_6ghz_client[WMI_REG_STANDARD_POWER_AP][i], ++ reg_info->max_bw_6ghz_client[WMI_REG_STANDARD_POWER_AP][i], ++ reg_info->min_bw_6ghz_client[WMI_REG_VERY_LOW_POWER_AP][i], ++ reg_info->max_bw_6ghz_client[WMI_REG_VERY_LOW_POWER_AP][i]); + } + + ath11k_dbg(ab, ATH11K_DBG_WMI, +- "%s:cc_ext %s dsf %d BW: min_2ghz %d max_2ghz %d min_5ghz %d max_5ghz %d", +- __func__, reg_info->alpha2, reg_info->dfs_region, ++ "cc_ext %s dsf %d BW: min_2ghz %d max_2ghz %d min_5ghz %d max_5ghz %d", ++ reg_info->alpha2, reg_info->dfs_region, + reg_info->min_bw_2ghz, reg_info->max_bw_2ghz, + reg_info->min_bw_5ghz, reg_info->max_bw_5ghz); + +@@ -5310,9 +5362,8 @@ static int ath11k_pull_reg_chan_list_ext + num_6ghz_client[WMI_REG_VERY_LOW_POWER_AP][j]); + + ext_wmi_reg_rule = +- (struct wmi_regulatory_ext_rule *)((u8 *)ext_chan_list_event_hdr +- + sizeof(*ext_chan_list_event_hdr) +- + sizeof(struct wmi_tlv)); ++ (struct wmi_regulatory_ext_rule *)((u8 *)ev + sizeof(*ev) + ++ sizeof(struct wmi_tlv)); + if (num_2ghz_reg_rules) { + reg_info->reg_rules_2ghz_ptr = + create_ext_reg_rules_from_wmi(num_2ghz_reg_rules, +@@ -5323,6 +5374,10 @@ static int ath11k_pull_reg_chan_list_ext + ath11k_warn(ab, "Unable to Allocate memory for 2 GHz rules\n"); + return -ENOMEM; + } ++ ++ ath11k_print_reg_rule(ab, "2 GHz", ++ num_2ghz_reg_rules, ++ reg_info->reg_rules_2ghz_ptr); + } + + ext_wmi_reg_rule += num_2ghz_reg_rules; +@@ -5358,6 +5413,10 @@ static int ath11k_pull_reg_chan_list_ext + ath11k_warn(ab, "Unable to Allocate memory for 5 GHz rules\n"); + return -ENOMEM; + } ++ ++ ath11k_print_reg_rule(ab, "5 GHz", ++ num_5ghz_reg_rules, ++ reg_info->reg_rules_5ghz_ptr); + } + + /* We have adjusted the number of 5 GHz reg rules above. But still those +@@ -5378,10 +5437,17 @@ static int ath11k_pull_reg_chan_list_ext + return -ENOMEM; + } + ++ ath11k_print_reg_rule(ab, ath11k_6ghz_ap_type_to_str(i), ++ num_6ghz_reg_rules_ap[i], ++ reg_info->reg_rules_6ghz_ap_ptr[i]); ++ + ext_wmi_reg_rule += num_6ghz_reg_rules_ap[i]; + } + + for (j = 0; j < WMI_REG_CURRENT_MAX_AP_TYPE; j++) { ++ ath11k_dbg(ab, ATH11K_DBG_WMI, ++ "6 GHz AP type %s", ath11k_6ghz_ap_type_to_str(j)); ++ + for (i = 0; i < WMI_REG_MAX_CLIENT_TYPE; i++) { + reg_info->reg_rules_6ghz_client_ptr[j][i] = + create_ext_reg_rules_from_wmi(num_6ghz_client[j][i], +@@ -5393,35 +5459,58 @@ static int ath11k_pull_reg_chan_list_ext + return -ENOMEM; + } + ++ ath11k_print_reg_rule(ab, ++ ath11k_6ghz_client_type_to_str(i), ++ num_6ghz_client[j][i], ++ reg_info->reg_rules_6ghz_client_ptr[j][i]); ++ + ext_wmi_reg_rule += num_6ghz_client[j][i]; + } + } + +- reg_info->client_type = ext_chan_list_event_hdr->client_type; +- reg_info->rnr_tpe_usable = ext_chan_list_event_hdr->rnr_tpe_usable; ++ reg_info->client_type = ev->client_type; ++ reg_info->rnr_tpe_usable = ev->rnr_tpe_usable; + reg_info->unspecified_ap_usable = +- ext_chan_list_event_hdr->unspecified_ap_usable; ++ ev->unspecified_ap_usable; + reg_info->domain_code_6ghz_ap[WMI_REG_INDOOR_AP] = +- ext_chan_list_event_hdr->domain_code_6ghz_ap_lpi; ++ ev->domain_code_6ghz_ap_lpi; + reg_info->domain_code_6ghz_ap[WMI_REG_STANDARD_POWER_AP] = +- ext_chan_list_event_hdr->domain_code_6ghz_ap_sp; ++ ev->domain_code_6ghz_ap_sp; + reg_info->domain_code_6ghz_ap[WMI_REG_VERY_LOW_POWER_AP] = +- ext_chan_list_event_hdr->domain_code_6ghz_ap_vlp; ++ ev->domain_code_6ghz_ap_vlp; ++ ++ ath11k_dbg(ab, ATH11K_DBG_WMI, ++ "6 GHz reg info client type %s rnr_tpe_usable %d unspecified_ap_usable %d AP sub domain: lpi %s, sp %s, vlp %s\n", ++ ath11k_6ghz_client_type_to_str(reg_info->client_type), ++ reg_info->rnr_tpe_usable, ++ reg_info->unspecified_ap_usable, ++ ath11k_sub_reg_6ghz_to_str(ev->domain_code_6ghz_ap_lpi), ++ ath11k_sub_reg_6ghz_to_str(ev->domain_code_6ghz_ap_sp), ++ ath11k_sub_reg_6ghz_to_str(ev->domain_code_6ghz_ap_vlp)); + + for (i = 0; i < WMI_REG_MAX_CLIENT_TYPE; i++) { + reg_info->domain_code_6ghz_client[WMI_REG_INDOOR_AP][i] = +- ext_chan_list_event_hdr->domain_code_6ghz_client_lpi[i]; ++ ev->domain_code_6ghz_client_lpi[i]; + reg_info->domain_code_6ghz_client[WMI_REG_STANDARD_POWER_AP][i] = +- ext_chan_list_event_hdr->domain_code_6ghz_client_sp[i]; ++ ev->domain_code_6ghz_client_sp[i]; + reg_info->domain_code_6ghz_client[WMI_REG_VERY_LOW_POWER_AP][i] = +- ext_chan_list_event_hdr->domain_code_6ghz_client_vlp[i]; ++ ev->domain_code_6ghz_client_vlp[i]; ++ ++ ath11k_dbg(ab, ATH11K_DBG_WMI, ++ "6 GHz client type %s client sub domain: lpi %s, sp %s, vlp %s\n", ++ ath11k_6ghz_client_type_to_str(i), ++ ath11k_sub_reg_6ghz_to_str(ev->domain_code_6ghz_client_lpi[i]), ++ ath11k_sub_reg_6ghz_to_str(ev->domain_code_6ghz_client_sp[i]), ++ ath11k_sub_reg_6ghz_to_str(ev->domain_code_6ghz_client_vlp[i]) ++ ); + } + +- reg_info->domain_code_6ghz_super_id = +- ext_chan_list_event_hdr->domain_code_6ghz_super_id; ++ reg_info->domain_code_6ghz_super_id = ev->domain_code_6ghz_super_id; + +- ath11k_dbg(ab, ATH11K_DBG_WMI, "6 GHz client_type: %d domain_code_6ghz_super_id: %d", +- reg_info->client_type, reg_info->domain_code_6ghz_super_id); ++ ath11k_dbg(ab, ATH11K_DBG_WMI, ++ "6 GHz client_type %s 6 GHz super domain %s", ++ ath11k_6ghz_client_type_to_str(reg_info->client_type), ++ ath11k_super_reg_6ghz_to_str(reg_info->domain_code_6ghz_super_id)); + + ath11k_dbg(ab, ATH11K_DBG_WMI, "processed regulatory ext channel list\n"); + +--- a/drivers/net/wireless/ath/ath11k/wmi.h ++++ b/drivers/net/wireless/ath/ath11k/wmi.h +@@ -4139,6 +4139,7 @@ enum cc_setting_code { + + /* add new setting code above, update in + * @enum wmi_reg_cc_setting_code as well. ++ * Also handle it in ath11k_cc_status_to_str() + */ + }; + +@@ -4163,21 +4164,162 @@ ath11k_wmi_cc_setting_code_to_reg(enum w + return REG_SET_CC_STATUS_FAIL; + } + ++static inline const char *ath11k_cc_status_to_str(enum cc_setting_code code) ++{ ++ switch (code) { ++ case REG_SET_CC_STATUS_PASS: ++ return "REG_SET_CC_STATUS_PASS"; ++ case REG_CURRENT_ALPHA2_NOT_FOUND: ++ return "REG_CURRENT_ALPHA2_NOT_FOUND"; ++ case REG_INIT_ALPHA2_NOT_FOUND: ++ return "REG_INIT_ALPHA2_NOT_FOUND"; ++ case REG_SET_CC_CHANGE_NOT_ALLOWED: ++ return "REG_SET_CC_CHANGE_NOT_ALLOWED"; ++ case REG_SET_CC_STATUS_NO_MEMORY: ++ return "REG_SET_CC_STATUS_NO_MEMORY"; ++ case REG_SET_CC_STATUS_FAIL: ++ return "REG_SET_CC_STATUS_FAIL"; ++ } ++ ++ return "Unknown CC status"; ++} ++ + enum wmi_reg_6ghz_ap_type { + WMI_REG_INDOOR_AP = 0, + WMI_REG_STANDARD_POWER_AP = 1, + WMI_REG_VERY_LOW_POWER_AP = 2, + ++ /* add AP type above, handle in ath11k_6ghz_ap_type_to_str() ++ */ + WMI_REG_CURRENT_MAX_AP_TYPE, + WMI_REG_MAX_AP_TYPE = 7, + }; + ++static inline const char * ++ath11k_6ghz_ap_type_to_str(enum wmi_reg_6ghz_ap_type type) ++{ ++ switch (type) { ++ case WMI_REG_INDOOR_AP: ++ return "INDOOR AP"; ++ case WMI_REG_STANDARD_POWER_AP: ++ return "STANDARD POWER AP"; ++ case WMI_REG_VERY_LOW_POWER_AP: ++ return "VERY LOW POWER AP"; ++ case WMI_REG_CURRENT_MAX_AP_TYPE: ++ return "CURRENT_MAX_AP_TYPE"; ++ case WMI_REG_MAX_AP_TYPE: ++ return "MAX_AP_TYPE"; ++ } ++ ++ return "unknown 6 GHz AP type"; ++} ++ + enum wmi_reg_6ghz_client_type { + WMI_REG_DEFAULT_CLIENT = 0, + WMI_REG_SUBORDINATE_CLIENT = 1, + WMI_REG_MAX_CLIENT_TYPE = 2, ++ ++ /* add client type above, handle it in ++ * ath11k_6ghz_client_type_to_str() ++ */ ++}; ++ ++static inline const char * ++ath11k_6ghz_client_type_to_str(enum wmi_reg_6ghz_client_type type) ++{ ++ switch (type) { ++ case WMI_REG_DEFAULT_CLIENT: ++ return "DEFAULT CLIENT"; ++ case WMI_REG_SUBORDINATE_CLIENT: ++ return "SUBORDINATE CLIENT"; ++ case WMI_REG_MAX_CLIENT_TYPE: ++ return "MAX_CLIENT_TYPE"; ++ } ++ ++ return "unknown 6 GHz client type"; ++} ++ ++enum reg_subdomains_6ghz { ++ EMPTY_6GHZ = 0x0, ++ FCC1_CLIENT_LPI_REGULAR_6GHZ = 0x01, ++ FCC1_CLIENT_SP_6GHZ = 0x02, ++ FCC1_AP_LPI_6GHZ = 0x03, ++ FCC1_CLIENT_LPI_SUBORDINATE = FCC1_AP_LPI_6GHZ, ++ FCC1_AP_SP_6GHZ = 0x04, ++ ETSI1_LPI_6GHZ = 0x10, ++ ETSI1_VLP_6GHZ = 0x11, ++ ETSI2_LPI_6GHZ = 0x12, ++ ETSI2_VLP_6GHZ = 0x13, ++ APL1_LPI_6GHZ = 0x20, ++ APL1_VLP_6GHZ = 0x21, ++ ++ /* add sub-domain above, handle it in ++ * ath11k_sub_reg_6ghz_to_str() ++ */ ++}; ++ ++static inline const char * ++ath11k_sub_reg_6ghz_to_str(enum reg_subdomains_6ghz sub_id) ++{ ++ switch (sub_id) { ++ case EMPTY_6GHZ: ++ return "N/A"; ++ case FCC1_CLIENT_LPI_REGULAR_6GHZ: ++ return "FCC1_CLIENT_LPI_REGULAR_6GHZ"; ++ case FCC1_CLIENT_SP_6GHZ: ++ return "FCC1_CLIENT_SP_6GHZ"; ++ case FCC1_AP_LPI_6GHZ: ++ return "FCC1_AP_LPI_6GHZ/FCC1_CLIENT_LPI_SUBORDINATE"; ++ case FCC1_AP_SP_6GHZ: ++ return "FCC1_AP_SP_6GHZ"; ++ case ETSI1_LPI_6GHZ: ++ return "ETSI1_LPI_6GHZ"; ++ case ETSI1_VLP_6GHZ: ++ return "ETSI1_VLP_6GHZ"; ++ case ETSI2_LPI_6GHZ: ++ return "ETSI2_LPI_6GHZ"; ++ case ETSI2_VLP_6GHZ: ++ return "ETSI2_VLP_6GHZ"; ++ case APL1_LPI_6GHZ: ++ return "APL1_LPI_6GHZ"; ++ case APL1_VLP_6GHZ: ++ return "APL1_VLP_6GHZ"; ++ } ++ ++ return "unknown sub reg id"; ++} ++ ++enum reg_super_domain_6ghz { ++ FCC1_6GHZ = 0x01, ++ ETSI1_6GHZ = 0x02, ++ ETSI2_6GHZ = 0x03, ++ APL1_6GHZ = 0x04, ++ FCC1_6GHZ_CL = 0x05, ++ ++ /* add super domain above, handle it in ++ * ath11k_super_reg_6ghz_to_str() ++ */ + }; + ++static inline const char * ++ath11k_super_reg_6ghz_to_str(enum reg_super_domain_6ghz domain_id) ++{ ++ switch (domain_id) { ++ case FCC1_6GHZ: ++ return "FCC1_6GHZ"; ++ case ETSI1_6GHZ: ++ return "ETSI1_6GHZ"; ++ case ETSI2_6GHZ: ++ return "ETSI2_6GHZ"; ++ case APL1_6GHZ: ++ return "APL1_6GHZ"; ++ case FCC1_6GHZ_CL: ++ return "FCC1_6GHZ_CL"; ++ } ++ ++ return "unknown domain id"; ++} ++ + struct cur_reg_rule { + u16 start_freq; + u16 end_freq; diff --git a/package/kernel/mac80211/patches/ath11k/0046-wifi-ath11k-Replace-fake-flex-array-with-flexible-ar.patch b/package/kernel/mac80211/patches/ath11k/0046-wifi-ath11k-Replace-fake-flex-array-with-flexible-ar.patch new file mode 100644 index 000000000..bd1617856 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0046-wifi-ath11k-Replace-fake-flex-array-with-flexible-ar.patch @@ -0,0 +1,246 @@ +From 3b1088a09ec9438523c251d8435e78988824bc0d Mon Sep 17 00:00:00 2001 +From: "Gustavo A. R. Silva" +Date: Tue, 7 Mar 2023 16:22:39 -0600 +Subject: [PATCH] wifi: ath11k: Replace fake flex-array with flexible-array + member +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Zero-length arrays as fake flexible arrays are deprecated and we are +moving towards adopting C99 flexible-array members instead. + +Address 25 of the following warnings found with GCC-13 and +-fstrict-flex-arrays=3 enabled: +drivers/net/wireless/ath/ath11k/debugfs_htt_stats.c:30:51: warning: array subscript is outside array bounds of ‘const u32[0]’ {aka ‘const unsigned int[]’} [-Warray-bounds=] + +This helps with the ongoing efforts to tighten the FORTIFY_SOURCE +routines on memcpy() and help us make progress towards globally +enabling -fstrict-flex-arrays=3 [1]. + +Link: https://github.com/KSPP/linux/issues/21 +Link: https://github.com/KSPP/linux/issues/266 +Link: https://gcc.gnu.org/pipermail/gcc-patches/2022-October/602902.html [1] +Signed-off-by: Gustavo A. R. Silva +Reviewed-by: Simon Horman +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/ZAe5L5DtmsQxzqRH@work +--- + .../wireless/ath/ath11k/debugfs_htt_stats.h | 73 +++++++++++-------- + 1 file changed, 43 insertions(+), 30 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/debugfs_htt_stats.h ++++ b/drivers/net/wireless/ath/ath11k/debugfs_htt_stats.h +@@ -143,7 +143,8 @@ enum htt_tx_pdev_underrun_enum { + /* Bytes stored in little endian order */ + /* Length should be multiple of DWORD */ + struct htt_stats_string_tlv { +- u32 data[0]; /* Can be variable length */ ++ /* Can be variable length */ ++ DECLARE_FLEX_ARRAY(u32, data); + } __packed; + + #define HTT_STATS_MAC_ID GENMASK(7, 0) +@@ -205,27 +206,32 @@ struct htt_tx_pdev_stats_cmn_tlv { + + /* NOTE: Variable length TLV, use length spec to infer array size */ + struct htt_tx_pdev_stats_urrn_tlv_v { +- u32 urrn_stats[0]; /* HTT_TX_PDEV_MAX_URRN_STATS */ ++ /* HTT_TX_PDEV_MAX_URRN_STATS */ ++ DECLARE_FLEX_ARRAY(u32, urrn_stats); + }; + + /* NOTE: Variable length TLV, use length spec to infer array size */ + struct htt_tx_pdev_stats_flush_tlv_v { +- u32 flush_errs[0]; /* HTT_TX_PDEV_MAX_FLUSH_REASON_STATS */ ++ /* HTT_TX_PDEV_MAX_FLUSH_REASON_STATS */ ++ DECLARE_FLEX_ARRAY(u32, flush_errs); + }; + + /* NOTE: Variable length TLV, use length spec to infer array size */ + struct htt_tx_pdev_stats_sifs_tlv_v { +- u32 sifs_status[0]; /* HTT_TX_PDEV_MAX_SIFS_BURST_STATS */ ++ /* HTT_TX_PDEV_MAX_SIFS_BURST_STATS */ ++ DECLARE_FLEX_ARRAY(u32, sifs_status); + }; + + /* NOTE: Variable length TLV, use length spec to infer array size */ + struct htt_tx_pdev_stats_phy_err_tlv_v { +- u32 phy_errs[0]; /* HTT_TX_PDEV_MAX_PHY_ERR_STATS */ ++ /* HTT_TX_PDEV_MAX_PHY_ERR_STATS */ ++ DECLARE_FLEX_ARRAY(u32, phy_errs); + }; + + /* NOTE: Variable length TLV, use length spec to infer array size */ + struct htt_tx_pdev_stats_sifs_hist_tlv_v { +- u32 sifs_hist_status[0]; /* HTT_TX_PDEV_SIFS_BURST_HIST_STATS */ ++ /* HTT_TX_PDEV_SIFS_BURST_HIST_STATS */ ++ DECLARE_FLEX_ARRAY(u32, sifs_hist_status); + }; + + struct htt_tx_pdev_stats_tx_ppdu_stats_tlv_v { +@@ -590,20 +596,20 @@ struct htt_tx_hwq_difs_latency_stats_tlv + + /* NOTE: Variable length TLV, use length spec to infer array size */ + struct htt_tx_hwq_cmd_result_stats_tlv_v { +- /* Histogram of sched cmd result */ +- u32 cmd_result[0]; /* HTT_TX_HWQ_MAX_CMD_RESULT_STATS */ ++ /* Histogram of sched cmd result, HTT_TX_HWQ_MAX_CMD_RESULT_STATS */ ++ DECLARE_FLEX_ARRAY(u32, cmd_result); + }; + + /* NOTE: Variable length TLV, use length spec to infer array size */ + struct htt_tx_hwq_cmd_stall_stats_tlv_v { +- /* Histogram of various pause conitions */ +- u32 cmd_stall_status[0]; /* HTT_TX_HWQ_MAX_CMD_STALL_STATS */ ++ /* Histogram of various pause conitions, HTT_TX_HWQ_MAX_CMD_STALL_STATS */ ++ DECLARE_FLEX_ARRAY(u32, cmd_stall_status); + }; + + /* NOTE: Variable length TLV, use length spec to infer array size */ + struct htt_tx_hwq_fes_result_stats_tlv_v { +- /* Histogram of number of user fes result */ +- u32 fes_result[0]; /* HTT_TX_HWQ_MAX_FES_RESULT_STATS */ ++ /* Histogram of number of user fes result, HTT_TX_HWQ_MAX_FES_RESULT_STATS */ ++ DECLARE_FLEX_ARRAY(u32, fes_result); + }; + + /* NOTE: Variable length TLV, use length spec to infer array size +@@ -635,8 +641,8 @@ struct htt_tx_hwq_tried_mpdu_cnt_hist_tl + * #define WAL_TXOP_USED_HISTOGRAM_INTERVAL 1000 ( 1 ms ) + */ + struct htt_tx_hwq_txop_used_cnt_hist_tlv_v { +- /* Histogram of txop used cnt */ +- u32 txop_used_cnt_hist[0]; /* HTT_TX_HWQ_TXOP_USED_CNT_HIST */ ++ /* Histogram of txop used cnt, HTT_TX_HWQ_TXOP_USED_CNT_HIST */ ++ DECLARE_FLEX_ARRAY(u32, txop_used_cnt_hist); + }; + + /* == TX SELFGEN STATS == */ +@@ -804,17 +810,20 @@ struct htt_tx_pdev_mpdu_stats_tlv { + /* == TX SCHED STATS == */ + /* NOTE: Variable length TLV, use length spec to infer array size */ + struct htt_sched_txq_cmd_posted_tlv_v { +- u32 sched_cmd_posted[0]; /* HTT_TX_PDEV_SCHED_TX_MODE_MAX */ ++ /* HTT_TX_PDEV_SCHED_TX_MODE_MAX */ ++ DECLARE_FLEX_ARRAY(u32, sched_cmd_posted); + }; + + /* NOTE: Variable length TLV, use length spec to infer array size */ + struct htt_sched_txq_cmd_reaped_tlv_v { +- u32 sched_cmd_reaped[0]; /* HTT_TX_PDEV_SCHED_TX_MODE_MAX */ ++ /* HTT_TX_PDEV_SCHED_TX_MODE_MAX */ ++ DECLARE_FLEX_ARRAY(u32, sched_cmd_reaped); + }; + + /* NOTE: Variable length TLV, use length spec to infer array size */ + struct htt_sched_txq_sched_order_su_tlv_v { +- u32 sched_order_su[0]; /* HTT_TX_PDEV_NUM_SCHED_ORDER_LOG */ ++ /* HTT_TX_PDEV_NUM_SCHED_ORDER_LOG */ ++ DECLARE_FLEX_ARRAY(u32, sched_order_su); + }; + + enum htt_sched_txq_sched_ineligibility_tlv_enum { +@@ -842,7 +851,7 @@ enum htt_sched_txq_sched_ineligibility_t + /* NOTE: Variable length TLV, use length spec to infer array size */ + struct htt_sched_txq_sched_ineligibility_tlv_v { + /* indexed by htt_sched_txq_sched_ineligibility_tlv_enum */ +- u32 sched_ineligibility[0]; ++ DECLARE_FLEX_ARRAY(u32, sched_ineligibility); + }; + + #define HTT_TX_PDEV_STATS_SCHED_PER_TXQ_MAC_ID GENMASK(7, 0) +@@ -888,18 +897,20 @@ struct htt_stats_tx_sched_cmn_tlv { + + /* NOTE: Variable length TLV, use length spec to infer array size */ + struct htt_tx_tqm_gen_mpdu_stats_tlv_v { +- u32 gen_mpdu_end_reason[0]; /* HTT_TX_TQM_MAX_GEN_MPDU_END_REASON */ ++ /* HTT_TX_TQM_MAX_GEN_MPDU_END_REASON */ ++ DECLARE_FLEX_ARRAY(u32, gen_mpdu_end_reason); + }; + + /* NOTE: Variable length TLV, use length spec to infer array size */ + struct htt_tx_tqm_list_mpdu_stats_tlv_v { +- u32 list_mpdu_end_reason[0]; /* HTT_TX_TQM_MAX_LIST_MPDU_END_REASON */ ++ /* HTT_TX_TQM_MAX_LIST_MPDU_END_REASON */ ++ DECLARE_FLEX_ARRAY(u32, list_mpdu_end_reason); + }; + + /* NOTE: Variable length TLV, use length spec to infer array size */ + struct htt_tx_tqm_list_mpdu_cnt_tlv_v { +- u32 list_mpdu_cnt_hist[0]; +- /* HTT_TX_TQM_MAX_LIST_MPDU_CNT_HISTOGRAM_BINS */ ++ /* HTT_TX_TQM_MAX_LIST_MPDU_CNT_HISTOGRAM_BINS */ ++ DECLARE_FLEX_ARRAY(u32, list_mpdu_cnt_hist); + }; + + struct htt_tx_tqm_pdev_stats_tlv_v { +@@ -1098,7 +1109,7 @@ struct htt_tx_de_compl_stats_tlv { + * ENTRIES_PER_BIN_COUNT) + */ + struct htt_tx_de_fw2wbm_ring_full_hist_tlv { +- u32 fw2wbm_ring_full_hist[0]; ++ DECLARE_FLEX_ARRAY(u32, fw2wbm_ring_full_hist); + }; + + struct htt_tx_de_cmn_stats_tlv { +@@ -1151,7 +1162,7 @@ struct htt_ring_if_cmn_tlv { + /* NOTE: Variable length TLV, use length spec to infer array size */ + struct htt_sfm_client_user_tlv_v { + /* Number of DWORDS used per user and per client */ +- u32 dwords_used_by_user_n[0]; ++ DECLARE_FLEX_ARRAY(u32, dwords_used_by_user_n); + }; + + struct htt_sfm_client_tlv { +@@ -1436,12 +1447,14 @@ struct htt_rx_soc_fw_stats_tlv { + + /* NOTE: Variable length TLV, use length spec to infer array size */ + struct htt_rx_soc_fw_refill_ring_empty_tlv_v { +- u32 refill_ring_empty_cnt[0]; /* HTT_RX_STATS_REFILL_MAX_RING */ ++ /* HTT_RX_STATS_REFILL_MAX_RING */ ++ DECLARE_FLEX_ARRAY(u32, refill_ring_empty_cnt); + }; + + /* NOTE: Variable length TLV, use length spec to infer array size */ + struct htt_rx_soc_fw_refill_ring_num_refill_tlv_v { +- u32 refill_ring_num_refill[0]; /* HTT_RX_STATS_REFILL_MAX_RING */ ++ /* HTT_RX_STATS_REFILL_MAX_RING */ ++ DECLARE_FLEX_ARRAY(u32, refill_ring_num_refill); + }; + + /* RXDMA error code from WBM released packets */ +@@ -1473,7 +1486,7 @@ enum htt_rx_rxdma_error_code_enum { + + /* NOTE: Variable length TLV, use length spec to infer array size */ + struct htt_rx_soc_fw_refill_ring_num_rxdma_err_tlv_v { +- u32 rxdma_err[0]; /* HTT_RX_RXDMA_MAX_ERR_CODE */ ++ DECLARE_FLEX_ARRAY(u32, rxdma_err); /* HTT_RX_RXDMA_MAX_ERR_CODE */ + }; + + /* REO error code from WBM released packets */ +@@ -1505,7 +1518,7 @@ enum htt_rx_reo_error_code_enum { + + /* NOTE: Variable length TLV, use length spec to infer array size */ + struct htt_rx_soc_fw_refill_ring_num_reo_err_tlv_v { +- u32 reo_err[0]; /* HTT_RX_REO_MAX_ERR_CODE */ ++ DECLARE_FLEX_ARRAY(u32, reo_err); /* HTT_RX_REO_MAX_ERR_CODE */ + }; + + /* == RX PDEV STATS == */ +@@ -1622,13 +1635,13 @@ struct htt_rx_pdev_fw_stats_phy_err_tlv + /* NOTE: Variable length TLV, use length spec to infer array size */ + struct htt_rx_pdev_fw_ring_mpdu_err_tlv_v { + /* Num error MPDU for each RxDMA error type */ +- u32 fw_ring_mpdu_err[0]; /* HTT_RX_STATS_RXDMA_MAX_ERR */ ++ DECLARE_FLEX_ARRAY(u32, fw_ring_mpdu_err); /* HTT_RX_STATS_RXDMA_MAX_ERR */ + }; + + /* NOTE: Variable length TLV, use length spec to infer array size */ + struct htt_rx_pdev_fw_mpdu_drop_tlv_v { + /* Num MPDU dropped */ +- u32 fw_mpdu_drop[0]; /* HTT_RX_STATS_FW_DROP_REASON_MAX */ ++ DECLARE_FLEX_ARRAY(u32, fw_mpdu_drop); /* HTT_RX_STATS_FW_DROP_REASON_MAX */ + }; + + #define HTT_PDEV_CCA_STATS_TX_FRAME_INFO_PRESENT (0x1) diff --git a/package/kernel/mac80211/patches/ath11k/0047-wifi-ath11k-fix-deinitialization-of-firmware-resourc.patch b/package/kernel/mac80211/patches/ath11k/0047-wifi-ath11k-fix-deinitialization-of-firmware-resourc.patch new file mode 100644 index 000000000..eec11f50e --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0047-wifi-ath11k-fix-deinitialization-of-firmware-resourc.patch @@ -0,0 +1,79 @@ +From 5a78ac33e3cb8822da64dd1af196e83664b332b0 Mon Sep 17 00:00:00 2001 +From: Aditya Kumar Singh +Date: Thu, 9 Mar 2023 15:23:08 +0530 +Subject: [PATCH] wifi: ath11k: fix deinitialization of firmware resources + +Currently, in ath11k_ahb_fw_resources_init(), iommu domain +mapping is done only for the chipsets having fixed firmware +memory. Also, for such chipsets, mapping is done only if it +does not have TrustZone support. + +During deinitialization, only if TrustZone support is not there, +iommu is unmapped back. However, for non fixed firmware memory +chipsets, TrustZone support is not there and this makes the +condition check to true and it tries to unmap the memory which +was not mapped during initialization. + +This leads to the following trace - + +[ 83.198790] Unable to handle kernel NULL pointer dereference at virtual address 0000000000000008 +[ 83.259537] Modules linked in: ath11k_ahb ath11k qmi_helpers +.. snip .. +[ 83.280286] pstate: 20000005 (nzCv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--) +[ 83.287228] pc : __iommu_unmap+0x30/0x140 +[ 83.293907] lr : iommu_unmap+0x5c/0xa4 +[ 83.298072] sp : ffff80000b3abad0 +.. snip .. +[ 83.369175] Call trace: +[ 83.376282] __iommu_unmap+0x30/0x140 +[ 83.378541] iommu_unmap+0x5c/0xa4 +[ 83.382360] ath11k_ahb_fw_resource_deinit.part.12+0x2c/0xac [ath11k_ahb] +[ 83.385666] ath11k_ahb_free_resources+0x140/0x17c [ath11k_ahb] +[ 83.392521] ath11k_ahb_shutdown+0x34/0x40 [ath11k_ahb] +[ 83.398248] platform_shutdown+0x20/0x2c +[ 83.403455] device_shutdown+0x16c/0x1c4 +[ 83.407621] kernel_restart_prepare+0x34/0x3c +[ 83.411529] kernel_restart+0x14/0x74 +[ 83.415781] __do_sys_reboot+0x1c4/0x22c +[ 83.419427] __arm64_sys_reboot+0x1c/0x24 +[ 83.423420] invoke_syscall+0x44/0xfc +[ 83.427326] el0_svc_common.constprop.3+0xac/0xe8 +[ 83.430974] do_el0_svc+0xa0/0xa8 +[ 83.435659] el0_svc+0x1c/0x44 +[ 83.438957] el0t_64_sync_handler+0x60/0x144 +[ 83.441910] el0t_64_sync+0x15c/0x160 +[ 83.446343] Code: aa0103f4 f9400001 f90027a1 d2800001 (f94006a0) +[ 83.449903] ---[ end trace 0000000000000000 ]--- + +This can be reproduced by probing an AHB chipset which is not +having a fixed memory region. During reboot (or rmmod) trace +can be seen. + +Fix this issue by adding a condition check on firmware fixed memory +hw_param as done in the counter initialization function. + +Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 + +Fixes: f9eec4947add ("ath11k: Add support for targets without trustzone") +Signed-off-by: Aditya Kumar Singh +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20230309095308.24937-1-quic_adisi@quicinc.com +--- + drivers/net/wireless/ath/ath11k/ahb.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/drivers/net/wireless/ath/ath11k/ahb.c ++++ b/drivers/net/wireless/ath/ath11k/ahb.c +@@ -1078,6 +1078,12 @@ static int ath11k_ahb_fw_resource_deinit + struct iommu_domain *iommu; + size_t unmapped_size; + ++ /* Chipsets not requiring MSA would have not initialized ++ * MSA resources, return success in such cases. ++ */ ++ if (!ab->hw_params.fixed_fw_mem) ++ return 0; ++ + if (ab_ahb->fw.use_tz) + return 0; + diff --git a/package/kernel/mac80211/patches/ath11k/0048-wifi-ath11k-fix-BUFFER_DONE-read-on-monitor-ring-rx-.patch b/package/kernel/mac80211/patches/ath11k/0048-wifi-ath11k-fix-BUFFER_DONE-read-on-monitor-ring-rx-.patch new file mode 100644 index 000000000..3e2264533 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0048-wifi-ath11k-fix-BUFFER_DONE-read-on-monitor-ring-rx-.patch @@ -0,0 +1,130 @@ +From 68e93ac5a31d4975b25f819b2dfe914c72abc3bb Mon Sep 17 00:00:00 2001 +From: Harshitha Prem +Date: Wed, 15 Mar 2023 12:24:43 +0200 +Subject: [PATCH] wifi: ath11k: fix BUFFER_DONE read on monitor ring rx buffer + +Perform dma_sync_single_for_cpu() on monitor ring rx buffer before +reading BUFFER_DONE tag and do dma_unmap_single() only after device +had set BUFFER_DONE tag to the buffer. + +Also when BUFFER_DONE tag is not set, allow the buffer to get read +next time without freeing skb. + +This helps to fix AP+Monitor VAP with flood traffic scenario to see +monitor ring rx buffer overrun missing BUFFER_DONE tag to be set. + +Also remove redundant rx dma buf free performed on DP +rx_mon_status_refill_ring. + +Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Sathishkumar Muruganandam +Signed-off-by: Harshitha Prem +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20230309164434.32660-1-quic_hprem@quicinc.com +--- + drivers/net/wireless/ath/ath11k/dp_rx.c | 57 ++++++++++--------------- + 1 file changed, 23 insertions(+), 34 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath11k/dp_rx.c +@@ -435,7 +435,6 @@ fail_free_skb: + static int ath11k_dp_rxdma_buf_ring_free(struct ath11k *ar, + struct dp_rxdma_ring *rx_ring) + { +- struct ath11k_pdev_dp *dp = &ar->dp; + struct sk_buff *skb; + int buf_id; + +@@ -453,28 +452,6 @@ static int ath11k_dp_rxdma_buf_ring_free + idr_destroy(&rx_ring->bufs_idr); + spin_unlock_bh(&rx_ring->idr_lock); + +- /* if rxdma1_enable is false, mon_status_refill_ring +- * isn't setup, so don't clean. +- */ +- if (!ar->ab->hw_params.rxdma1_enable) +- return 0; +- +- rx_ring = &dp->rx_mon_status_refill_ring[0]; +- +- spin_lock_bh(&rx_ring->idr_lock); +- idr_for_each_entry(&rx_ring->bufs_idr, skb, buf_id) { +- idr_remove(&rx_ring->bufs_idr, buf_id); +- /* XXX: Understand where internal driver does this dma_unmap +- * of rxdma_buffer. +- */ +- dma_unmap_single(ar->ab->dev, ATH11K_SKB_RXCB(skb)->paddr, +- skb->len + skb_tailroom(skb), DMA_BIDIRECTIONAL); +- dev_kfree_skb_any(skb); +- } +- +- idr_destroy(&rx_ring->bufs_idr); +- spin_unlock_bh(&rx_ring->idr_lock); +- + return 0; + } + +@@ -3029,39 +3006,51 @@ static int ath11k_dp_rx_reap_mon_status_ + + spin_lock_bh(&rx_ring->idr_lock); + skb = idr_find(&rx_ring->bufs_idr, buf_id); ++ spin_unlock_bh(&rx_ring->idr_lock); ++ + if (!skb) { + ath11k_warn(ab, "rx monitor status with invalid buf_id %d\n", + buf_id); +- spin_unlock_bh(&rx_ring->idr_lock); + pmon->buf_state = DP_MON_STATUS_REPLINISH; + goto move_next; + } + +- idr_remove(&rx_ring->bufs_idr, buf_id); +- spin_unlock_bh(&rx_ring->idr_lock); +- + rxcb = ATH11K_SKB_RXCB(skb); + +- dma_unmap_single(ab->dev, rxcb->paddr, +- skb->len + skb_tailroom(skb), +- DMA_FROM_DEVICE); ++ dma_sync_single_for_cpu(ab->dev, rxcb->paddr, ++ skb->len + skb_tailroom(skb), ++ DMA_FROM_DEVICE); + + tlv = (struct hal_tlv_hdr *)skb->data; + if (FIELD_GET(HAL_TLV_HDR_TAG, tlv->tl) != + HAL_RX_STATUS_BUFFER_DONE) { +- ath11k_warn(ab, "mon status DONE not set %lx\n", ++ ath11k_warn(ab, "mon status DONE not set %lx, buf_id %d\n", + FIELD_GET(HAL_TLV_HDR_TAG, +- tlv->tl)); +- dev_kfree_skb_any(skb); ++ tlv->tl), buf_id); ++ /* If done status is missing, hold onto status ++ * ring until status is done for this status ++ * ring buffer. ++ * Keep HP in mon_status_ring unchanged, ++ * and break from here. ++ * Check status for same buffer for next time ++ */ + pmon->buf_state = DP_MON_STATUS_NO_DMA; +- goto move_next; ++ break; + } + ++ spin_lock_bh(&rx_ring->idr_lock); ++ idr_remove(&rx_ring->bufs_idr, buf_id); ++ spin_unlock_bh(&rx_ring->idr_lock); + if (ab->hw_params.full_monitor_mode) { + ath11k_dp_rx_mon_update_status_buf_state(pmon, tlv); + if (paddr == pmon->mon_status_paddr) + pmon->buf_state = DP_MON_STATUS_MATCH; + } ++ ++ dma_unmap_single(ab->dev, rxcb->paddr, ++ skb->len + skb_tailroom(skb), ++ DMA_FROM_DEVICE); ++ + __skb_queue_tail(skb_list, skb); + } else { + pmon->buf_state = DP_MON_STATUS_REPLINISH; diff --git a/package/kernel/mac80211/patches/ath11k/0049-wifi-ath11k-Optimize-6-GHz-scan-time.patch b/package/kernel/mac80211/patches/ath11k/0049-wifi-ath11k-Optimize-6-GHz-scan-time.patch new file mode 100644 index 000000000..f468990fe --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0049-wifi-ath11k-Optimize-6-GHz-scan-time.patch @@ -0,0 +1,101 @@ +From 8b4d2f080afbd4280ecca0f4b3ceea943a7a86d0 Mon Sep 17 00:00:00 2001 +From: Manikanta Pubbisetty +Date: Thu, 23 Mar 2023 11:39:13 +0530 +Subject: [PATCH] wifi: ath11k: Optimize 6 GHz scan time + +Currently, time taken to scan all supported channels on WCN6750 +is ~8 seconds and connection time is almost 10 seconds. WCN6750 +supports three Wi-Fi bands (i.e., 2.4/5/6 GHz) and the numbers of +channels for scan come around ~100 channels (default case). +Since the chip doesn't have support for DBS (Dual Band Simultaneous), +scans cannot be parallelized resulting in longer scan times. + +Among the 100 odd channels, ~60 channels are in 6 GHz band. Therefore, +optimizing the scan for 6 GHz channels will bring down the overall +scan time. + +WCN6750 firmware has support to scan a 6 GHz channel based on co-located +AP information i.e., RNR IE which is found in the legacy 2.4/5 GHz scan +results. When a scan request with all supported channel list is enqueued +to the firmware, then based on WMI_SCAN_CHAN_FLAG_SCAN_ONLY_IF_RNR_FOUND +scan channel flag, firmware will scan only those 6 GHz channels for which +RNR IEs are found in the legacy scan results. + +In the proposed design, based on NL80211_SCAN_FLAG_COLOCATED_6GHZ scan +flag, driver will set the WMI_SCAN_CHAN_FLAG_SCAN_ONLY_IF_RNR_FOUND flag +for non-PSC channels. Since there is high probability to find 6 GHz APs +on PSC channels, these channels are always scanned. Only non-PSC channels +are selectively scanned based on cached RNR information from the legacy +scan results. + +If NL80211_SCAN_FLAG_COLOCATED_6GHZ is not set in the scan flags, +then scan will happen on all supported channels (default behavior). + +With these optimizations, scan time is improved by 1.5-1.8 seconds on +WCN6750. Similar savings have been observed on WCN6855. + +Tested-on: WCN6750 hw1.0 AHB WLAN.MSL.1.0.1-00887-QCAMSLSWPLZ-1 +Tested-on: WCN6855 hw2.1 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3.6510.16 + +Signed-off-by: Manikanta Pubbisetty +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20230323060913.10097-1-quic_mpubbise@quicinc.com +--- + drivers/net/wireless/ath/ath11k/mac.c | 25 +++++++++++++++++++++++-- + drivers/net/wireless/ath/ath11k/wmi.h | 4 ++++ + 2 files changed, 27 insertions(+), 2 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -3819,8 +3819,29 @@ static int ath11k_mac_op_hw_scan(struct + goto exit; + } + +- for (i = 0; i < arg->num_chan; i++) +- arg->chan_list[i] = req->channels[i]->center_freq; ++ for (i = 0; i < arg->num_chan; i++) { ++ if (test_bit(WMI_TLV_SERVICE_SCAN_CONFIG_PER_CHANNEL, ++ ar->ab->wmi_ab.svc_map)) { ++ arg->chan_list[i] = ++ u32_encode_bits(req->channels[i]->center_freq, ++ WMI_SCAN_CONFIG_PER_CHANNEL_MASK); ++ ++ /* If NL80211_SCAN_FLAG_COLOCATED_6GHZ is set in scan ++ * flags, then scan all PSC channels in 6 GHz band and ++ * those non-PSC channels where RNR IE is found during ++ * the legacy 2.4/5 GHz scan. ++ * If NL80211_SCAN_FLAG_COLOCATED_6GHZ is not set, ++ * then all channels in 6 GHz will be scanned. ++ */ ++ if (req->channels[i]->band == NL80211_BAND_6GHZ && ++ req->flags & NL80211_SCAN_FLAG_COLOCATED_6GHZ && ++ !cfg80211_channel_is_psc(req->channels[i])) ++ arg->chan_list[i] |= ++ WMI_SCAN_CH_FLAG_SCAN_ONLY_IF_RNR_FOUND; ++ } else { ++ arg->chan_list[i] = req->channels[i]->center_freq; ++ } ++ } + } + + if (req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) { +--- a/drivers/net/wireless/ath/ath11k/wmi.h ++++ b/drivers/net/wireless/ath/ath11k/wmi.h +@@ -2100,6 +2100,7 @@ enum wmi_tlv_service { + + /* The second 128 bits */ + WMI_MAX_EXT_SERVICE = 256, ++ WMI_TLV_SERVICE_SCAN_CONFIG_PER_CHANNEL = 265, + WMI_TLV_SERVICE_REG_CC_EXT_EVENT_SUPPORT = 281, + WMI_TLV_SERVICE_BIOS_SAR_SUPPORT = 326, + +@@ -3249,6 +3250,9 @@ struct wmi_start_scan_cmd { + #define WMI_SCAN_DWELL_MODE_SHIFT 21 + #define WMI_SCAN_FLAG_EXT_PASSIVE_SCAN_START_TIME_ENHANCE 0x00000800 + ++#define WMI_SCAN_CONFIG_PER_CHANNEL_MASK GENMASK(19, 0) ++#define WMI_SCAN_CH_FLAG_SCAN_ONLY_IF_RNR_FOUND BIT(20) ++ + enum { + WMI_SCAN_DWELL_MODE_DEFAULT = 0, + WMI_SCAN_DWELL_MODE_CONSERVATIVE = 1, diff --git a/package/kernel/mac80211/patches/ath11k/0050-wifi-ath11k-Configure-the-FTM-responder-role-using-f.patch b/package/kernel/mac80211/patches/ath11k/0050-wifi-ath11k-Configure-the-FTM-responder-role-using-f.patch new file mode 100644 index 000000000..bca08b177 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0050-wifi-ath11k-Configure-the-FTM-responder-role-using-f.patch @@ -0,0 +1,117 @@ +From 813968c24126cc5c8320cd5db0e262069a535063 Mon Sep 17 00:00:00 2001 +From: Ganesh Babu Jothiram +Date: Fri, 24 Mar 2023 16:57:00 +0200 +Subject: [PATCH] wifi: ath11k: Configure the FTM responder role using firmware + capability flag + +Fine Time Measurement(FTM) is offloaded feature to firmware. +Hence, the configuration of FTM responder role is done using +firmware capability flag instead of hw param. + +Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Ganesh Babu Jothiram +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20230317072034.8217-1-quic_gjothira@quicinc.com +--- + drivers/net/wireless/ath/ath11k/core.c | 8 -------- + drivers/net/wireless/ath/ath11k/hw.h | 1 - + drivers/net/wireless/ath/ath11k/mac.c | 4 ++-- + 3 files changed, 2 insertions(+), 11 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/core.c ++++ b/drivers/net/wireless/ath/ath11k/core.c +@@ -116,7 +116,6 @@ static const struct ath11k_hw_params ath + .tcl_ring_retry = true, + .tx_ring_size = DP_TCL_DATA_RING_SIZE, + .smp2p_wow_exit = false, +- .ftm_responder = true, + }, + { + .hw_rev = ATH11K_HW_IPQ6018_HW10, +@@ -199,7 +198,6 @@ static const struct ath11k_hw_params ath + .tx_ring_size = DP_TCL_DATA_RING_SIZE, + .smp2p_wow_exit = false, + .support_fw_mac_sequence = false, +- .ftm_responder = true, + }, + { + .name = "qca6390 hw2.0", +@@ -284,7 +282,6 @@ static const struct ath11k_hw_params ath + .tx_ring_size = DP_TCL_DATA_RING_SIZE, + .smp2p_wow_exit = false, + .support_fw_mac_sequence = true, +- .ftm_responder = false, + }, + { + .name = "qcn9074 hw1.0", +@@ -366,7 +363,6 @@ static const struct ath11k_hw_params ath + .tx_ring_size = DP_TCL_DATA_RING_SIZE, + .smp2p_wow_exit = false, + .support_fw_mac_sequence = false, +- .ftm_responder = true, + }, + { + .name = "wcn6855 hw2.0", +@@ -451,7 +447,6 @@ static const struct ath11k_hw_params ath + .tx_ring_size = DP_TCL_DATA_RING_SIZE, + .smp2p_wow_exit = false, + .support_fw_mac_sequence = true, +- .ftm_responder = false, + }, + { + .name = "wcn6855 hw2.1", +@@ -534,7 +529,6 @@ static const struct ath11k_hw_params ath + .tx_ring_size = DP_TCL_DATA_RING_SIZE, + .smp2p_wow_exit = false, + .support_fw_mac_sequence = true, +- .ftm_responder = false, + }, + { + .name = "wcn6750 hw1.0", +@@ -615,7 +609,6 @@ static const struct ath11k_hw_params ath + .tx_ring_size = DP_TCL_DATA_RING_SIZE_WCN6750, + .smp2p_wow_exit = true, + .support_fw_mac_sequence = true, +- .ftm_responder = false, + }, + { + .hw_rev = ATH11K_HW_IPQ5018_HW10, +@@ -695,7 +688,6 @@ static const struct ath11k_hw_params ath + .tx_ring_size = DP_TCL_DATA_RING_SIZE, + .smp2p_wow_exit = false, + .support_fw_mac_sequence = false, +- .ftm_responder = true, + }, + }; + +--- a/drivers/net/wireless/ath/ath11k/hw.h ++++ b/drivers/net/wireless/ath/ath11k/hw.h +@@ -224,7 +224,6 @@ struct ath11k_hw_params { + u32 tx_ring_size; + bool smp2p_wow_exit; + bool support_fw_mac_sequence; +- bool ftm_responder; + }; + + struct ath11k_hw_ops { +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -3538,7 +3538,7 @@ static void ath11k_mac_op_bss_info_chang + + if (changed & BSS_CHANGED_FTM_RESPONDER && + arvif->ftm_responder != info->ftm_responder && +- ar->ab->hw_params.ftm_responder && ++ test_bit(WMI_TLV_SERVICE_RTT, ar->ab->wmi_ab.svc_map) && + (vif->type == NL80211_IFTYPE_AP || + vif->type == NL80211_IFTYPE_MESH_POINT)) { + arvif->ftm_responder = info->ftm_responder; +@@ -9234,7 +9234,7 @@ static int __ath11k_mac_register(struct + wiphy_ext_feature_set(ar->hw->wiphy, + NL80211_EXT_FEATURE_SET_SCAN_DWELL); + +- if (ab->hw_params.ftm_responder) ++ if (test_bit(WMI_TLV_SERVICE_RTT, ar->ab->wmi_ab.svc_map)) + wiphy_ext_feature_set(ar->hw->wiphy, + NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER); + diff --git a/package/kernel/mac80211/patches/ath11k/0051-wifi-ath11k-fix-rssi-station-dump-not-updated-in-QCN.patch b/package/kernel/mac80211/patches/ath11k/0051-wifi-ath11k-fix-rssi-station-dump-not-updated-in-QCN.patch new file mode 100644 index 000000000..835dece1f --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0051-wifi-ath11k-fix-rssi-station-dump-not-updated-in-QCN.patch @@ -0,0 +1,158 @@ +From 031ffa6c2cd305a57ccc6d610f2decd956b2e7f6 Mon Sep 17 00:00:00 2001 +From: P Praneesh +Date: Fri, 24 Mar 2023 16:57:00 +0200 +Subject: [PATCH] wifi: ath11k: fix rssi station dump not updated in QCN9074 + +In QCN9074, station dump signal values display default value which +is -95 dbm, since there is firmware header change for HAL_RX_MPDU_START +between QCN9074 and IPQ8074 which cause wrong peer_id fetch from msdu. +Fix this by updating hal_rx_mpdu_info with corresponding QCN9074 tlv +format. + +Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 +Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.4.0.1-01695-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: P Praneesh +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20230320110312.20639-1-quic_ppranees@quicinc.com +--- + drivers/net/wireless/ath/ath11k/hal_rx.c | 10 ++++++++- + drivers/net/wireless/ath/ath11k/hal_rx.h | 18 +++++++++++++++- + drivers/net/wireless/ath/ath11k/hw.c | 27 ++++++++++++++++-------- + drivers/net/wireless/ath/ath11k/hw.h | 2 +- + 4 files changed, 45 insertions(+), 12 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/hal_rx.c ++++ b/drivers/net/wireless/ath/ath11k/hal_rx.c +@@ -865,6 +865,12 @@ ath11k_hal_rx_populate_mu_user_info(void + ath11k_hal_rx_populate_byte_count(rx_tlv, ppdu_info, rx_user_status); + } + ++static u16 ath11k_hal_rx_mpduinfo_get_peerid(struct ath11k_base *ab, ++ struct hal_rx_mpdu_info *mpdu_info) ++{ ++ return ab->hw_params.hw_ops->mpdu_info_get_peerid(mpdu_info); ++} ++ + static enum hal_rx_mon_status + ath11k_hal_rx_parse_mon_status_tlv(struct ath11k_base *ab, + struct hal_rx_mon_ppdu_info *ppdu_info, +@@ -1459,9 +1465,11 @@ ath11k_hal_rx_parse_mon_status_tlv(struc + break; + } + case HAL_RX_MPDU_START: { ++ struct hal_rx_mpdu_info *mpdu_info = ++ (struct hal_rx_mpdu_info *)tlv_data; + u16 peer_id; + +- peer_id = ab->hw_params.hw_ops->mpdu_info_get_peerid(tlv_data); ++ peer_id = ath11k_hal_rx_mpduinfo_get_peerid(ab, mpdu_info); + if (peer_id) + ppdu_info->peer_id = peer_id; + break; +--- a/drivers/net/wireless/ath/ath11k/hal_rx.h ++++ b/drivers/net/wireless/ath/ath11k/hal_rx.h +@@ -405,7 +405,7 @@ struct hal_rx_phyrx_rssi_legacy_info { + #define HAL_RX_MPDU_INFO_INFO0_PEERID_WCN6855 GENMASK(15, 0) + #define HAL_RX_MPDU_INFO_INFO1_MPDU_LEN GENMASK(13, 0) + +-struct hal_rx_mpdu_info { ++struct hal_rx_mpdu_info_ipq8074 { + __le32 rsvd0; + __le32 info0; + __le32 rsvd1[11]; +@@ -413,12 +413,28 @@ struct hal_rx_mpdu_info { + __le32 rsvd2[9]; + } __packed; + ++struct hal_rx_mpdu_info_qcn9074 { ++ __le32 rsvd0[10]; ++ __le32 info0; ++ __le32 rsvd1[2]; ++ __le32 info1; ++ __le32 rsvd2[9]; ++} __packed; ++ + struct hal_rx_mpdu_info_wcn6855 { + __le32 rsvd0[8]; + __le32 info0; + __le32 rsvd1[14]; + } __packed; + ++struct hal_rx_mpdu_info { ++ union { ++ struct hal_rx_mpdu_info_ipq8074 ipq8074; ++ struct hal_rx_mpdu_info_qcn9074 qcn9074; ++ struct hal_rx_mpdu_info_wcn6855 wcn6855; ++ } u; ++} __packed; ++ + #define HAL_RX_PPDU_END_DURATION GENMASK(23, 0) + struct hal_rx_ppdu_end_duration { + __le32 rsvd0[9]; +--- a/drivers/net/wireless/ath/ath11k/hw.c ++++ b/drivers/net/wireless/ath/ath11k/hw.c +@@ -835,26 +835,35 @@ static void ath11k_hw_ipq5018_reo_setup( + ring_hash_map); + } + +-static u16 ath11k_hw_ipq8074_mpdu_info_get_peerid(u8 *tlv_data) ++static u16 ++ath11k_hw_ipq8074_mpdu_info_get_peerid(struct hal_rx_mpdu_info *mpdu_info) + { + u16 peer_id = 0; +- struct hal_rx_mpdu_info *mpdu_info = +- (struct hal_rx_mpdu_info *)tlv_data; + + peer_id = FIELD_GET(HAL_RX_MPDU_INFO_INFO0_PEERID, +- __le32_to_cpu(mpdu_info->info0)); ++ __le32_to_cpu(mpdu_info->u.ipq8074.info0)); + + return peer_id; + } + +-static u16 ath11k_hw_wcn6855_mpdu_info_get_peerid(u8 *tlv_data) ++static u16 ++ath11k_hw_qcn9074_mpdu_info_get_peerid(struct hal_rx_mpdu_info *mpdu_info) ++{ ++ u16 peer_id = 0; ++ ++ peer_id = FIELD_GET(HAL_RX_MPDU_INFO_INFO0_PEERID, ++ __le32_to_cpu(mpdu_info->u.qcn9074.info0)); ++ ++ return peer_id; ++} ++ ++static u16 ++ath11k_hw_wcn6855_mpdu_info_get_peerid(struct hal_rx_mpdu_info *mpdu_info) + { + u16 peer_id = 0; +- struct hal_rx_mpdu_info_wcn6855 *mpdu_info = +- (struct hal_rx_mpdu_info_wcn6855 *)tlv_data; + + peer_id = FIELD_GET(HAL_RX_MPDU_INFO_INFO0_PEERID_WCN6855, +- __le32_to_cpu(mpdu_info->info0)); ++ __le32_to_cpu(mpdu_info->u.wcn6855.info0)); + return peer_id; + } + +@@ -1042,7 +1051,7 @@ const struct ath11k_hw_ops qcn9074_ops = + .rx_desc_get_attention = ath11k_hw_qcn9074_rx_desc_get_attention, + .rx_desc_get_msdu_payload = ath11k_hw_qcn9074_rx_desc_get_msdu_payload, + .reo_setup = ath11k_hw_ipq8074_reo_setup, +- .mpdu_info_get_peerid = ath11k_hw_ipq8074_mpdu_info_get_peerid, ++ .mpdu_info_get_peerid = ath11k_hw_qcn9074_mpdu_info_get_peerid, + .rx_desc_mac_addr2_valid = ath11k_hw_ipq9074_rx_desc_mac_addr2_valid, + .rx_desc_mpdu_start_addr2 = ath11k_hw_ipq9074_rx_desc_mpdu_start_addr2, + .get_ring_selector = ath11k_hw_ipq8074_get_tcl_ring_selector, +--- a/drivers/net/wireless/ath/ath11k/hw.h ++++ b/drivers/net/wireless/ath/ath11k/hw.h +@@ -263,7 +263,7 @@ struct ath11k_hw_ops { + struct rx_attention *(*rx_desc_get_attention)(struct hal_rx_desc *desc); + u8 *(*rx_desc_get_msdu_payload)(struct hal_rx_desc *desc); + void (*reo_setup)(struct ath11k_base *ab); +- u16 (*mpdu_info_get_peerid)(u8 *tlv_data); ++ u16 (*mpdu_info_get_peerid)(struct hal_rx_mpdu_info *mpdu_info); + bool (*rx_desc_mac_addr2_valid)(struct hal_rx_desc *desc); + u8* (*rx_desc_mpdu_start_addr2)(struct hal_rx_desc *desc); + u32 (*get_ring_selector)(struct sk_buff *skb); diff --git a/package/kernel/mac80211/patches/ath11k/0052-wifi-ath11k-Fix-invalid-management-rx-frame-length-i.patch b/package/kernel/mac80211/patches/ath11k/0052-wifi-ath11k-Fix-invalid-management-rx-frame-length-i.patch new file mode 100644 index 000000000..0c1637fb0 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0052-wifi-ath11k-Fix-invalid-management-rx-frame-length-i.patch @@ -0,0 +1,115 @@ +From 447b0398a9cd41ca343dfd43e555af92d6214487 Mon Sep 17 00:00:00 2001 +From: Bhagavathi Perumal S +Date: Fri, 24 Mar 2023 16:57:00 +0200 +Subject: [PATCH] wifi: ath11k: Fix invalid management rx frame length issue + +The WMI management rx event has multiple arrays of TLVs, however the common +WMI TLV parser won't handle multiple TLV tags of same type. +So the multiple array tags of WMI management rx TLV is parsed incorrectly +and the length calculated becomes wrong when the target sends multiple +array tags. + +Add separate TLV parser to handle multiple arrays for WMI management rx +TLV. This fixes invalid length issue when the target sends multiple array +tags. + +Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Bhagavathi Perumal S +Co-developed-by: Nagarajan Maran +Signed-off-by: Nagarajan Maran +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20230320133840.30162-1-quic_nmaran@quicinc.com +--- + drivers/net/wireless/ath/ath11k/wmi.c | 45 +++++++++++++++++++++------ + 1 file changed, 35 insertions(+), 10 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/wmi.c ++++ b/drivers/net/wireless/ath/ath11k/wmi.c +@@ -82,6 +82,12 @@ struct wmi_tlv_fw_stats_parse { + bool chain_rssi_done; + }; + ++struct wmi_tlv_mgmt_rx_parse { ++ const struct wmi_mgmt_rx_hdr *fixed; ++ const u8 *frame_buf; ++ bool frame_buf_done; ++}; ++ + static const struct wmi_tlv_policy wmi_tlv_policies[] = { + [WMI_TAG_ARRAY_BYTE] + = { .min_len = 0 }, +@@ -5633,28 +5639,49 @@ static int ath11k_pull_vdev_stopped_para + return 0; + } + ++static int ath11k_wmi_tlv_mgmt_rx_parse(struct ath11k_base *ab, ++ u16 tag, u16 len, ++ const void *ptr, void *data) ++{ ++ struct wmi_tlv_mgmt_rx_parse *parse = data; ++ ++ switch (tag) { ++ case WMI_TAG_MGMT_RX_HDR: ++ parse->fixed = ptr; ++ break; ++ case WMI_TAG_ARRAY_BYTE: ++ if (!parse->frame_buf_done) { ++ parse->frame_buf = ptr; ++ parse->frame_buf_done = true; ++ } ++ break; ++ } ++ return 0; ++} ++ + static int ath11k_pull_mgmt_rx_params_tlv(struct ath11k_base *ab, + struct sk_buff *skb, + struct mgmt_rx_event_params *hdr) + { +- const void **tb; ++ struct wmi_tlv_mgmt_rx_parse parse = { }; + const struct wmi_mgmt_rx_hdr *ev; + const u8 *frame; + int ret; + +- tb = ath11k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC); +- if (IS_ERR(tb)) { +- ret = PTR_ERR(tb); +- ath11k_warn(ab, "failed to parse tlv: %d\n", ret); ++ ret = ath11k_wmi_tlv_iter(ab, skb->data, skb->len, ++ ath11k_wmi_tlv_mgmt_rx_parse, ++ &parse); ++ if (ret) { ++ ath11k_warn(ab, "failed to parse mgmt rx tlv %d\n", ++ ret); + return ret; + } + +- ev = tb[WMI_TAG_MGMT_RX_HDR]; +- frame = tb[WMI_TAG_ARRAY_BYTE]; ++ ev = parse.fixed; ++ frame = parse.frame_buf; + + if (!ev || !frame) { + ath11k_warn(ab, "failed to fetch mgmt rx hdr"); +- kfree(tb); + return -EPROTO; + } + +@@ -5673,7 +5700,6 @@ static int ath11k_pull_mgmt_rx_params_tl + + if (skb->len < (frame - skb->data) + hdr->buf_len) { + ath11k_warn(ab, "invalid length in mgmt rx hdr ev"); +- kfree(tb); + return -EPROTO; + } + +@@ -5685,7 +5711,6 @@ static int ath11k_pull_mgmt_rx_params_tl + + ath11k_ce_byte_swap(skb->data, hdr->buf_len); + +- kfree(tb); + return 0; + } + diff --git a/package/kernel/mac80211/patches/ath11k/0053-wifi-ath11k-fix-writing-to-unintended-memory-region.patch b/package/kernel/mac80211/patches/ath11k/0053-wifi-ath11k-fix-writing-to-unintended-memory-region.patch new file mode 100644 index 000000000..7b8a7d454 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0053-wifi-ath11k-fix-writing-to-unintended-memory-region.patch @@ -0,0 +1,43 @@ +From 756a7f90878f0866fd2fe167ef37e90b47326b96 Mon Sep 17 00:00:00 2001 +From: P Praneesh +Date: Fri, 24 Mar 2023 16:57:01 +0200 +Subject: [PATCH] wifi: ath11k: fix writing to unintended memory region + +While initializing spectral, the magic value is getting written to the +invalid memory address leading to random boot-up crash. This occurs +due to the incorrect index increment in ath11k_dbring_fill_magic_value +function. Fix it by replacing the existing logic with memset32 to ensure +there is no invalid memory access. + +Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.4.0.1-01838-QCAHKSWPL_SILICONZ-1 + +Fixes: d3d358efc553 ("ath11k: add spectral/CFR buffer validation support") +Signed-off-by: P Praneesh +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20230321052900.16895-1-quic_ppranees@quicinc.com +--- + drivers/net/wireless/ath/ath11k/dbring.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/dbring.c ++++ b/drivers/net/wireless/ath/ath11k/dbring.c +@@ -26,13 +26,13 @@ int ath11k_dbring_validate_buffer(struct + static void ath11k_dbring_fill_magic_value(struct ath11k *ar, + void *buffer, u32 size) + { +- u32 *temp; +- int idx; ++ /* memset32 function fills buffer payload with the ATH11K_DB_MAGIC_VALUE ++ * and the variable size is expected to be the number of u32 values ++ * to be stored, not the number of bytes. ++ */ ++ size = size / sizeof(u32); + +- size = size >> 2; +- +- for (idx = 0, temp = buffer; idx < size; idx++, temp++) +- *temp++ = ATH11K_DB_MAGIC_VALUE; ++ memset32(buffer, ATH11K_DB_MAGIC_VALUE, size); + } + + static int ath11k_dbring_bufs_replenish(struct ath11k *ar, diff --git a/package/kernel/mac80211/patches/ath11k/0054-wifi-ath11k-Send-11d-scan-start-before-WMI_START_SCA.patch b/package/kernel/mac80211/patches/ath11k/0054-wifi-ath11k-Send-11d-scan-start-before-WMI_START_SCA.patch new file mode 100644 index 000000000..0f8e63759 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0054-wifi-ath11k-Send-11d-scan-start-before-WMI_START_SCA.patch @@ -0,0 +1,61 @@ +From e89a51aedf380bc60219dc9afa96c36507060fb3 Mon Sep 17 00:00:00 2001 +From: Manikanta Pubbisetty +Date: Wed, 15 Mar 2023 21:48:17 +0530 +Subject: [PATCH] wifi: ath11k: Send 11d scan start before WMI_START_SCAN_CMDID + +Firmwares advertising the support of triggering 11d algorithm on the +scan results of a regular scan expects driver to send +WMI_11D_SCAN_START_CMDID before sending WMI_START_SCAN_CMDID. +Triggering 11d algorithm on the scan results of a normal scan helps +in completely avoiding a separate 11d scan for determining regdomain. +This indirectly helps in speeding up connections on station +interfaces on the chipsets supporting 11D scan. + +To enable this feature, send WMI_11D_SCAN_START_CMDID just before +sending WMI_START_SCAN_CMDID if the firmware advertises +WMI_TLV_SERVICE_SUPPORT_11D_FOR_HOST_SCAN service flag. + +WCN6750 & WCN6855 supports this feature. + +Tested-on: WCN6750 hw1.0 AHB WLAN.MSL.1.0.1-01160-QCAMSLSWPLZ-1 +Tested-on: WCN6855 hw2.1 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3.6510.23 + +Signed-off-by: Manikanta Pubbisetty +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20230315161817.29627-1-quic_mpubbise@quicinc.com +--- + drivers/net/wireless/ath/ath11k/mac.c | 12 ++++++++++++ + drivers/net/wireless/ath/ath11k/wmi.h | 1 + + 2 files changed, 13 insertions(+) + +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -3755,6 +3755,18 @@ static int ath11k_mac_op_hw_scan(struct + int i; + u32 scan_timeout; + ++ /* Firmwares advertising the support of triggering 11D algorithm ++ * on the scan results of a regular scan expects driver to send ++ * WMI_11D_SCAN_START_CMDID before sending WMI_START_SCAN_CMDID. ++ * With this feature, separate 11D scan can be avoided since ++ * regdomain can be determined with the scan results of the ++ * regular scan. ++ */ ++ if (ar->state_11d == ATH11K_11D_PREPARING && ++ test_bit(WMI_TLV_SERVICE_SUPPORT_11D_FOR_HOST_SCAN, ++ ar->ab->wmi_ab.svc_map)) ++ ath11k_mac_11d_scan_start(ar, arvif->vdev_id); ++ + mutex_lock(&ar->conf_mutex); + + spin_lock_bh(&ar->data_lock); +--- a/drivers/net/wireless/ath/ath11k/wmi.h ++++ b/drivers/net/wireless/ath/ath11k/wmi.h +@@ -2103,6 +2103,7 @@ enum wmi_tlv_service { + WMI_TLV_SERVICE_SCAN_CONFIG_PER_CHANNEL = 265, + WMI_TLV_SERVICE_REG_CC_EXT_EVENT_SUPPORT = 281, + WMI_TLV_SERVICE_BIOS_SAR_SUPPORT = 326, ++ WMI_TLV_SERVICE_SUPPORT_11D_FOR_HOST_SCAN = 357, + + /* The third 128 bits */ + WMI_MAX_EXT2_SERVICE = 384 diff --git a/package/kernel/mac80211/patches/ath11k/0055-wifi-ath11k-Remove-redundant-pci_clear_master.patch b/package/kernel/mac80211/patches/ath11k/0055-wifi-ath11k-Remove-redundant-pci_clear_master.patch new file mode 100644 index 000000000..0439727e7 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0055-wifi-ath11k-Remove-redundant-pci_clear_master.patch @@ -0,0 +1,58 @@ +From f812e2a9f85d6bea78957ccb5197e4491316848b Mon Sep 17 00:00:00 2001 +From: Cai Huoqing +Date: Thu, 23 Mar 2023 19:26:09 +0800 +Subject: [PATCH] wifi: ath11k: Remove redundant pci_clear_master + +Remove pci_clear_master to simplify the code, +the bus-mastering is also cleared in do_pci_disable_device, +like this: +./drivers/pci/pci.c:2197 +static void do_pci_disable_device(struct pci_dev *dev) +{ + u16 pci_command; + + pci_read_config_word(dev, PCI_COMMAND, &pci_command); + if (pci_command & PCI_COMMAND_MASTER) { + pci_command &= ~PCI_COMMAND_MASTER; + pci_write_config_word(dev, PCI_COMMAND, pci_command); + } + + pcibios_disable_device(dev); +}. +And dev->is_busmaster is set to 0 in pci_disable_device. + +Signed-off-by: Cai Huoqing +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20230323112613.7550-1-cai.huoqing@linux.dev +--- + drivers/net/wireless/ath/ath11k/pci.c | 5 +---- + 1 file changed, 1 insertion(+), 4 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/pci.c ++++ b/drivers/net/wireless/ath/ath11k/pci.c +@@ -540,7 +540,7 @@ static int ath11k_pci_claim(struct ath11 + if (!ab->mem) { + ath11k_err(ab, "failed to map pci bar %d\n", ATH11K_PCI_BAR_NUM); + ret = -EIO; +- goto clear_master; ++ goto release_region; + } + + ab->mem_ce = ab->mem; +@@ -548,8 +548,6 @@ static int ath11k_pci_claim(struct ath11 + ath11k_dbg(ab, ATH11K_DBG_BOOT, "boot pci_mem 0x%pK\n", ab->mem); + return 0; + +-clear_master: +- pci_clear_master(pdev); + release_region: + pci_release_region(pdev, ATH11K_PCI_BAR_NUM); + disable_device: +@@ -565,7 +563,6 @@ static void ath11k_pci_free_region(struc + + pci_iounmap(pci_dev, ab->mem); + ab->mem = NULL; +- pci_clear_master(pci_dev); + pci_release_region(pci_dev, ATH11K_PCI_BAR_NUM); + if (pci_is_enabled(pci_dev)) + pci_disable_device(pci_dev); diff --git a/package/kernel/mac80211/patches/ath11k/0056-wifi-ath11k-Disable-Spectral-scan-upon-removing-inte.patch b/package/kernel/mac80211/patches/ath11k/0056-wifi-ath11k-Disable-Spectral-scan-upon-removing-inte.patch new file mode 100644 index 000000000..44532a4d7 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0056-wifi-ath11k-Disable-Spectral-scan-upon-removing-inte.patch @@ -0,0 +1,36 @@ +From 5c690db63b45c6c4c4932b13173af71df369dba5 Mon Sep 17 00:00:00 2001 +From: Tamizh Chelvam Raja +Date: Tue, 28 Mar 2023 12:41:50 +0530 +Subject: [PATCH] wifi: ath11k: Disable Spectral scan upon removing interface + +Host might receive spectral events during interface +down sequence and this might create below errors. + +failed to handle dma buf release event -22 +failed to handle dma buf release event -22 + +Fix this by disabling spectral config during remove interface. + +Tested-on: IPQ5018 hw1.0 AHB WLAN.HK.2.6.0.1-00861-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Tamizh Chelvam Raja +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20230328071150.29645-1-quic_tamizhr@quicinc.com +--- + drivers/net/wireless/ath/ath11k/mac.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -6685,6 +6685,11 @@ static void ath11k_mac_op_remove_interfa + ath11k_dbg(ab, ATH11K_DBG_MAC, "mac remove interface (vdev %d)\n", + arvif->vdev_id); + ++ ret = ath11k_spectral_vif_stop(arvif); ++ if (ret) ++ ath11k_warn(ab, "failed to stop spectral for vdev %i: %d\n", ++ arvif->vdev_id, ret); ++ + if (arvif->vdev_type == WMI_VDEV_TYPE_STA) + ath11k_mac_11d_scan_stop(ar); + diff --git a/package/kernel/mac80211/patches/ath11k/0057-wifi-ath11k-enable-SAR-support-on-WCN6750.patch b/package/kernel/mac80211/patches/ath11k/0057-wifi-ath11k-enable-SAR-support-on-WCN6750.patch new file mode 100644 index 000000000..5e64e552c --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0057-wifi-ath11k-enable-SAR-support-on-WCN6750.patch @@ -0,0 +1,29 @@ +From abf57d84973ce1abcb67504ac0df8aea1fe09a76 Mon Sep 17 00:00:00 2001 +From: Youghandhar Chintala +Date: Tue, 28 Mar 2023 17:04:55 +0530 +Subject: [PATCH] wifi: ath11k: enable SAR support on WCN6750 + +Currently, SAR is enabled only on WCN6855, enable this for WCN6750 too. This +functionality gets triggered, when the user space application calls +NL80211_CMD_SET_SAR_SPECS. + +Tested-on: WCN6750 hw1.0 AHB WLAN.MSL.1.0.1-00887-QCAMSLSWPLZ-1 + +Signed-off-by: Youghandhar Chintala +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20230328113455.11252-1-quic_youghand@quicinc.com +--- + drivers/net/wireless/ath/ath11k/core.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/wireless/ath/ath11k/core.c ++++ b/drivers/net/wireless/ath/ath11k/core.c +@@ -593,7 +593,7 @@ static const struct ath11k_hw_params ath + .current_cc_support = true, + .dbr_debug_support = false, + .global_reset = false, +- .bios_sar_capa = NULL, ++ .bios_sar_capa = &ath11k_hw_sar_capa_wcn6855, + .m3_fw_support = false, + .fixed_bdf_addr = false, + .fixed_mem_region = false, diff --git a/package/kernel/mac80211/patches/ath11k/0058-wifi-ath11k-pci-Add-more-MODULE_FIRMWARE-entries.patch b/package/kernel/mac80211/patches/ath11k/0058-wifi-ath11k-pci-Add-more-MODULE_FIRMWARE-entries.patch new file mode 100644 index 000000000..585864eff --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0058-wifi-ath11k-pci-Add-more-MODULE_FIRMWARE-entries.patch @@ -0,0 +1,36 @@ +From 06c58473969239e00d76b683edd511952060ca56 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Thu, 30 Mar 2023 16:37:18 +0200 +Subject: [PATCH] wifi: ath11k: pci: Add more MODULE_FIRMWARE() entries + +As there are a few more models supported by the driver, let's add the +missing MODULE_FIRMWARE() entries for them. The lack of them resulted +in the missing device enablement on some systems, such as the +installation image of openSUSE. + +While we are at it, use the wildcard instead of listing each firmware +files individually for each. + +Signed-off-by: Takashi Iwai +Reviewed-by: Simon Horman +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20230330143718.19511-1-tiwai@suse.de +--- + drivers/net/wireless/ath/ath11k/pci.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/pci.c ++++ b/drivers/net/wireless/ath/ath11k/pci.c +@@ -1036,7 +1036,8 @@ module_exit(ath11k_pci_exit); + MODULE_DESCRIPTION("Driver support for Qualcomm Technologies 802.11ax WLAN PCIe devices"); + MODULE_LICENSE("Dual BSD/GPL"); + +-/* QCA639x 2.0 firmware files */ +-MODULE_FIRMWARE(ATH11K_FW_DIR "/QCA6390/hw2.0/" ATH11K_BOARD_API2_FILE); +-MODULE_FIRMWARE(ATH11K_FW_DIR "/QCA6390/hw2.0/" ATH11K_AMSS_FILE); +-MODULE_FIRMWARE(ATH11K_FW_DIR "/QCA6390/hw2.0/" ATH11K_M3_FILE); ++/* firmware files */ ++MODULE_FIRMWARE(ATH11K_FW_DIR "/QCA6390/hw2.0/*"); ++MODULE_FIRMWARE(ATH11K_FW_DIR "/QCN9074/hw1.0/*"); ++MODULE_FIRMWARE(ATH11K_FW_DIR "/WCN6855/hw2.0/*"); ++MODULE_FIRMWARE(ATH11K_FW_DIR "/WCN6855/hw2.1/*"); diff --git a/package/kernel/mac80211/patches/ath11k/0059-wifi-ath11k-print-a-warning-when-crypto_alloc_shash-.patch b/package/kernel/mac80211/patches/ath11k/0059-wifi-ath11k-print-a-warning-when-crypto_alloc_shash-.patch new file mode 100644 index 000000000..fab52a0fa --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0059-wifi-ath11k-print-a-warning-when-crypto_alloc_shash-.patch @@ -0,0 +1,34 @@ +From a87a9110ac0dcbfd9458b6665c141fa1c16a669d Mon Sep 17 00:00:00 2001 +From: Kalle Valo +Date: Wed, 5 Apr 2023 12:04:25 +0300 +Subject: [PATCH] wifi: ath11k: print a warning when crypto_alloc_shash() fails + +Christoph reported that ath11k failed to initialise when michael_mic.ko +module was not installed. To make it easier to notice that case print a +warning when crypto_alloc_shash() fails. + +Compile tested only. + +Reported-by: Christoph Hellwig +Link: https://lore.kernel.org/all/20221130133016.GC3055@lst.de/ +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20230405090425.1351-1-kvalo@kernel.org +--- + drivers/net/wireless/ath/ath11k/dp_rx.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/drivers/net/wireless/ath/ath11k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath11k/dp_rx.c +@@ -3106,8 +3106,11 @@ int ath11k_peer_rx_frag_setup(struct ath + int i; + + tfm = crypto_alloc_shash("michael_mic", 0, 0); +- if (IS_ERR(tfm)) ++ if (IS_ERR(tfm)) { ++ ath11k_warn(ab, "failed to allocate michael_mic shash: %ld\n", ++ PTR_ERR(tfm)); + return PTR_ERR(tfm); ++ } + + spin_lock_bh(&ab->base_lock); + diff --git a/package/kernel/mac80211/patches/ath11k/0060-wifi-ath11k-Ignore-frags-from-uninitialized-peer-in-.patch b/package/kernel/mac80211/patches/ath11k/0060-wifi-ath11k-Ignore-frags-from-uninitialized-peer-in-.patch new file mode 100644 index 000000000..5bbf9e04a --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0060-wifi-ath11k-Ignore-frags-from-uninitialized-peer-in-.patch @@ -0,0 +1,104 @@ +From a06bfb3c9f69f303692cdae87bc0899d2ae8b2a6 Mon Sep 17 00:00:00 2001 +From: Harshitha Prem +Date: Tue, 4 Apr 2023 00:11:54 +0530 +Subject: [PATCH] wifi: ath11k: Ignore frags from uninitialized peer in dp. + +When max virtual ap interfaces are configured in all the bands with +ACS and hostapd restart is done every 60s, a crash is observed at +random times. +In this certain scenario, a fragmented packet is received for +self peer, for which rx_tid and rx_frags are not initialized in +datapath. While handling this fragment, crash is observed as the +rx_frag list is uninitialised and when we walk in +ath11k_dp_rx_h_sort_frags, skb null leads to exception. + +To address this, before processing received fragments we check +dp_setup_done flag is set to ensure that peer has completed its +dp peer setup for fragment queue, else ignore processing the +fragments. + +Call trace: + ath11k_dp_process_rx_err+0x550/0x1084 [ath11k] + ath11k_dp_service_srng+0x70/0x370 [ath11k] + 0xffffffc009693a04 + __napi_poll+0x30/0xa4 + net_rx_action+0x118/0x270 + __do_softirq+0x10c/0x244 + irq_exit+0x64/0xb4 + __handle_domain_irq+0x88/0xac + gic_handle_irq+0x74/0xbc + el1_irq+0xf0/0x1c0 + arch_cpu_idle+0x10/0x18 + do_idle+0x104/0x248 + cpu_startup_entry+0x20/0x64 + rest_init+0xd0/0xdc + arch_call_rest_init+0xc/0x14 + start_kernel+0x480/0x4b8 + Code: f9400281 f94066a2 91405021 b94a0023 (f9406401) + +Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Harshitha Prem +Signed-off-by: Nagarajan Maran +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20230403184155.8670-2-quic_nmaran@quicinc.com +--- + drivers/net/wireless/ath/ath11k/dp.c | 4 +++- + drivers/net/wireless/ath/ath11k/dp_rx.c | 8 ++++++++ + drivers/net/wireless/ath/ath11k/peer.h | 1 + + 3 files changed, 12 insertions(+), 1 deletion(-) + +--- a/drivers/net/wireless/ath/ath11k/dp.c ++++ b/drivers/net/wireless/ath/ath11k/dp.c +@@ -36,6 +36,7 @@ void ath11k_dp_peer_cleanup(struct ath11 + } + + ath11k_peer_rx_tid_cleanup(ar, peer); ++ peer->dp_setup_done = false; + crypto_free_shash(peer->tfm_mmic); + spin_unlock_bh(&ab->base_lock); + } +@@ -72,7 +73,8 @@ int ath11k_dp_peer_setup(struct ath11k * + ret = ath11k_peer_rx_frag_setup(ar, addr, vdev_id); + if (ret) { + ath11k_warn(ab, "failed to setup rx defrag context\n"); +- return ret; ++ tid--; ++ goto peer_clean; + } + + /* TODO: Setup other peer specific resource used in data path */ +--- a/drivers/net/wireless/ath/ath11k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath11k/dp_rx.c +@@ -3130,6 +3130,7 @@ int ath11k_peer_rx_frag_setup(struct ath + } + + peer->tfm_mmic = tfm; ++ peer->dp_setup_done = true; + spin_unlock_bh(&ab->base_lock); + + return 0; +@@ -3575,6 +3576,13 @@ static int ath11k_dp_rx_frag_h_mpdu(stru + ret = -ENOENT; + goto out_unlock; + } ++ if (!peer->dp_setup_done) { ++ ath11k_warn(ab, "The peer %pM [%d] has uninitialized datapath\n", ++ peer->addr, peer_id); ++ ret = -ENOENT; ++ goto out_unlock; ++ } ++ + rx_tid = &peer->rx_tid[tid]; + + if ((!skb_queue_empty(&rx_tid->rx_frags) && seqno != rx_tid->cur_sn) || +--- a/drivers/net/wireless/ath/ath11k/peer.h ++++ b/drivers/net/wireless/ath/ath11k/peer.h +@@ -35,6 +35,7 @@ struct ath11k_peer { + u16 sec_type; + u16 sec_type_grp; + bool is_authorized; ++ bool dp_setup_done; + }; + + void ath11k_peer_unmap_event(struct ath11k_base *ab, u16 peer_id); diff --git a/package/kernel/mac80211/patches/ath11k/0061-wifi-ath11k-fix-undefined-behavior-with-__fls-in-dp.patch b/package/kernel/mac80211/patches/ath11k/0061-wifi-ath11k-fix-undefined-behavior-with-__fls-in-dp.patch new file mode 100644 index 000000000..d68c19f16 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0061-wifi-ath11k-fix-undefined-behavior-with-__fls-in-dp.patch @@ -0,0 +1,29 @@ +From 41e02bf4ae32cf2ac47b08b4caaa9c1a032e4ce7 Mon Sep 17 00:00:00 2001 +From: Harshitha Prem +Date: Tue, 4 Apr 2023 00:11:55 +0530 +Subject: [PATCH] wifi: ath11k: fix undefined behavior with __fls in dp + +"__fls" would have an undefined behavior if the argument is passed +as "0". Hence, added changes to handle the same. + +Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Harshitha Prem +Signed-off-by: Nagarajan Maran +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20230403184155.8670-3-quic_nmaran@quicinc.com +--- + drivers/net/wireless/ath/ath11k/dp_rx.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/wireless/ath/ath11k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath11k/dp_rx.c +@@ -3598,7 +3598,7 @@ static int ath11k_dp_rx_frag_h_mpdu(stru + goto out_unlock; + } + +- if (frag_no > __fls(rx_tid->rx_frag_bitmap)) ++ if (!rx_tid->rx_frag_bitmap || (frag_no > __fls(rx_tid->rx_frag_bitmap))) + __skb_queue_tail(&rx_tid->rx_frags, msdu); + else + ath11k_dp_rx_h_sort_frags(ar, &rx_tid->rx_frags, msdu); diff --git a/package/kernel/mac80211/patches/ath11k/0062-wifi-ath11k-fix-double-free-of-peer-rx_tid-during-re.patch b/package/kernel/mac80211/patches/ath11k/0062-wifi-ath11k-fix-double-free-of-peer-rx_tid-during-re.patch new file mode 100644 index 000000000..dd37b1e4f --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0062-wifi-ath11k-fix-double-free-of-peer-rx_tid-during-re.patch @@ -0,0 +1,144 @@ +From 93a91f40c25c3d0e61f8540a7accf105090f9995 Mon Sep 17 00:00:00 2001 +From: Harshitha Prem +Date: Mon, 17 Apr 2023 13:35:00 +0300 +Subject: [PATCH] wifi: ath11k: fix double free of peer rx_tid during reo cmd + failure + +Peer rx_tid is locally copied thrice during peer_rx_tid_cleanup to +send REO_CMD_UPDATE_RX_QUEUE followed by REO_CMD_FLUSH_CACHE to flush +all aged REO descriptors from HW cache. + +When sending REO_CMD_FLUSH_CACHE fails, we do dma unmap of already +mapped rx_tid->vaddr and free it. This is not checked during +reo_cmd_list_cleanup() and dp_reo_cmd_free() before trying to free and +unmap again. + +Fix this by setting rx_tid->vaddr NULL in rx tid delete and also +wherever freeing it to check in reo_cmd_list_cleanup() and +reo_cmd_free() before trying to free again. + +Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 +Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Sathishkumar Muruganandam +Signed-off-by: Harshitha Prem +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20230403182420.23375-2-quic_hprem@quicinc.com +--- + drivers/net/wireless/ath/ath11k/dp_rx.c | 43 ++++++++++++++++++------- + 1 file changed, 31 insertions(+), 12 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath11k/dp_rx.c +@@ -668,13 +668,18 @@ void ath11k_dp_reo_cmd_list_cleanup(stru + struct ath11k_dp *dp = &ab->dp; + struct dp_reo_cmd *cmd, *tmp; + struct dp_reo_cache_flush_elem *cmd_cache, *tmp_cache; ++ struct dp_rx_tid *rx_tid; + + spin_lock_bh(&dp->reo_cmd_lock); + list_for_each_entry_safe(cmd, tmp, &dp->reo_cmd_list, list) { + list_del(&cmd->list); +- dma_unmap_single(ab->dev, cmd->data.paddr, +- cmd->data.size, DMA_BIDIRECTIONAL); +- kfree(cmd->data.vaddr); ++ rx_tid = &cmd->data; ++ if (rx_tid->vaddr) { ++ dma_unmap_single(ab->dev, rx_tid->paddr, ++ rx_tid->size, DMA_BIDIRECTIONAL); ++ kfree(rx_tid->vaddr); ++ rx_tid->vaddr = NULL; ++ } + kfree(cmd); + } + +@@ -682,9 +687,13 @@ void ath11k_dp_reo_cmd_list_cleanup(stru + &dp->reo_cmd_cache_flush_list, list) { + list_del(&cmd_cache->list); + dp->reo_cmd_cache_flush_count--; +- dma_unmap_single(ab->dev, cmd_cache->data.paddr, +- cmd_cache->data.size, DMA_BIDIRECTIONAL); +- kfree(cmd_cache->data.vaddr); ++ rx_tid = &cmd_cache->data; ++ if (rx_tid->vaddr) { ++ dma_unmap_single(ab->dev, rx_tid->paddr, ++ rx_tid->size, DMA_BIDIRECTIONAL); ++ kfree(rx_tid->vaddr); ++ rx_tid->vaddr = NULL; ++ } + kfree(cmd_cache); + } + spin_unlock_bh(&dp->reo_cmd_lock); +@@ -698,10 +707,12 @@ static void ath11k_dp_reo_cmd_free(struc + if (status != HAL_REO_CMD_SUCCESS) + ath11k_warn(dp->ab, "failed to flush rx tid hw desc, tid %d status %d\n", + rx_tid->tid, status); +- +- dma_unmap_single(dp->ab->dev, rx_tid->paddr, rx_tid->size, +- DMA_BIDIRECTIONAL); +- kfree(rx_tid->vaddr); ++ if (rx_tid->vaddr) { ++ dma_unmap_single(dp->ab->dev, rx_tid->paddr, rx_tid->size, ++ DMA_BIDIRECTIONAL); ++ kfree(rx_tid->vaddr); ++ rx_tid->vaddr = NULL; ++ } + } + + static void ath11k_dp_reo_cache_flush(struct ath11k_base *ab, +@@ -740,6 +751,7 @@ static void ath11k_dp_reo_cache_flush(st + dma_unmap_single(ab->dev, rx_tid->paddr, rx_tid->size, + DMA_BIDIRECTIONAL); + kfree(rx_tid->vaddr); ++ rx_tid->vaddr = NULL; + } + } + +@@ -792,6 +804,7 @@ free_desc: + dma_unmap_single(ab->dev, rx_tid->paddr, rx_tid->size, + DMA_BIDIRECTIONAL); + kfree(rx_tid->vaddr); ++ rx_tid->vaddr = NULL; + } + + void ath11k_peer_rx_tid_delete(struct ath11k *ar, +@@ -804,6 +817,8 @@ void ath11k_peer_rx_tid_delete(struct at + if (!rx_tid->active) + return; + ++ rx_tid->active = false; ++ + cmd.flag = HAL_REO_CMD_FLG_NEED_STATUS; + cmd.addr_lo = lower_32_bits(rx_tid->paddr); + cmd.addr_hi = upper_32_bits(rx_tid->paddr); +@@ -818,9 +833,11 @@ void ath11k_peer_rx_tid_delete(struct at + dma_unmap_single(ar->ab->dev, rx_tid->paddr, rx_tid->size, + DMA_BIDIRECTIONAL); + kfree(rx_tid->vaddr); ++ rx_tid->vaddr = NULL; + } + +- rx_tid->active = false; ++ rx_tid->paddr = 0; ++ rx_tid->size = 0; + } + + static int ath11k_dp_rx_link_desc_return(struct ath11k_base *ab, +@@ -967,6 +984,7 @@ static void ath11k_dp_rx_tid_mem_free(st + dma_unmap_single(ab->dev, rx_tid->paddr, rx_tid->size, + DMA_BIDIRECTIONAL); + kfree(rx_tid->vaddr); ++ rx_tid->vaddr = NULL; + + rx_tid->active = false; + +@@ -1067,7 +1085,8 @@ int ath11k_peer_rx_tid_setup(struct ath1 + return ret; + + err_mem_free: +- kfree(vaddr); ++ kfree(rx_tid->vaddr); ++ rx_tid->vaddr = NULL; + + return ret; + } diff --git a/package/kernel/mac80211/patches/ath11k/0063-wifi-ath11k-Prevent-REO-cmd-failures.patch b/package/kernel/mac80211/patches/ath11k/0063-wifi-ath11k-Prevent-REO-cmd-failures.patch new file mode 100644 index 000000000..4b9af1806 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0063-wifi-ath11k-Prevent-REO-cmd-failures.patch @@ -0,0 +1,43 @@ +From a8ae833657a45746debde85c38bb7f070d344026 Mon Sep 17 00:00:00 2001 +From: Harshitha Prem +Date: Mon, 17 Apr 2023 13:35:01 +0300 +Subject: [PATCH] wifi: ath11k: Prevent REO cmd failures + +Prevent REO cmd failures causing double free by increasing REO cmd +ring size and moving REO status ring mask to IRQ group 3 from group +0 to separate from tx completion ring on IRQ group 0 which may delay +reo status processing. + +Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 +Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Sathishkumar Muruganandam +Signed-off-by: Harshitha Prem +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20230403182420.23375-3-quic_hprem@quicinc.com +--- + drivers/net/wireless/ath/ath11k/dp.h | 2 +- + drivers/net/wireless/ath/ath11k/hw.c | 1 + + 2 files changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/net/wireless/ath/ath11k/dp.h ++++ b/drivers/net/wireless/ath/ath11k/dp.h +@@ -214,7 +214,7 @@ struct ath11k_pdev_dp { + #define DP_REO_REINJECT_RING_SIZE 32 + #define DP_RX_RELEASE_RING_SIZE 1024 + #define DP_REO_EXCEPTION_RING_SIZE 128 +-#define DP_REO_CMD_RING_SIZE 128 ++#define DP_REO_CMD_RING_SIZE 256 + #define DP_REO_STATUS_RING_SIZE 2048 + #define DP_RXDMA_BUF_RING_SIZE 4096 + #define DP_RXDMA_REFILL_RING_SIZE 2048 +--- a/drivers/net/wireless/ath/ath11k/hw.c ++++ b/drivers/net/wireless/ath/ath11k/hw.c +@@ -1233,6 +1233,7 @@ const struct ath11k_hw_ring_mask ath11k_ + ATH11K_RX_WBM_REL_RING_MASK_0, + }, + .reo_status = { ++ 0, 0, 0, + ATH11K_REO_STATUS_RING_MASK_0, + }, + .rxdma2host = { diff --git a/package/kernel/mac80211/patches/ath11k/0064-wifi-ath11k-add-peer-mac-information-in-failure-case.patch b/package/kernel/mac80211/patches/ath11k/0064-wifi-ath11k-add-peer-mac-information-in-failure-case.patch new file mode 100644 index 000000000..fbcbdfff7 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0064-wifi-ath11k-add-peer-mac-information-in-failure-case.patch @@ -0,0 +1,74 @@ +From 20487cc3ff36bbfa9505f0a078ba98f09abfc717 Mon Sep 17 00:00:00 2001 +From: Harshitha Prem +Date: Mon, 17 Apr 2023 13:35:01 +0300 +Subject: [PATCH] wifi: ath11k: add peer mac information in failure cases + +During reo command failure, the peer mac detail for which the reo +command was not successful is unknown. Hence, to improve the +debuggability, add the peer mac information in the failure cases +which would be useful during multi client cases. + +Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 +Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Sathishkumar Muruganandam +Signed-off-by: Harshitha Prem +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20230403182420.23375-4-quic_hprem@quicinc.com +--- + drivers/net/wireless/ath/ath11k/dp_rx.c | 16 ++++++++++------ + 1 file changed, 10 insertions(+), 6 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath11k/dp_rx.c +@@ -1009,7 +1009,8 @@ int ath11k_peer_rx_tid_setup(struct ath1 + + peer = ath11k_peer_find(ab, vdev_id, peer_mac); + if (!peer) { +- ath11k_warn(ab, "failed to find the peer to set up rx tid\n"); ++ ath11k_warn(ab, "failed to find the peer %pM to set up rx tid\n", ++ peer_mac); + spin_unlock_bh(&ab->base_lock); + return -ENOENT; + } +@@ -1022,7 +1023,8 @@ int ath11k_peer_rx_tid_setup(struct ath1 + ba_win_sz, ssn, true); + spin_unlock_bh(&ab->base_lock); + if (ret) { +- ath11k_warn(ab, "failed to update reo for rx tid %d\n", tid); ++ ath11k_warn(ab, "failed to update reo for peer %pM rx tid %d\n: %d", ++ peer_mac, tid, ret); + return ret; + } + +@@ -1030,8 +1032,8 @@ int ath11k_peer_rx_tid_setup(struct ath1 + peer_mac, paddr, + tid, 1, ba_win_sz); + if (ret) +- ath11k_warn(ab, "failed to send wmi command to update rx reorder queue, tid :%d (%d)\n", +- tid, ret); ++ ath11k_warn(ab, "failed to send wmi rx reorder queue for peer %pM tid %d: %d\n", ++ peer_mac, tid, ret); + return ret; + } + +@@ -1064,6 +1066,8 @@ int ath11k_peer_rx_tid_setup(struct ath1 + ret = dma_mapping_error(ab->dev, paddr); + if (ret) { + spin_unlock_bh(&ab->base_lock); ++ ath11k_warn(ab, "failed to setup dma map for peer %pM rx tid %d: %d\n", ++ peer_mac, tid, ret); + goto err_mem_free; + } + +@@ -1077,8 +1081,8 @@ int ath11k_peer_rx_tid_setup(struct ath1 + ret = ath11k_wmi_peer_rx_reorder_queue_setup(ar, vdev_id, peer_mac, + paddr, tid, 1, ba_win_sz); + if (ret) { +- ath11k_warn(ar->ab, "failed to setup rx reorder queue, tid :%d (%d)\n", +- tid, ret); ++ ath11k_warn(ar->ab, "failed to setup rx reorder queue for peer %pM tid %d: %d\n", ++ peer_mac, tid, ret); + ath11k_dp_rx_tid_mem_free(ab, peer_mac, vdev_id, tid); + } + diff --git a/package/kernel/mac80211/patches/ath11k/0065-wifi-ath11k-fix-tx-status-reporting-in-encap-offload.patch b/package/kernel/mac80211/patches/ath11k/0065-wifi-ath11k-fix-tx-status-reporting-in-encap-offload.patch new file mode 100644 index 000000000..e2fe41915 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0065-wifi-ath11k-fix-tx-status-reporting-in-encap-offload.patch @@ -0,0 +1,119 @@ +From 6257c702264c44d74c6b71f0c62a7665da2dc356 Mon Sep 17 00:00:00 2001 +From: Pradeep Kumar Chitrapu +Date: Mon, 17 Apr 2023 13:35:02 +0300 +Subject: [PATCH] wifi: ath11k: fix tx status reporting in encap offload mode + +ieee80211_tx_status() treats packets in 802.11 frame format and +tries to extract sta address from packet header. When tx encap +offload is enabled, this becomes invalid operation. Hence, switch +to using ieee80211_tx_status_ext() after filling in station +address for handling both 802.11 and 802.3 frames. + +Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Pradeep Kumar Chitrapu +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20230403195738.25367-2-quic_pradeepc@quicinc.com +--- + drivers/net/wireless/ath/ath11k/dp.h | 4 +++ + drivers/net/wireless/ath/ath11k/dp_tx.c | 33 ++++++++++++++++++++++++- + drivers/net/wireless/ath/ath11k/dp_tx.h | 1 + + 3 files changed, 37 insertions(+), 1 deletion(-) + +--- a/drivers/net/wireless/ath/ath11k/dp.h ++++ b/drivers/net/wireless/ath/ath11k/dp.h +@@ -303,12 +303,16 @@ struct ath11k_dp { + + #define HTT_TX_WBM_COMP_STATUS_OFFSET 8 + ++#define HTT_INVALID_PEER_ID 0xffff ++ + /* HTT tx completion is overlaid in wbm_release_ring */ + #define HTT_TX_WBM_COMP_INFO0_STATUS GENMASK(12, 9) + #define HTT_TX_WBM_COMP_INFO0_REINJECT_REASON GENMASK(16, 13) + #define HTT_TX_WBM_COMP_INFO0_REINJECT_REASON GENMASK(16, 13) + + #define HTT_TX_WBM_COMP_INFO1_ACK_RSSI GENMASK(31, 24) ++#define HTT_TX_WBM_COMP_INFO2_SW_PEER_ID GENMASK(15, 0) ++#define HTT_TX_WBM_COMP_INFO2_VALID BIT(21) + + struct htt_tx_wbm_completion { + u32 info0; +--- a/drivers/net/wireless/ath/ath11k/dp_tx.c ++++ b/drivers/net/wireless/ath/ath11k/dp_tx.c +@@ -316,10 +316,12 @@ ath11k_dp_tx_htt_tx_complete_buf(struct + struct dp_tx_ring *tx_ring, + struct ath11k_dp_htt_wbm_tx_status *ts) + { ++ struct ieee80211_tx_status status = { 0 }; + struct sk_buff *msdu; + struct ieee80211_tx_info *info; + struct ath11k_skb_cb *skb_cb; + struct ath11k *ar; ++ struct ath11k_peer *peer; + + spin_lock(&tx_ring->tx_idr_lock); + msdu = idr_remove(&tx_ring->txbuf_idr, ts->msdu_id); +@@ -341,6 +343,11 @@ ath11k_dp_tx_htt_tx_complete_buf(struct + + dma_unmap_single(ab->dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE); + ++ if (!skb_cb->vif) { ++ dev_kfree_skb_any(msdu); ++ return; ++ } ++ + memset(&info->status, 0, sizeof(info->status)); + + if (ts->acked) { +@@ -355,7 +362,23 @@ ath11k_dp_tx_htt_tx_complete_buf(struct + } + } + +- ieee80211_tx_status(ar->hw, msdu); ++ spin_lock_bh(&ab->base_lock); ++ peer = ath11k_peer_find_by_id(ab, ts->peer_id); ++ if (!peer || !peer->sta) { ++ ath11k_dbg(ab, ATH11K_DBG_DATA, ++ "dp_tx: failed to find the peer with peer_id %d\n", ++ ts->peer_id); ++ spin_unlock_bh(&ab->base_lock); ++ dev_kfree_skb_any(msdu); ++ return; ++ } ++ spin_unlock_bh(&ab->base_lock); ++ ++ status.sta = peer->sta; ++ status.info = info; ++ status.skb = msdu; ++ ++ ieee80211_tx_status_ext(ar->hw, &status); + } + + static void +@@ -379,7 +402,15 @@ ath11k_dp_tx_process_htt_tx_complete(str + ts.msdu_id = msdu_id; + ts.ack_rssi = FIELD_GET(HTT_TX_WBM_COMP_INFO1_ACK_RSSI, + status_desc->info1); ++ ++ if (FIELD_GET(HTT_TX_WBM_COMP_INFO2_VALID, status_desc->info2)) ++ ts.peer_id = FIELD_GET(HTT_TX_WBM_COMP_INFO2_SW_PEER_ID, ++ status_desc->info2); ++ else ++ ts.peer_id = HTT_INVALID_PEER_ID; ++ + ath11k_dp_tx_htt_tx_complete_buf(ab, tx_ring, &ts); ++ + break; + case HAL_WBM_REL_HTT_TX_COMP_STATUS_REINJ: + case HAL_WBM_REL_HTT_TX_COMP_STATUS_INSPECT: +--- a/drivers/net/wireless/ath/ath11k/dp_tx.h ++++ b/drivers/net/wireless/ath/ath11k/dp_tx.h +@@ -13,6 +13,7 @@ struct ath11k_dp_htt_wbm_tx_status { + u32 msdu_id; + bool acked; + int ack_rssi; ++ u16 peer_id; + }; + + void ath11k_dp_tx_update_txcompl(struct ath11k *ar, struct hal_tx_status *ts); diff --git a/package/kernel/mac80211/patches/ath11k/0066-wifi-ath11k-Fix-incorrect-update-of-radiotap-fields.patch b/package/kernel/mac80211/patches/ath11k/0066-wifi-ath11k-Fix-incorrect-update-of-radiotap-fields.patch new file mode 100644 index 000000000..4f9458010 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0066-wifi-ath11k-Fix-incorrect-update-of-radiotap-fields.patch @@ -0,0 +1,49 @@ +From 2f0c9ac8362da09c80f1cd422ef7fd6fa9b252b9 Mon Sep 17 00:00:00 2001 +From: Pradeep Kumar Chitrapu +Date: Mon, 17 Apr 2023 13:35:02 +0300 +Subject: [PATCH] wifi: ath11k: Fix incorrect update of radiotap fields + +Fix incorrect update of ppdu stats causing incorrect radiotap +fields. + +Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Pradeep Kumar Chitrapu +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20230403195738.25367-3-quic_pradeepc@quicinc.com +--- + drivers/net/wireless/ath/ath11k/hal_rx.c | 4 ++-- + drivers/net/wireless/ath/ath11k/hal_rx.h | 2 +- + 2 files changed, 3 insertions(+), 3 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/hal_rx.c ++++ b/drivers/net/wireless/ath/ath11k/hal_rx.c +@@ -1029,7 +1029,7 @@ ath11k_hal_rx_parse_mon_status_tlv(struc + info1 = __le32_to_cpu(vht_sig->info1); + + ppdu_info->ldpc = FIELD_GET(HAL_RX_VHT_SIG_A_INFO_INFO1_SU_MU_CODING, +- info0); ++ info1); + ppdu_info->mcs = FIELD_GET(HAL_RX_VHT_SIG_A_INFO_INFO1_MCS, + info1); + gi_setting = FIELD_GET(HAL_RX_VHT_SIG_A_INFO_INFO1_GI_SETTING, +@@ -1452,7 +1452,7 @@ ath11k_hal_rx_parse_mon_status_tlv(struc + * PHYRX_OTHER_RECEIVE_INFO TLV. + */ + ppdu_info->rssi_comb = +- FIELD_GET(HAL_RX_PHYRX_RSSI_LEGACY_INFO_INFO1_RSSI_COMB, ++ FIELD_GET(HAL_RX_PHYRX_RSSI_LEGACY_INFO_INFO0_RSSI_COMB, + __le32_to_cpu(rssi->info0)); + + if (db2dbm) { +--- a/drivers/net/wireless/ath/ath11k/hal_rx.h ++++ b/drivers/net/wireless/ath/ath11k/hal_rx.h +@@ -385,7 +385,7 @@ struct hal_rx_he_sig_b2_ofdma_info { + __le32 info0; + } __packed; + +-#define HAL_RX_PHYRX_RSSI_LEGACY_INFO_INFO1_RSSI_COMB GENMASK(15, 8) ++#define HAL_RX_PHYRX_RSSI_LEGACY_INFO_INFO0_RSSI_COMB GENMASK(15, 8) + + #define HAL_RX_PHYRX_RSSI_PREAMBLE_PRI20 GENMASK(7, 0) + diff --git a/package/kernel/mac80211/patches/ath11k/0067-wifi-ath11k-Fix-SKB-corruption-in-REO-destination-ri.patch b/package/kernel/mac80211/patches/ath11k/0067-wifi-ath11k-Fix-SKB-corruption-in-REO-destination-ri.patch new file mode 100644 index 000000000..8b300f3a7 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0067-wifi-ath11k-Fix-SKB-corruption-in-REO-destination-ri.patch @@ -0,0 +1,70 @@ +From f9fff67d2d7ca6fa8066132003a3deef654c55b1 Mon Sep 17 00:00:00 2001 +From: Nagarajan Maran +Date: Mon, 17 Apr 2023 13:35:02 +0300 +Subject: [PATCH] wifi: ath11k: Fix SKB corruption in REO destination ring + +While running traffics for a long time, randomly an RX descriptor +filled with value "0" from REO destination ring is received. +This descriptor which is invalid causes the wrong SKB (SKB stored in +the IDR lookup with buffer id "0") to be fetched which in turn +causes SKB memory corruption issue and the same leads to crash +after some time. + +Changed the start id for idr allocation to "1" and the buffer id "0" +is reserved for error validation. Introduced Sanity check to validate +the descriptor, before processing the SKB. + +Crash Signature : + +Unable to handle kernel paging request at virtual address 3f004900 +PC points to "b15_dma_inv_range+0x30/0x50" +LR points to "dma_cache_maint_page+0x8c/0x128". +The Backtrace obtained is as follows: +[<8031716c>] (b15_dma_inv_range) from [<80313a4c>] (dma_cache_maint_page+0x8c/0x128) +[<80313a4c>] (dma_cache_maint_page) from [<80313b90>] (__dma_page_dev_to_cpu+0x28/0xcc) +[<80313b90>] (__dma_page_dev_to_cpu) from [<7fb5dd68>] (ath11k_dp_process_rx+0x1e8/0x4a4 [ath11k]) +[<7fb5dd68>] (ath11k_dp_process_rx [ath11k]) from [<7fb53c20>] (ath11k_dp_service_srng+0xb0/0x2ac [ath11k]) +[<7fb53c20>] (ath11k_dp_service_srng [ath11k]) from [<7f67bba4>] (ath11k_pci_ext_grp_napi_poll+0x1c/0x78 [ath11k_pci]) +[<7f67bba4>] (ath11k_pci_ext_grp_napi_poll [ath11k_pci]) from [<807d5cf4>] (__napi_poll+0x28/0xb8) +[<807d5cf4>] (__napi_poll) from [<807d5f28>] (net_rx_action+0xf0/0x280) +[<807d5f28>] (net_rx_action) from [<80302148>] (__do_softirq+0xd0/0x280) +[<80302148>] (__do_softirq) from [<80320408>] (irq_exit+0x74/0xd4) +[<80320408>] (irq_exit) from [<803638a4>] (__handle_domain_irq+0x90/0xb4) +[<803638a4>] (__handle_domain_irq) from [<805bedec>] (gic_handle_irq+0x58/0x90) +[<805bedec>] (gic_handle_irq) from [<80301a78>] (__irq_svc+0x58/0x8c) + +Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Nagarajan Maran +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20230403191533.28114-1-quic_nmaran@quicinc.com +--- + drivers/net/wireless/ath/ath11k/dp_rx.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath11k/dp_rx.c +@@ -389,10 +389,10 @@ int ath11k_dp_rxbufs_replenish(struct at + goto fail_free_skb; + + spin_lock_bh(&rx_ring->idr_lock); +- buf_id = idr_alloc(&rx_ring->bufs_idr, skb, 0, +- rx_ring->bufs_max * 3, GFP_ATOMIC); ++ buf_id = idr_alloc(&rx_ring->bufs_idr, skb, 1, ++ (rx_ring->bufs_max * 3) + 1, GFP_ATOMIC); + spin_unlock_bh(&rx_ring->idr_lock); +- if (buf_id < 0) ++ if (buf_id <= 0) + goto fail_dma_unmap; + + desc = ath11k_hal_srng_src_get_next_entry(ab, srng); +@@ -2665,6 +2665,9 @@ try_again: + cookie); + mac_id = FIELD_GET(DP_RXDMA_BUF_COOKIE_PDEV_ID, cookie); + ++ if (unlikely(buf_id == 0)) ++ continue; ++ + ar = ab->pdevs[mac_id].ar; + rx_ring = &ar->dp.rx_refill_buf_ring; + spin_lock_bh(&rx_ring->idr_lock); diff --git a/package/kernel/mac80211/patches/ath11k/0068-wifi-ath11k-Remove-disabling-of-80-80-and-160-MHz.patch b/package/kernel/mac80211/patches/ath11k/0068-wifi-ath11k-Remove-disabling-of-80-80-and-160-MHz.patch new file mode 100644 index 000000000..ce5ffd273 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0068-wifi-ath11k-Remove-disabling-of-80-80-and-160-MHz.patch @@ -0,0 +1,49 @@ +From b100722a777f6455d913666a376f81342b2cb995 Mon Sep 17 00:00:00 2001 +From: Muna Sinada +Date: Mon, 17 Apr 2023 13:22:27 -0700 +Subject: [PATCH] wifi: ath11k: Remove disabling of 80+80 and 160 MHz + +This is a regression fix for 80+80 and 160 MHz support bits being +cleared, therefore not adverised. Remove disable of 80+80 and 160 MHz +capability flags and assign valid center frequency 2 similar to +VHT80_80. + +Fixes: 38dfe775d0ab ("wifi: ath11k: push MU-MIMO params from hostapd to hardware") +Reported-by: Robert Marko +Tested-by: Robert Marko # IPQ8074 WLAN.HK.2.9.0.1-01385-QCAHKSWPL_SILICONZ-1 +Link: https://bugzilla.kernel.org/show_bug.cgi?id=217299 +Co-developed-by: P Praneesh +Signed-off-by: P Praneesh +Signed-off-by: Muna Sinada +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/1681762947-13882-1-git-send-email-quic_msinada@quicinc.com +--- + drivers/net/wireless/ath/ath11k/mac.c | 4 ---- + drivers/net/wireless/ath/ath11k/wmi.c | 3 ++- + 2 files changed, 2 insertions(+), 5 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -5585,10 +5585,6 @@ static int ath11k_mac_copy_he_cap(struct + + he_cap_elem->mac_cap_info[1] &= + IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_MASK; +- he_cap_elem->phy_cap_info[0] &= +- ~IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G; +- he_cap_elem->phy_cap_info[0] &= +- ~IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G; + + he_cap_elem->phy_cap_info[5] &= + ~IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_MASK; +--- a/drivers/net/wireless/ath/ath11k/wmi.c ++++ b/drivers/net/wireless/ath/ath11k/wmi.c +@@ -871,7 +871,8 @@ static void ath11k_wmi_put_wmi_channel(s + + chan->band_center_freq2 = arg->channel.band_center_freq1; + +- } else if (arg->channel.mode == MODE_11AC_VHT80_80) { ++ } else if ((arg->channel.mode == MODE_11AC_VHT80_80) || ++ (arg->channel.mode == MODE_11AX_HE80_80)) { + chan->band_center_freq2 = arg->channel.band_center_freq2; + } else { + chan->band_center_freq2 = 0; diff --git a/package/kernel/mac80211/patches/ath11k/0069-wifi-ath11k-fix-registration-of-6Ghz-only-phy-withou.patch b/package/kernel/mac80211/patches/ath11k/0069-wifi-ath11k-fix-registration-of-6Ghz-only-phy-withou.patch new file mode 100644 index 000000000..32468dbc4 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0069-wifi-ath11k-fix-registration-of-6Ghz-only-phy-withou.patch @@ -0,0 +1,61 @@ +From e2ceb1de2f83aafd8003f0b72dfd4b7441e97d14 Mon Sep 17 00:00:00 2001 +From: Maxime Bizon +Date: Fri, 21 Apr 2023 16:54:45 +0200 +Subject: [PATCH] wifi: ath11k: fix registration of 6Ghz-only phy without the + full channel range + +Because of what seems to be a typo, a 6Ghz-only phy for which the BDF +does not allow the 7115Mhz channel will fail to register: + + WARNING: CPU: 2 PID: 106 at net/wireless/core.c:907 wiphy_register+0x914/0x954 + Modules linked in: ath11k_pci sbsa_gwdt + CPU: 2 PID: 106 Comm: kworker/u8:5 Not tainted 6.3.0-rc7-next-20230418-00549-g1e096a17625a-dirty #9 + Hardware name: Freebox V7R Board (DT) + Workqueue: ath11k_qmi_driver_event ath11k_qmi_driver_event_work + pstate: 60000005 (nZCv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--) + pc : wiphy_register+0x914/0x954 + lr : ieee80211_register_hw+0x67c/0xc10 + sp : ffffff800b123aa0 + x29: ffffff800b123aa0 x28: 0000000000000000 x27: 0000000000000000 + x26: 0000000000000000 x25: 0000000000000006 x24: ffffffc008d51418 + x23: ffffffc008cb0838 x22: ffffff80176c2460 x21: 0000000000000168 + x20: ffffff80176c0000 x19: ffffff80176c03e0 x18: 0000000000000014 + x17: 00000000cbef338c x16: 00000000d2a26f21 x15: 00000000ad6bb85f + x14: 0000000000000020 x13: 0000000000000020 x12: 00000000ffffffbd + x11: 0000000000000208 x10: 00000000fffffdf7 x9 : ffffffc009394718 + x8 : ffffff80176c0528 x7 : 000000007fffffff x6 : 0000000000000006 + x5 : 0000000000000005 x4 : ffffff800b304284 x3 : ffffff800b304284 + x2 : ffffff800b304d98 x1 : 0000000000000000 x0 : 0000000000000000 + Call trace: + wiphy_register+0x914/0x954 + ieee80211_register_hw+0x67c/0xc10 + ath11k_mac_register+0x7c4/0xe10 + ath11k_core_qmi_firmware_ready+0x1f4/0x570 + ath11k_qmi_driver_event_work+0x198/0x590 + process_one_work+0x1b8/0x328 + worker_thread+0x6c/0x414 + kthread+0x100/0x104 + ret_from_fork+0x10/0x20 + ---[ end trace 0000000000000000 ]--- + ath11k_pci 0002:01:00.0: ieee80211 registration failed: -22 + ath11k_pci 0002:01:00.0: failed register the radio with mac80211: -22 + ath11k_pci 0002:01:00.0: failed to create pdev core: -22 + +Signed-off-by: Maxime Bizon +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20230421145445.2612280-1-mbizon@freebox.fr +--- + drivers/net/wireless/ath/ath11k/mac.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -8892,7 +8892,7 @@ static int ath11k_mac_setup_channels_rat + } + + if (supported_bands & WMI_HOST_WLAN_5G_CAP) { +- if (reg_cap->high_5ghz_chan >= ATH11K_MAX_6G_FREQ) { ++ if (reg_cap->high_5ghz_chan >= ATH11K_MIN_6G_FREQ) { + channels = kmemdup(ath11k_6ghz_channels, + sizeof(ath11k_6ghz_channels), GFP_KERNEL); + if (!channels) { diff --git a/package/kernel/mac80211/patches/ath11k/0070-wifi-ath-work-around-false-positive-stringop-overrea.patch b/package/kernel/mac80211/patches/ath11k/0070-wifi-ath-work-around-false-positive-stringop-overrea.patch new file mode 100644 index 000000000..aa4df16a9 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0070-wifi-ath-work-around-false-positive-stringop-overrea.patch @@ -0,0 +1,84 @@ +From 695df2f417d25202bdac9cde3c82d2acb6492b4d Mon Sep 17 00:00:00 2001 +From: Arnd Bergmann +Date: Fri, 5 May 2023 16:11:25 +0300 +Subject: [PATCH] wifi: ath: work around false-positive stringop-overread + warning + +In a rare arm64 randconfig build, I got multiple warnings for ath11k +and ath12k: + +In function 'ath11k_peer_assoc_h_ht', + inlined from 'ath11k_peer_assoc_prepare' at drivers/net/wireless/ath/ath11k/mac.c:2665:2: +drivers/net/wireless/ath/ath11k/mac.c:1709:13: error: 'ath11k_peer_assoc_h_ht_masked' reading 10 bytes from a region of size 0 [-Werror=stringop-overread] + 1709 | if (ath11k_peer_assoc_h_ht_masked(ht_mcs_mask)) + | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This happens whenever gcc-13 fails to inline one of the functions +that take a fixed-length array argument but gets passed a pointer. + +Change these functions to all take a regular pointer argument +instead. + +Signed-off-by: Arnd Bergmann +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20230417205447.1800912-1-arnd@kernel.org +--- + drivers/net/wireless/ath/ath11k/mac.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -433,7 +433,7 @@ u8 ath11k_mac_bitrate_to_idx(const struc + } + + static u32 +-ath11k_mac_max_ht_nss(const u8 ht_mcs_mask[IEEE80211_HT_MCS_MASK_LEN]) ++ath11k_mac_max_ht_nss(const u8 *ht_mcs_mask) + { + int nss; + +@@ -445,7 +445,7 @@ ath11k_mac_max_ht_nss(const u8 ht_mcs_ma + } + + static u32 +-ath11k_mac_max_vht_nss(const u16 vht_mcs_mask[NL80211_VHT_NSS_MAX]) ++ath11k_mac_max_vht_nss(const u16 *vht_mcs_mask) + { + int nss; + +@@ -457,7 +457,7 @@ ath11k_mac_max_vht_nss(const u16 vht_mcs + } + + static u32 +-ath11k_mac_max_he_nss(const u16 he_mcs_mask[NL80211_HE_NSS_MAX]) ++ath11k_mac_max_he_nss(const u16 *he_mcs_mask) + { + int nss; + +@@ -1658,7 +1658,7 @@ static void ath11k_peer_assoc_h_rates(st + } + + static bool +-ath11k_peer_assoc_h_ht_masked(const u8 ht_mcs_mask[IEEE80211_HT_MCS_MASK_LEN]) ++ath11k_peer_assoc_h_ht_masked(const u8 *ht_mcs_mask) + { + int nss; + +@@ -1670,7 +1670,7 @@ ath11k_peer_assoc_h_ht_masked(const u8 h + } + + static bool +-ath11k_peer_assoc_h_vht_masked(const u16 vht_mcs_mask[]) ++ath11k_peer_assoc_h_vht_masked(const u16 *vht_mcs_mask) + { + int nss; + +@@ -2065,7 +2065,7 @@ static u16 ath11k_peer_assoc_h_he_limit( + } + + static bool +-ath11k_peer_assoc_h_he_masked(const u16 he_mcs_mask[NL80211_HE_NSS_MAX]) ++ath11k_peer_assoc_h_he_masked(const u16 *he_mcs_mask) + { + int nss; + diff --git a/package/kernel/mac80211/patches/ath11k/0071-wifi-ath11k-driver-settings-for-MBSSID-and-EMA.patch b/package/kernel/mac80211/patches/ath11k/0071-wifi-ath11k-driver-settings-for-MBSSID-and-EMA.patch new file mode 100644 index 000000000..bede4819c --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0071-wifi-ath11k-driver-settings-for-MBSSID-and-EMA.patch @@ -0,0 +1,133 @@ +From a08dbb04d7365a04d52882143cf196005bfc88c3 Mon Sep 17 00:00:00 2001 +From: Aloka Dixit +Date: Fri, 5 May 2023 16:11:27 +0300 +Subject: [PATCH 71/77] wifi: ath11k: driver settings for MBSSID and EMA + +Advertise the driver support for multiple BSSID (MBSSID) and +enhanced multi-BSSID advertisements (EMA) by setting extended +capabilities. + +Configure mbssid_max_interfaces and ema_max_profile_periodicity +fields in structure wiphy which are used to advertise maximum number +of interfaces and profile periodicity supported by the driver. + +Add new WMI fields to configure maximum vdev count supported for +MBSSID and profile periodicity in case of EMA. +Setting WMI_RSRC_CFG_FLAG2_CALC_NEXT_DTIM_COUNT_SET flag +indicates that the firmware should track and update the DTIM counts +for each non-transmitted profile. + +Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Aloka Dixit +Co-developed-by: John Crispin +Signed-off-by: John Crispin +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20230405221648.17950-2-quic_alokad@quicinc.com +--- + drivers/net/wireless/ath/ath11k/hw.c | 3 +++ + drivers/net/wireless/ath/ath11k/hw.h | 1 + + drivers/net/wireless/ath/ath11k/mac.c | 7 +++++++ + drivers/net/wireless/ath/ath11k/wmi.c | 3 +++ + drivers/net/wireless/ath/ath11k/wmi.h | 6 ++++++ + 5 files changed, 20 insertions(+) + +--- a/drivers/net/wireless/ath/ath11k/hw.c ++++ b/drivers/net/wireless/ath/ath11k/hw.c +@@ -202,6 +202,9 @@ static void ath11k_init_wmi_config_ipq80 + config->twt_ap_sta_count = 1000; + config->flag1 |= WMI_RSRC_CFG_FLAG1_BSS_CHANNEL_INFO_64; + config->flag1 |= WMI_RSRC_CFG_FLAG1_ACK_RSSI; ++ config->ema_max_vap_cnt = ab->num_radios; ++ config->ema_max_profile_period = TARGET_EMA_MAX_PROFILE_PERIOD; ++ config->beacon_tx_offload_max_vdev += config->ema_max_vap_cnt; + } + + static int ath11k_hw_mac_id_to_pdev_id_ipq8074(struct ath11k_hw_params *hw, +--- a/drivers/net/wireless/ath/ath11k/hw.h ++++ b/drivers/net/wireless/ath/ath11k/hw.h +@@ -64,6 +64,7 @@ + #define TARGET_NUM_WDS_ENTRIES 32 + #define TARGET_DMA_BURST_SIZE 1 + #define TARGET_RX_BATCHMODE 1 ++#define TARGET_EMA_MAX_PROFILE_PERIOD 8 + + #define ATH11K_HW_MAX_QUEUES 4 + #define ATH11K_QUEUE_LEN 4096 +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -9001,19 +9001,23 @@ static int ath11k_mac_setup_iface_combin + + static const u8 ath11k_if_types_ext_capa[] = { + [0] = WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING, ++ [2] = WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT, + [7] = WLAN_EXT_CAPA8_OPMODE_NOTIF, + }; + + static const u8 ath11k_if_types_ext_capa_sta[] = { + [0] = WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING, ++ [2] = WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT, + [7] = WLAN_EXT_CAPA8_OPMODE_NOTIF, + [9] = WLAN_EXT_CAPA10_TWT_REQUESTER_SUPPORT, + }; + + static const u8 ath11k_if_types_ext_capa_ap[] = { + [0] = WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING, ++ [2] = WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT, + [7] = WLAN_EXT_CAPA8_OPMODE_NOTIF, + [9] = WLAN_EXT_CAPA10_TWT_RESPONDER_SUPPORT, ++ [10] = WLAN_EXT_CAPA11_EMA_SUPPORT, + }; + + static const struct wiphy_iftype_ext_capab ath11k_iftypes_ext_capa[] = { +@@ -9251,6 +9255,9 @@ static int __ath11k_mac_register(struct + wiphy_ext_feature_set(ar->hw->wiphy, + NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER); + ++ ar->hw->wiphy->mbssid_max_interfaces = TARGET_NUM_VDEVS(ab); ++ ar->hw->wiphy->ema_max_profile_periodicity = TARGET_EMA_MAX_PROFILE_PERIOD; ++ + ath11k_reg_init(ar); + + if (!test_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags)) { +--- a/drivers/net/wireless/ath/ath11k/wmi.c ++++ b/drivers/net/wireless/ath/ath11k/wmi.c +@@ -3987,6 +3987,9 @@ ath11k_wmi_copy_resource_config(struct w + ~(1 << WMI_CFG_HOST_SERVICE_FLAG_REG_CC_EXT); + wmi_cfg->host_service_flags |= (tg_cfg->is_reg_cc_ext_event_supported << + WMI_CFG_HOST_SERVICE_FLAG_REG_CC_EXT); ++ wmi_cfg->flags2 = WMI_RSRC_CFG_FLAG2_CALC_NEXT_DTIM_COUNT_SET; ++ wmi_cfg->ema_max_vap_cnt = tg_cfg->ema_max_vap_cnt; ++ wmi_cfg->ema_max_profile_period = tg_cfg->ema_max_profile_period; + } + + static int ath11k_init_cmd_send(struct ath11k_pdev_wmi *wmi, +--- a/drivers/net/wireless/ath/ath11k/wmi.h ++++ b/drivers/net/wireless/ath/ath11k/wmi.h +@@ -2317,6 +2317,7 @@ struct wmi_init_cmd { + } __packed; + + #define WMI_RSRC_CFG_FLAG1_BSS_CHANNEL_INFO_64 BIT(5) ++#define WMI_RSRC_CFG_FLAG2_CALC_NEXT_DTIM_COUNT_SET BIT(9) + #define WMI_RSRC_CFG_FLAG1_ACK_RSSI BIT(18) + + #define WMI_CFG_HOST_SERVICE_FLAG_REG_CC_EXT 4 +@@ -2389,6 +2390,9 @@ struct wmi_resource_config { + u32 msdu_flow_override_config1; + u32 flags2; + u32 host_service_flags; ++ u32 max_rnr_neighbours; ++ u32 ema_max_vap_cnt; ++ u32 ema_max_profile_period; + } __packed; + + struct wmi_service_ready_event { +@@ -5646,6 +5650,8 @@ struct target_resource_config { + u32 twt_ap_pdev_count; + u32 twt_ap_sta_count; + u8 is_reg_cc_ext_event_supported; ++ u32 ema_max_vap_cnt; ++ u32 ema_max_profile_period; + }; + + enum wmi_debug_log_param { diff --git a/package/kernel/mac80211/patches/ath11k/0072-wifi-ath11k-MBSSID-configuration-during-vdev-create-.patch b/package/kernel/mac80211/patches/ath11k/0072-wifi-ath11k-MBSSID-configuration-during-vdev-create-.patch new file mode 100644 index 000000000..4ba071731 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0072-wifi-ath11k-MBSSID-configuration-during-vdev-create-.patch @@ -0,0 +1,215 @@ +From 5a81610acf66c4ad6e1a1fbd09f3f555fca863b1 Mon Sep 17 00:00:00 2001 +From: Aloka Dixit +Date: Fri, 5 May 2023 16:11:27 +0300 +Subject: [PATCH 72/77] wifi: ath11k: MBSSID configuration during vdev + create/start + +Configure multiple BSSID flags and index of the transmitting interface +in vdev create/start commands depending on the service bit +WMI_TLV_SERVICE_MBSS_PARAM_IN_VDEV_START_SUPPORT. + +Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Aloka Dixit +Co-developed-by: John Crispin +Signed-off-by: John Crispin +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20230405221648.17950-3-quic_alokad@quicinc.com +--- + drivers/net/wireless/ath/ath11k/mac.c | 70 +++++++++++++++++++++++++-- + drivers/net/wireless/ath/ath11k/wmi.c | 5 ++ + drivers/net/wireless/ath/ath11k/wmi.h | 19 ++++++++ + 3 files changed, 90 insertions(+), 4 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -6181,17 +6181,62 @@ static void ath11k_mac_op_stop(struct ie + atomic_set(&ar->num_pending_mgmt_tx, 0); + } + +-static void +-ath11k_mac_setup_vdev_create_params(struct ath11k_vif *arvif, +- struct vdev_create_params *params) ++static int ath11k_mac_setup_vdev_params_mbssid(struct ath11k_vif *arvif, ++ u32 *flags, u32 *tx_vdev_id) ++{ ++ struct ath11k *ar = arvif->ar; ++ struct ath11k_vif *tx_arvif; ++ struct ieee80211_vif *tx_vif; ++ ++ *tx_vdev_id = 0; ++ tx_vif = arvif->vif->mbssid_tx_vif; ++ if (!tx_vif) { ++ *flags = WMI_HOST_VDEV_FLAGS_NON_MBSSID_AP; ++ return 0; ++ } ++ ++ tx_arvif = (void *)tx_vif->drv_priv; ++ ++ if (arvif->vif->bss_conf.nontransmitted) { ++ if (ar->hw->wiphy != ieee80211_vif_to_wdev(tx_vif)->wiphy) ++ return -EINVAL; ++ ++ *flags = WMI_HOST_VDEV_FLAGS_NON_TRANSMIT_AP; ++ *tx_vdev_id = ath11k_vif_to_arvif(tx_vif)->vdev_id; ++ } else if (tx_arvif == arvif) { ++ *flags = WMI_HOST_VDEV_FLAGS_TRANSMIT_AP; ++ } else { ++ return -EINVAL; ++ } ++ ++ if (arvif->vif->bss_conf.ema_ap) ++ *flags |= WMI_HOST_VDEV_FLAGS_EMA_MODE; ++ ++ return 0; ++} ++ ++static int ath11k_mac_setup_vdev_create_params(struct ath11k_vif *arvif, ++ struct vdev_create_params *params) + { + struct ath11k *ar = arvif->ar; + struct ath11k_pdev *pdev = ar->pdev; ++ int ret; + + params->if_id = arvif->vdev_id; + params->type = arvif->vdev_type; + params->subtype = arvif->vdev_subtype; + params->pdev_id = pdev->pdev_id; ++ params->mbssid_flags = 0; ++ params->mbssid_tx_vdev_id = 0; ++ ++ if (!test_bit(WMI_TLV_SERVICE_MBSS_PARAM_IN_VDEV_START_SUPPORT, ++ ar->ab->wmi_ab.svc_map)) { ++ ret = ath11k_mac_setup_vdev_params_mbssid(arvif, ++ ¶ms->mbssid_flags, ++ ¶ms->mbssid_tx_vdev_id); ++ if (ret) ++ return ret; ++ } + + if (pdev->cap.supported_bands & WMI_HOST_WLAN_2G_CAP) { + params->chains[NL80211_BAND_2GHZ].tx = ar->num_tx_chains; +@@ -6206,6 +6251,7 @@ ath11k_mac_setup_vdev_create_params(stru + params->chains[NL80211_BAND_6GHZ].tx = ar->num_tx_chains; + params->chains[NL80211_BAND_6GHZ].rx = ar->num_rx_chains; + } ++ return 0; + } + + static void ath11k_mac_op_update_vif_offload(struct ieee80211_hw *hw, +@@ -6500,7 +6546,12 @@ static int ath11k_mac_op_add_interface(s + for (i = 0; i < ARRAY_SIZE(vif->hw_queue); i++) + vif->hw_queue[i] = i % (ATH11K_HW_MAX_QUEUES - 1); + +- ath11k_mac_setup_vdev_create_params(arvif, &vdev_param); ++ ret = ath11k_mac_setup_vdev_create_params(arvif, &vdev_param); ++ if (ret) { ++ ath11k_warn(ab, "failed to create vdev parameters %d: %d\n", ++ arvif->vdev_id, ret); ++ goto err; ++ } + + ret = ath11k_wmi_vdev_create(ar, vif->addr, &vdev_param); + if (ret) { +@@ -6905,6 +6956,17 @@ ath11k_mac_vdev_start_restart(struct ath + arg.pref_tx_streams = ar->num_tx_chains; + arg.pref_rx_streams = ar->num_rx_chains; + ++ arg.mbssid_flags = 0; ++ arg.mbssid_tx_vdev_id = 0; ++ if (test_bit(WMI_TLV_SERVICE_MBSS_PARAM_IN_VDEV_START_SUPPORT, ++ ar->ab->wmi_ab.svc_map)) { ++ ret = ath11k_mac_setup_vdev_params_mbssid(arvif, ++ &arg.mbssid_flags, ++ &arg.mbssid_tx_vdev_id); ++ if (ret) ++ return ret; ++ } ++ + if (arvif->vdev_type == WMI_VDEV_TYPE_AP) { + arg.ssid = arvif->u.ap.ssid; + arg.ssid_len = arvif->u.ap.ssid_len; +--- a/drivers/net/wireless/ath/ath11k/wmi.c ++++ b/drivers/net/wireless/ath/ath11k/wmi.c +@@ -724,6 +724,9 @@ int ath11k_wmi_vdev_create(struct ath11k + cmd->vdev_subtype = param->subtype; + cmd->num_cfg_txrx_streams = WMI_NUM_SUPPORTED_BAND_MAX; + cmd->pdev_id = param->pdev_id; ++ cmd->mbssid_flags = param->mbssid_flags; ++ cmd->mbssid_tx_vdev_id = param->mbssid_tx_vdev_id; ++ + ether_addr_copy(cmd->vdev_macaddr.addr, macaddr); + + ptr = skb->data + sizeof(*cmd); +@@ -941,6 +944,8 @@ int ath11k_wmi_vdev_start(struct ath11k + cmd->cac_duration_ms = arg->cac_duration_ms; + cmd->regdomain = arg->regdomain; + cmd->he_ops = arg->he_ops; ++ cmd->mbssid_flags = arg->mbssid_flags; ++ cmd->mbssid_tx_vdev_id = arg->mbssid_tx_vdev_id; + + if (!restart) { + if (arg->ssid) { +--- a/drivers/net/wireless/ath/ath11k/wmi.h ++++ b/drivers/net/wireless/ath/ath11k/wmi.h +@@ -137,6 +137,14 @@ enum { + WMI_AUTORATE_3200NS_GI = BIT(11), + }; + ++enum { ++ WMI_HOST_VDEV_FLAGS_NON_MBSSID_AP = 0x00000001, ++ WMI_HOST_VDEV_FLAGS_TRANSMIT_AP = 0x00000002, ++ WMI_HOST_VDEV_FLAGS_NON_TRANSMIT_AP = 0x00000004, ++ WMI_HOST_VDEV_FLAGS_EMA_MODE = 0x00000008, ++ WMI_HOST_VDEV_FLAGS_SCAN_MODE_VAP = 0x00000010, ++}; ++ + /* + * wmi command groups. + */ +@@ -2096,6 +2104,7 @@ enum wmi_tlv_service { + WMI_TLV_SERVICE_EXT2_MSG = 220, + WMI_TLV_SERVICE_PEER_POWER_SAVE_DURATION_SUPPORT = 246, + WMI_TLV_SERVICE_SRG_SRP_SPATIAL_REUSE_SUPPORT = 249, ++ WMI_TLV_SERVICE_MBSS_PARAM_IN_VDEV_START_SUPPORT = 253, + WMI_TLV_SERVICE_PASSIVE_SCAN_START_TIME_ENHANCE = 263, + + /* The second 128 bits */ +@@ -2583,6 +2592,8 @@ struct vdev_create_params { + u8 rx; + } chains[NUM_NL80211_BANDS]; + u32 pdev_id; ++ u32 mbssid_flags; ++ u32 mbssid_tx_vdev_id; + }; + + struct wmi_vdev_create_cmd { +@@ -2593,6 +2604,8 @@ struct wmi_vdev_create_cmd { + struct wmi_mac_addr vdev_macaddr; + u32 num_cfg_txrx_streams; + u32 pdev_id; ++ u32 mbssid_flags; ++ u32 mbssid_tx_vdev_id; + } __packed; + + struct wmi_vdev_txrx_streams { +@@ -2656,6 +2669,9 @@ struct wmi_vdev_start_request_cmd { + u32 he_ops; + u32 cac_duration_ms; + u32 regdomain; ++ u32 min_data_rate; ++ u32 mbssid_flags; ++ u32 mbssid_tx_vdev_id; + } __packed; + + #define MGMT_TX_DL_FRM_LEN 64 +@@ -2825,6 +2841,9 @@ struct wmi_vdev_start_req_arg { + u32 pref_rx_streams; + u32 pref_tx_streams; + u32 num_noa_descriptors; ++ u32 min_data_rate; ++ u32 mbssid_flags; ++ u32 mbssid_tx_vdev_id; + }; + + struct peer_create_params { diff --git a/package/kernel/mac80211/patches/ath11k/0073-wifi-ath11k-rename-MBSSID-fields-in-wmi_vdev_up_cmd.patch b/package/kernel/mac80211/patches/ath11k/0073-wifi-ath11k-rename-MBSSID-fields-in-wmi_vdev_up_cmd.patch new file mode 100644 index 000000000..023a1dbb9 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0073-wifi-ath11k-rename-MBSSID-fields-in-wmi_vdev_up_cmd.patch @@ -0,0 +1,52 @@ +From cf604e72bc6e6db68c7fcaa8779b03ec14b8d2fa Mon Sep 17 00:00:00 2001 +From: Aloka Dixit +Date: Fri, 5 May 2023 16:11:27 +0300 +Subject: [PATCH 73/77] wifi: ath11k: rename MBSSID fields in wmi_vdev_up_cmd + +Rename trans_bssid to tx_vdev_bssid to make it similar to vdev_bssid. + +Rename profile_num to nontx_profile_cnt, and profile_idx to +nontx_profile_idx which makes it clear that these store configurations +related to MBSSID non-transmitting profiles. + +Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Aloka Dixit +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20230405221648.17950-4-quic_alokad@quicinc.com +--- + drivers/net/wireless/ath/ath11k/wmi.c | 6 +++--- + drivers/net/wireless/ath/ath11k/wmi.h | 6 +++--- + 2 files changed, 6 insertions(+), 6 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/wmi.c ++++ b/drivers/net/wireless/ath/ath11k/wmi.c +@@ -1029,10 +1029,10 @@ int ath11k_wmi_vdev_up(struct ath11k *ar + bss_conf = &arvif->vif->bss_conf; + + if (bss_conf->nontransmitted) { +- ether_addr_copy(cmd->trans_bssid.addr, ++ ether_addr_copy(cmd->tx_vdev_bssid.addr, + bss_conf->transmitter_bssid); +- cmd->profile_idx = bss_conf->bssid_index; +- cmd->profile_num = bss_conf->bssid_indicator; ++ cmd->nontx_profile_idx = bss_conf->bssid_index; ++ cmd->nontx_profile_cnt = bss_conf->bssid_indicator; + } + } + +--- a/drivers/net/wireless/ath/ath11k/wmi.h ++++ b/drivers/net/wireless/ath/ath11k/wmi.h +@@ -2625,9 +2625,9 @@ struct wmi_vdev_up_cmd { + u32 vdev_id; + u32 vdev_assoc_id; + struct wmi_mac_addr vdev_bssid; +- struct wmi_mac_addr trans_bssid; +- u32 profile_idx; +- u32 profile_num; ++ struct wmi_mac_addr tx_vdev_bssid; ++ u32 nontx_profile_idx; ++ u32 nontx_profile_cnt; + } __packed; + + struct wmi_vdev_stop_cmd { diff --git a/package/kernel/mac80211/patches/ath11k/0074-wifi-ath11k-MBSSID-parameter-configuration-in-AP-mod.patch b/package/kernel/mac80211/patches/ath11k/0074-wifi-ath11k-MBSSID-parameter-configuration-in-AP-mod.patch new file mode 100644 index 000000000..d93e27dd4 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0074-wifi-ath11k-MBSSID-parameter-configuration-in-AP-mod.patch @@ -0,0 +1,138 @@ +From c82dc33f252fd8883be66f2d0230af0fd734c683 Mon Sep 17 00:00:00 2001 +From: Aloka Dixit +Date: Fri, 5 May 2023 16:11:27 +0300 +Subject: [PATCH 74/77] wifi: ath11k: MBSSID parameter configuration in AP mode + +Include MBSSID parameters in WMI vdev up operation. + +Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Aloka Dixit +Co-developed-by: John Crispin +Signed-off-by: John Crispin +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20230405221648.17950-5-quic_alokad@quicinc.com +--- + drivers/net/wireless/ath/ath11k/mac.c | 29 +++++++++++++++++++++------ + drivers/net/wireless/ath/ath11k/wmi.c | 8 +++++++- + drivers/net/wireless/ath/ath11k/wmi.h | 3 ++- + 3 files changed, 32 insertions(+), 8 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -964,7 +964,7 @@ static int ath11k_mac_monitor_vdev_start + return ret; + } + +- ret = ath11k_wmi_vdev_up(ar, vdev_id, 0, ar->mac_addr); ++ ret = ath11k_wmi_vdev_up(ar, vdev_id, 0, ar->mac_addr, NULL, 0, 0); + if (ret) { + ath11k_warn(ar->ab, "failed to put up monitor vdev %i: %d\n", + vdev_id, ret); +@@ -1423,6 +1423,7 @@ static void ath11k_control_beaconing(str + struct ieee80211_bss_conf *info) + { + struct ath11k *ar = arvif->ar; ++ struct ath11k_vif *tx_arvif = NULL; + int ret = 0; + + lockdep_assert_held(&arvif->ar->conf_mutex); +@@ -1451,8 +1452,14 @@ static void ath11k_control_beaconing(str + + ether_addr_copy(arvif->bssid, info->bssid); + ++ if (arvif->vif->mbssid_tx_vif) ++ tx_arvif = (struct ath11k_vif *)arvif->vif->mbssid_tx_vif->drv_priv; ++ + ret = ath11k_wmi_vdev_up(arvif->ar, arvif->vdev_id, arvif->aid, +- arvif->bssid); ++ arvif->bssid, ++ tx_arvif ? tx_arvif->bssid : NULL, ++ info->bssid_index, ++ 1 << info->bssid_indicator); + if (ret) { + ath11k_warn(ar->ab, "failed to bring up vdev %d: %i\n", + arvif->vdev_id, ret); +@@ -2879,7 +2886,8 @@ static void ath11k_bss_assoc(struct ieee + arvif->aid = vif->cfg.aid; + ether_addr_copy(arvif->bssid, bss_conf->bssid); + +- ret = ath11k_wmi_vdev_up(ar, arvif->vdev_id, arvif->aid, arvif->bssid); ++ ret = ath11k_wmi_vdev_up(ar, arvif->vdev_id, arvif->aid, arvif->bssid, ++ NULL, 0, 0); + if (ret) { + ath11k_warn(ar->ab, "failed to set vdev %d up: %d\n", + arvif->vdev_id, ret); +@@ -7133,7 +7141,8 @@ ath11k_mac_update_vif_chan(struct ath11k + int n_vifs) + { + struct ath11k_base *ab = ar->ab; +- struct ath11k_vif *arvif; ++ struct ath11k_vif *arvif, *tx_arvif = NULL; ++ struct ieee80211_vif *mbssid_tx_vif; + int ret; + int i; + bool monitor_vif = false; +@@ -7187,8 +7196,15 @@ ath11k_mac_update_vif_chan(struct ath11k + ath11k_warn(ab, "failed to update bcn tmpl during csa: %d\n", + ret); + ++ mbssid_tx_vif = arvif->vif->mbssid_tx_vif; ++ if (mbssid_tx_vif) ++ tx_arvif = (struct ath11k_vif *)mbssid_tx_vif->drv_priv; ++ + ret = ath11k_wmi_vdev_up(arvif->ar, arvif->vdev_id, arvif->aid, +- arvif->bssid); ++ arvif->bssid, ++ tx_arvif ? tx_arvif->bssid : NULL, ++ arvif->vif->bss_conf.bssid_index, ++ 1 << arvif->vif->bss_conf.bssid_indicator); + if (ret) { + ath11k_warn(ab, "failed to bring vdev up %d: %d\n", + arvif->vdev_id, ret); +@@ -7306,7 +7322,8 @@ static int ath11k_start_vdev_delay(struc + } + + if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) { +- ret = ath11k_wmi_vdev_up(ar, arvif->vdev_id, 0, ar->mac_addr); ++ ret = ath11k_wmi_vdev_up(ar, arvif->vdev_id, 0, ar->mac_addr, ++ NULL, 0, 0); + if (ret) { + ath11k_warn(ab, "failed put monitor up: %d\n", ret); + return ret; +--- a/drivers/net/wireless/ath/ath11k/wmi.c ++++ b/drivers/net/wireless/ath/ath11k/wmi.c +@@ -1001,7 +1001,8 @@ int ath11k_wmi_vdev_start(struct ath11k + return ret; + } + +-int ath11k_wmi_vdev_up(struct ath11k *ar, u32 vdev_id, u32 aid, const u8 *bssid) ++int ath11k_wmi_vdev_up(struct ath11k *ar, u32 vdev_id, u32 aid, const u8 *bssid, ++ u8 *tx_bssid, u32 nontx_profile_idx, u32 nontx_profile_cnt) + { + struct ath11k_pdev_wmi *wmi = ar->wmi; + struct wmi_vdev_up_cmd *cmd; +@@ -1025,6 +1026,11 @@ int ath11k_wmi_vdev_up(struct ath11k *ar + + ether_addr_copy(cmd->vdev_bssid.addr, bssid); + ++ cmd->nontx_profile_idx = nontx_profile_idx; ++ cmd->nontx_profile_cnt = nontx_profile_cnt; ++ if (tx_bssid) ++ ether_addr_copy(cmd->tx_vdev_bssid.addr, tx_bssid); ++ + if (arvif && arvif->vif->type == NL80211_IFTYPE_STATION) { + bss_conf = &arvif->vif->bss_conf; + +--- a/drivers/net/wireless/ath/ath11k/wmi.h ++++ b/drivers/net/wireless/ath/ath11k/wmi.h +@@ -6301,7 +6301,8 @@ int ath11k_wmi_bcn_tmpl(struct ath11k *a + struct sk_buff *bcn); + int ath11k_wmi_vdev_down(struct ath11k *ar, u8 vdev_id); + int ath11k_wmi_vdev_up(struct ath11k *ar, u32 vdev_id, u32 aid, +- const u8 *bssid); ++ const u8 *bssid, u8 *tx_bssid, u32 nontx_profile_idx, ++ u32 nontx_profile_cnt); + int ath11k_wmi_vdev_stop(struct ath11k *ar, u8 vdev_id); + int ath11k_wmi_vdev_start(struct ath11k *ar, struct wmi_vdev_start_req_arg *arg, + bool restart); diff --git a/package/kernel/mac80211/patches/ath11k/0075-wifi-ath11k-refactor-vif-parameter-configurations.patch b/package/kernel/mac80211/patches/ath11k/0075-wifi-ath11k-refactor-vif-parameter-configurations.patch new file mode 100644 index 000000000..8509e5597 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0075-wifi-ath11k-refactor-vif-parameter-configurations.patch @@ -0,0 +1,86 @@ +From cb9bea773c85e372931cd7a177db4165adf29d95 Mon Sep 17 00:00:00 2001 +From: Aloka Dixit +Date: Fri, 5 May 2023 16:11:28 +0300 +Subject: [PATCH 75/77] wifi: ath11k: refactor vif parameter configurations + +Security parameters for each non-transmitting profile can be +different when MBSSID is enabled and this information is included +in the MBSSID element in the Beacon frame. Current implementation +to set rsnie_present and wpaie_present does not parse this element +hence it applies only to the transmitting interface. + +Move the code to a separate function to make additions for +non-transmitting interfaces cleaner. + +Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Aloka Dixit +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20230405221648.17950-6-quic_alokad@quicinc.com +--- + drivers/net/wireless/ath/ath11k/mac.c | 41 ++++++++++++++++----------- + 1 file changed, 24 insertions(+), 17 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -1351,28 +1351,14 @@ err_mon_del: + return ret; + } + +-static int ath11k_mac_setup_bcn_tmpl(struct ath11k_vif *arvif) ++static void ath11k_mac_set_vif_params(struct ath11k_vif *arvif, ++ struct sk_buff *bcn) + { +- struct ath11k *ar = arvif->ar; +- struct ath11k_base *ab = ar->ab; +- struct ieee80211_hw *hw = ar->hw; +- struct ieee80211_vif *vif = arvif->vif; +- struct ieee80211_mutable_offsets offs = {}; +- struct sk_buff *bcn; + struct ieee80211_mgmt *mgmt; + u8 *ies; +- int ret; +- +- if (arvif->vdev_type != WMI_VDEV_TYPE_AP) +- return 0; +- +- bcn = ieee80211_beacon_get_template(hw, vif, &offs, 0); +- if (!bcn) { +- ath11k_warn(ab, "failed to get beacon template from mac80211\n"); +- return -EPERM; +- } + + ies = bcn->data + ieee80211_get_hdrlen_from_skb(bcn); ++ mgmt = (struct ieee80211_mgmt *)bcn->data; + ies += sizeof(mgmt->u.beacon); + + if (cfg80211_find_ie(WLAN_EID_RSN, ies, (skb_tail_pointer(bcn) - ies))) +@@ -1386,7 +1372,28 @@ static int ath11k_mac_setup_bcn_tmpl(str + arvif->wpaie_present = true; + else + arvif->wpaie_present = false; ++} ++ ++static int ath11k_mac_setup_bcn_tmpl(struct ath11k_vif *arvif) ++{ ++ struct ath11k *ar = arvif->ar; ++ struct ath11k_base *ab = ar->ab; ++ struct ieee80211_hw *hw = ar->hw; ++ struct ieee80211_vif *vif = arvif->vif; ++ struct ieee80211_mutable_offsets offs = {}; ++ struct sk_buff *bcn; ++ int ret; ++ ++ if (arvif->vdev_type != WMI_VDEV_TYPE_AP) ++ return 0; ++ ++ bcn = ieee80211_beacon_get_template(hw, vif, &offs, 0); ++ if (!bcn) { ++ ath11k_warn(ab, "failed to get beacon template from mac80211\n"); ++ return -EPERM; ++ } + ++ ath11k_mac_set_vif_params(arvif, bcn); + ret = ath11k_wmi_bcn_tmpl(ar, arvif->vdev_id, &offs, bcn); + + kfree_skb(bcn); diff --git a/package/kernel/mac80211/patches/ath11k/0076-wifi-ath11k-MBSSID-beacon-support.patch b/package/kernel/mac80211/patches/ath11k/0076-wifi-ath11k-MBSSID-beacon-support.patch new file mode 100644 index 000000000..d23ea8dee --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0076-wifi-ath11k-MBSSID-beacon-support.patch @@ -0,0 +1,190 @@ +From 335a92765d308dfe22826f5562cd4b4389b45e71 Mon Sep 17 00:00:00 2001 +From: Aloka Dixit +Date: Fri, 5 May 2023 16:11:28 +0300 +Subject: [PATCH 76/77] wifi: ath11k: MBSSID beacon support + +- Split ath11k_mac_setup_bcn_tmpl() to move the beacon retrieval and + WMI command to a new function, ath11k_mac_setup_bcn_tmpl_legacy(). + In the original function add checks to use the transmitting interface + when MBSSID is enabled. +- Set rsnie_present and wpaie_present fields for the non-transmitting + interfaces when MBSSID is enabled. + +Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Aloka Dixit +Co-developed-by: John Crispin +Signed-off-by: John Crispin +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20230405221648.17950-7-quic_alokad@quicinc.com +--- + drivers/net/wireless/ath/ath11k/mac.c | 116 ++++++++++++++++++++++++-- + drivers/net/wireless/ath/ath11k/wmi.c | 1 + + 2 files changed, 112 insertions(+), 5 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -1351,6 +1351,84 @@ err_mon_del: + return ret; + } + ++static void ath11k_mac_setup_nontx_vif_rsnie(struct ath11k_vif *arvif, ++ bool tx_arvif_rsnie_present, ++ const u8 *profile, u8 profile_len) ++{ ++ if (cfg80211_find_ie(WLAN_EID_RSN, profile, profile_len)) { ++ arvif->rsnie_present = true; ++ } else if (tx_arvif_rsnie_present) { ++ int i; ++ u8 nie_len; ++ const u8 *nie = cfg80211_find_ext_ie(WLAN_EID_EXT_NON_INHERITANCE, ++ profile, profile_len); ++ if (!nie) ++ return; ++ ++ nie_len = nie[1]; ++ nie += 2; ++ for (i = 0; i < nie_len; i++) { ++ if (nie[i] == WLAN_EID_RSN) { ++ arvif->rsnie_present = false; ++ break; ++ } ++ } ++ } ++} ++ ++static bool ath11k_mac_set_nontx_vif_params(struct ath11k_vif *tx_arvif, ++ struct ath11k_vif *arvif, ++ struct sk_buff *bcn) ++{ ++ struct ieee80211_mgmt *mgmt; ++ const u8 *ies, *profile, *next_profile; ++ int ies_len; ++ ++ ies = bcn->data + ieee80211_get_hdrlen_from_skb(bcn); ++ mgmt = (struct ieee80211_mgmt *)bcn->data; ++ ies += sizeof(mgmt->u.beacon); ++ ies_len = skb_tail_pointer(bcn) - ies; ++ ++ ies = cfg80211_find_ie(WLAN_EID_MULTIPLE_BSSID, ies, ies_len); ++ arvif->rsnie_present = tx_arvif->rsnie_present; ++ ++ while (ies) { ++ u8 mbssid_len; ++ ++ ies_len -= (2 + ies[1]); ++ mbssid_len = ies[1] - 1; ++ profile = &ies[3]; ++ ++ while (mbssid_len) { ++ u8 profile_len; ++ ++ profile_len = profile[1]; ++ next_profile = profile + (2 + profile_len); ++ mbssid_len -= (2 + profile_len); ++ ++ profile += 2; ++ profile_len -= (2 + profile[1]); ++ profile += (2 + profile[1]); /* nontx capabilities */ ++ profile_len -= (2 + profile[1]); ++ profile += (2 + profile[1]); /* SSID */ ++ if (profile[2] == arvif->vif->bss_conf.bssid_index) { ++ profile_len -= 5; ++ profile = profile + 5; ++ ath11k_mac_setup_nontx_vif_rsnie(arvif, ++ tx_arvif->rsnie_present, ++ profile, ++ profile_len); ++ return true; ++ } ++ profile = next_profile; ++ } ++ ies = cfg80211_find_ie(WLAN_EID_MULTIPLE_BSSID, profile, ++ ies_len); ++ } ++ ++ return false; ++} ++ + static void ath11k_mac_set_vif_params(struct ath11k_vif *arvif, + struct sk_buff *bcn) + { +@@ -1374,18 +1452,26 @@ static void ath11k_mac_set_vif_params(st + arvif->wpaie_present = false; + } + +-static int ath11k_mac_setup_bcn_tmpl(struct ath11k_vif *arvif) ++static int ath11k_mac_setup_bcn_tmpl_mbssid(struct ath11k_vif *arvif) + { + struct ath11k *ar = arvif->ar; + struct ath11k_base *ab = ar->ab; ++ struct ath11k_vif *tx_arvif = arvif; + struct ieee80211_hw *hw = ar->hw; + struct ieee80211_vif *vif = arvif->vif; + struct ieee80211_mutable_offsets offs = {}; + struct sk_buff *bcn; + int ret; + +- if (arvif->vdev_type != WMI_VDEV_TYPE_AP) +- return 0; ++ if (arvif->vif->mbssid_tx_vif) { ++ tx_arvif = (void *)arvif->vif->mbssid_tx_vif->drv_priv; ++ if (tx_arvif != arvif) { ++ ar = tx_arvif->ar; ++ ab = ar->ab; ++ hw = ar->hw; ++ vif = tx_arvif->vif; ++ } ++ } + + bcn = ieee80211_beacon_get_template(hw, vif, &offs, 0); + if (!bcn) { +@@ -1393,9 +1479,12 @@ static int ath11k_mac_setup_bcn_tmpl(str + return -EPERM; + } + +- ath11k_mac_set_vif_params(arvif, bcn); +- ret = ath11k_wmi_bcn_tmpl(ar, arvif->vdev_id, &offs, bcn); ++ if (tx_arvif == arvif) ++ ath11k_mac_set_vif_params(tx_arvif, bcn); ++ else if (!ath11k_mac_set_nontx_vif_params(tx_arvif, arvif, bcn)) ++ return -EINVAL; + ++ ret = ath11k_wmi_bcn_tmpl(ar, arvif->vdev_id, &offs, bcn); + kfree_skb(bcn); + + if (ret) +@@ -1405,6 +1494,23 @@ static int ath11k_mac_setup_bcn_tmpl(str + return ret; + } + ++static int ath11k_mac_setup_bcn_tmpl(struct ath11k_vif *arvif) ++{ ++ struct ieee80211_vif *vif = arvif->vif; ++ ++ if (arvif->vdev_type != WMI_VDEV_TYPE_AP) ++ return 0; ++ ++ /* Target does not expect beacon templates for the already up ++ * non-transmitting interfaces, and results in a crash if sent. ++ */ ++ if (vif->mbssid_tx_vif && ++ arvif != (void *)vif->mbssid_tx_vif->drv_priv && arvif->is_up) ++ return 0; ++ ++ return ath11k_mac_setup_bcn_tmpl_mbssid(arvif); ++} ++ + void ath11k_mac_bcn_tx_event(struct ath11k_vif *arvif) + { + struct ieee80211_vif *vif = arvif->vif; +--- a/drivers/net/wireless/ath/ath11k/wmi.c ++++ b/drivers/net/wireless/ath/ath11k/wmi.c +@@ -1737,6 +1737,7 @@ int ath11k_wmi_bcn_tmpl(struct ath11k *a + } + + cmd->buf_len = bcn->len; ++ cmd->mbssid_ie_offset = offs->mbssid_off; + + ptr = skb->data + sizeof(*cmd); + diff --git a/package/kernel/mac80211/patches/ath11k/0077-wifi-ath11k-EMA-beacon-support.patch b/package/kernel/mac80211/patches/ath11k/0077-wifi-ath11k-EMA-beacon-support.patch new file mode 100644 index 000000000..51353fa3e --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0077-wifi-ath11k-EMA-beacon-support.patch @@ -0,0 +1,156 @@ +From 87bd401138161008fdb82fbca6e213af117bfeb9 Mon Sep 17 00:00:00 2001 +From: Aloka Dixit +Date: Fri, 5 May 2023 16:11:28 +0300 +Subject: [PATCH 77/77] wifi: ath11k: EMA beacon support + +Add new function ath11k_mac_setup_bcn_tmpl_ema() which invokes the new +API provided by MAC80211 to retrieve EMA beacons. + +Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Aloka Dixit +Co-developed-by: John Crispin +Signed-off-by: John Crispin +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20230405221648.17950-8-quic_alokad@quicinc.com +--- + drivers/net/wireless/ath/ath11k/mac.c | 59 ++++++++++++++++++++++++++- + drivers/net/wireless/ath/ath11k/wmi.c | 3 +- + drivers/net/wireless/ath/ath11k/wmi.h | 11 ++++- + 3 files changed, 70 insertions(+), 3 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -1452,6 +1452,60 @@ static void ath11k_mac_set_vif_params(st + arvif->wpaie_present = false; + } + ++static int ath11k_mac_setup_bcn_tmpl_ema(struct ath11k_vif *arvif) ++{ ++ struct ath11k_vif *tx_arvif; ++ struct ieee80211_ema_beacons *beacons; ++ int ret = 0; ++ bool nontx_vif_params_set = false; ++ u32 params = 0; ++ u8 i = 0; ++ ++ tx_arvif = (void *)arvif->vif->mbssid_tx_vif->drv_priv; ++ ++ beacons = ieee80211_beacon_get_template_ema_list(tx_arvif->ar->hw, ++ tx_arvif->vif, 0); ++ if (!beacons || !beacons->cnt) { ++ ath11k_warn(arvif->ar->ab, ++ "failed to get ema beacon templates from mac80211\n"); ++ return -EPERM; ++ } ++ ++ if (tx_arvif == arvif) ++ ath11k_mac_set_vif_params(tx_arvif, beacons->bcn[0].skb); ++ else ++ arvif->wpaie_present = tx_arvif->wpaie_present; ++ ++ for (i = 0; i < beacons->cnt; i++) { ++ if (tx_arvif != arvif && !nontx_vif_params_set) ++ nontx_vif_params_set = ++ ath11k_mac_set_nontx_vif_params(tx_arvif, arvif, ++ beacons->bcn[i].skb); ++ ++ params = beacons->cnt; ++ params |= (i << WMI_EMA_TMPL_IDX_SHIFT); ++ params |= ((!i ? 1 : 0) << WMI_EMA_FIRST_TMPL_SHIFT); ++ params |= ((i + 1 == beacons->cnt ? 1 : 0) << WMI_EMA_LAST_TMPL_SHIFT); ++ ++ ret = ath11k_wmi_bcn_tmpl(tx_arvif->ar, tx_arvif->vdev_id, ++ &beacons->bcn[i].offs, ++ beacons->bcn[i].skb, params); ++ if (ret) { ++ ath11k_warn(tx_arvif->ar->ab, ++ "failed to set ema beacon template id %i error %d\n", ++ i, ret); ++ break; ++ } ++ } ++ ++ ieee80211_beacon_free_ema_list(beacons); ++ ++ if (tx_arvif != arvif && !nontx_vif_params_set) ++ return -EINVAL; /* Profile not found in the beacons */ ++ ++ return ret; ++} ++ + static int ath11k_mac_setup_bcn_tmpl_mbssid(struct ath11k_vif *arvif) + { + struct ath11k *ar = arvif->ar; +@@ -1484,7 +1538,7 @@ static int ath11k_mac_setup_bcn_tmpl_mbs + else if (!ath11k_mac_set_nontx_vif_params(tx_arvif, arvif, bcn)) + return -EINVAL; + +- ret = ath11k_wmi_bcn_tmpl(ar, arvif->vdev_id, &offs, bcn); ++ ret = ath11k_wmi_bcn_tmpl(ar, arvif->vdev_id, &offs, bcn, 0); + kfree_skb(bcn); + + if (ret) +@@ -1508,6 +1562,9 @@ static int ath11k_mac_setup_bcn_tmpl(str + arvif != (void *)vif->mbssid_tx_vif->drv_priv && arvif->is_up) + return 0; + ++ if (vif->bss_conf.ema_ap && vif->mbssid_tx_vif) ++ return ath11k_mac_setup_bcn_tmpl_ema(arvif); ++ + return ath11k_mac_setup_bcn_tmpl_mbssid(arvif); + } + +--- a/drivers/net/wireless/ath/ath11k/wmi.c ++++ b/drivers/net/wireless/ath/ath11k/wmi.c +@@ -1699,7 +1699,7 @@ int ath11k_wmi_send_bcn_offload_control_ + + int ath11k_wmi_bcn_tmpl(struct ath11k *ar, u32 vdev_id, + struct ieee80211_mutable_offsets *offs, +- struct sk_buff *bcn) ++ struct sk_buff *bcn, u32 ema_params) + { + struct ath11k_pdev_wmi *wmi = ar->wmi; + struct wmi_bcn_tmpl_cmd *cmd; +@@ -1738,6 +1738,7 @@ int ath11k_wmi_bcn_tmpl(struct ath11k *a + + cmd->buf_len = bcn->len; + cmd->mbssid_ie_offset = offs->mbssid_off; ++ cmd->ema_params = ema_params; + + ptr = skb->data + sizeof(*cmd); + +--- a/drivers/net/wireless/ath/ath11k/wmi.h ++++ b/drivers/net/wireless/ath/ath11k/wmi.h +@@ -3566,6 +3566,10 @@ struct wmi_get_pdev_temperature_cmd { + + #define WMI_BEACON_TX_BUFFER_SIZE 512 + ++#define WMI_EMA_TMPL_IDX_SHIFT 8 ++#define WMI_EMA_FIRST_TMPL_SHIFT 16 ++#define WMI_EMA_LAST_TMPL_SHIFT 24 ++ + struct wmi_bcn_tmpl_cmd { + u32 tlv_header; + u32 vdev_id; +@@ -3576,6 +3580,11 @@ struct wmi_bcn_tmpl_cmd { + u32 csa_event_bitmap; + u32 mbssid_ie_offset; + u32 esp_ie_offset; ++ u32 csc_switch_count_offset; ++ u32 csc_event_bitmap; ++ u32 mu_edca_ie_offset; ++ u32 feature_enable_bitmap; ++ u32 ema_params; + } __packed; + + struct wmi_key_seq_counter { +@@ -6298,7 +6307,7 @@ int ath11k_wmi_mgmt_send(struct ath11k * + struct sk_buff *frame); + int ath11k_wmi_bcn_tmpl(struct ath11k *ar, u32 vdev_id, + struct ieee80211_mutable_offsets *offs, +- struct sk_buff *bcn); ++ struct sk_buff *bcn, u32 ema_param); + int ath11k_wmi_vdev_down(struct ath11k *ar, u8 vdev_id); + int ath11k_wmi_vdev_up(struct ath11k *ar, u32 vdev_id, u32 aid, + const u8 *bssid, u8 *tx_bssid, u32 nontx_profile_idx, diff --git a/package/kernel/mac80211/patches/ath11k/0078-wifi-ath11k-Relocate-the-func-ath11k_mac_bitrate_mas.patch b/package/kernel/mac80211/patches/ath11k/0078-wifi-ath11k-Relocate-the-func-ath11k_mac_bitrate_mas.patch new file mode 100644 index 000000000..610bf7251 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0078-wifi-ath11k-Relocate-the-func-ath11k_mac_bitrate_mas.patch @@ -0,0 +1,75 @@ +From 570eec3d40505c30babbe3b8f85a38496c975ab2 Mon Sep 17 00:00:00 2001 +From: Maharaja Kennadyrajan +Date: Tue, 9 May 2023 20:07:23 +0300 +Subject: [PATCH] wifi: ath11k: Relocate the func + ath11k_mac_bitrate_mask_num_ht_rates() and change hweight16 to hweight8 + +Relocate the function ath11k_mac_bitrate_mask_num_ht_rates() definition +to call this function from other functions which helps to avoid the +compilation error (function not defined). + +ht_mcs[] is 1 byte array and it is enough to use hweight8() instead +of hweight16(). Hence, fixed the same. + +Tested on: Compile tested only. + +Signed-off-by: Maharaja Kennadyrajan +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20230504092033.3542456-2-quic_mkenna@quicinc.com +--- + drivers/net/wireless/ath/ath11k/mac.c | 30 +++++++++++++-------------- + 1 file changed, 15 insertions(+), 15 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -1,7 +1,7 @@ + // SPDX-License-Identifier: BSD-3-Clause-Clear + /* + * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. +- * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. ++ * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. + */ + + #include +@@ -4338,6 +4338,20 @@ exit: + } + + static int ++ath11k_mac_bitrate_mask_num_ht_rates(struct ath11k *ar, ++ enum nl80211_band band, ++ const struct cfg80211_bitrate_mask *mask) ++{ ++ int num_rates = 0; ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(mask->control[band].ht_mcs); i++) ++ num_rates += hweight8(mask->control[band].ht_mcs[i]); ++ ++ return num_rates; ++} ++ ++static int + ath11k_mac_bitrate_mask_num_vht_rates(struct ath11k *ar, + enum nl80211_band band, + const struct cfg80211_bitrate_mask *mask) +@@ -7791,20 +7805,6 @@ static void ath11k_mac_op_flush(struct i + ath11k_mac_flush_tx_complete(ar); + } + +-static int +-ath11k_mac_bitrate_mask_num_ht_rates(struct ath11k *ar, +- enum nl80211_band band, +- const struct cfg80211_bitrate_mask *mask) +-{ +- int num_rates = 0; +- int i; +- +- for (i = 0; i < ARRAY_SIZE(mask->control[band].ht_mcs); i++) +- num_rates += hweight16(mask->control[band].ht_mcs[i]); +- +- return num_rates; +-} +- + static bool + ath11k_mac_has_single_legacy_rate(struct ath11k *ar, + enum nl80211_band band, diff --git a/package/kernel/mac80211/patches/ath11k/0079-wifi-ath11k-Send-HT-fixed-rate-in-WMI-peer-fixed-par.patch b/package/kernel/mac80211/patches/ath11k/0079-wifi-ath11k-Send-HT-fixed-rate-in-WMI-peer-fixed-par.patch new file mode 100644 index 000000000..6282f4462 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0079-wifi-ath11k-Send-HT-fixed-rate-in-WMI-peer-fixed-par.patch @@ -0,0 +1,141 @@ +From df8e3729ffc0aa645839693f74ee7b6d999cdf64 Mon Sep 17 00:00:00 2001 +From: Maharaja Kennadyrajan +Date: Tue, 9 May 2023 20:07:24 +0300 +Subject: [PATCH] wifi: ath11k: Send HT fixed rate in WMI peer fixed param + +Due to the firmware behavior with HT fixed rate setting, +HT fixed rate MCS with NSS > 1 are treated as NSS = 1 +HT rates in the firmware and enables the HT fixed rate of +NSS = 1. + +This leads to HT fixed rate is always configured for NSS = 1 +even though the user sets NSS = 2 or > 1 HT fixed MCS in the +set bitrate command. + +Currently HT fixed MCS is sent via WMI peer assoc command. +Fix this issue, by sending the HT fixed rate MCS in WMI peer +fixed param instead of sending in peer assoc command. + +Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Maharaja Kennadyrajan +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20230504092033.3542456-3-quic_mkenna@quicinc.com +--- + drivers/net/wireless/ath/ath11k/mac.c | 63 ++++++++++++++++++++++++++- + 1 file changed, 61 insertions(+), 2 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -4480,6 +4480,54 @@ ath11k_mac_set_peer_he_fixed_rate(struct + return ret; + } + ++static int ++ath11k_mac_set_peer_ht_fixed_rate(struct ath11k_vif *arvif, ++ struct ieee80211_sta *sta, ++ const struct cfg80211_bitrate_mask *mask, ++ enum nl80211_band band) ++{ ++ struct ath11k *ar = arvif->ar; ++ u8 ht_rate, nss = 0; ++ u32 rate_code; ++ int ret, i; ++ ++ lockdep_assert_held(&ar->conf_mutex); ++ ++ for (i = 0; i < ARRAY_SIZE(mask->control[band].ht_mcs); i++) { ++ if (hweight8(mask->control[band].ht_mcs[i]) == 1) { ++ nss = i + 1; ++ ht_rate = ffs(mask->control[band].ht_mcs[i]) - 1; ++ } ++ } ++ ++ if (!nss) { ++ ath11k_warn(ar->ab, "No single HT Fixed rate found to set for %pM", ++ sta->addr); ++ return -EINVAL; ++ } ++ ++ /* Avoid updating invalid nss as fixed rate*/ ++ if (nss > sta->deflink.rx_nss) ++ return -EINVAL; ++ ++ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, ++ "Setting Fixed HT Rate for peer %pM. Device will not switch to any other selected rates", ++ sta->addr); ++ ++ rate_code = ATH11K_HW_RATE_CODE(ht_rate, nss - 1, ++ WMI_RATE_PREAMBLE_HT); ++ ret = ath11k_wmi_set_peer_param(ar, sta->addr, ++ arvif->vdev_id, ++ WMI_PEER_PARAM_FIXED_RATE, ++ rate_code); ++ if (ret) ++ ath11k_warn(ar->ab, ++ "failed to update STA %pM HT Fixed Rate %d: %d\n", ++ sta->addr, rate_code, ret); ++ ++ return ret; ++} ++ + static int ath11k_station_assoc(struct ath11k *ar, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, +@@ -4491,7 +4539,7 @@ static int ath11k_station_assoc(struct a + struct cfg80211_chan_def def; + enum nl80211_band band; + struct cfg80211_bitrate_mask *mask; +- u8 num_vht_rates, num_he_rates; ++ u8 num_ht_rates, num_vht_rates, num_he_rates; + + lockdep_assert_held(&ar->conf_mutex); + +@@ -4519,6 +4567,7 @@ static int ath11k_station_assoc(struct a + + num_vht_rates = ath11k_mac_bitrate_mask_num_vht_rates(ar, band, mask); + num_he_rates = ath11k_mac_bitrate_mask_num_he_rates(ar, band, mask); ++ num_ht_rates = ath11k_mac_bitrate_mask_num_ht_rates(ar, band, mask); + + /* If single VHT/HE rate is configured (by set_bitrate_mask()), + * peer_assoc will disable VHT/HE. This is now enabled by a peer specific +@@ -4535,6 +4584,11 @@ static int ath11k_station_assoc(struct a + band); + if (ret) + return ret; ++ } else if (sta->deflink.ht_cap.ht_supported && num_ht_rates == 1) { ++ ret = ath11k_mac_set_peer_ht_fixed_rate(arvif, sta, mask, ++ band); ++ if (ret) ++ return ret; + } + + /* Re-assoc is run only to update supported rates for given station. It +@@ -4608,7 +4662,7 @@ static void ath11k_sta_rc_update_wk(stru + const u16 *vht_mcs_mask; + const u16 *he_mcs_mask; + u32 changed, bw, nss, smps, bw_prev; +- int err, num_vht_rates, num_he_rates; ++ int err, num_ht_rates, num_vht_rates, num_he_rates; + const struct cfg80211_bitrate_mask *mask; + struct peer_assoc_params peer_arg; + enum wmi_phy_mode peer_phymode; +@@ -4724,6 +4778,8 @@ static void ath11k_sta_rc_update_wk(stru + + if (changed & IEEE80211_RC_SUPP_RATES_CHANGED) { + mask = &arvif->bitrate_mask; ++ num_ht_rates = ath11k_mac_bitrate_mask_num_ht_rates(ar, band, ++ mask); + num_vht_rates = ath11k_mac_bitrate_mask_num_vht_rates(ar, band, + mask); + num_he_rates = ath11k_mac_bitrate_mask_num_he_rates(ar, band, +@@ -4746,6 +4802,9 @@ static void ath11k_sta_rc_update_wk(stru + } else if (sta->deflink.he_cap.has_he && num_he_rates == 1) { + ath11k_mac_set_peer_he_fixed_rate(arvif, sta, mask, + band); ++ } else if (sta->deflink.ht_cap.ht_supported && num_ht_rates == 1) { ++ ath11k_mac_set_peer_ht_fixed_rate(arvif, sta, mask, ++ band); + } else { + /* If the peer is non-VHT/HE or no fixed VHT/HE rate + * is provided in the new bitrate mask we set the diff --git a/package/kernel/mac80211/patches/ath11k/0080-wifi-ath11k-add-support-default-regdb-while-searchin.patch b/package/kernel/mac80211/patches/ath11k/0080-wifi-ath11k-add-support-default-regdb-while-searchin.patch new file mode 100644 index 000000000..5ff40aac7 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0080-wifi-ath11k-add-support-default-regdb-while-searchin.patch @@ -0,0 +1,127 @@ +From 88ca89202f8e8afb5225eb5244d79cd67c15d744 Mon Sep 17 00:00:00 2001 +From: Wen Gong +Date: Fri, 26 May 2023 12:41:06 +0300 +Subject: [PATCH] wifi: ath11k: add support default regdb while searching + board-2.bin for WCN6855 + +Sometimes board-2.bin does not have the regdb data which matched the +parameters such as vendor, device, subsystem-vendor, subsystem-device +and etc. Add default regdb data with 'bus=%s' into board-2.bin for +WCN6855, then ath11k use 'bus=pci' to search regdb data in board-2.bin +for WCN6855. + +kernel: [ 122.515808] ath11k_pci 0000:03:00.0: boot using board name 'bus=pci,vendor=17cb,device=1103,subsystem-vendor=17cb,subsystem-device=3374,qmi-chip-id=2,qmi-board-id=262' +kernel: [ 122.517240] ath11k_pci 0000:03:00.0: boot firmware request ath11k/WCN6855/hw2.0/board-2.bin size 6179564 +kernel: [ 122.517280] ath11k_pci 0000:03:00.0: failed to fetch regdb data for bus=pci,vendor=17cb,device=1103,subsystem-vendor=17cb,subsystem-device=3374,qmi-chip-id=2,qmi-board-id=262 from ath11k/WCN6855/hw2.0/board-2.bin +kernel: [ 122.517464] ath11k_pci 0000:03:00.0: boot using board name 'bus=pci' +kernel: [ 122.518901] ath11k_pci 0000:03:00.0: boot firmware request ath11k/WCN6855/hw2.0/board-2.bin size 6179564 +kernel: [ 122.518915] ath11k_pci 0000:03:00.0: board name +kernel: [ 122.518917] ath11k_pci 0000:03:00.0: 00000000: 62 75 73 3d 70 63 69 bus=pci +kernel: [ 122.518918] ath11k_pci 0000:03:00.0: boot found match regdb data for name 'bus=pci' +kernel: [ 122.518920] ath11k_pci 0000:03:00.0: boot found regdb data for 'bus=pci' +kernel: [ 122.518921] ath11k_pci 0000:03:00.0: fetched regdb + +Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3 + +Signed-off-by: Wen Gong +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20230517133959.8224-1-quic_wgong@quicinc.com +--- + drivers/net/wireless/ath/ath11k/core.c | 53 +++++++++++++++++++------- + 1 file changed, 40 insertions(+), 13 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/core.c ++++ b/drivers/net/wireless/ath/ath11k/core.c +@@ -961,7 +961,8 @@ int ath11k_core_check_dt(struct ath11k_b + } + + static int __ath11k_core_create_board_name(struct ath11k_base *ab, char *name, +- size_t name_len, bool with_variant) ++ size_t name_len, bool with_variant, ++ bool bus_type_mode) + { + /* strlen(',variant=') + strlen(ab->qmi.target.bdf_ext) */ + char variant[9 + ATH11K_QMI_BDF_EXT_STR_LENGTH] = { 0 }; +@@ -972,15 +973,20 @@ static int __ath11k_core_create_board_na + + switch (ab->id.bdf_search) { + case ATH11K_BDF_SEARCH_BUS_AND_BOARD: +- scnprintf(name, name_len, +- "bus=%s,vendor=%04x,device=%04x,subsystem-vendor=%04x,subsystem-device=%04x,qmi-chip-id=%d,qmi-board-id=%d%s", +- ath11k_bus_str(ab->hif.bus), +- ab->id.vendor, ab->id.device, +- ab->id.subsystem_vendor, +- ab->id.subsystem_device, +- ab->qmi.target.chip_id, +- ab->qmi.target.board_id, +- variant); ++ if (bus_type_mode) ++ scnprintf(name, name_len, ++ "bus=%s", ++ ath11k_bus_str(ab->hif.bus)); ++ else ++ scnprintf(name, name_len, ++ "bus=%s,vendor=%04x,device=%04x,subsystem-vendor=%04x,subsystem-device=%04x,qmi-chip-id=%d,qmi-board-id=%d%s", ++ ath11k_bus_str(ab->hif.bus), ++ ab->id.vendor, ab->id.device, ++ ab->id.subsystem_vendor, ++ ab->id.subsystem_device, ++ ab->qmi.target.chip_id, ++ ab->qmi.target.board_id, ++ variant); + break; + default: + scnprintf(name, name_len, +@@ -999,13 +1005,19 @@ static int __ath11k_core_create_board_na + static int ath11k_core_create_board_name(struct ath11k_base *ab, char *name, + size_t name_len) + { +- return __ath11k_core_create_board_name(ab, name, name_len, true); ++ return __ath11k_core_create_board_name(ab, name, name_len, true, false); + } + + static int ath11k_core_create_fallback_board_name(struct ath11k_base *ab, char *name, + size_t name_len) + { +- return __ath11k_core_create_board_name(ab, name, name_len, false); ++ return __ath11k_core_create_board_name(ab, name, name_len, false, false); ++} ++ ++static int ath11k_core_create_bus_type_board_name(struct ath11k_base *ab, char *name, ++ size_t name_len) ++{ ++ return __ath11k_core_create_board_name(ab, name, name_len, false, true); + } + + const struct firmware *ath11k_core_firmware_request(struct ath11k_base *ab, +@@ -1309,7 +1321,7 @@ success: + + int ath11k_core_fetch_regdb(struct ath11k_base *ab, struct ath11k_board_data *bd) + { +- char boardname[BOARD_NAME_SIZE]; ++ char boardname[BOARD_NAME_SIZE], default_boardname[BOARD_NAME_SIZE]; + int ret; + + ret = ath11k_core_create_board_name(ab, boardname, BOARD_NAME_SIZE); +@@ -1323,6 +1335,21 @@ int ath11k_core_fetch_regdb(struct ath11 + ATH11K_BD_IE_REGDB, + ATH11K_BD_IE_REGDB_NAME, + ATH11K_BD_IE_REGDB_DATA); ++ if (!ret) ++ goto exit; ++ ++ ret = ath11k_core_create_bus_type_board_name(ab, default_boardname, ++ BOARD_NAME_SIZE); ++ if (ret) { ++ ath11k_dbg(ab, ATH11K_DBG_BOOT, ++ "failed to create default board name for regdb: %d", ret); ++ goto exit; ++ } ++ ++ ret = ath11k_core_fetch_board_data_api_n(ab, bd, default_boardname, ++ ATH11K_BD_IE_REGDB, ++ ATH11K_BD_IE_REGDB_NAME, ++ ATH11K_BD_IE_REGDB_DATA); + if (!ret) + goto exit; + diff --git a/package/kernel/mac80211/patches/ath11k/0081-wifi-ath11k-remove-unused-function-ath11k_tm_event_w.patch b/package/kernel/mac80211/patches/ath11k/0081-wifi-ath11k-remove-unused-function-ath11k_tm_event_w.patch new file mode 100644 index 000000000..b5dc83f00 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0081-wifi-ath11k-remove-unused-function-ath11k_tm_event_w.patch @@ -0,0 +1,128 @@ +From 86f85575a3f6a20cef1c8bb98e78585fe3a53ccc Mon Sep 17 00:00:00 2001 +From: Govindaraj Saminathan +Date: Fri, 26 May 2023 12:41:06 +0300 +Subject: [PATCH 82/84] wifi: ath11k: remove unused function + ath11k_tm_event_wmi() + +The function ath11k_tm_event_wmi() is only defined and it is not used +anywhere. Hence remove the unused. + +Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Govindaraj Saminathan +Signed-off-by: Raj Kumar Bhagat +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20230517135934.16408-2-quic_rajkbhag@quicinc.com +--- + drivers/net/wireless/ath/ath11k/testmode.c | 64 +--------------------- + drivers/net/wireless/ath/ath11k/testmode.h | 8 +-- + 2 files changed, 2 insertions(+), 70 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/testmode.c ++++ b/drivers/net/wireless/ath/ath11k/testmode.c +@@ -1,6 +1,7 @@ + // SPDX-License-Identifier: BSD-3-Clause-Clear + /* + * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. ++ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. + */ + + #include "testmode.h" +@@ -20,69 +21,6 @@ static const struct nla_policy ath11k_tm + [ATH11K_TM_ATTR_VERSION_MINOR] = { .type = NLA_U32 }, + }; + +-/* Returns true if callee consumes the skb and the skb should be discarded. +- * Returns false if skb is not used. Does not sleep. +- */ +-bool ath11k_tm_event_wmi(struct ath11k *ar, u32 cmd_id, struct sk_buff *skb) +-{ +- struct sk_buff *nl_skb; +- bool consumed; +- int ret; +- +- ath11k_dbg(ar->ab, ATH11K_DBG_TESTMODE, +- "testmode event wmi cmd_id %d skb %pK skb->len %d\n", +- cmd_id, skb, skb->len); +- +- ath11k_dbg_dump(ar->ab, ATH11K_DBG_TESTMODE, NULL, "", skb->data, skb->len); +- +- spin_lock_bh(&ar->data_lock); +- +- consumed = true; +- +- nl_skb = cfg80211_testmode_alloc_event_skb(ar->hw->wiphy, +- 2 * sizeof(u32) + skb->len, +- GFP_ATOMIC); +- if (!nl_skb) { +- ath11k_warn(ar->ab, +- "failed to allocate skb for testmode wmi event\n"); +- goto out; +- } +- +- ret = nla_put_u32(nl_skb, ATH11K_TM_ATTR_CMD, ATH11K_TM_CMD_WMI); +- if (ret) { +- ath11k_warn(ar->ab, +- "failed to put testmode wmi event cmd attribute: %d\n", +- ret); +- kfree_skb(nl_skb); +- goto out; +- } +- +- ret = nla_put_u32(nl_skb, ATH11K_TM_ATTR_WMI_CMDID, cmd_id); +- if (ret) { +- ath11k_warn(ar->ab, +- "failed to put testmode wmi even cmd_id: %d\n", +- ret); +- kfree_skb(nl_skb); +- goto out; +- } +- +- ret = nla_put(nl_skb, ATH11K_TM_ATTR_DATA, skb->len, skb->data); +- if (ret) { +- ath11k_warn(ar->ab, +- "failed to copy skb to testmode wmi event: %d\n", +- ret); +- kfree_skb(nl_skb); +- goto out; +- } +- +- cfg80211_testmode_event(nl_skb, GFP_ATOMIC); +- +-out: +- spin_unlock_bh(&ar->data_lock); +- +- return consumed; +-} +- + static int ath11k_tm_cmd_get_version(struct ath11k *ar, struct nlattr *tb[]) + { + struct sk_buff *skb; +--- a/drivers/net/wireless/ath/ath11k/testmode.h ++++ b/drivers/net/wireless/ath/ath11k/testmode.h +@@ -1,24 +1,18 @@ + /* SPDX-License-Identifier: BSD-3-Clause-Clear */ + /* + * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. ++ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. + */ + + #include "core.h" + + #ifdef CPTCFG_NL80211_TESTMODE + +-bool ath11k_tm_event_wmi(struct ath11k *ar, u32 cmd_id, struct sk_buff *skb); + int ath11k_tm_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + void *data, int len); + + #else + +-static inline bool ath11k_tm_event_wmi(struct ath11k *ar, u32 cmd_id, +- struct sk_buff *skb) +-{ +- return false; +-} +- + static inline int ath11k_tm_cmd(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + void *data, int len) diff --git a/package/kernel/mac80211/patches/ath11k/0082-wifi-ath11k-factory-test-mode-support.patch b/package/kernel/mac80211/patches/ath11k/0082-wifi-ath11k-factory-test-mode-support.patch new file mode 100644 index 000000000..f1b262724 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0082-wifi-ath11k-factory-test-mode-support.patch @@ -0,0 +1,850 @@ +From b43310e44edc823a7f02af1e1e2b4e8a9abc7d91 Mon Sep 17 00:00:00 2001 +From: Govindaraj Saminathan +Date: Fri, 26 May 2023 12:41:07 +0300 +Subject: [PATCH 83/84] wifi: ath11k: factory test mode support + +Add support to process factory test mode commands (FTM) for calibration. +By default firmware start with NORMAL mode and to process the FTM commands +firmware needs to be restarted in FTM mode using module parameter ftm_mode. +The pre-request is all the radios should be down before starting the test. + +When start command ATH11K_TM_CMD_TESTMODE_START is received, ar->state +is set to Test Mode. If the FTM command or event length is greater +than 256 bytes, it will be broken down into multiple segments and +encoded with TLV header if it is segmented commands, else it is sent +to firmware as it is. + +On receiving UTF event from firmware, if it is segmented event, the driver +will wait until it receives all the segments and notify the complete +data to user application. In case the segmented sequence are missed or +lost from the firmware, driver will skip the already received partial data. + +In case of unsegmented UTF event from firmware, driver notifies the +data to the user application as it comes. Applications handles +the data further. + +Command to boot in ftm mode: + +insmod ath11k ftm_mode=1 + +Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Govindaraj Saminathan +Co-developed-by: Sowmiya Sree Elavalagan +Signed-off-by: Sowmiya Sree Elavalagan +Signed-off-by: Raj Kumar Bhagat +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20230517135934.16408-4-quic_rajkbhag@quicinc.com +--- + drivers/net/wireless/ath/ath11k/ahb.c | 3 +- + drivers/net/wireless/ath/ath11k/core.c | 21 +- + drivers/net/wireless/ath/ath11k/core.h | 16 +- + drivers/net/wireless/ath/ath11k/debug.h | 1 + + drivers/net/wireless/ath/ath11k/mac.c | 11 +- + drivers/net/wireless/ath/ath11k/pci.c | 3 +- + drivers/net/wireless/ath/ath11k/testmode.c | 350 ++++++++++++++++++- + drivers/net/wireless/ath/ath11k/testmode.h | 6 + + drivers/net/wireless/ath/ath11k/testmode_i.h | 18 +- + drivers/net/wireless/ath/ath11k/wmi.c | 11 +- + drivers/net/wireless/ath/ath11k/wmi.h | 22 ++ + drivers/net/wireless/ath/ath11k/wow.c | 3 +- + 12 files changed, 444 insertions(+), 21 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/ahb.c ++++ b/drivers/net/wireless/ath/ath11k/ahb.c +@@ -1,7 +1,7 @@ + // SPDX-License-Identifier: BSD-3-Clause-Clear + /* + * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. +- * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. ++ * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. + */ + + #include +@@ -1155,6 +1155,7 @@ static int ath11k_ahb_probe(struct platf + ab->hif.ops = hif_ops; + ab->pdev = pdev; + ab->hw_rev = hw_rev; ++ ab->fw_mode = ATH11K_FIRMWARE_MODE_NORMAL; + platform_set_drvdata(pdev, ab); + + ret = ath11k_pcic_register_pci_ops(ab, pci_ops); +--- a/drivers/net/wireless/ath/ath11k/core.c ++++ b/drivers/net/wireless/ath/ath11k/core.c +@@ -1,7 +1,7 @@ + // SPDX-License-Identifier: BSD-3-Clause-Clear + /* + * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. +- * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. ++ * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. + */ + + #include +@@ -32,6 +32,10 @@ module_param_named(frame_mode, ath11k_fr + MODULE_PARM_DESC(frame_mode, + "Datapath frame mode (0: raw, 1: native wifi (default), 2: ethernet)"); + ++bool ath11k_ftm_mode; ++module_param_named(ftm_mode, ath11k_ftm_mode, bool, 0444); ++MODULE_PARM_DESC(ftm_mode, "Boots up in factory test mode"); ++ + static const struct ath11k_hw_params ath11k_hw_params[] = { + { + .hw_rev = ATH11K_HW_IPQ8074, +@@ -1381,6 +1385,11 @@ static int ath11k_core_soc_create(struct + { + int ret; + ++ if (ath11k_ftm_mode) { ++ ab->fw_mode = ATH11K_FIRMWARE_MODE_FTM; ++ ath11k_info(ab, "Booting in factory test mode\n"); ++ } ++ + ret = ath11k_qmi_init_service(ab); + if (ret) { + ath11k_err(ab, "failed to initialize qmi :%d\n", ret); +@@ -1607,7 +1616,7 @@ int ath11k_core_qmi_firmware_ready(struc + { + int ret; + +- ret = ath11k_core_start_firmware(ab, ATH11K_FIRMWARE_MODE_NORMAL); ++ ret = ath11k_core_start_firmware(ab, ab->fw_mode); + if (ret) { + ath11k_err(ab, "failed to start firmware: %d\n", ret); + return ret; +@@ -1772,7 +1781,8 @@ void ath11k_core_pre_reconfigure_recover + for (i = 0; i < ab->num_radios; i++) { + pdev = &ab->pdevs[i]; + ar = pdev->ar; +- if (!ar || ar->state == ATH11K_STATE_OFF) ++ if (!ar || ar->state == ATH11K_STATE_OFF || ++ ar->state == ATH11K_STATE_FTM) + continue; + + ieee80211_stop_queues(ar->hw); +@@ -1841,7 +1851,12 @@ static void ath11k_core_post_reconfigure + ath11k_warn(ab, + "device is wedged, will not restart radio %d\n", i); + break; ++ case ATH11K_STATE_FTM: ++ ath11k_dbg(ab, ATH11K_DBG_TESTMODE, ++ "fw mode reset done radio %d\n", i); ++ break; + } ++ + mutex_unlock(&ar->conf_mutex); + } + complete(&ab->driver_recovery); +--- a/drivers/net/wireless/ath/ath11k/core.h ++++ b/drivers/net/wireless/ath/ath11k/core.h +@@ -1,7 +1,7 @@ + /* SPDX-License-Identifier: BSD-3-Clause-Clear */ + /* + * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. +- * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. ++ * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. + */ + + #ifndef ATH11K_CORE_H +@@ -52,6 +52,7 @@ + #define ATH11K_SMBIOS_BDF_EXT_MAGIC "BDF_" + + extern unsigned int ath11k_frame_mode; ++extern bool ath11k_ftm_mode; + + #define ATH11K_SCAN_TIMEOUT_HZ (20 * HZ) + +@@ -277,6 +278,7 @@ enum ath11k_dev_flags { + ATH11K_FLAG_FIXED_MEM_RGN, + ATH11K_FLAG_DEVICE_INIT_DONE, + ATH11K_FLAG_MULTI_MSI_VECTORS, ++ ATH11K_FLAG_FTM_SEGMENTED, + }; + + enum ath11k_monitor_flags { +@@ -530,6 +532,7 @@ enum ath11k_state { + ATH11K_STATE_RESTARTING, + ATH11K_STATE_RESTARTED, + ATH11K_STATE_WEDGED, ++ ATH11K_STATE_FTM, + /* Add other states as required */ + }; + +@@ -709,6 +712,8 @@ struct ath11k { + u32 last_ppdu_id; + u32 cached_ppdu_id; + int monitor_vdev_id; ++ struct completion fw_mode_reset; ++ u8 ftm_msgref; + #ifdef CPTCFG_ATH11K_DEBUGFS + struct ath11k_debug debug; + #endif +@@ -838,6 +843,7 @@ struct ath11k_msi_config { + /* Master structure to hold the hw data which may be used in core module */ + struct ath11k_base { + enum ath11k_hw_rev hw_rev; ++ enum ath11k_firmware_mode fw_mode; + struct platform_device *pdev; + struct device *dev; + struct ath11k_qmi qmi; +@@ -978,6 +984,14 @@ struct ath11k_base { + const struct ath11k_pci_ops *ops; + } pci; + ++#ifdef CPTCFG_NL80211_TESTMODE ++ struct { ++ u32 data_pos; ++ u32 expected_seq; ++ u8 *eventdata; ++ } testmode; ++#endif ++ + /* must be last */ + u8 drv_priv[] __aligned(sizeof(void *)); + }; +--- a/drivers/net/wireless/ath/ath11k/debug.h ++++ b/drivers/net/wireless/ath/ath11k/debug.h +@@ -1,6 +1,7 @@ + /* SPDX-License-Identifier: BSD-3-Clause-Clear */ + /* + * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. ++ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. + */ + + #ifndef _ATH11K_DEBUG_H_ +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -643,7 +643,10 @@ struct ath11k *ath11k_mac_get_ar_by_pdev + return NULL; + + for (i = 0; i < ab->num_radios; i++) { +- pdev = rcu_dereference(ab->pdevs_active[i]); ++ if (ab->fw_mode == ATH11K_FIRMWARE_MODE_FTM) ++ pdev = &ab->pdevs[i]; ++ else ++ pdev = rcu_dereference(ab->pdevs_active[i]); + + if (pdev && pdev->pdev_id == pdev_id) + return (pdev->ar ? pdev->ar : NULL); +@@ -6271,6 +6274,11 @@ static int ath11k_mac_op_start(struct ie + struct ath11k_pdev *pdev = ar->pdev; + int ret; + ++ if (ath11k_ftm_mode) { ++ ath11k_warn(ab, "mac operations not supported in factory test mode\n"); ++ return -EOPNOTSUPP; ++ } ++ + ath11k_mac_drain_tx(ar); + mutex_lock(&ar->conf_mutex); + +@@ -6285,6 +6293,7 @@ static int ath11k_mac_op_start(struct ie + case ATH11K_STATE_RESTARTED: + case ATH11K_STATE_WEDGED: + case ATH11K_STATE_ON: ++ case ATH11K_STATE_FTM: + WARN_ON(1); + ret = -EINVAL; + goto err; +--- a/drivers/net/wireless/ath/ath11k/pci.c ++++ b/drivers/net/wireless/ath/ath11k/pci.c +@@ -1,7 +1,7 @@ + // SPDX-License-Identifier: BSD-3-Clause-Clear + /* + * Copyright (c) 2019-2020 The Linux Foundation. All rights reserved. +- * Copyright (c) 2021-2022, Qualcomm Innovation Center, Inc. All rights reserved. ++ * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. + */ + + #include +@@ -745,6 +745,7 @@ static int ath11k_pci_probe(struct pci_d + ab_pci->ab = ab; + ab_pci->pdev = pdev; + ab->hif.ops = &ath11k_pci_hif_ops; ++ ab->fw_mode = ATH11K_FIRMWARE_MODE_NORMAL; + pci_set_drvdata(pdev, ab); + spin_lock_init(&ab_pci->window_lock); + +--- a/drivers/net/wireless/ath/ath11k/testmode.c ++++ b/drivers/net/wireless/ath/ath11k/testmode.c +@@ -12,6 +12,9 @@ + #include "core.h" + #include "testmode_i.h" + ++#define ATH11K_FTM_SEGHDR_CURRENT_SEQ GENMASK(3, 0) ++#define ATH11K_FTM_SEGHDR_TOTAL_SEGMENTS GENMASK(7, 4) ++ + static const struct nla_policy ath11k_tm_policy[ATH11K_TM_ATTR_MAX + 1] = { + [ATH11K_TM_ATTR_CMD] = { .type = NLA_U32 }, + [ATH11K_TM_ATTR_DATA] = { .type = NLA_BINARY, +@@ -21,13 +24,217 @@ static const struct nla_policy ath11k_tm + [ATH11K_TM_ATTR_VERSION_MINOR] = { .type = NLA_U32 }, + }; + ++static struct ath11k *ath11k_tm_get_ar(struct ath11k_base *ab) ++{ ++ struct ath11k_pdev *pdev; ++ struct ath11k *ar = NULL; ++ int i; ++ ++ for (i = 0; i < ab->num_radios; i++) { ++ pdev = &ab->pdevs[i]; ++ ar = pdev->ar; ++ ++ if (ar && ar->state == ATH11K_STATE_FTM) ++ break; ++ } ++ ++ return ar; ++} ++ ++/* This function handles unsegmented events. Data in various events are aggregated ++ * in application layer, this event is unsegmented from host perspective. ++ */ ++static void ath11k_tm_wmi_event_unsegmented(struct ath11k_base *ab, u32 cmd_id, ++ struct sk_buff *skb) ++{ ++ struct sk_buff *nl_skb; ++ struct ath11k *ar; ++ ++ ath11k_dbg(ab, ATH11K_DBG_TESTMODE, ++ "event wmi cmd_id %d skb length %d\n", ++ cmd_id, skb->len); ++ ath11k_dbg_dump(ab, ATH11K_DBG_TESTMODE, NULL, "", skb->data, skb->len); ++ ++ ar = ath11k_tm_get_ar(ab); ++ if (!ar) { ++ ath11k_warn(ab, "testmode event not handled due to invalid pdev\n"); ++ return; ++ } ++ ++ spin_lock_bh(&ar->data_lock); ++ ++ nl_skb = cfg80211_testmode_alloc_event_skb(ar->hw->wiphy, ++ 2 * nla_total_size(sizeof(u32)) + ++ nla_total_size(skb->len), ++ GFP_ATOMIC); ++ if (!nl_skb) { ++ ath11k_warn(ab, ++ "failed to allocate skb for unsegmented testmode wmi event\n"); ++ goto out; ++ } ++ ++ if (nla_put_u32(nl_skb, ATH11K_TM_ATTR_CMD, ATH11K_TM_CMD_WMI) || ++ nla_put_u32(nl_skb, ATH11K_TM_ATTR_WMI_CMDID, cmd_id) || ++ nla_put(nl_skb, ATH11K_TM_ATTR_DATA, skb->len, skb->data)) { ++ ath11k_warn(ab, "failed to populate testmode unsegmented event\n"); ++ kfree_skb(nl_skb); ++ goto out; ++ } ++ ++ cfg80211_testmode_event(nl_skb, GFP_ATOMIC); ++ spin_unlock_bh(&ar->data_lock); ++ return; ++ ++out: ++ spin_unlock_bh(&ar->data_lock); ++ ath11k_warn(ab, "Failed to send testmode event to higher layers\n"); ++} ++ ++/* This function handles segmented events. Data of various events received ++ * from firmware is aggregated and sent to application layer ++ */ ++static int ath11k_tm_process_event(struct ath11k_base *ab, u32 cmd_id, ++ const struct wmi_ftm_event_msg *ftm_msg, ++ u16 length) ++{ ++ struct sk_buff *nl_skb; ++ int ret = 0; ++ struct ath11k *ar; ++ u8 const *buf_pos; ++ u16 datalen; ++ u8 total_segments, current_seq; ++ u32 data_pos; ++ u32 pdev_id; ++ ++ ath11k_dbg(ab, ATH11K_DBG_TESTMODE, ++ "event wmi cmd_id %d ftm event msg %pK datalen %d\n", ++ cmd_id, ftm_msg, length); ++ ath11k_dbg_dump(ab, ATH11K_DBG_TESTMODE, NULL, "", ftm_msg, length); ++ pdev_id = DP_HW2SW_MACID(ftm_msg->seg_hdr.pdev_id); ++ ++ if (pdev_id >= ab->num_radios) { ++ ath11k_warn(ab, "testmode event not handled due to invalid pdev id: %d\n", ++ pdev_id); ++ return -EINVAL; ++ } ++ ++ ar = ab->pdevs[pdev_id].ar; ++ if (!ar) { ++ ath11k_warn(ab, "testmode event not handled due to absence of pdev\n"); ++ return -ENODEV; ++ } ++ ++ current_seq = FIELD_GET(ATH11K_FTM_SEGHDR_CURRENT_SEQ, ++ ftm_msg->seg_hdr.segmentinfo); ++ total_segments = FIELD_GET(ATH11K_FTM_SEGHDR_TOTAL_SEGMENTS, ++ ftm_msg->seg_hdr.segmentinfo); ++ datalen = length - (sizeof(struct wmi_ftm_seg_hdr)); ++ buf_pos = ftm_msg->data; ++ ++ spin_lock_bh(&ar->data_lock); ++ ++ if (current_seq == 0) { ++ ab->testmode.expected_seq = 0; ++ ab->testmode.data_pos = 0; ++ } ++ ++ data_pos = ab->testmode.data_pos; ++ ++ if ((data_pos + datalen) > ATH11K_FTM_EVENT_MAX_BUF_LENGTH) { ++ ath11k_warn(ab, "Invalid ftm event length at %d: %d\n", ++ data_pos, datalen); ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ memcpy(&ab->testmode.eventdata[data_pos], buf_pos, datalen); ++ data_pos += datalen; ++ ++ if (++ab->testmode.expected_seq != total_segments) { ++ ab->testmode.data_pos = data_pos; ++ ath11k_dbg(ab, ATH11K_DBG_TESTMODE, ++ "partial data received current_seq %d total_seg %d\n", ++ current_seq, total_segments); ++ goto out; ++ } ++ ++ ath11k_dbg(ab, ATH11K_DBG_TESTMODE, ++ "total data length pos %d len %d\n", ++ data_pos, ftm_msg->seg_hdr.len); ++ nl_skb = cfg80211_testmode_alloc_event_skb(ar->hw->wiphy, ++ 2 * nla_total_size(sizeof(u32)) + ++ nla_total_size(data_pos), ++ GFP_ATOMIC); ++ if (!nl_skb) { ++ ath11k_warn(ab, ++ "failed to allocate skb for segmented testmode wmi event\n"); ++ ret = -ENOMEM; ++ goto out; ++ } ++ ++ if (nla_put_u32(nl_skb, ATH11K_TM_ATTR_CMD, ++ ATH11K_TM_CMD_WMI_FTM) || ++ nla_put_u32(nl_skb, ATH11K_TM_ATTR_WMI_CMDID, cmd_id) || ++ nla_put(nl_skb, ATH11K_TM_ATTR_DATA, data_pos, ++ &ab->testmode.eventdata[0])) { ++ ath11k_warn(ab, "failed to populate segmented testmode event"); ++ kfree_skb(nl_skb); ++ ret = -ENOBUFS; ++ goto out; ++ } ++ ++ cfg80211_testmode_event(nl_skb, GFP_ATOMIC); ++ ++out: ++ spin_unlock_bh(&ar->data_lock); ++ return ret; ++} ++ ++static void ath11k_tm_wmi_event_segmented(struct ath11k_base *ab, u32 cmd_id, ++ struct sk_buff *skb) ++{ ++ const void **tb; ++ const struct wmi_ftm_event_msg *ev; ++ u16 length; ++ int ret; ++ ++ tb = ath11k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC); ++ if (IS_ERR(tb)) { ++ ret = PTR_ERR(tb); ++ ath11k_warn(ab, "failed to parse ftm event tlv: %d\n", ret); ++ return; ++ } ++ ++ ev = tb[WMI_TAG_ARRAY_BYTE]; ++ if (!ev) { ++ ath11k_warn(ab, "failed to fetch ftm msg\n"); ++ kfree(tb); ++ return; ++ } ++ ++ length = skb->len - TLV_HDR_SIZE; ++ ret = ath11k_tm_process_event(ab, cmd_id, ev, length); ++ if (ret) ++ ath11k_warn(ab, "Failed to process ftm event\n"); ++ ++ kfree(tb); ++} ++ ++void ath11k_tm_wmi_event(struct ath11k_base *ab, u32 cmd_id, struct sk_buff *skb) ++{ ++ if (test_bit(ATH11K_FLAG_FTM_SEGMENTED, &ab->dev_flags)) ++ ath11k_tm_wmi_event_segmented(ab, cmd_id, skb); ++ else ++ ath11k_tm_wmi_event_unsegmented(ab, cmd_id, skb); ++} ++ + static int ath11k_tm_cmd_get_version(struct ath11k *ar, struct nlattr *tb[]) + { + struct sk_buff *skb; + int ret; + + ath11k_dbg(ar->ab, ATH11K_DBG_TESTMODE, +- "testmode cmd get version_major %d version_minor %d\n", ++ "cmd get version_major %d version_minor %d\n", + ATH11K_TESTMODE_VERSION_MAJOR, + ATH11K_TESTMODE_VERSION_MINOR); + +@@ -53,6 +260,43 @@ static int ath11k_tm_cmd_get_version(str + return cfg80211_testmode_reply(skb); + } + ++static int ath11k_tm_cmd_testmode_start(struct ath11k *ar, struct nlattr *tb[]) ++{ ++ int ret; ++ ++ mutex_lock(&ar->conf_mutex); ++ ++ if (ar->state == ATH11K_STATE_FTM) { ++ ret = -EALREADY; ++ goto err; ++ } ++ ++ /* start utf only when the driver is not in use */ ++ if (ar->state != ATH11K_STATE_OFF) { ++ ret = -EBUSY; ++ goto err; ++ } ++ ++ ar->ab->testmode.eventdata = kzalloc(ATH11K_FTM_EVENT_MAX_BUF_LENGTH, ++ GFP_KERNEL); ++ if (!ar->ab->testmode.eventdata) { ++ ret = -ENOMEM; ++ goto err; ++ } ++ ++ ar->state = ATH11K_STATE_FTM; ++ ar->ftm_msgref = 0; ++ ++ mutex_unlock(&ar->conf_mutex); ++ ++ ath11k_dbg(ar->ab, ATH11K_DBG_TESTMODE, "cmd start\n"); ++ return 0; ++ ++err: ++ mutex_unlock(&ar->conf_mutex); ++ return ret; ++} ++ + static int ath11k_tm_cmd_wmi(struct ath11k *ar, struct nlattr *tb[]) + { + struct ath11k_pdev_wmi *wmi = ar->wmi; +@@ -63,11 +307,6 @@ static int ath11k_tm_cmd_wmi(struct ath1 + + mutex_lock(&ar->conf_mutex); + +- if (ar->state != ATH11K_STATE_ON) { +- ret = -ENETDOWN; +- goto out; +- } +- + if (!tb[ATH11K_TM_ATTR_DATA]) { + ret = -EINVAL; + goto out; +@@ -80,11 +319,17 @@ static int ath11k_tm_cmd_wmi(struct ath1 + + buf = nla_data(tb[ATH11K_TM_ATTR_DATA]); + buf_len = nla_len(tb[ATH11K_TM_ATTR_DATA]); ++ if (!buf_len) { ++ ath11k_warn(ar->ab, "No data present in testmode wmi command\n"); ++ ret = -EINVAL; ++ goto out; ++ } ++ + cmd_id = nla_get_u32(tb[ATH11K_TM_ATTR_WMI_CMDID]); + + ath11k_dbg(ar->ab, ATH11K_DBG_TESTMODE, +- "testmode cmd wmi cmd_id %d buf %pK buf_len %d\n", +- cmd_id, buf, buf_len); ++ "cmd wmi cmd_id %d buf length %d\n", ++ cmd_id, buf_len); + + ath11k_dbg_dump(ar->ab, ATH11K_DBG_TESTMODE, NULL, "", buf, buf_len); + +@@ -111,6 +356,91 @@ out: + return ret; + } + ++static int ath11k_tm_cmd_wmi_ftm(struct ath11k *ar, struct nlattr *tb[]) ++{ ++ struct ath11k_pdev_wmi *wmi = ar->wmi; ++ struct ath11k_base *ab = ar->ab; ++ struct sk_buff *skb; ++ u32 cmd_id, buf_len, hdr_info; ++ int ret; ++ void *buf; ++ u8 segnumber = 0, seginfo; ++ u16 chunk_len, total_bytes, num_segments; ++ u8 *bufpos; ++ struct wmi_ftm_cmd *ftm_cmd; ++ ++ set_bit(ATH11K_FLAG_FTM_SEGMENTED, &ab->dev_flags); ++ ++ mutex_lock(&ar->conf_mutex); ++ ++ if (ar->state != ATH11K_STATE_FTM) { ++ ret = -ENETDOWN; ++ goto out; ++ } ++ ++ if (!tb[ATH11K_TM_ATTR_DATA]) { ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ buf = nla_data(tb[ATH11K_TM_ATTR_DATA]); ++ buf_len = nla_len(tb[ATH11K_TM_ATTR_DATA]); ++ cmd_id = WMI_PDEV_UTF_CMDID; ++ ++ ath11k_dbg(ar->ab, ATH11K_DBG_TESTMODE, ++ "cmd wmi ftm cmd_id %d buffer length %d\n", ++ cmd_id, buf_len); ++ ath11k_dbg_dump(ar->ab, ATH11K_DBG_TESTMODE, NULL, "", buf, buf_len); ++ ++ bufpos = buf; ++ total_bytes = buf_len; ++ num_segments = total_bytes / MAX_WMI_UTF_LEN; ++ ++ if (buf_len - (num_segments * MAX_WMI_UTF_LEN)) ++ num_segments++; ++ ++ while (buf_len) { ++ chunk_len = min_t(u16, buf_len, MAX_WMI_UTF_LEN); ++ ++ skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, (chunk_len + ++ sizeof(struct wmi_ftm_cmd))); ++ if (!skb) { ++ ret = -ENOMEM; ++ goto out; ++ } ++ ++ ftm_cmd = (struct wmi_ftm_cmd *)skb->data; ++ hdr_info = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_ARRAY_BYTE) | ++ FIELD_PREP(WMI_TLV_LEN, (chunk_len + ++ sizeof(struct wmi_ftm_seg_hdr))); ++ ftm_cmd->tlv_header = hdr_info; ++ ftm_cmd->seg_hdr.len = total_bytes; ++ ftm_cmd->seg_hdr.msgref = ar->ftm_msgref; ++ seginfo = FIELD_PREP(ATH11K_FTM_SEGHDR_TOTAL_SEGMENTS, num_segments) | ++ FIELD_PREP(ATH11K_FTM_SEGHDR_CURRENT_SEQ, segnumber); ++ ftm_cmd->seg_hdr.segmentinfo = seginfo; ++ segnumber++; ++ ++ memcpy(&ftm_cmd->data, bufpos, chunk_len); ++ ++ ret = ath11k_wmi_cmd_send(wmi, skb, cmd_id); ++ if (ret) { ++ ath11k_warn(ar->ab, "failed to send wmi ftm command: %d\n", ret); ++ goto out; ++ } ++ ++ buf_len -= chunk_len; ++ bufpos += chunk_len; ++ } ++ ++ ar->ftm_msgref++; ++ ret = 0; ++ ++out: ++ mutex_unlock(&ar->conf_mutex); ++ return ret; ++} ++ + int ath11k_tm_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + void *data, int len) + { +@@ -131,6 +461,10 @@ int ath11k_tm_cmd(struct ieee80211_hw *h + return ath11k_tm_cmd_get_version(ar, tb); + case ATH11K_TM_CMD_WMI: + return ath11k_tm_cmd_wmi(ar, tb); ++ case ATH11K_TM_CMD_TESTMODE_START: ++ return ath11k_tm_cmd_testmode_start(ar, tb); ++ case ATH11K_TM_CMD_WMI_FTM: ++ return ath11k_tm_cmd_wmi_ftm(ar, tb); + default: + return -EOPNOTSUPP; + } +--- a/drivers/net/wireless/ath/ath11k/testmode.h ++++ b/drivers/net/wireless/ath/ath11k/testmode.h +@@ -8,11 +8,17 @@ + + #ifdef CPTCFG_NL80211_TESTMODE + ++void ath11k_tm_wmi_event(struct ath11k_base *ab, u32 cmd_id, struct sk_buff *skb); + int ath11k_tm_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + void *data, int len); + + #else + ++static inline void ath11k_tm_wmi_event(struct ath11k_base *ab, u32 cmd_id, ++ struct sk_buff *skb) ++{ ++} ++ + static inline int ath11k_tm_cmd(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + void *data, int len) +--- a/drivers/net/wireless/ath/ath11k/testmode_i.h ++++ b/drivers/net/wireless/ath/ath11k/testmode_i.h +@@ -1,6 +1,7 @@ + /* SPDX-License-Identifier: BSD-3-Clause-Clear */ + /* + * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. ++ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. + */ + + /* "API" level of the ath11k testmode interface. Bump it after every +@@ -11,9 +12,10 @@ + /* Bump this after every _compatible_ interface change, for example + * addition of a new command or an attribute. + */ +-#define ATH11K_TESTMODE_VERSION_MINOR 0 ++#define ATH11K_TESTMODE_VERSION_MINOR 1 + + #define ATH11K_TM_DATA_MAX_LEN 5000 ++#define ATH11K_FTM_EVENT_MAX_BUF_LENGTH 2048 + + enum ath11k_tm_attr { + __ATH11K_TM_ATTR_INVALID = 0, +@@ -47,4 +49,18 @@ enum ath11k_tm_cmd { + * ATH11K_TM_ATTR_DATA. + */ + ATH11K_TM_CMD_WMI = 1, ++ ++ /* Boots the UTF firmware, the netdev interface must be down at the ++ * time. ++ */ ++ ATH11K_TM_CMD_TESTMODE_START = 2, ++ ++ /* The command used to transmit a FTM WMI command to the firmware ++ * and the event to receive WMI events from the firmware. The data ++ * received only contain the payload, need to add the tlv header ++ * and send the cmd to firmware with command id WMI_PDEV_UTF_CMDID. ++ * The data payload size could be large and the driver needs to ++ * send segmented data to firmware. ++ */ ++ ATH11K_TM_CMD_WMI_FTM = 3, + }; +--- a/drivers/net/wireless/ath/ath11k/wmi.c ++++ b/drivers/net/wireless/ath/ath11k/wmi.c +@@ -1,7 +1,7 @@ + // SPDX-License-Identifier: BSD-3-Clause-Clear + /* + * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. +- * Copyright (c) 2021, Qualcomm Innovation Center, Inc. All rights reserved. ++ * Copyright (c) 2021, 2023 Qualcomm Innovation Center, Inc. All rights reserved. + */ + #include + #include +@@ -19,6 +19,7 @@ + #include "mac.h" + #include "hw.h" + #include "peer.h" ++#include "testmode.h" + + struct wmi_tlv_policy { + size_t min_len; +@@ -237,9 +238,8 @@ static int ath11k_wmi_tlv_parse(struct a + (void *)tb); + } + +-static const void ** +-ath11k_wmi_tlv_parse_alloc(struct ath11k_base *ab, const void *ptr, +- size_t len, gfp_t gfp) ++const void **ath11k_wmi_tlv_parse_alloc(struct ath11k_base *ab, const void *ptr, ++ size_t len, gfp_t gfp) + { + const void **tb; + int ret; +@@ -8628,6 +8628,9 @@ static void ath11k_wmi_tlv_op_rx(struct + case WMI_PDEV_CSA_SWITCH_COUNT_STATUS_EVENTID: + ath11k_wmi_pdev_csa_switch_count_status_event(ab, skb); + break; ++ case WMI_PDEV_UTF_EVENTID: ++ ath11k_tm_wmi_event(ab, id, skb); ++ break; + case WMI_PDEV_TEMPERATURE_EVENTID: + ath11k_wmi_pdev_temperature_event(ab, skb); + break; +--- a/drivers/net/wireless/ath/ath11k/wmi.h ++++ b/drivers/net/wireless/ath/ath11k/wmi.h +@@ -1,6 +1,7 @@ + /* SPDX-License-Identifier: BSD-3-Clause-Clear */ + /* + * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. ++ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. + */ + + #ifndef ATH11K_WMI_H +@@ -68,6 +69,7 @@ struct wmi_tlv { + + #define WMI_APPEND_TO_EXISTING_CHAN_LIST_FLAG 1 + ++#define MAX_WMI_UTF_LEN 252 + #define WMI_BA_MODE_BUFFER_SIZE_256 3 + /* + * HW mode config type replicated from FW header +@@ -3564,6 +3566,24 @@ struct wmi_get_pdev_temperature_cmd { + u32 pdev_id; + } __packed; + ++struct wmi_ftm_seg_hdr { ++ u32 len; ++ u32 msgref; ++ u32 segmentinfo; ++ u32 pdev_id; ++} __packed; ++ ++struct wmi_ftm_cmd { ++ u32 tlv_header; ++ struct wmi_ftm_seg_hdr seg_hdr; ++ u8 data[]; ++} __packed; ++ ++struct wmi_ftm_event_msg { ++ struct wmi_ftm_seg_hdr seg_hdr; ++ u8 data[]; ++} __packed; ++ + #define WMI_BEACON_TX_BUFFER_SIZE 512 + + #define WMI_EMA_TMPL_IDX_SHIFT 8 +@@ -6300,6 +6320,8 @@ enum wmi_sta_keepalive_method { + #define WMI_STA_KEEPALIVE_INTERVAL_DEFAULT 30 + #define WMI_STA_KEEPALIVE_INTERVAL_DISABLE 0 + ++const void **ath11k_wmi_tlv_parse_alloc(struct ath11k_base *ab, const void *ptr, ++ size_t len, gfp_t gfp); + int ath11k_wmi_cmd_send(struct ath11k_pdev_wmi *wmi, struct sk_buff *skb, + u32 cmd_id); + struct sk_buff *ath11k_wmi_alloc_skb(struct ath11k_wmi_base *wmi_sc, u32 len); +--- a/drivers/net/wireless/ath/ath11k/wow.c ++++ b/drivers/net/wireless/ath/ath11k/wow.c +@@ -1,7 +1,7 @@ + // SPDX-License-Identifier: BSD-3-Clause-Clear + /* + * Copyright (c) 2020 The Linux Foundation. All rights reserved. +- * Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved. ++ * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. + */ + + #include +@@ -838,6 +838,7 @@ exit: + case ATH11K_STATE_RESTARTING: + case ATH11K_STATE_RESTARTED: + case ATH11K_STATE_WEDGED: ++ case ATH11K_STATE_FTM: + ath11k_warn(ar->ab, "encountered unexpected device state %d on resume, cannot recover\n", + ar->state); + ret = -EIO; diff --git a/package/kernel/mac80211/patches/ath11k/0083-wifi-ath11k-Allow-ath11k-to-boot-without-caldata-in-.patch b/package/kernel/mac80211/patches/ath11k/0083-wifi-ath11k-Allow-ath11k-to-boot-without-caldata-in-.patch new file mode 100644 index 000000000..5a1fa8829 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0083-wifi-ath11k-Allow-ath11k-to-boot-without-caldata-in-.patch @@ -0,0 +1,47 @@ +From 8aeba427296bff6a6051686f1d139c89a0b00e4c Mon Sep 17 00:00:00 2001 +From: Sowmiya Sree Elavalagan +Date: Fri, 26 May 2023 12:41:07 +0300 +Subject: [PATCH 84/84] wifi: ath11k: Allow ath11k to boot without caldata in + ftm mode + +Currently, if ath11k is unable to load the calibration data file it will +always exit. However the calibration data may not be present in factory +test mode, so update the logic to allow the driver to execute in FTM mode +even if downloading the calibration data fails. + +Tested-on : IPQ8074 hw2.0 AHB WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Sowmiya Sree Elavalagan +Signed-off-by: Raj Kumar Bhagat +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20230517135934.16408-5-quic_rajkbhag@quicinc.com +--- + drivers/net/wireless/ath/ath11k/qmi.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +--- a/drivers/net/wireless/ath/ath11k/qmi.c ++++ b/drivers/net/wireless/ath/ath11k/qmi.c +@@ -1,7 +1,7 @@ + // SPDX-License-Identifier: BSD-3-Clause-Clear + /* + * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. +- * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. ++ * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. + */ + + #include +@@ -2460,6 +2460,14 @@ static int ath11k_qmi_load_bdf_qmi(struc + + fw_entry = ath11k_core_firmware_request(ab, ATH11K_DEFAULT_CAL_FILE); + if (IS_ERR(fw_entry)) { ++ /* Caldata may not be present during first time calibration in ++ * factory hence allow to boot without loading caldata in ftm mode ++ */ ++ if (ath11k_ftm_mode) { ++ ath11k_info(ab, ++ "Booting without cal data file in factory test mode\n"); ++ return 0; ++ } + ret = PTR_ERR(fw_entry); + ath11k_warn(ab, + "qmi failed to load CAL data file:%s\n", diff --git a/package/kernel/mac80211/patches/ath11k/0084-wifi-ath11k-Add-HTT-stats-for-PHY-reset-case.patch b/package/kernel/mac80211/patches/ath11k/0084-wifi-ath11k-Add-HTT-stats-for-PHY-reset-case.patch new file mode 100644 index 000000000..946f5f7b5 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0084-wifi-ath11k-Add-HTT-stats-for-PHY-reset-case.patch @@ -0,0 +1,261 @@ +From 2d4f9093e2d8531ad0a2bb98fe5b36dc8addf2a2 Mon Sep 17 00:00:00 2001 +From: Nidhi Jain +Date: Fri, 26 May 2023 12:41:07 +0300 +Subject: [PATCH] wifi: ath11k: Add HTT stats for PHY reset case + +New HTT stats are added with stats type 37 to +provide PHY reset stats and PHY reset counter stats. + +PHY reset stats are used to display the current +PHY-related operation information such as band, CCA +threshold, current operating channel etc., + +PHY reset counter stats are used to display the +PHY reset counter values like calibration counts, +temperature based recalibration counts etc., + +Usage: +echo 37 > /sys/kernel/debug/ieee80211/phyX/ath11k/htt_stats_type +cat /sys/kernel/debug/ieee80211/phyx/ath11k/htt_stats + +Output: + +HTT_PHY_RESET_STATS_TLV: +pdev_id = 0 +chan_mhz = 5180 +chan_band_center_freq1 = 5210 +chan_band_center_freq2 = 0 +chan_phy_mode = 18 +chan_flags = 0x8 +chan_num = 36 +reset_cause = 0x50000 +prev_reset_cause = 0x50000 +phy_warm_reset_src = 0x0 +rx_gain_tbl_mode = 0 +xbar_val = 0xfac688 +force_calibration = 0 +phyrf_mode = 0 +phy_homechan = 0 +phy_tx_ch_mask = 0x3 +phy_rx_ch_mask = 0x3 +phybb_ini_mask = 0x5 +phyrf_ini_mask = 0x0 +phy_dfs_en_mask = 0x0 +phy_sscan_en_mask = 0x0 +phy_synth_sel_mask = 0x0 +phy_adfs_freq = 0 +cck_fir_settings = 0x0 +phy_dyn_pri_chan = 6 +cca_thresh = 0x26232020 +dyn_cca_status = 0 +rxdesense_thresh_hw = 0xcfe0afe +rxdesense_thresh_sw = 0xcfe0afe + +HTT_PHY_RESET_COUNTERS_TLV: +pdev_id = 0 +cf_active_low_fail_cnt = 0 +cf_active_low_pass_cnt = 0 +phy_off_through_vreg_cnt = 0 +force_calibration_cnt = 0 +rf_mode_switch_phy_off_cnt = 0 + +Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Nidhi Jain +Signed-off-by: Maharaja Kennadyrajan +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20230517141242.2754293-1-quic_mkenna@quicinc.com +--- + .../wireless/ath/ath11k/debugfs_htt_stats.c | 114 ++++++++++++++++++ + .../wireless/ath/ath11k/debugfs_htt_stats.h | 43 +++++++ + 2 files changed, 157 insertions(+) + +--- a/drivers/net/wireless/ath/ath11k/debugfs_htt_stats.c ++++ b/drivers/net/wireless/ath/ath11k/debugfs_htt_stats.c +@@ -4011,6 +4011,114 @@ void htt_print_phy_stats_tlv(const void + stats_req->buf_len = len; + } + ++static inline void ++htt_print_phy_reset_counters_tlv(const void *tag_buf, ++ u16 tag_len, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_phy_reset_counters_tlv *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH11K_HTT_STATS_BUF_SIZE; ++ ++ if (tag_len < sizeof(*htt_stats_buf)) ++ return; ++ ++ len += scnprintf(buf + len, buf_len - len, "HTT_PHY_RESET_COUNTERS_TLV:\n"); ++ ++ len += scnprintf(buf + len, buf_len - len, "pdev_id = %u\n", ++ htt_stats_buf->pdev_id); ++ len += scnprintf(buf + len, buf_len - len, "cf_active_low_fail_cnt = %u\n", ++ htt_stats_buf->cf_active_low_fail_cnt); ++ len += scnprintf(buf + len, buf_len - len, "cf_active_low_pass_cnt = %u\n", ++ htt_stats_buf->cf_active_low_pass_cnt); ++ len += scnprintf(buf + len, buf_len - len, "phy_off_through_vreg_cnt = %u\n", ++ htt_stats_buf->phy_off_through_vreg_cnt); ++ len += scnprintf(buf + len, buf_len - len, "force_calibration_cnt = %u\n", ++ htt_stats_buf->force_calibration_cnt); ++ len += scnprintf(buf + len, buf_len - len, "rf_mode_switch_phy_off_cnt = %u\n", ++ htt_stats_buf->rf_mode_switch_phy_off_cnt); ++ ++ stats_req->buf_len = len; ++} ++ ++static inline void ++htt_print_phy_reset_stats_tlv(const void *tag_buf, ++ u16 tag_len, ++ struct debug_htt_stats_req *stats_req) ++{ ++ const struct htt_phy_reset_stats_tlv *htt_stats_buf = tag_buf; ++ u8 *buf = stats_req->buf; ++ u32 len = stats_req->buf_len; ++ u32 buf_len = ATH11K_HTT_STATS_BUF_SIZE; ++ ++ if (tag_len < sizeof(*htt_stats_buf)) ++ return; ++ ++ len += scnprintf(buf + len, buf_len - len, "HTT_PHY_RESET_STATS_TLV:\n"); ++ ++ len += scnprintf(buf + len, buf_len - len, "pdev_id = %u\n", ++ htt_stats_buf->pdev_id); ++ len += scnprintf(buf + len, buf_len - len, "chan_mhz = %u\n", ++ htt_stats_buf->chan_mhz); ++ len += scnprintf(buf + len, buf_len - len, "chan_band_center_freq1 = %u\n", ++ htt_stats_buf->chan_band_center_freq1); ++ len += scnprintf(buf + len, buf_len - len, "chan_band_center_freq2 = %u\n", ++ htt_stats_buf->chan_band_center_freq2); ++ len += scnprintf(buf + len, buf_len - len, "chan_phy_mode = %u\n", ++ htt_stats_buf->chan_phy_mode); ++ len += scnprintf(buf + len, buf_len - len, "chan_flags = 0x%0x\n", ++ htt_stats_buf->chan_flags); ++ len += scnprintf(buf + len, buf_len - len, "chan_num = %u\n", ++ htt_stats_buf->chan_num); ++ len += scnprintf(buf + len, buf_len - len, "reset_cause = 0x%0x\n", ++ htt_stats_buf->reset_cause); ++ len += scnprintf(buf + len, buf_len - len, "prev_reset_cause = 0x%0x\n", ++ htt_stats_buf->prev_reset_cause); ++ len += scnprintf(buf + len, buf_len - len, "phy_warm_reset_src = 0x%0x\n", ++ htt_stats_buf->phy_warm_reset_src); ++ len += scnprintf(buf + len, buf_len - len, "rx_gain_tbl_mode = %d\n", ++ htt_stats_buf->rx_gain_tbl_mode); ++ len += scnprintf(buf + len, buf_len - len, "xbar_val = 0x%0x\n", ++ htt_stats_buf->xbar_val); ++ len += scnprintf(buf + len, buf_len - len, "force_calibration = %u\n", ++ htt_stats_buf->force_calibration); ++ len += scnprintf(buf + len, buf_len - len, "phyrf_mode = %u\n", ++ htt_stats_buf->phyrf_mode); ++ len += scnprintf(buf + len, buf_len - len, "phy_homechan = %u\n", ++ htt_stats_buf->phy_homechan); ++ len += scnprintf(buf + len, buf_len - len, "phy_tx_ch_mask = 0x%0x\n", ++ htt_stats_buf->phy_tx_ch_mask); ++ len += scnprintf(buf + len, buf_len - len, "phy_rx_ch_mask = 0x%0x\n", ++ htt_stats_buf->phy_rx_ch_mask); ++ len += scnprintf(buf + len, buf_len - len, "phybb_ini_mask = 0x%0x\n", ++ htt_stats_buf->phybb_ini_mask); ++ len += scnprintf(buf + len, buf_len - len, "phyrf_ini_mask = 0x%0x\n", ++ htt_stats_buf->phyrf_ini_mask); ++ len += scnprintf(buf + len, buf_len - len, "phy_dfs_en_mask = 0x%0x\n", ++ htt_stats_buf->phy_dfs_en_mask); ++ len += scnprintf(buf + len, buf_len - len, "phy_sscan_en_mask = 0x%0x\n", ++ htt_stats_buf->phy_sscan_en_mask); ++ len += scnprintf(buf + len, buf_len - len, "phy_synth_sel_mask = 0x%0x\n", ++ htt_stats_buf->phy_synth_sel_mask); ++ len += scnprintf(buf + len, buf_len - len, "phy_adfs_freq = %u\n", ++ htt_stats_buf->phy_adfs_freq); ++ len += scnprintf(buf + len, buf_len - len, "cck_fir_settings = 0x%0x\n", ++ htt_stats_buf->cck_fir_settings); ++ len += scnprintf(buf + len, buf_len - len, "phy_dyn_pri_chan = %u\n", ++ htt_stats_buf->phy_dyn_pri_chan); ++ len += scnprintf(buf + len, buf_len - len, "cca_thresh = 0x%0x\n", ++ htt_stats_buf->cca_thresh); ++ len += scnprintf(buf + len, buf_len - len, "dyn_cca_status = %u\n", ++ htt_stats_buf->dyn_cca_status); ++ len += scnprintf(buf + len, buf_len - len, "rxdesense_thresh_hw = 0x%x\n", ++ htt_stats_buf->rxdesense_thresh_hw); ++ len += scnprintf(buf + len, buf_len - len, "rxdesense_thresh_sw = 0x%x\n", ++ htt_stats_buf->rxdesense_thresh_sw); ++ ++ stats_req->buf_len = len; ++} ++ + static inline + void htt_print_peer_ctrl_path_txrx_stats_tlv(const void *tag_buf, + struct debug_htt_stats_req *stats_req) +@@ -4425,6 +4533,12 @@ static int ath11k_dbg_htt_ext_stats_pars + case HTT_STATS_PHY_STATS_TAG: + htt_print_phy_stats_tlv(tag_buf, stats_req); + break; ++ case HTT_STATS_PHY_RESET_COUNTERS_TAG: ++ htt_print_phy_reset_counters_tlv(tag_buf, len, stats_req); ++ break; ++ case HTT_STATS_PHY_RESET_STATS_TAG: ++ htt_print_phy_reset_stats_tlv(tag_buf, len, stats_req); ++ break; + case HTT_STATS_PEER_CTRL_PATH_TXRX_STATS_TAG: + htt_print_peer_ctrl_path_txrx_stats_tlv(tag_buf, stats_req); + break; +--- a/drivers/net/wireless/ath/ath11k/debugfs_htt_stats.h ++++ b/drivers/net/wireless/ath/ath11k/debugfs_htt_stats.h +@@ -111,6 +111,8 @@ enum htt_tlv_tag_t { + HTT_STATS_TXBF_OFDMA_STEER_STATS_TAG = 116, + HTT_STATS_PHY_COUNTERS_TAG = 121, + HTT_STATS_PHY_STATS_TAG = 122, ++ HTT_STATS_PHY_RESET_COUNTERS_TAG = 123, ++ HTT_STATS_PHY_RESET_STATS_TAG = 124, + + HTT_STATS_MAX_TAG, + }; +@@ -1964,6 +1966,47 @@ struct htt_phy_stats_tlv { + u32 fw_run_time; + }; + ++struct htt_phy_reset_counters_tlv { ++ u32 pdev_id; ++ u32 cf_active_low_fail_cnt; ++ u32 cf_active_low_pass_cnt; ++ u32 phy_off_through_vreg_cnt; ++ u32 force_calibration_cnt; ++ u32 rf_mode_switch_phy_off_cnt; ++}; ++ ++struct htt_phy_reset_stats_tlv { ++ u32 pdev_id; ++ u32 chan_mhz; ++ u32 chan_band_center_freq1; ++ u32 chan_band_center_freq2; ++ u32 chan_phy_mode; ++ u32 chan_flags; ++ u32 chan_num; ++ u32 reset_cause; ++ u32 prev_reset_cause; ++ u32 phy_warm_reset_src; ++ u32 rx_gain_tbl_mode; ++ u32 xbar_val; ++ u32 force_calibration; ++ u32 phyrf_mode; ++ u32 phy_homechan; ++ u32 phy_tx_ch_mask; ++ u32 phy_rx_ch_mask; ++ u32 phybb_ini_mask; ++ u32 phyrf_ini_mask; ++ u32 phy_dfs_en_mask; ++ u32 phy_sscan_en_mask; ++ u32 phy_synth_sel_mask; ++ u32 phy_adfs_freq; ++ u32 cck_fir_settings; ++ u32 phy_dyn_pri_chan; ++ u32 cca_thresh; ++ u32 dyn_cca_status; ++ u32 rxdesense_thresh_hw; ++ u32 rxdesense_thresh_sw; ++}; ++ + struct htt_peer_ctrl_path_txrx_stats_tlv { + /* peer mac address */ + u8 peer_mac_addr[ETH_ALEN]; diff --git a/package/kernel/mac80211/patches/ath11k/0085-wifi-ath11k-fix-memory-leak-in-WMI-firmware-stats.patch b/package/kernel/mac80211/patches/ath11k/0085-wifi-ath11k-fix-memory-leak-in-WMI-firmware-stats.patch new file mode 100644 index 000000000..dde30b962 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0085-wifi-ath11k-fix-memory-leak-in-WMI-firmware-stats.patch @@ -0,0 +1,51 @@ +From 6aafa1c2d3e3fea2ebe84c018003f2a91722e607 Mon Sep 17 00:00:00 2001 +From: P Praneesh +Date: Tue, 6 Jun 2023 14:41:28 +0530 +Subject: [PATCH] wifi: ath11k: fix memory leak in WMI firmware stats + +Memory allocated for firmware pdev, vdev and beacon statistics +are not released during rmmod. + +Fix it by calling ath11k_fw_stats_free() function before hardware +unregister. + +While at it, avoid calling ath11k_fw_stats_free() while processing +the firmware stats received in the WMI event because the local list +is getting spliced and reinitialised and hence there are no elements +in the list after splicing. + +Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: P Praneesh +Signed-off-by: Aditya Kumar Singh +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20230606091128.14202-1-quic_adisi@quicinc.com +--- + drivers/net/wireless/ath/ath11k/mac.c | 1 + + drivers/net/wireless/ath/ath11k/wmi.c | 5 +++++ + 2 files changed, 6 insertions(+) + +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -9792,6 +9792,7 @@ void ath11k_mac_destroy(struct ath11k_ba + if (!ar) + continue; + ++ ath11k_fw_stats_free(&ar->fw_stats); + ieee80211_free_hw(ar->hw); + pdev->ar = NULL; + } +--- a/drivers/net/wireless/ath/ath11k/wmi.c ++++ b/drivers/net/wireless/ath/ath11k/wmi.c +@@ -8119,6 +8119,11 @@ complete: + rcu_read_unlock(); + spin_unlock_bh(&ar->data_lock); + ++ /* Since the stats's pdev, vdev and beacon list are spliced and reinitialised ++ * at this point, no need to free the individual list. ++ */ ++ return; ++ + free: + ath11k_fw_stats_free(&stats); + } diff --git a/package/kernel/mac80211/patches/ath11k/0086-wifi-ath11k-Add-missing-check-for-ioremap.patch b/package/kernel/mac80211/patches/ath11k/0086-wifi-ath11k-Add-missing-check-for-ioremap.patch new file mode 100644 index 000000000..e536c3bd6 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0086-wifi-ath11k-Add-missing-check-for-ioremap.patch @@ -0,0 +1,38 @@ +From 16e0077e14a73866e9b0f4a6bf4ad3d4a5cb0f2a Mon Sep 17 00:00:00 2001 +From: Jiasheng Jiang +Date: Tue, 13 Jun 2023 12:19:40 +0300 +Subject: [PATCH] wifi: ath11k: Add missing check for ioremap + +Add check for ioremap() and return the error if it fails in order to +guarantee the success of ioremap(), same as in +ath11k_qmi_load_file_target_mem(). + +Fixes: 6ac04bdc5edb ("ath11k: Use reserved host DDR addresses from DT for PCI devices") +Signed-off-by: Jiasheng Jiang +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20230608022858.27405-1-jiasheng@iscas.ac.cn +--- + drivers/net/wireless/ath/ath11k/qmi.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/drivers/net/wireless/ath/ath11k/qmi.c ++++ b/drivers/net/wireless/ath/ath11k/qmi.c +@@ -2061,6 +2061,9 @@ static int ath11k_qmi_assign_target_mem_ + ab->qmi.target_mem[idx].iaddr = + ioremap(ab->qmi.target_mem[idx].paddr, + ab->qmi.target_mem[i].size); ++ if (!ab->qmi.target_mem[idx].iaddr) ++ return -EIO; ++ + ab->qmi.target_mem[idx].size = ab->qmi.target_mem[i].size; + host_ddr_sz = ab->qmi.target_mem[i].size; + ab->qmi.target_mem[idx].type = ab->qmi.target_mem[i].type; +@@ -2086,6 +2089,8 @@ static int ath11k_qmi_assign_target_mem_ + ab->qmi.target_mem[idx].iaddr = + ioremap(ab->qmi.target_mem[idx].paddr, + ab->qmi.target_mem[i].size); ++ if (!ab->qmi.target_mem[idx].iaddr) ++ return -EIO; + } else { + ab->qmi.target_mem[idx].paddr = + ATH11K_QMI_CALDB_ADDRESS; diff --git a/package/kernel/mac80211/patches/ath11k/0087-wifi-ath11k-Add-missing-ops-config-for-IPQ5018-in.patch b/package/kernel/mac80211/patches/ath11k/0087-wifi-ath11k-Add-missing-ops-config-for-IPQ5018-in.patch new file mode 100644 index 000000000..fa539ef45 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0087-wifi-ath11k-Add-missing-ops-config-for-IPQ5018-in.patch @@ -0,0 +1,30 @@ +From 469ddb20cae61cad9c4f208a4c8682305905a511 Mon Sep 17 00:00:00 2001 +From: Ziyang Huang +Date: Thu, 15 Jun 2023 14:41:47 +0300 +Subject: [PATCH] wifi: ath11k: Add missing ops config for IPQ5018 in + ath11k_ahb_probe() + +Without this patch, the IPQ5018 WiFi will fail and print the following +logs: + + [ 11.033179] ath11k c000000.wifi: unsupported device type 7 + [ 11.033223] ath11k: probe of c000000.wifi failed with error -95 + +Fixes: 25edca7bb18a ("wifi: ath11k: add ipq5018 device support") +Signed-off-by: Ziyang Huang +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/TYZPR01MB5556D7AA10ABEDDDD2D8F39EC953A@TYZPR01MB5556.apcprd01.prod.exchangelabs.com +--- + drivers/net/wireless/ath/ath11k/ahb.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/net/wireless/ath/ath11k/ahb.c ++++ b/drivers/net/wireless/ath/ath11k/ahb.c +@@ -1127,6 +1127,7 @@ static int ath11k_ahb_probe(struct platf + switch (hw_rev) { + case ATH11K_HW_IPQ8074: + case ATH11K_HW_IPQ6018_HW10: ++ case ATH11K_HW_IPQ5018_HW10: + hif_ops = &ath11k_ahb_hif_ops_ipq8074; + pci_ops = NULL; + break; diff --git a/package/kernel/mac80211/patches/ath11k/0088-wifi-ath11k-Restart-firmware-after-cold-boot-calibration.patch b/package/kernel/mac80211/patches/ath11k/0088-wifi-ath11k-Restart-firmware-after-cold-boot-calibration.patch new file mode 100644 index 000000000..4a9385218 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0088-wifi-ath11k-Restart-firmware-after-cold-boot-calibration.patch @@ -0,0 +1,47 @@ +From 80c5390e1f5e5b16d820512265530ef26073d8e0 Mon Sep 17 00:00:00 2001 +From: Ziyang Huang +Date: Thu, 15 Jun 2023 14:41:48 +0300 +Subject: [PATCH] wifi: ath11k: Restart firmware after cold boot calibration + for IPQ5018 + +Restart is required after cold boot calibration on IPQ5018. Otherwise, +we get the following exception: + + [ 14.412829] qcom-q6-mpd cd00000.remoteproc: fatal error received: err_smem_ver.2.1: + [ 14.412829] QC Image Version : QC_IMAGE_VERSION_STRING=WLAN.HK.2.6.0.1-00974-QCAHKSWPL_SILICONZ-1 + [ 14.412829] Image Variant : IMAGE_VARIANT_STRING=5018.wlanfw2.map_spr_spr_evalQ + [ 14.412829] DALSysLogEvent.c:174 Assertion 0 failed param0 :zero,param1 :zero,param2 :zero + [ 14.412829] Thread ID : 0x00000048 Thread name : WLAN RT0 Process ID : 0x00000001 Process name :wlan0 + [ 14.412829] + [ 14.412829] Registers: + [ 14.412829] SP : 0x4c81c120 + [ 14.412829] FP : 0x4c81c138 + [ 14.412829] PC : 0xb022c590 + [ 14.412829] SSR : 0x00000000 + [ 14.412829] BADVA : 0x00000000 + [ 14.412829] LR : 0xb0008490 + [ 14.412829] + [ 14.412829] StackDump + [ 14.412829] from:0x4c81c120 + [ 14.412829] to: 0x00000000: + [ 14.412829] + [ 14.463006] remoteproc remoteproc0: crash detected in cd00000.remoteproc: type fatal error + +Fixes: 8dfe875aa24a ("wifi: ath11k: update hw params for IPQ5018") +Signed-off-by: Ziyang Huang +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/TYZPR01MB55566969818BD4B49E770445C953A@TYZPR01MB5556.apcprd01.prod.exchangelabs.com +--- + drivers/net/wireless/ath/ath11k/core.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/net/wireless/ath/ath11k/core.c ++++ b/drivers/net/wireless/ath/ath11k/core.c +@@ -668,6 +668,7 @@ static const struct ath11k_hw_params ath + .hal_params = &ath11k_hw_hal_params_ipq8074, + .single_pdev_only = false, + .cold_boot_calib = true, ++ .cbcal_restart_fw = true, + .fix_l1ss = true, + .supports_dynamic_smps_6ghz = false, + .alloc_cacheable_memory = true, diff --git a/package/kernel/mac80211/patches/ath11k/0089-wifi-ath11k-Add-missing-hw_ops-get_ring_selector-for.patch b/package/kernel/mac80211/patches/ath11k/0089-wifi-ath11k-Add-missing-hw_ops-get_ring_selector-for.patch new file mode 100644 index 000000000..cb6667f14 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0089-wifi-ath11k-Add-missing-hw_ops-get_ring_selector-for.patch @@ -0,0 +1,58 @@ +From ce282d8de71f07f0056ea319541141152c65f552 Mon Sep 17 00:00:00 2001 +From: Ziyang Huang +Date: Thu, 15 Jun 2023 14:41:48 +0300 +Subject: [PATCH] wifi: ath11k: Add missing hw_ops->get_ring_selector() for + IPQ5018 + +During sending data after clients connected, hw_ops->get_ring_selector() +will be called. But for IPQ5018, this member isn't set, and the +following NULL pointer exception will be occurred: + + [ 38.840478] 8<--- cut here --- + [ 38.840517] Unable to handle kernel NULL pointer dereference at virtual address 00000000 + ... + [ 38.923161] PC is at 0x0 + [ 38.927930] LR is at ath11k_dp_tx+0x70/0x730 [ath11k] + ... + [ 39.063264] Process hostapd (pid: 1034, stack limit = 0x801ceb3d) + [ 39.068994] Stack: (0x856a9a68 to 0x856aa000) + ... + [ 39.438467] [<7f323804>] (ath11k_dp_tx [ath11k]) from [<7f314e6c>] (ath11k_mac_op_tx+0x80/0x190 [ath11k]) + [ 39.446607] [<7f314e6c>] (ath11k_mac_op_tx [ath11k]) from [<7f17dbe0>] (ieee80211_handle_wake_tx_queue+0x7c/0xc0 [mac80211]) + [ 39.456162] [<7f17dbe0>] (ieee80211_handle_wake_tx_queue [mac80211]) from [<7f174450>] (ieee80211_probereq_get+0x584/0x704 [mac80211]) + [ 39.467443] [<7f174450>] (ieee80211_probereq_get [mac80211]) from [<7f178c40>] (ieee80211_tx_prepare_skb+0x1f8/0x248 [mac80211]) + [ 39.479334] [<7f178c40>] (ieee80211_tx_prepare_skb [mac80211]) from [<7f179e28>] (__ieee80211_subif_start_xmit+0x32c/0x3d4 [mac80211]) + [ 39.491053] [<7f179e28>] (__ieee80211_subif_start_xmit [mac80211]) from [<7f17af08>] (ieee80211_tx_control_port+0x19c/0x288 [mac80211]) + [ 39.502946] [<7f17af08>] (ieee80211_tx_control_port [mac80211]) from [<7f0fc704>] (nl80211_tx_control_port+0x174/0x1d4 [cfg80211]) + [ 39.515017] [<7f0fc704>] (nl80211_tx_control_port [cfg80211]) from [<808ceac4>] (genl_rcv_msg+0x154/0x340) + [ 39.526814] [<808ceac4>] (genl_rcv_msg) from [<808cdb74>] (netlink_rcv_skb+0xb8/0x11c) + [ 39.536446] [<808cdb74>] (netlink_rcv_skb) from [<808ce1d0>] (genl_rcv+0x28/0x34) + [ 39.544344] [<808ce1d0>] (genl_rcv) from [<808cd234>] (netlink_unicast+0x174/0x274) + [ 39.551895] [<808cd234>] (netlink_unicast) from [<808cd510>] (netlink_sendmsg+0x1dc/0x440) + [ 39.559362] [<808cd510>] (netlink_sendmsg) from [<808596e0>] (____sys_sendmsg+0x1a8/0x1fc) + [ 39.567697] [<808596e0>] (____sys_sendmsg) from [<8085b1a8>] (___sys_sendmsg+0xa4/0xdc) + [ 39.575941] [<8085b1a8>] (___sys_sendmsg) from [<8085b310>] (sys_sendmsg+0x44/0x74) + [ 39.583841] [<8085b310>] (sys_sendmsg) from [<80300060>] (ret_fast_syscall+0x0/0x40) + ... + [ 39.620734] Code: bad PC value + [ 39.625869] ---[ end trace 8aef983ad3cbc032 ]--- + +Fixes: ba60f2793d3a ("wifi: ath11k: initialize hw_ops for IPQ5018") +Signed-off-by: Ziyang Huang +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/TYZPR01MB5556D6E3F63EAB5129D11420C953A@TYZPR01MB5556.apcprd01.prod.exchangelabs.com +--- + drivers/net/wireless/ath/ath11k/hw.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/wireless/ath/ath11k/hw.c ++++ b/drivers/net/wireless/ath/ath11k/hw.c +@@ -1178,7 +1178,7 @@ const struct ath11k_hw_ops ipq5018_ops = + .mpdu_info_get_peerid = ath11k_hw_ipq8074_mpdu_info_get_peerid, + .rx_desc_mac_addr2_valid = ath11k_hw_ipq9074_rx_desc_mac_addr2_valid, + .rx_desc_mpdu_start_addr2 = ath11k_hw_ipq9074_rx_desc_mpdu_start_addr2, +- ++ .get_ring_selector = ath11k_hw_ipq8074_get_tcl_ring_selector, + }; + + #define ATH11K_TX_RING_MASK_0 BIT(0) diff --git a/package/kernel/mac80211/patches/ath11k/0090-Revert-wifi-ath11k-Enable-threaded-NAPI.patch b/package/kernel/mac80211/patches/ath11k/0090-Revert-wifi-ath11k-Enable-threaded-NAPI.patch new file mode 100644 index 000000000..313c18c55 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0090-Revert-wifi-ath11k-Enable-threaded-NAPI.patch @@ -0,0 +1,44 @@ +From d265ebe41c911314bd273c218a37088835959fa1 Mon Sep 17 00:00:00 2001 +From: Kalle Valo +Date: Thu, 20 Jul 2023 18:14:44 +0300 +Subject: [PATCH] Revert "wifi: ath11k: Enable threaded NAPI" + +This reverts commit 13aa2fb692d3717767303817f35b3e650109add3. + +This commit broke QCN9074 initialisation: + +[ 358.960477] ath11k_pci 0000:04:00.0: ce desc not available for wmi command 36866 +[ 358.960481] ath11k_pci 0000:04:00.0: failed to send WMI_STA_POWERSAVE_PARAM_CMDID +[ 358.960484] ath11k_pci 0000:04:00.0: could not set uapsd params -105 + +As there's no fix available let's just revert it to get QCN9074 working again. + +Closes: https://bugzilla.kernel.org/show_bug.cgi?id=217536 +Signed-off-by: Kalle Valo +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20230720151444.2016637-1-kvalo@kernel.org +--- + drivers/net/wireless/ath/ath11k/ahb.c | 1 - + drivers/net/wireless/ath/ath11k/pcic.c | 1 - + 2 files changed, 2 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/ahb.c ++++ b/drivers/net/wireless/ath/ath11k/ahb.c +@@ -376,7 +376,6 @@ static void ath11k_ahb_ext_irq_enable(st + struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i]; + + if (!irq_grp->napi_enabled) { +- dev_set_threaded(&irq_grp->napi_ndev, true); + napi_enable(&irq_grp->napi); + irq_grp->napi_enabled = true; + } +--- a/drivers/net/wireless/ath/ath11k/pcic.c ++++ b/drivers/net/wireless/ath/ath11k/pcic.c +@@ -466,7 +466,6 @@ void ath11k_pcic_ext_irq_enable(struct a + struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i]; + + if (!irq_grp->napi_enabled) { +- dev_set_threaded(&irq_grp->napi_ndev, true); + napi_enable(&irq_grp->napi); + irq_grp->napi_enabled = true; + } diff --git a/package/kernel/mac80211/patches/ath11k/0091-wifi-ath11k-Split-coldboot-calibration-hw_param.patch b/package/kernel/mac80211/patches/ath11k/0091-wifi-ath11k-Split-coldboot-calibration-hw_param.patch new file mode 100644 index 000000000..470535468 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0091-wifi-ath11k-Split-coldboot-calibration-hw_param.patch @@ -0,0 +1,180 @@ +From 011e5a3052a22d3758d17442bf0c04c68bf79bea Mon Sep 17 00:00:00 2001 +From: Seevalamuthu Mariappan +Date: Wed, 26 Jul 2023 19:40:30 +0530 +Subject: [PATCH 3/5] wifi: ath11k: Split coldboot calibration hw_param + +QCN9074 enables coldboot calibration only in Factory Test Mode (FTM). +Hence, split cold_boot_calib to two hw_params for mission and FTM +mode. + +Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Seevalamuthu Mariappan +Signed-off-by: Raj Kumar Bhagat +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20230726141032.3061-2-quic_rajkbhag@quicinc.com +--- + drivers/net/wireless/ath/ath11k/ahb.c | 3 +-- + drivers/net/wireless/ath/ath11k/core.c | 36 ++++++++++++++++++++------ + drivers/net/wireless/ath/ath11k/core.h | 1 + + drivers/net/wireless/ath/ath11k/hw.h | 3 ++- + drivers/net/wireless/ath/ath11k/qmi.c | 6 ++--- + 5 files changed, 35 insertions(+), 14 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/ahb.c ++++ b/drivers/net/wireless/ath/ath11k/ahb.c +@@ -422,8 +422,7 @@ static int ath11k_ahb_fwreset_from_cold_ + { + int timeout; + +- if (ath11k_cold_boot_cal == 0 || ab->qmi.cal_done || +- ab->hw_params.cold_boot_calib == 0 || ++ if (!ath11k_core_coldboot_cal_support(ab) || ab->qmi.cal_done || + ab->hw_params.cbcal_restart_fw == 0) + return 0; + +--- a/drivers/net/wireless/ath/ath11k/core.c ++++ b/drivers/net/wireless/ath/ath11k/core.c +@@ -86,7 +86,8 @@ static const struct ath11k_hw_params ath + .supports_shadow_regs = false, + .idle_ps = false, + .supports_sta_ps = false, +- .cold_boot_calib = true, ++ .coldboot_cal_mm = true, ++ .coldboot_cal_ftm = true, + .cbcal_restart_fw = true, + .fw_mem_mode = 0, + .num_vdevs = 16 + 1, +@@ -167,7 +168,8 @@ static const struct ath11k_hw_params ath + .supports_shadow_regs = false, + .idle_ps = false, + .supports_sta_ps = false, +- .cold_boot_calib = true, ++ .coldboot_cal_mm = true, ++ .coldboot_cal_ftm = true, + .cbcal_restart_fw = true, + .fw_mem_mode = 0, + .num_vdevs = 16 + 1, +@@ -248,7 +250,8 @@ static const struct ath11k_hw_params ath + .supports_shadow_regs = true, + .idle_ps = true, + .supports_sta_ps = true, +- .cold_boot_calib = false, ++ .coldboot_cal_mm = false, ++ .coldboot_cal_ftm = false, + .cbcal_restart_fw = false, + .fw_mem_mode = 0, + .num_vdevs = 16 + 1, +@@ -332,7 +335,8 @@ static const struct ath11k_hw_params ath + .supports_shadow_regs = false, + .idle_ps = false, + .supports_sta_ps = false, +- .cold_boot_calib = false, ++ .coldboot_cal_mm = false, ++ .coldboot_cal_ftm = false, + .cbcal_restart_fw = false, + .fw_mem_mode = 2, + .num_vdevs = 8, +@@ -413,7 +417,8 @@ static const struct ath11k_hw_params ath + .supports_shadow_regs = true, + .idle_ps = true, + .supports_sta_ps = true, +- .cold_boot_calib = false, ++ .coldboot_cal_mm = false, ++ .coldboot_cal_ftm = false, + .cbcal_restart_fw = false, + .fw_mem_mode = 0, + .num_vdevs = 16 + 1, +@@ -495,7 +500,8 @@ static const struct ath11k_hw_params ath + .supports_shadow_regs = true, + .idle_ps = true, + .supports_sta_ps = true, +- .cold_boot_calib = false, ++ .coldboot_cal_mm = false, ++ .coldboot_cal_ftm = false, + .cbcal_restart_fw = false, + .fw_mem_mode = 0, + .num_vdevs = 16 + 1, +@@ -578,7 +584,8 @@ static const struct ath11k_hw_params ath + .supports_shadow_regs = true, + .idle_ps = true, + .supports_sta_ps = true, +- .cold_boot_calib = true, ++ .coldboot_cal_mm = true, ++ .coldboot_cal_ftm = true, + .cbcal_restart_fw = false, + .fw_mem_mode = 0, + .num_vdevs = 16 + 1, +@@ -667,7 +674,8 @@ static const struct ath11k_hw_params ath + .supports_suspend = false, + .hal_params = &ath11k_hw_hal_params_ipq8074, + .single_pdev_only = false, +- .cold_boot_calib = true, ++ .coldboot_cal_mm = true, ++ .coldboot_cal_ftm = true, + .cbcal_restart_fw = true, + .fix_l1ss = true, + .supports_dynamic_smps_6ghz = false, +@@ -749,6 +757,18 @@ void ath11k_fw_stats_free(struct ath11k_ + ath11k_fw_stats_bcn_free(&stats->bcn); + } + ++bool ath11k_core_coldboot_cal_support(struct ath11k_base *ab) ++{ ++ if (!ath11k_cold_boot_cal) ++ return false; ++ ++ if (ath11k_ftm_mode) ++ return ab->hw_params.coldboot_cal_ftm; ++ ++ else ++ return ab->hw_params.coldboot_cal_mm; ++} ++ + int ath11k_core_suspend(struct ath11k_base *ab) + { + int ret; +--- a/drivers/net/wireless/ath/ath11k/core.h ++++ b/drivers/net/wireless/ath/ath11k/core.h +@@ -1186,6 +1186,7 @@ void ath11k_core_halt(struct ath11k *ar) + int ath11k_core_resume(struct ath11k_base *ab); + int ath11k_core_suspend(struct ath11k_base *ab); + void ath11k_core_pre_reconfigure_recovery(struct ath11k_base *ab); ++bool ath11k_core_coldboot_cal_support(struct ath11k_base *ab); + + const struct firmware *ath11k_core_firmware_request(struct ath11k_base *ab, + const char *filename); +--- a/drivers/net/wireless/ath/ath11k/hw.h ++++ b/drivers/net/wireless/ath/ath11k/hw.h +@@ -187,7 +187,8 @@ struct ath11k_hw_params { + bool supports_shadow_regs; + bool idle_ps; + bool supports_sta_ps; +- bool cold_boot_calib; ++ bool coldboot_cal_mm; ++ bool coldboot_cal_ftm; + bool cbcal_restart_fw; + int fw_mem_mode; + u32 num_vdevs; +--- a/drivers/net/wireless/ath/ath11k/qmi.c ++++ b/drivers/net/wireless/ath/ath11k/qmi.c +@@ -2082,7 +2082,7 @@ static int ath11k_qmi_assign_target_mem_ + return -EINVAL; + } + +- if (ath11k_cold_boot_cal && ab->hw_params.cold_boot_calib) { ++ if (ath11k_core_coldboot_cal_support(ab)) { + if (hremote_node) { + ab->qmi.target_mem[idx].paddr = + res.start + host_ddr_sz; +@@ -3212,8 +3212,8 @@ static void ath11k_qmi_driver_event_work + break; + } + +- if (ath11k_cold_boot_cal && ab->qmi.cal_done == 0 && +- ab->hw_params.cold_boot_calib) { ++ if (ab->qmi.cal_done == 0 && ++ ath11k_core_coldboot_cal_support(ab)) { + ath11k_qmi_process_coldboot_calibration(ab); + } else { + clear_bit(ATH11K_FLAG_CRASH_FLUSH, diff --git a/package/kernel/mac80211/patches/ath11k/0092-wifi-ath11k-Add-coldboot-calibration-support-for-QCN.patch b/package/kernel/mac80211/patches/ath11k/0092-wifi-ath11k-Add-coldboot-calibration-support-for-QCN.patch new file mode 100644 index 000000000..31b11ddee --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0092-wifi-ath11k-Add-coldboot-calibration-support-for-QCN.patch @@ -0,0 +1,176 @@ +From bdfc967bf5fcd762473a01d39edb81f1165ba290 Mon Sep 17 00:00:00 2001 +From: Anilkumar Kolli +Date: Wed, 26 Jul 2023 19:40:31 +0530 +Subject: [PATCH 4/5] wifi: ath11k: Add coldboot calibration support for + QCN9074 + +QCN9074 supports 6 GHz, which has increased number of channels +compared to 5 GHz/2 GHz. So, to support coldboot calibration in +QCN9074 ATH11K_COLD_BOOT_FW_RESET_DELAY extended to 60 seconds. To +avoid code redundancy, fwreset_from_cold_boot moved to QMI and made +common for both ahb and pci. Coldboot calibration is enabled only in +FTM mode for QCN9074. QCN9074 requires firmware restart after coldboot, +hence enable cbcal_restart_fw in hw_params. + +This support can be enabled/disabled using hw params for different +hardware. Currently it is not enabled for QCA6390. + +Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Anilkumar Kolli +Signed-off-by: Seevalamuthu Mariappan +Signed-off-by: Raj Kumar Bhagat +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20230726141032.3061-3-quic_rajkbhag@quicinc.com +--- + drivers/net/wireless/ath/ath11k/ahb.c | 28 ++------------------------ + drivers/net/wireless/ath/ath11k/core.c | 4 ++-- + drivers/net/wireless/ath/ath11k/pci.c | 2 ++ + drivers/net/wireless/ath/ath11k/qmi.c | 28 ++++++++++++++++++++++++++ + drivers/net/wireless/ath/ath11k/qmi.h | 3 ++- + 5 files changed, 36 insertions(+), 29 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/ahb.c ++++ b/drivers/net/wireless/ath/ath11k/ahb.c +@@ -14,6 +14,7 @@ + #include "ahb.h" + #include "debug.h" + #include "hif.h" ++#include "qmi.h" + #include + #include "pcic.h" + #include +@@ -418,31 +419,6 @@ static void ath11k_ahb_power_down(struct + rproc_shutdown(ab_ahb->tgt_rproc); + } + +-static int ath11k_ahb_fwreset_from_cold_boot(struct ath11k_base *ab) +-{ +- int timeout; +- +- if (!ath11k_core_coldboot_cal_support(ab) || ab->qmi.cal_done || +- ab->hw_params.cbcal_restart_fw == 0) +- return 0; +- +- ath11k_dbg(ab, ATH11K_DBG_AHB, "wait for cold boot done\n"); +- timeout = wait_event_timeout(ab->qmi.cold_boot_waitq, +- (ab->qmi.cal_done == 1), +- ATH11K_COLD_BOOT_FW_RESET_DELAY); +- if (timeout <= 0) { +- ath11k_cold_boot_cal = 0; +- ath11k_warn(ab, "Coldboot Calibration failed timed out\n"); +- } +- +- /* reset the firmware */ +- ath11k_ahb_power_down(ab); +- ath11k_ahb_power_up(ab); +- +- ath11k_dbg(ab, ATH11K_DBG_AHB, "exited from cold boot mode\n"); +- return 0; +-} +- + static void ath11k_ahb_init_qmi_ce_config(struct ath11k_base *ab) + { + struct ath11k_qmi_ce_cfg *cfg = &ab->qmi.ce_cfg; +@@ -1225,7 +1201,7 @@ static int ath11k_ahb_probe(struct platf + goto err_ce_free; + } + +- ath11k_ahb_fwreset_from_cold_boot(ab); ++ ath11k_qmi_fwreset_from_cold_boot(ab); + + return 0; + +--- a/drivers/net/wireless/ath/ath11k/core.c ++++ b/drivers/net/wireless/ath/ath11k/core.c +@@ -336,8 +336,8 @@ static const struct ath11k_hw_params ath + .idle_ps = false, + .supports_sta_ps = false, + .coldboot_cal_mm = false, +- .coldboot_cal_ftm = false, +- .cbcal_restart_fw = false, ++ .coldboot_cal_ftm = true, ++ .cbcal_restart_fw = true, + .fw_mem_mode = 2, + .num_vdevs = 8, + .num_peers = 128, +--- a/drivers/net/wireless/ath/ath11k/pci.c ++++ b/drivers/net/wireless/ath/ath11k/pci.c +@@ -15,6 +15,7 @@ + #include "mhi.h" + #include "debug.h" + #include "pcic.h" ++#include "qmi.h" + + #define ATH11K_PCI_BAR_NUM 0 + #define ATH11K_PCI_DMA_MASK 32 +@@ -897,6 +898,7 @@ unsupported_wcn6855_soc: + ath11k_err(ab, "failed to init core: %d\n", ret); + goto err_irq_affinity_cleanup; + } ++ ath11k_qmi_fwreset_from_cold_boot(ab); + return 0; + + err_irq_affinity_cleanup: +--- a/drivers/net/wireless/ath/ath11k/qmi.c ++++ b/drivers/net/wireless/ath/ath11k/qmi.c +@@ -9,6 +9,7 @@ + #include "qmi.h" + #include "core.h" + #include "debug.h" ++#include "hif.h" + #include + #include + #include +@@ -2842,6 +2843,33 @@ int ath11k_qmi_firmware_start(struct ath + return 0; + } + ++int ath11k_qmi_fwreset_from_cold_boot(struct ath11k_base *ab) ++{ ++ int timeout; ++ ++ if (!ath11k_core_coldboot_cal_support(ab) || ab->qmi.cal_done || ++ ab->hw_params.cbcal_restart_fw == 0) ++ return 0; ++ ++ ath11k_dbg(ab, ATH11K_DBG_QMI, "wait for cold boot done\n"); ++ ++ timeout = wait_event_timeout(ab->qmi.cold_boot_waitq, ++ (ab->qmi.cal_done == 1), ++ ATH11K_COLD_BOOT_FW_RESET_DELAY); ++ ++ if (timeout <= 0) { ++ ath11k_warn(ab, "Coldboot Calibration timed out\n"); ++ return -ETIMEDOUT; ++ } ++ ++ /* reset the firmware */ ++ ath11k_hif_power_down(ab); ++ ath11k_hif_power_up(ab); ++ ath11k_dbg(ab, ATH11K_DBG_QMI, "exit wait for cold boot done\n"); ++ return 0; ++} ++EXPORT_SYMBOL(ath11k_qmi_fwreset_from_cold_boot); ++ + static int ath11k_qmi_process_coldboot_calibration(struct ath11k_base *ab) + { + int timeout; +--- a/drivers/net/wireless/ath/ath11k/qmi.h ++++ b/drivers/net/wireless/ath/ath11k/qmi.h +@@ -37,7 +37,7 @@ + + #define QMI_WLANFW_MAX_DATA_SIZE_V01 6144 + #define ATH11K_FIRMWARE_MODE_OFF 4 +-#define ATH11K_COLD_BOOT_FW_RESET_DELAY (40 * HZ) ++#define ATH11K_COLD_BOOT_FW_RESET_DELAY (60 * HZ) + + #define ATH11K_QMI_DEVICE_BAR_SIZE 0x200000 + +@@ -519,5 +519,6 @@ void ath11k_qmi_msg_recv_work(struct wor + void ath11k_qmi_deinit_service(struct ath11k_base *ab); + int ath11k_qmi_init_service(struct ath11k_base *ab); + void ath11k_qmi_free_resource(struct ath11k_base *ab); ++int ath11k_qmi_fwreset_from_cold_boot(struct ath11k_base *ab); + + #endif diff --git a/package/kernel/mac80211/patches/ath11k/0093-wifi-ath11k-Remove-cal_done-check-during-probe.patch b/package/kernel/mac80211/patches/ath11k/0093-wifi-ath11k-Remove-cal_done-check-during-probe.patch new file mode 100644 index 000000000..513ea3f0b --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0093-wifi-ath11k-Remove-cal_done-check-during-probe.patch @@ -0,0 +1,33 @@ +From 13329d0cb7212b058bd8451a99d215a8f97645ea Mon Sep 17 00:00:00 2001 +From: Seevalamuthu Mariappan +Date: Wed, 26 Jul 2023 19:40:32 +0530 +Subject: [PATCH] wifi: ath11k: Remove cal_done check during probe + +In some race conditions, calibration done QMI message is received even +before host wait starts for calibration to be done. +Due to this, resetting firmware was not performed after calibration. + +Hence, remove cal_done check in ath11k_qmi_fwreset_from_cold_boot() +as this is called only from probe. + +Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Seevalamuthu Mariappan +Signed-off-by: Raj Kumar Bhagat +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20230726141032.3061-4-quic_rajkbhag@quicinc.com +--- + drivers/net/wireless/ath/ath11k/qmi.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/wireless/ath/ath11k/qmi.c ++++ b/drivers/net/wireless/ath/ath11k/qmi.c +@@ -2847,7 +2847,7 @@ int ath11k_qmi_fwreset_from_cold_boot(st + { + int timeout; + +- if (!ath11k_core_coldboot_cal_support(ab) || ab->qmi.cal_done || ++ if (!ath11k_core_coldboot_cal_support(ab) || + ab->hw_params.cbcal_restart_fw == 0) + return 0; + diff --git a/package/kernel/mac80211/patches/ath11k/0094-wifi-ath11k-mhi-add-a-warning-message-for-MHI_CB_EE.patch b/package/kernel/mac80211/patches/ath11k/0094-wifi-ath11k-mhi-add-a-warning-message-for-MHI_CB_EE.patch new file mode 100644 index 000000000..e1286c953 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0094-wifi-ath11k-mhi-add-a-warning-message-for-MHI_CB_EE.patch @@ -0,0 +1,34 @@ +From 4a93b554cf9fa64faa7cf164c0d32fc3ce67108b Mon Sep 17 00:00:00 2001 +From: Arowa Suliman +Date: Sat, 26 Aug 2023 08:42:42 +0300 +Subject: [PATCH] wifi: ath11k: mhi: add a warning message for MHI_CB_EE_RDDM + crash + +Currently, the ath11k driver does not print a crash signature when a +MHI_CB_EE_RDDM crash happens. Checked by triggering a simulated crash using the +command and checking dmesg for logs: + +echo assert > /sys/kernel/debug/ath11k/../simulate_fw_crash + +Add a warning when firmware crash MHI_CB_EE_RDDM happens. + +Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3.6510.23 + +Signed-off-by: Arowa Suliman +Reviewed-by: Jeff Johnson +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20230714001126.463127-1-arowa@chromium.org +--- + drivers/net/wireless/ath/ath11k/mhi.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/net/wireless/ath/ath11k/mhi.c ++++ b/drivers/net/wireless/ath/ath11k/mhi.c +@@ -333,6 +333,7 @@ static void ath11k_mhi_op_status_cb(stru + ath11k_warn(ab, "firmware crashed: MHI_CB_SYS_ERROR\n"); + break; + case MHI_CB_EE_RDDM: ++ ath11k_warn(ab, "firmware crashed: MHI_CB_EE_RDDM\n"); + if (!(test_bit(ATH11K_FLAG_UNREGISTERING, &ab->dev_flags))) + queue_work(ab->workqueue_aux, &ab->reset_work); + break; diff --git a/package/kernel/mac80211/patches/ath11k/0095-wifi-ath11k-add-chip-id-board-name-while-searching-b.patch b/package/kernel/mac80211/patches/ath11k/0095-wifi-ath11k-add-chip-id-board-name-while-searching-b.patch new file mode 100644 index 000000000..662e28f4e --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0095-wifi-ath11k-add-chip-id-board-name-while-searching-b.patch @@ -0,0 +1,214 @@ +From 1133af5aea588a58043244a4ecb5ce511b310356 Mon Sep 17 00:00:00 2001 +From: Wen Gong +Date: Wed, 30 Aug 2023 02:02:26 -0400 +Subject: [PATCH] wifi: ath11k: add chip id board name while searching + board-2.bin for WCN6855 + +Sometimes board-2.bin does not have the board data which matched the +parameters such as bus type, vendor, device, subsystem-vendor, +subsystem-device, qmi-chip-id and qmi-board-id, then wlan will load fail. + +Hence add another type which only matches the bus type and qmi-chip-id, +then the ratio of missing board data reduced. + +Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3.6510.23 + +Signed-off-by: Wen Gong +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20230830060226.18664-1-quic_wgong@quicinc.com +--- + drivers/net/wireless/ath/ath11k/core.c | 108 ++++++++++++++++++++----- + 1 file changed, 87 insertions(+), 21 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/core.c ++++ b/drivers/net/wireless/ath/ath11k/core.c +@@ -985,9 +985,15 @@ int ath11k_core_check_dt(struct ath11k_b + return 0; + } + ++enum ath11k_bdf_name_type { ++ ATH11K_BDF_NAME_FULL, ++ ATH11K_BDF_NAME_BUS_NAME, ++ ATH11K_BDF_NAME_CHIP_ID, ++}; ++ + static int __ath11k_core_create_board_name(struct ath11k_base *ab, char *name, + size_t name_len, bool with_variant, +- bool bus_type_mode) ++ enum ath11k_bdf_name_type name_type) + { + /* strlen(',variant=') + strlen(ab->qmi.target.bdf_ext) */ + char variant[9 + ATH11K_QMI_BDF_EXT_STR_LENGTH] = { 0 }; +@@ -998,11 +1004,8 @@ static int __ath11k_core_create_board_na + + switch (ab->id.bdf_search) { + case ATH11K_BDF_SEARCH_BUS_AND_BOARD: +- if (bus_type_mode) +- scnprintf(name, name_len, +- "bus=%s", +- ath11k_bus_str(ab->hif.bus)); +- else ++ switch (name_type) { ++ case ATH11K_BDF_NAME_FULL: + scnprintf(name, name_len, + "bus=%s,vendor=%04x,device=%04x,subsystem-vendor=%04x,subsystem-device=%04x,qmi-chip-id=%d,qmi-board-id=%d%s", + ath11k_bus_str(ab->hif.bus), +@@ -1012,6 +1015,19 @@ static int __ath11k_core_create_board_na + ab->qmi.target.chip_id, + ab->qmi.target.board_id, + variant); ++ break; ++ case ATH11K_BDF_NAME_BUS_NAME: ++ scnprintf(name, name_len, ++ "bus=%s", ++ ath11k_bus_str(ab->hif.bus)); ++ break; ++ case ATH11K_BDF_NAME_CHIP_ID: ++ scnprintf(name, name_len, ++ "bus=%s,qmi-chip-id=%d", ++ ath11k_bus_str(ab->hif.bus), ++ ab->qmi.target.chip_id); ++ break; ++ } + break; + default: + scnprintf(name, name_len, +@@ -1030,19 +1046,29 @@ static int __ath11k_core_create_board_na + static int ath11k_core_create_board_name(struct ath11k_base *ab, char *name, + size_t name_len) + { +- return __ath11k_core_create_board_name(ab, name, name_len, true, false); ++ return __ath11k_core_create_board_name(ab, name, name_len, true, ++ ATH11K_BDF_NAME_FULL); + } + + static int ath11k_core_create_fallback_board_name(struct ath11k_base *ab, char *name, + size_t name_len) + { +- return __ath11k_core_create_board_name(ab, name, name_len, false, false); ++ return __ath11k_core_create_board_name(ab, name, name_len, false, ++ ATH11K_BDF_NAME_FULL); + } + + static int ath11k_core_create_bus_type_board_name(struct ath11k_base *ab, char *name, + size_t name_len) + { +- return __ath11k_core_create_board_name(ab, name, name_len, false, true); ++ return __ath11k_core_create_board_name(ab, name, name_len, false, ++ ATH11K_BDF_NAME_BUS_NAME); ++} ++ ++static int ath11k_core_create_chip_id_board_name(struct ath11k_base *ab, char *name, ++ size_t name_len) ++{ ++ return __ath11k_core_create_board_name(ab, name, name_len, false, ++ ATH11K_BDF_NAME_CHIP_ID); + } + + const struct firmware *ath11k_core_firmware_request(struct ath11k_base *ab, +@@ -1289,16 +1315,21 @@ int ath11k_core_fetch_board_data_api_1(s + #define BOARD_NAME_SIZE 200 + int ath11k_core_fetch_bdf(struct ath11k_base *ab, struct ath11k_board_data *bd) + { +- char boardname[BOARD_NAME_SIZE], fallback_boardname[BOARD_NAME_SIZE]; ++ char *boardname = NULL, *fallback_boardname = NULL, *chip_id_boardname = NULL; + char *filename, filepath[100]; +- int ret; ++ int ret = 0; + + filename = ATH11K_BOARD_API2_FILE; ++ boardname = kzalloc(BOARD_NAME_SIZE, GFP_KERNEL); ++ if (!boardname) { ++ ret = -ENOMEM; ++ goto exit; ++ } + +- ret = ath11k_core_create_board_name(ab, boardname, sizeof(boardname)); ++ ret = ath11k_core_create_board_name(ab, boardname, BOARD_NAME_SIZE); + if (ret) { + ath11k_err(ab, "failed to create board name: %d", ret); +- return ret; ++ goto exit; + } + + ab->bd_api = 2; +@@ -1307,13 +1338,19 @@ int ath11k_core_fetch_bdf(struct ath11k_ + ATH11K_BD_IE_BOARD_NAME, + ATH11K_BD_IE_BOARD_DATA); + if (!ret) +- goto success; ++ goto exit; ++ ++ fallback_boardname = kzalloc(BOARD_NAME_SIZE, GFP_KERNEL); ++ if (!fallback_boardname) { ++ ret = -ENOMEM; ++ goto exit; ++ } + + ret = ath11k_core_create_fallback_board_name(ab, fallback_boardname, +- sizeof(fallback_boardname)); ++ BOARD_NAME_SIZE); + if (ret) { + ath11k_err(ab, "failed to create fallback board name: %d", ret); +- return ret; ++ goto exit; + } + + ret = ath11k_core_fetch_board_data_api_n(ab, bd, fallback_boardname, +@@ -1321,7 +1358,28 @@ int ath11k_core_fetch_bdf(struct ath11k_ + ATH11K_BD_IE_BOARD_NAME, + ATH11K_BD_IE_BOARD_DATA); + if (!ret) +- goto success; ++ goto exit; ++ ++ chip_id_boardname = kzalloc(BOARD_NAME_SIZE, GFP_KERNEL); ++ if (!chip_id_boardname) { ++ ret = -ENOMEM; ++ goto exit; ++ } ++ ++ ret = ath11k_core_create_chip_id_board_name(ab, chip_id_boardname, ++ BOARD_NAME_SIZE); ++ if (ret) { ++ ath11k_err(ab, "failed to create chip id board name: %d", ret); ++ goto exit; ++ } ++ ++ ret = ath11k_core_fetch_board_data_api_n(ab, bd, chip_id_boardname, ++ ATH11K_BD_IE_BOARD, ++ ATH11K_BD_IE_BOARD_NAME, ++ ATH11K_BD_IE_BOARD_DATA); ++ ++ if (!ret) ++ goto exit; + + ab->bd_api = 1; + ret = ath11k_core_fetch_board_data_api_1(ab, bd, ATH11K_DEFAULT_BOARD_FILE); +@@ -1334,14 +1392,22 @@ int ath11k_core_fetch_bdf(struct ath11k_ + ath11k_err(ab, "failed to fetch board data for %s from %s\n", + fallback_boardname, filepath); + ++ ath11k_err(ab, "failed to fetch board data for %s from %s\n", ++ chip_id_boardname, filepath); ++ + ath11k_err(ab, "failed to fetch board.bin from %s\n", + ab->hw_params.fw.dir); +- return ret; + } + +-success: +- ath11k_dbg(ab, ATH11K_DBG_BOOT, "using board api %d\n", ab->bd_api); +- return 0; ++exit: ++ kfree(boardname); ++ kfree(fallback_boardname); ++ kfree(chip_id_boardname); ++ ++ if (!ret) ++ ath11k_dbg(ab, ATH11K_DBG_BOOT, "using board api %d\n", ab->bd_api); ++ ++ return ret; + } + + int ath11k_core_fetch_regdb(struct ath11k_base *ab, struct ath11k_board_data *bd) diff --git a/package/kernel/mac80211/patches/ath11k/0096-wifi-ath11k-fix-boot-failure-with-one-MSI-vector.patch b/package/kernel/mac80211/patches/ath11k/0096-wifi-ath11k-fix-boot-failure-with-one-MSI-vector.patch new file mode 100644 index 000000000..9101a1ea1 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0096-wifi-ath11k-fix-boot-failure-with-one-MSI-vector.patch @@ -0,0 +1,103 @@ +From 39564b475ac5a589e6c22c43a08cbd283c295d2c Mon Sep 17 00:00:00 2001 +From: Baochen Qiang +Date: Thu, 7 Sep 2023 09:56:06 +0800 +Subject: [PATCH] wifi: ath11k: fix boot failure with one MSI vector + +Commit 5b32b6dd96633 ("ath11k: Remove core PCI references from +PCI common code") breaks with one MSI vector because it moves +affinity setting after IRQ request, see below log: + +[ 1417.278835] ath11k_pci 0000:02:00.0: failed to receive control response completion, polling.. +[ 1418.302829] ath11k_pci 0000:02:00.0: Service connect timeout +[ 1418.302833] ath11k_pci 0000:02:00.0: failed to connect to HTT: -110 +[ 1418.303669] ath11k_pci 0000:02:00.0: failed to start core: -110 + +The detail is, if do affinity request after IRQ activated, +which is done in request_irq(), kernel caches that request and +returns success directly. Later when a subsequent MHI interrupt is +fired, kernel will do the real affinity setting work, as a result, +changs the MSI vector. However at that time host has configured +old vector to hardware, so host never receives CE or DP interrupts. + +Fix it by setting affinity before registering MHI controller +where host is, for the first time, doing IRQ request. + +Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3 +Tested-on: WCN6855 hw2.1 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3.6510.23 +Tested-on: WCN6750 hw1.0 AHB WLAN.MSL.1.0.1-01160-QCAMSLSWPLZ-1 + +Fixes: 5b32b6dd9663 ("ath11k: Remove core PCI references from PCI common code") +Signed-off-by: Baochen Qiang +Acked-by: Jeff Johnson +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20230907015606.16297-1-quic_bqiang@quicinc.com +--- + drivers/net/wireless/ath/ath11k/pci.c | 24 ++++++++++++------------ + 1 file changed, 12 insertions(+), 12 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/pci.c ++++ b/drivers/net/wireless/ath/ath11k/pci.c +@@ -852,10 +852,16 @@ unsupported_wcn6855_soc: + if (ret) + goto err_pci_disable_msi; + ++ ret = ath11k_pci_set_irq_affinity_hint(ab_pci, cpumask_of(0)); ++ if (ret) { ++ ath11k_err(ab, "failed to set irq affinity %d\n", ret); ++ goto err_pci_disable_msi; ++ } ++ + ret = ath11k_mhi_register(ab_pci); + if (ret) { + ath11k_err(ab, "failed to register mhi: %d\n", ret); +- goto err_pci_disable_msi; ++ goto err_irq_affinity_cleanup; + } + + ret = ath11k_hal_srng_init(ab); +@@ -876,12 +882,6 @@ unsupported_wcn6855_soc: + goto err_ce_free; + } + +- ret = ath11k_pci_set_irq_affinity_hint(ab_pci, cpumask_of(0)); +- if (ret) { +- ath11k_err(ab, "failed to set irq affinity %d\n", ret); +- goto err_free_irq; +- } +- + /* kernel may allocate a dummy vector before request_irq and + * then allocate a real vector when request_irq is called. + * So get msi_data here again to avoid spurious interrupt +@@ -890,20 +890,17 @@ unsupported_wcn6855_soc: + ret = ath11k_pci_config_msi_data(ab_pci); + if (ret) { + ath11k_err(ab, "failed to config msi_data: %d\n", ret); +- goto err_irq_affinity_cleanup; ++ goto err_free_irq; + } + + ret = ath11k_core_init(ab); + if (ret) { + ath11k_err(ab, "failed to init core: %d\n", ret); +- goto err_irq_affinity_cleanup; ++ goto err_free_irq; + } + ath11k_qmi_fwreset_from_cold_boot(ab); + return 0; + +-err_irq_affinity_cleanup: +- ath11k_pci_set_irq_affinity_hint(ab_pci, NULL); +- + err_free_irq: + ath11k_pcic_free_irq(ab); + +@@ -916,6 +913,9 @@ err_hal_srng_deinit: + err_mhi_unregister: + ath11k_mhi_unregister(ab_pci); + ++err_irq_affinity_cleanup: ++ ath11k_pci_set_irq_affinity_hint(ab_pci, NULL); ++ + err_pci_disable_msi: + ath11k_pci_free_msi(ab_pci); + diff --git a/package/kernel/mac80211/patches/ath11k/0906-wifi-ath11k-disable-coldboot-for-ipq6018.patch b/package/kernel/mac80211/patches/ath11k/0906-wifi-ath11k-disable-coldboot-for-ipq6018.patch deleted file mode 100644 index 325724e68..000000000 --- a/package/kernel/mac80211/patches/ath11k/0906-wifi-ath11k-disable-coldboot-for-ipq6018.patch +++ /dev/null @@ -1,26 +0,0 @@ -From a3be23672b4a81256d275af31afc6edcce5c5a26 Mon Sep 17 00:00:00 2001 -From: Mantas Pucka -Date: Mon, 22 Jan 2024 11:38:28 +0200 -Subject: [PATCH] wifi: ath11k: disable coldboot for ipq6018 - -Coldboot calibration does not work at the moment and causes failure during -wifi startup. - -Signed-off-by: Mantas Pucka ---- - drivers/net/wireless/ath/ath11k/core.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/drivers/net/wireless/ath/ath11k/core.c -+++ b/drivers/net/wireless/ath/ath11k/core.c -@@ -170,8 +170,8 @@ static const struct ath11k_hw_params ath - .supports_shadow_regs = false, - .idle_ps = false, - .supports_sta_ps = false, -- .coldboot_cal_mm = true, -- .coldboot_cal_ftm = true, -+ .coldboot_cal_mm = false, -+ .coldboot_cal_ftm = false, - .cbcal_restart_fw = true, - .fw_mem_mode = 0, - .num_vdevs = 16 + 1, diff --git a/package/kernel/mac80211/patches/ath11k/100-wifi-ath11k-use-unique-QRTR-instance-ID.patch b/package/kernel/mac80211/patches/ath11k/100-wifi-ath11k-use-unique-QRTR-instance-ID.patch index f1583b6e9..30472b322 100644 --- a/package/kernel/mac80211/patches/ath11k/100-wifi-ath11k-use-unique-QRTR-instance-ID.patch +++ b/package/kernel/mac80211/patches/ath11k/100-wifi-ath11k-use-unique-QRTR-instance-ID.patch @@ -49,7 +49,7 @@ Signed-off-by: Robert Marko --- a/drivers/net/wireless/ath/ath11k/mhi.c +++ b/drivers/net/wireless/ath/ath11k/mhi.c -@@ -239,6 +239,34 @@ static void ath11k_mhi_op_runtime_put(st +@@ -294,6 +294,34 @@ static void ath11k_mhi_op_runtime_put(st { } @@ -84,7 +84,7 @@ Signed-off-by: Robert Marko static char *ath11k_mhi_op_callback_to_str(enum mhi_callback reason) { switch (reason) { -@@ -260,6 +288,8 @@ static char *ath11k_mhi_op_callback_to_s +@@ -315,6 +343,8 @@ static char *ath11k_mhi_op_callback_to_s return "MHI_CB_FATAL_ERROR"; case MHI_CB_BW_REQ: return "MHI_CB_BW_REQ"; @@ -93,7 +93,7 @@ Signed-off-by: Robert Marko default: return "UNKNOWN"; } -@@ -282,27 +312,14 @@ static void ath11k_mhi_op_status_cb(stru +@@ -337,27 +367,14 @@ static void ath11k_mhi_op_status_cb(stru if (!(test_bit(ATH11K_FLAG_UNREGISTERING, &ab->dev_flags))) queue_work(ab->workqueue_aux, &ab->reset_work); break; @@ -126,7 +126,7 @@ Signed-off-by: Robert Marko struct device_node *np; --- a/drivers/net/wireless/ath/ath11k/mhi.h +++ b/drivers/net/wireless/ath/ath11k/mhi.h -@@ -17,6 +17,9 @@ +@@ -16,6 +16,9 @@ #define MHICTRL 0x38 #define MHICTRL_RESET_MASK 0x2 @@ -138,7 +138,7 @@ Signed-off-by: Robert Marko int ath11k_mhi_register(struct ath11k_pci *ar_pci); --- a/drivers/net/wireless/ath/ath11k/pci.c +++ b/drivers/net/wireless/ath/ath11k/pci.c -@@ -374,13 +374,20 @@ static void ath11k_pci_sw_reset(struct a +@@ -371,13 +371,20 @@ static void ath11k_pci_sw_reset(struct a static void ath11k_pci_init_qmi_ce_config(struct ath11k_base *ab) { struct ath11k_qmi_ce_cfg *cfg = &ab->qmi.ce_cfg; diff --git a/package/kernel/mac80211/patches/ath11k/101-wifi-ath11k-add-support-DT-ieee80211-freq-limit.patch b/package/kernel/mac80211/patches/ath11k/101-wifi-ath11k-add-support-DT-ieee80211-freq-limit.patch deleted file mode 100644 index 6088b26e6..000000000 --- a/package/kernel/mac80211/patches/ath11k/101-wifi-ath11k-add-support-DT-ieee80211-freq-limit.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 1338da257f299d35b4d954b9fda2cc7e0a54a69d Mon Sep 17 00:00:00 2001 -From: Christian Lamparter -Date: Sun, 11 Jun 2023 14:37:32 +0200 -Subject: [PATCH] wifi: ath11k: add support DT ieee80211-freq-limit - -The common DT property can be used to limit the available -channels/frequencies. But ath11k has to manually call -wiphy_read_of_freq_limits(). - -Signed-off-by: Christian Lamparter ---- - drivers/net/wireless/ath/ath11k/mac.c | 1 + - 1 file changed, 1 insertion(+) - ---- a/drivers/net/wireless/ath/ath11k/mac.c -+++ b/drivers/net/wireless/ath/ath11k/mac.c -@@ -10034,6 +10034,7 @@ static int __ath11k_mac_register(struct - if (ret) - goto err; - -+ wiphy_read_of_freq_limits(ar->hw->wiphy); - ath11k_mac_setup_ht_vht_cap(ar, cap, &ht_cap); - ath11k_mac_setup_he_cap(ar, cap); - diff --git a/package/kernel/mac80211/patches/ath11k/900-ath11k-control-thermal-support-via-symbol.patch b/package/kernel/mac80211/patches/ath11k/900-ath11k-control-thermal-support-via-symbol.patch index 6b351cc81..60720a721 100644 --- a/package/kernel/mac80211/patches/ath11k/900-ath11k-control-thermal-support-via-symbol.patch +++ b/package/kernel/mac80211/patches/ath11k/900-ath11k-control-thermal-support-via-symbol.patch @@ -34,7 +34,7 @@ Signed-off-by: Robert Marko + Enable ath11k thermal sensors and throttling support. --- a/drivers/net/wireless/ath/ath11k/Makefile +++ b/drivers/net/wireless/ath/ath11k/Makefile -@@ -23,7 +23,7 @@ ath11k-y += core.o \ +@@ -22,7 +22,7 @@ ath11k-y += core.o \ ath11k-$(CPTCFG_ATH11K_DEBUGFS) += debugfs.o debugfs_htt_stats.o debugfs_sta.o ath11k-$(CPTCFG_NL80211_TESTMODE) += testmode.o ath11k-$(CPTCFG_ATH11K_TRACING) += trace.o @@ -45,22 +45,22 @@ Signed-off-by: Robert Marko --- a/drivers/net/wireless/ath/ath11k/thermal.h +++ b/drivers/net/wireless/ath/ath11k/thermal.h -@@ -26,7 +26,7 @@ struct ath11k_thermal { +@@ -25,7 +25,7 @@ struct ath11k_thermal { int temperature; }; -#if IS_REACHABLE(CONFIG_THERMAL) +#if IS_REACHABLE(CPTCFG_ATH11K_THERMAL) - int ath11k_thermal_register(struct ath11k_base *ab); - void ath11k_thermal_unregister(struct ath11k_base *ab); + int ath11k_thermal_register(struct ath11k_base *sc); + void ath11k_thermal_unregister(struct ath11k_base *sc); int ath11k_thermal_set_throttling(struct ath11k *ar, u32 throttle_state); --- a/local-symbols +++ b/local-symbols -@@ -166,6 +166,7 @@ ATH11K_DEBUG= +@@ -174,6 +174,7 @@ ATH11K_DEBUG= ATH11K_DEBUGFS= ATH11K_TRACING= ATH11K_SPECTRAL= +ATH11K_THERMAL= - ATH12K= - ATH12K_DEBUG= - ATH12K_TRACING= + WLAN_VENDOR_ATMEL= + ATMEL= + PCI_ATMEL= diff --git a/package/kernel/mac80211/patches/ath11k/901-wifi-ath11k-pci-fix-compilation-in-5.16-and-older.patch b/package/kernel/mac80211/patches/ath11k/901-wifi-ath11k-pci-fix-compilation-in-5.16-and-older.patch new file mode 100644 index 000000000..9a0ca8009 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/901-wifi-ath11k-pci-fix-compilation-in-5.16-and-older.patch @@ -0,0 +1,29 @@ +From 04178918e7f6b5f34dde81ec79ee8a1ccace3be3 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Mon, 17 Oct 2022 11:45:03 +0200 +Subject: [PATCH] wifi: ath11k: pci: fix compilation in 5.16 and older + +Commit ("genirq/msi, treewide: Use a named struct for PCI/MSI attributes") +changed the msi_desc structure a bit, however that is only available in +kernels 5.17 and newer, so check for kernel version to allow compilation +in 5.16 and older. + +Signed-off-by: Robert Marko +--- + drivers/net/wireless/ath/ath11k/pci.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/net/wireless/ath/ath11k/pci.c ++++ b/drivers/net/wireless/ath/ath11k/pci.c +@@ -459,7 +459,11 @@ static int ath11k_pci_alloc_msi(struct a + pci_read_config_dword(pci_dev, pci_dev->msi_cap + PCI_MSI_ADDRESS_LO, + &ab->pci.msi.addr_lo); + ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(5, 17, 0)) + if (msi_desc->pci.msi_attrib.is_64) { ++#else ++ if (msi_desc->msi_attrib.is_64) { ++#endif + pci_read_config_dword(pci_dev, pci_dev->msi_cap + PCI_MSI_ADDRESS_HI, + &ab->pci.msi.addr_hi); + } else { diff --git a/package/kernel/mac80211/patches/ath11k/902-ath11k-Disable-coldboot-calibration-for-IPQ8074.patch b/package/kernel/mac80211/patches/ath11k/902-ath11k-Disable-coldboot-calibration-for-IPQ8074.patch new file mode 100644 index 000000000..0c92fa914 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/902-ath11k-Disable-coldboot-calibration-for-IPQ8074.patch @@ -0,0 +1,26 @@ +From dd3b9c59cfa1e9e0b73a575f4646be905691eaef Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Sat, 16 Oct 2021 19:34:10 +0200 +Subject: [PATCH 241/241] ath11k: Disable coldboot calibration for IPQ8074 + +There is a bug with the remoteproc reset after coldboot calibration, +so until that is resolved disabled it to allow using the radio. + +Signed-off-by: Robert Marko +--- + drivers/net/wireless/ath/ath11k/core.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/wireless/ath/ath11k/core.c ++++ b/drivers/net/wireless/ath/ath11k/core.c +@@ -86,8 +86,8 @@ static const struct ath11k_hw_params ath + .supports_shadow_regs = false, + .idle_ps = false, + .supports_sta_ps = false, +- .coldboot_cal_mm = true, +- .coldboot_cal_ftm = true, ++ .coldboot_cal_mm = false, ++ .coldboot_cal_ftm = false, + .cbcal_restart_fw = true, + .fw_mem_mode = 0, + .num_vdevs = 16 + 1, diff --git a/package/kernel/mac80211/patches/ath11k/903-ath11k-support-setting-FW-memory-mode-via-DT.patch b/package/kernel/mac80211/patches/ath11k/903-ath11k-support-setting-FW-memory-mode-via-DT.patch index dcf1f5f27..71373b213 100644 --- a/package/kernel/mac80211/patches/ath11k/903-ath11k-support-setting-FW-memory-mode-via-DT.patch +++ b/package/kernel/mac80211/patches/ath11k/903-ath11k-support-setting-FW-memory-mode-via-DT.patch @@ -22,7 +22,7 @@ Signed-off-by: Robert Marko --- a/drivers/net/wireless/ath/ath11k/core.c +++ b/drivers/net/wireless/ath/ath11k/core.c -@@ -37,7 +37,7 @@ bool ath11k_ftm_mode; +@@ -36,7 +36,7 @@ bool ath11k_ftm_mode; module_param_named(ftm_mode, ath11k_ftm_mode, bool, 0444); MODULE_PARM_DESC(ftm_mode, "Boots up in factory test mode"); @@ -31,7 +31,7 @@ Signed-off-by: Robert Marko { .hw_rev = ATH11K_HW_IPQ8074, .name = "ipq8074 hw2.0", -@@ -2138,7 +2138,8 @@ static void ath11k_core_reset(struct wor +@@ -2040,7 +2040,8 @@ static void ath11k_core_reset(struct wor static int ath11k_init_hw_params(struct ath11k_base *ab) { const struct ath11k_hw_params *hw_params = NULL; @@ -41,7 +41,7 @@ Signed-off-by: Robert Marko for (i = 0; i < ARRAY_SIZE(ath11k_hw_params); i++) { hw_params = &ath11k_hw_params[i]; -@@ -2154,7 +2155,31 @@ static int ath11k_init_hw_params(struct +@@ -2056,7 +2057,31 @@ static int ath11k_init_hw_params(struct ab->hw_params = *hw_params; diff --git a/package/kernel/mac80211/patches/ath11k/905-ath11k-remove-intersection-support-for-regulatory-ru.patch b/package/kernel/mac80211/patches/ath11k/905-ath11k-remove-intersection-support-for-regulatory-ru.patch index 19f4e7dbe..b0ceb00ba 100644 --- a/package/kernel/mac80211/patches/ath11k/905-ath11k-remove-intersection-support-for-regulatory-ru.patch +++ b/package/kernel/mac80211/patches/ath11k/905-ath11k-remove-intersection-support-for-regulatory-ru.patch @@ -23,7 +23,7 @@ Signed-off-by: Aditya Kumar Singh --- a/drivers/net/wireless/ath/ath11k/reg.c +++ b/drivers/net/wireless/ath/ath11k/reg.c -@@ -363,134 +363,6 @@ static u32 ath11k_map_fw_phy_flags(u32 p +@@ -352,129 +352,6 @@ static u32 ath11k_map_fw_reg_flags(u16 r return flags; } @@ -89,11 +89,6 @@ Signed-off-by: Aditya Kumar Singh - /* Use the flags of both the rules */ - new_rule->flags = rule1->flags | rule2->flags; - -- if ((rule1->flags & NL80211_RRF_PSD) && (rule2->flags & NL80211_RRF_PSD)) -- new_rule->psd = min_t(s8, rule1->psd, rule2->psd); -- else -- new_rule->flags &= ~NL80211_RRF_PSD; -- - /* To be safe, lts use the max cac timeout of both rules */ - new_rule->dfs_cac_ms = max_t(u32, rule1->dfs_cac_ms, - rule2->dfs_cac_ms); @@ -158,22 +153,20 @@ Signed-off-by: Aditya Kumar Singh static const char * ath11k_reg_get_regdom_str(enum nl80211_dfs_regions dfs_region) { -@@ -641,11 +513,11 @@ ath11k_reg_ap_pwr_convert(enum ieee80211 +@@ -609,9 +486,9 @@ ath11k_reg_update_weather_radar_band(str struct ieee80211_regdomain * ath11k_reg_build_regd(struct ath11k_base *ab, -- struct cur_regulatory_info *reg_info, bool intersect, -+ struct cur_regulatory_info *reg_info, - enum wmi_vdev_type vdev_type, - enum ieee80211_ap_reg_power power_type) +- struct cur_regulatory_info *reg_info, bool intersect) ++ struct cur_regulatory_info *reg_info) { - struct ieee80211_regdomain *tmp_regd, *default_regd, *new_regd = NULL; + struct ieee80211_regdomain *new_regd = NULL; - struct cur_reg_rule *reg_rule, *reg_rule_6ghz; + struct cur_reg_rule *reg_rule; u8 i = 0, j = 0, k = 0; u8 num_rules; -@@ -688,26 +560,26 @@ ath11k_reg_build_regd(struct ath11k_base - } +@@ -628,26 +505,26 @@ ath11k_reg_build_regd(struct ath11k_base + num_rules += reg_info->num_6ghz_rules_ap[WMI_REG_INDOOR_AP]; if (!num_rules) - goto ret; @@ -206,16 +199,16 @@ Signed-off-by: Aditya Kumar Singh reg_info->dfs_region, num_rules); /* Update reg_rules[] below. Firmware is expected to * send these rules in order(2 GHz rules first and then 5 GHz) -@@ -746,7 +618,7 @@ ath11k_reg_build_regd(struct ath11k_base +@@ -686,7 +563,7 @@ ath11k_reg_build_regd(struct ath11k_base + flags |= ath11k_map_fw_reg_flags(reg_rule->flags); - flags |= ath11k_map_fw_phy_flags(reg_info->phybitmap); - ath11k_reg_update_rule(tmp_regd->reg_rules + i, + ath11k_reg_update_rule(new_regd->reg_rules + i, reg_rule->start_freq, reg_rule->end_freq, max_bw, reg_rule->ant_gain, reg_rule->reg_power, -@@ -761,7 +633,7 @@ ath11k_reg_build_regd(struct ath11k_base +@@ -701,7 +578,7 @@ ath11k_reg_build_regd(struct ath11k_base reg_info->dfs_region == ATH11K_DFS_REG_ETSI && (reg_rule->end_freq > ETSI_WEATHER_RADAR_BAND_LOW && reg_rule->start_freq < ETSI_WEATHER_RADAR_BAND_HIGH)){ @@ -224,7 +217,7 @@ Signed-off-by: Aditya Kumar Singh reg_rule, &i, flags, max_bw); continue; -@@ -772,51 +644,23 @@ ath11k_reg_build_regd(struct ath11k_base +@@ -712,37 +589,20 @@ ath11k_reg_build_regd(struct ath11k_base "\t%d. (%d - %d @ %d) (%d, %d) (%d ms) (FLAGS %d) (%d, %d)\n", i + 1, reg_rule->start_freq, reg_rule->end_freq, max_bw, reg_rule->ant_gain, reg_rule->reg_power, @@ -243,8 +236,7 @@ Signed-off-by: Aditya Kumar Singh } - tmp_regd->n_reg_rules = i; -+ new_regd->n_reg_rules = i; - +- - if (intersect) { - default_regd = ab->default_regd[reg_info->phy_id]; - @@ -260,11 +252,29 @@ Signed-off-by: Aditya Kumar Singh - } else { - new_regd = tmp_regd; - } -- ++ new_regd->n_reg_rules = i; + -ret: return new_regd; } +--- a/drivers/net/wireless/ath/ath11k/reg.h ++++ b/drivers/net/wireless/ath/ath11k/reg.h +@@ -30,7 +30,7 @@ void ath11k_reg_free(struct ath11k_base + void ath11k_regd_update_work(struct work_struct *work); + struct ieee80211_regdomain * + ath11k_reg_build_regd(struct ath11k_base *ab, +- struct cur_regulatory_info *reg_info, bool intersect); ++ struct cur_regulatory_info *reg_info); + int ath11k_regd_update(struct ath11k *ar); + int ath11k_reg_update_chan_list(struct ath11k *ar, bool wait); + #endif +--- a/drivers/net/wireless/ath/ath11k/wmi.c ++++ b/drivers/net/wireless/ath/ath11k/wmi.c +@@ -6996,24 +6996,12 @@ static void ath11k_wmi_htc_tx_complete(s + wake_up(&wmi->tx_ce_desc_wq); + } + -static bool ath11k_reg_is_world_alpha(char *alpha) -{ - if (alpha[0] == '0' && alpha[1] == '0') @@ -276,20 +286,19 @@ Signed-off-by: Aditya Kumar Singh - return false; -} - - static enum wmi_vdev_type ath11k_reg_get_ar_vdev_type(struct ath11k *ar) + static int ath11k_reg_chan_list_event(struct ath11k_base *ab, + struct sk_buff *skb, + enum wmi_reg_chan_list_cmd_type id) { - struct ath11k_vif *arvif; -@@ -839,7 +683,6 @@ int ath11k_reg_handle_chan_list(struct a - enum ieee80211_ap_reg_power power_type) - { - struct ieee80211_regdomain *regd; + struct cur_regulatory_info *reg_info = NULL; + struct ieee80211_regdomain *regd = NULL; - bool intersect = false; - int pdev_idx; + int ret = 0, pdev_idx, i, j; struct ath11k *ar; - enum wmi_vdev_type vdev_type; -@@ -891,24 +734,14 @@ int ath11k_reg_handle_chan_list(struct a + +@@ -7075,17 +7063,7 @@ static int ath11k_reg_chan_list_event(st (char *)reg_info->alpha2, 2)) - goto retfail; + goto mem_free; - /* Intersect new rules with default regd if a new country setting was - * requested, i.e a default regd was already set during initialization @@ -301,28 +310,8 @@ Signed-off-by: Aditya Kumar Singh - !ath11k_reg_is_world_alpha((char *)reg_info->alpha2)) - intersect = true; - - ar = ab->pdevs[pdev_idx].ar; - vdev_type = ath11k_reg_get_ar_vdev_type(ar); - - ath11k_dbg(ab, ATH11K_DBG_WMI, -- "wmi handle chan list power type %d vdev type %d intersect %d\n", -- power_type, vdev_type, intersect); -+ "wmi handle chan list power type %d vdev type %d\n", -+ power_type, vdev_type); - -- regd = ath11k_reg_build_regd(ab, reg_info, intersect, vdev_type, power_type); -+ regd = ath11k_reg_build_regd(ab, reg_info, vdev_type, power_type); +- regd = ath11k_reg_build_regd(ab, reg_info, intersect); ++ regd = ath11k_reg_build_regd(ab, reg_info); if (!regd) { ath11k_warn(ab, "failed to build regd from reg_info\n"); goto fallback; ---- a/drivers/net/wireless/ath/ath11k/reg.h -+++ b/drivers/net/wireless/ath/ath11k/reg.h -@@ -35,7 +35,7 @@ void ath11k_reg_free(struct ath11k_base - void ath11k_regd_update_work(struct work_struct *work); - struct ieee80211_regdomain * - ath11k_reg_build_regd(struct ath11k_base *ab, -- struct cur_regulatory_info *reg_info, bool intersect, -+ struct cur_regulatory_info *reg_info, - enum wmi_vdev_type vdev_type, - enum ieee80211_ap_reg_power power_type); - int ath11k_regd_update(struct ath11k *ar); diff --git a/package/kernel/mac80211/patches/ath11k/906-ath11k-Disable-coldboot-calibration-for-IPQ6018.patch b/package/kernel/mac80211/patches/ath11k/906-ath11k-Disable-coldboot-calibration-for-IPQ6018.patch new file mode 100644 index 000000000..39a11d722 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/906-ath11k-Disable-coldboot-calibration-for-IPQ6018.patch @@ -0,0 +1,13 @@ +--- a/drivers/net/wireless/ath/ath11k/core.c ++++ b/drivers/net/wireless/ath/ath11k/core.c +@@ -168,8 +168,8 @@ static struct ath11k_hw_params ath11k_hw + .supports_shadow_regs = false, + .idle_ps = false, + .supports_sta_ps = false, +- .coldboot_cal_mm = true, +- .coldboot_cal_ftm = true, ++ .coldboot_cal_mm = false, ++ .coldboot_cal_ftm = false, + .cbcal_restart_fw = true, + .fw_mem_mode = 0, + .num_vdevs = 16 + 1, diff --git a/package/kernel/mac80211/patches/ath5k/440-ath5k_channel_bw_debugfs.patch b/package/kernel/mac80211/patches/ath5k/440-ath5k_channel_bw_debugfs.patch index 6ff95f95a..a63f0c881 100644 --- a/package/kernel/mac80211/patches/ath5k/440-ath5k_channel_bw_debugfs.patch +++ b/package/kernel/mac80211/patches/ath5k/440-ath5k_channel_bw_debugfs.patch @@ -109,7 +109,7 @@ drivers/net/wireless/ath/ath5k/debug.c | 86 ++++++++++++++++++++++++++++++++ /* debugfs: queues etc */ -@@ -995,6 +1086,8 @@ ath5k_debug_init_device(struct ath5k_hw +@@ -997,6 +1088,8 @@ ath5k_debug_init_device(struct ath5k_hw debugfs_create_file("queue", 0600, phydir, ah, &fops_queue); debugfs_create_bool("32khz_clock", 0600, phydir, &ah->ah_use_32khz_clock); diff --git a/package/kernel/mac80211/patches/ath9k/351-ath9k_hw-issue-external-reset-for-QCA955x.patch b/package/kernel/mac80211/patches/ath9k/351-ath9k_hw-issue-external-reset-for-QCA955x.patch index aac7e1392..53b7ba08b 100644 --- a/package/kernel/mac80211/patches/ath9k/351-ath9k_hw-issue-external-reset-for-QCA955x.patch +++ b/package/kernel/mac80211/patches/ath9k/351-ath9k_hw-issue-external-reset-for-QCA955x.patch @@ -75,7 +75,7 @@ Signed-off-by: Felix Fietkau + ath_dbg(ath9k_hw_common(ah), RESET, + "reset MAC via external reset\n"); -- REG_WRITE(ah, AR_RTC_RESET(ah), 1); +- REG_WRITE(ah, AR_RTC_RESET, 1); + err = ah->external_reset(); + if (err) { + ath_err(ath9k_hw_common(ah), @@ -84,11 +84,11 @@ Signed-off-by: Felix Fietkau } + if (AR_SREV_9550(ah)) { -+ REG_WRITE(ah, AR_RTC_RESET(ah), 0); ++ REG_WRITE(ah, AR_RTC_RESET, 0); + udelay(10); + } + -+ REG_WRITE(ah, AR_RTC_RESET(ah), 1); ++ REG_WRITE(ah, AR_RTC_RESET, 1); + udelay(10); + return true; @@ -124,6 +124,6 @@ Signed-off-by: Felix Fietkau + if (AR_SREV_9300(ah) || AR_SREV_9580(ah)) + REG_CLR_BIT(ah, AR_CFG, AR_CFG_HALT_REQ); + - REG_WRITE(ah, AR_RTC_RC(ah), rst_flags); + REG_WRITE(ah, AR_RTC_RC, rst_flags); REGWRITE_BUFFER_FLUSH(ah); diff --git a/package/kernel/mac80211/patches/ath9k/500-ath9k_eeprom_debugfs.patch b/package/kernel/mac80211/patches/ath9k/500-ath9k_eeprom_debugfs.patch index a0ec7ef97..e2bbb4a1b 100644 --- a/package/kernel/mac80211/patches/ath9k/500-ath9k_eeprom_debugfs.patch +++ b/package/kernel/mac80211/patches/ath9k/500-ath9k_eeprom_debugfs.patch @@ -1,24 +1,14 @@ --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c -@@ -1431,6 +1431,7 @@ int ath9k_init_debug(struct ath_hw *ah) - - ath9k_cmn_debug_base_eeprom(sc->debug.debugfs_phy, sc->sc_ah); - ath9k_cmn_debug_modal_eeprom(sc->debug.debugfs_phy, sc->sc_ah); -+ ath9k_cmn_debug_eeprom(sc->debug.debugfs_phy, sc->sc_ah); - - debugfs_create_u32("gpio_mask", 0600, - sc->debug.debugfs_phy, &sc->sc_ah->gpio_mask); ---- a/drivers/net/wireless/ath/ath9k/common-debug.c -+++ b/drivers/net/wireless/ath/ath9k/common-debug.c -@@ -260,3 +260,58 @@ void ath9k_cmn_debug_phy_err(struct dent - &fops_phy_err); +@@ -1413,6 +1413,53 @@ void ath9k_deinit_debug(struct ath_softc + ath9k_cmn_spectral_deinit_debug(&sc->spec_priv); } - EXPORT_SYMBOL(ath9k_cmn_debug_phy_err); -+ + +static ssize_t read_file_eeprom(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ -+ struct ath_hw *ah = file->private_data; ++ struct ath_softc *sc = file->private_data; ++ struct ath_hw *ah = sc->sc_ah; + struct ath_common *common = ath9k_hw_common(ah); + int bytes = 0; + int pos = *ppos; @@ -49,8 +39,7 @@ + } else { + bytes = 2; + } -+ if (copy_to_user(user_buf, from, bytes)) -+ return -EFAULT; ++ copy_to_user(user_buf, from, bytes); + user_buf += bytes; + } + return *ppos - pos; @@ -62,31 +51,15 @@ + .owner = THIS_MODULE +}; + -+void ath9k_cmn_debug_eeprom(struct dentry *debugfs_phy, -+ struct ath_hw *ah) -+{ -+ debugfs_create_file("eeprom", S_IRUSR, debugfs_phy, ah, + int ath9k_init_debug(struct ath_hw *ah) + { + struct ath_common *common = ath9k_hw_common(ah); +@@ -1432,6 +1479,8 @@ int ath9k_init_debug(struct ath_hw *ah) + ath9k_tx99_init_debug(sc); + ath9k_cmn_spectral_init_debug(&sc->spec_priv, sc->debug.debugfs_phy); + ++ debugfs_create_file("eeprom", S_IRUSR, sc->debug.debugfs_phy, sc, + &fops_eeprom); -+} -+EXPORT_SYMBOL(ath9k_cmn_debug_eeprom); ---- a/drivers/net/wireless/ath/ath9k/common-debug.h -+++ b/drivers/net/wireless/ath/ath9k/common-debug.h -@@ -69,6 +69,8 @@ void ath9k_cmn_debug_modal_eeprom(struct - struct ath_hw *ah); - void ath9k_cmn_debug_base_eeprom(struct dentry *debugfs_phy, - struct ath_hw *ah); -+void ath9k_cmn_debug_eeprom(struct dentry *debugfs_phy, -+ struct ath_hw *ah); - void ath9k_cmn_debug_stat_rx(struct ath_rx_stats *rxstats, - struct ath_rx_status *rs); - void ath9k_cmn_debug_recv(struct dentry *debugfs_phy, ---- a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c -+++ b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c -@@ -514,6 +514,7 @@ int ath9k_htc_init_debug(struct ath_hw * - - ath9k_cmn_debug_base_eeprom(priv->debug.debugfs_phy, priv->ah); - ath9k_cmn_debug_modal_eeprom(priv->debug.debugfs_phy, priv->ah); -+ ath9k_cmn_debug_eeprom(priv->debug.debugfs_phy, priv->ah); - - return 0; - } + debugfs_create_devm_seqfile(sc->dev, "dma", sc->debug.debugfs_phy, + read_file_dma); + debugfs_create_devm_seqfile(sc->dev, "interrupt", sc->debug.debugfs_phy, diff --git a/package/kernel/mac80211/patches/ath9k/511-ath9k_reduce_rxbuf.patch b/package/kernel/mac80211/patches/ath9k/511-ath9k_reduce_rxbuf.patch index 3abf16b03..15b8d7b86 100644 --- a/package/kernel/mac80211/patches/ath9k/511-ath9k_reduce_rxbuf.patch +++ b/package/kernel/mac80211/patches/ath9k/511-ath9k_reduce_rxbuf.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h -@@ -89,7 +89,7 @@ int ath_descdma_setup(struct ath_softc * +@@ -88,7 +88,7 @@ int ath_descdma_setup(struct ath_softc * (_l) &= ((_sz) - 1); \ } while (0) diff --git a/package/kernel/mac80211/patches/ath9k/512-ath9k_channelbw_debugfs.patch b/package/kernel/mac80211/patches/ath9k/512-ath9k_channelbw_debugfs.patch index 72eae8c7d..0c8b6920c 100644 --- a/package/kernel/mac80211/patches/ath9k/512-ath9k_channelbw_debugfs.patch +++ b/package/kernel/mac80211/patches/ath9k/512-ath9k_channelbw_debugfs.patch @@ -1,16 +1,70 @@ --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c -@@ -1432,6 +1432,7 @@ int ath9k_init_debug(struct ath_hw *ah) - ath9k_cmn_debug_base_eeprom(sc->debug.debugfs_phy, sc->sc_ah); - ath9k_cmn_debug_modal_eeprom(sc->debug.debugfs_phy, sc->sc_ah); - ath9k_cmn_debug_eeprom(sc->debug.debugfs_phy, sc->sc_ah); -+ ath9k_cmn_debug_chanbw(sc->debug.debugfs_phy, sc->sc_ah); +@@ -1460,6 +1460,52 @@ static const struct file_operations fops + .owner = THIS_MODULE + }; - debugfs_create_u32("gpio_mask", 0600, - sc->debug.debugfs_phy, &sc->sc_ah->gpio_mask); ++ ++static ssize_t read_file_chan_bw(struct file *file, char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct ath_softc *sc = file->private_data; ++ struct ath_common *common = ath9k_hw_common(sc->sc_ah); ++ char buf[32]; ++ unsigned int len; ++ ++ len = sprintf(buf, "0x%08x\n", common->chan_bw); ++ return simple_read_from_buffer(user_buf, count, ppos, buf, len); ++} ++ ++static ssize_t write_file_chan_bw(struct file *file, const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct ath_softc *sc = file->private_data; ++ struct ath_common *common = ath9k_hw_common(sc->sc_ah); ++ unsigned long chan_bw; ++ char buf[32]; ++ ssize_t len; ++ ++ len = min(count, sizeof(buf) - 1); ++ if (copy_from_user(buf, user_buf, len)) ++ return -EFAULT; ++ ++ buf[len] = '\0'; ++ if (kstrtoul(buf, 0, &chan_bw)) ++ return -EINVAL; ++ ++ common->chan_bw = chan_bw; ++ if (!test_bit(ATH_OP_INVALID, &common->op_flags)) ++ ath9k_ops.config(sc->hw, IEEE80211_CONF_CHANGE_CHANNEL); ++ ++ return count; ++} ++ ++static const struct file_operations fops_chanbw = { ++ .read = read_file_chan_bw, ++ .write = write_file_chan_bw, ++ .open = simple_open, ++ .owner = THIS_MODULE, ++ .llseek = default_llseek, ++}; ++ ++ + int ath9k_init_debug(struct ath_hw *ah) + { + struct ath_common *common = ath9k_hw_common(ah); +@@ -1481,6 +1527,8 @@ int ath9k_init_debug(struct ath_hw *ah) + + debugfs_create_file("eeprom", S_IRUSR, sc->debug.debugfs_phy, sc, + &fops_eeprom); ++ debugfs_create_file("chanbw", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, ++ sc, &fops_chanbw); + debugfs_create_devm_seqfile(sc->dev, "dma", sc->debug.debugfs_phy, + read_file_dma); + debugfs_create_devm_seqfile(sc->dev, "interrupt", sc->debug.debugfs_phy, --- a/drivers/net/wireless/ath/ath.h +++ b/drivers/net/wireless/ath/ath.h -@@ -151,6 +151,7 @@ struct ath_common { +@@ -149,6 +149,7 @@ struct ath_common { int debug_mask; enum ath_device_state state; unsigned long op_flags; @@ -18,14 +72,6 @@ struct ath_ani ani; -@@ -181,6 +182,7 @@ struct ath_common { - const struct ath_ops *ops; - const struct ath_bus_ops *bus_ops; - const struct ath_ps_ops *ps_ops; -+ const struct ieee80211_ops *ieee_ops; - - bool btcoex_enabled; - bool disable_ani; --- a/drivers/net/wireless/ath/ath9k/common.c +++ b/drivers/net/wireless/ath/ath9k/common.c @@ -297,11 +297,13 @@ EXPORT_SYMBOL(ath9k_cmn_get_hw_crypto_ke @@ -77,115 +123,3 @@ return channel; } ---- a/drivers/net/wireless/ath/ath9k/common-debug.c -+++ b/drivers/net/wireless/ath/ath9k/common-debug.c -@@ -315,3 +315,55 @@ void ath9k_cmn_debug_eeprom(struct dentr - &fops_eeprom); - } - EXPORT_SYMBOL(ath9k_cmn_debug_eeprom); -+ -+static ssize_t read_file_chan_bw(struct file *file, char __user *user_buf, -+ size_t count, loff_t *ppos) -+{ -+ struct ath_hw *ah = file->private_data; -+ struct ath_common *common = ath9k_hw_common(ah); -+ char buf[32]; -+ unsigned int len; -+ -+ len = sprintf(buf, "0x%08x\n", common->chan_bw); -+ return simple_read_from_buffer(user_buf, count, ppos, buf, len); -+} -+ -+static ssize_t write_file_chan_bw(struct file *file, const char __user *user_buf, -+ size_t count, loff_t *ppos) -+{ -+ struct ath_hw *ah = file->private_data; -+ struct ath_common *common = ath9k_hw_common(ah); -+ unsigned long chan_bw; -+ char buf[32]; -+ ssize_t len; -+ -+ len = min(count, sizeof(buf) - 1); -+ if (copy_from_user(buf, user_buf, len)) -+ return -EFAULT; -+ -+ buf[len] = '\0'; -+ if (kstrtoul(buf, 0, &chan_bw)) -+ return -EINVAL; -+ -+ common->chan_bw = chan_bw; -+ if (!test_bit(ATH_OP_INVALID, &common->op_flags)) -+ common->ieee_ops->config(ah->hw, IEEE80211_CONF_CHANGE_CHANNEL); -+ -+ return count; -+} -+ -+static const struct file_operations fops_chanbw = { -+ .read = read_file_chan_bw, -+ .write = write_file_chan_bw, -+ .open = simple_open, -+ .owner = THIS_MODULE, -+ .llseek = default_llseek, -+}; -+ -+void ath9k_cmn_debug_chanbw(struct dentry *debugfs_phy, -+ struct ath_hw *ah) -+{ -+ debugfs_create_file("chanbw", S_IRUSR | S_IWUSR, debugfs_phy, ah, -+ &fops_chanbw); -+} -+EXPORT_SYMBOL(ath9k_cmn_debug_chanbw); ---- a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c -+++ b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c -@@ -515,6 +515,7 @@ int ath9k_htc_init_debug(struct ath_hw * - ath9k_cmn_debug_base_eeprom(priv->debug.debugfs_phy, priv->ah); - ath9k_cmn_debug_modal_eeprom(priv->debug.debugfs_phy, priv->ah); - ath9k_cmn_debug_eeprom(priv->debug.debugfs_phy, priv->ah); -+ ath9k_cmn_debug_chanbw(priv->debug.debugfs_phy, priv->ah); - - return 0; - } ---- a/drivers/net/wireless/ath/ath9k/common-debug.h -+++ b/drivers/net/wireless/ath/ath9k/common-debug.h -@@ -71,6 +71,8 @@ void ath9k_cmn_debug_base_eeprom(struct - struct ath_hw *ah); - void ath9k_cmn_debug_eeprom(struct dentry *debugfs_phy, - struct ath_hw *ah); -+void ath9k_cmn_debug_chanbw(struct dentry *debugfs_phy, -+ struct ath_hw *ah); - void ath9k_cmn_debug_stat_rx(struct ath_rx_stats *rxstats, - struct ath_rx_status *rs); - void ath9k_cmn_debug_recv(struct dentry *debugfs_phy, ---- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c -+++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c -@@ -631,6 +631,7 @@ static int ath9k_init_priv(struct ath9k_ - priv->ah = ah; - - common = ath9k_hw_common(ah); -+ common->ieee_ops = &ath9k_htc_ops; - common->ops = &ah->reg_ops; - common->ps_ops = &ath9k_htc_ps_ops; - common->bus_ops = &ath9k_usb_bus_ops; -@@ -746,9 +747,9 @@ static void ath9k_set_hw_capab(struct at - - hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN | - WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | -- WIPHY_FLAG_HAS_CHANNEL_SWITCH; -- -- hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS; -+ WIPHY_FLAG_HAS_CHANNEL_SWITCH | -+ WIPHY_FLAG_SUPPORTS_5_10_MHZ | -+ WIPHY_FLAG_SUPPORTS_TDLS; - - hw->queues = 4; - hw->max_listen_interval = 1; ---- a/drivers/net/wireless/ath/ath9k/init.c -+++ b/drivers/net/wireless/ath/ath9k/init.c -@@ -733,6 +733,7 @@ static int ath9k_init_softc(u16 devid, s - if (!ath9k_is_chanctx_enabled()) - sc->cur_chan->hw_queue_base = 0; - -+ common->ieee_ops = &ath9k_ops; - common->ops = &ah->reg_ops; - common->bus_ops = bus_ops; - common->ps_ops = &ath9k_ps_ops; diff --git a/package/kernel/mac80211/patches/ath9k/530-ath9k_extra_leds.patch b/package/kernel/mac80211/patches/ath9k/530-ath9k_extra_leds.patch index 1b2d4cb5d..1fe004102 100644 --- a/package/kernel/mac80211/patches/ath9k/530-ath9k_extra_leds.patch +++ b/package/kernel/mac80211/patches/ath9k/530-ath9k_extra_leds.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h -@@ -844,6 +844,9 @@ static inline int ath9k_dump_btcoex(stru +@@ -843,6 +843,9 @@ static inline int ath9k_dump_btcoex(stru #ifdef CPTCFG_MAC80211_LEDS void ath_init_leds(struct ath_softc *sc); void ath_deinit_leds(struct ath_softc *sc); @@ -10,7 +10,7 @@ #else static inline void ath_init_leds(struct ath_softc *sc) { -@@ -980,6 +983,13 @@ void ath_ant_comb_scan(struct ath_softc +@@ -979,6 +982,13 @@ void ath_ant_comb_scan(struct ath_softc #define ATH9K_NUM_CHANCTX 2 /* supports 2 operating channels */ @@ -24,7 +24,7 @@ struct ath_softc { struct ieee80211_hw *hw; struct device *dev; -@@ -1033,9 +1043,8 @@ struct ath_softc { +@@ -1032,9 +1042,8 @@ struct ath_softc { spinlock_t chan_lock; #ifdef CPTCFG_MAC80211_LEDS @@ -181,7 +181,7 @@ --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c -@@ -1089,7 +1089,7 @@ int ath9k_init_device(u16 devid, struct +@@ -1088,7 +1088,7 @@ int ath9k_init_device(u16 devid, struct #ifdef CPTCFG_MAC80211_LEDS /* must be initialized before ieee80211_register_hw */ @@ -192,9 +192,9 @@ #endif --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c -@@ -123,6 +123,61 @@ static const struct file_operations fops - - #define DMA_BUF_LEN 1024 +@@ -1505,6 +1505,61 @@ static const struct file_operations fops + .llseek = default_llseek, + }; +#ifdef CONFIG_MAC80211_LEDS + @@ -252,12 +252,12 @@ +#endif + - static ssize_t read_file_ani(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -@@ -1392,6 +1447,10 @@ int ath9k_init_debug(struct ath_hw *ah) - ath9k_tx99_init_debug(sc); - ath9k_cmn_spectral_init_debug(&sc->spec_priv, sc->debug.debugfs_phy); - + int ath9k_init_debug(struct ath_hw *ah) + { +@@ -1529,6 +1584,10 @@ int ath9k_init_debug(struct ath_hw *ah) + &fops_eeprom); + debugfs_create_file("chanbw", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, + sc, &fops_chanbw); +#ifdef CONFIG_MAC80211_LEDS + debugfs_create_file("gpio_led", S_IWUSR, + sc->debug.debugfs_phy, sc, &fops_gpio_led); diff --git a/package/kernel/mac80211/patches/ath9k/531-ath9k_extra_platform_leds.patch b/package/kernel/mac80211/patches/ath9k/531-ath9k_extra_platform_leds.patch index 1055bd335..8ed7ad8a0 100644 --- a/package/kernel/mac80211/patches/ath9k/531-ath9k_extra_platform_leds.patch +++ b/package/kernel/mac80211/patches/ath9k/531-ath9k_extra_platform_leds.patch @@ -1,3 +1,15 @@ +--- a/include/linux/ath9k_platform.h ++++ b/include/linux/ath9k_platform.h +@@ -46,6 +46,9 @@ struct ath9k_platform_data { + int (*external_reset)(void); + + bool use_eeprom; ++ ++ int num_leds; ++ const struct gpio_led *leds; + }; + + #endif /* _LINUX_ATH9K_PLATFORM_H */ --- a/drivers/net/wireless/ath/ath9k/gpio.c +++ b/drivers/net/wireless/ath/ath9k/gpio.c @@ -15,6 +15,7 @@ diff --git a/package/kernel/mac80211/patches/ath9k/542-ath9k_debugfs_diag.patch b/package/kernel/mac80211/patches/ath9k/542-ath9k_debugfs_diag.patch index a0e5a24ed..70f7ee365 100644 --- a/package/kernel/mac80211/patches/ath9k/542-ath9k_debugfs_diag.patch +++ b/package/kernel/mac80211/patches/ath9k/542-ath9k_debugfs_diag.patch @@ -1,8 +1,8 @@ --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c -@@ -1428,6 +1428,50 @@ void ath9k_deinit_debug(struct ath_softc - ath9k_cmn_spectral_deinit_debug(&sc->spec_priv); - } +@@ -1561,6 +1561,50 @@ static const struct file_operations fops + #endif + +static ssize_t read_file_diag(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) @@ -51,7 +51,7 @@ int ath9k_init_debug(struct ath_hw *ah) { struct ath_common *common = ath9k_hw_common(ah); -@@ -1451,6 +1495,8 @@ int ath9k_init_debug(struct ath_hw *ah) +@@ -1588,6 +1632,8 @@ int ath9k_init_debug(struct ath_hw *ah) debugfs_create_file("gpio_led", S_IWUSR, sc->debug.debugfs_phy, sc, &fops_gpio_led); #endif @@ -125,7 +125,7 @@ REG_SET_BIT(ah, AR_BTCOEX_WL_LNADIV, AR_BTCOEX_WL_LNADIV_FORCE_ON); --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c -@@ -537,6 +537,11 @@ irqreturn_t ath_isr(int irq, void *dev) +@@ -538,6 +538,11 @@ irqreturn_t ath_isr(int irq, void *dev) return IRQ_HANDLED; } diff --git a/package/kernel/mac80211/patches/ath9k/543-ath9k_entropy_from_adc.patch b/package/kernel/mac80211/patches/ath9k/543-ath9k_entropy_from_adc.patch index 0fedc7127..6acc864d1 100644 --- a/package/kernel/mac80211/patches/ath9k/543-ath9k_entropy_from_adc.patch +++ b/package/kernel/mac80211/patches/ath9k/543-ath9k_entropy_from_adc.patch @@ -18,7 +18,7 @@ void (*spectral_scan_trigger)(struct ath_hw *ah); --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c -@@ -1915,6 +1915,26 @@ void ar9003_hw_init_rate_txpower(struct +@@ -1918,6 +1918,26 @@ void ar9003_hw_init_rate_txpower(struct } } @@ -26,9 +26,9 @@ +{ + int i, j; + -+ REG_RMW_FIELD(ah, AR_PHY_TEST(ah), AR_PHY_TEST_BBB_OBS_SEL, 1); -+ REG_CLR_BIT(ah, AR_PHY_TEST(ah), AR_PHY_TEST_RX_OBS_SEL_BIT5); -+ REG_RMW_FIELD(ah, AR_PHY_TEST_CTL_STATUS(ah), AR_PHY_TEST_CTL_RX_OBS_SEL, 0); ++ REG_RMW_FIELD(ah, AR_PHY_TEST, AR_PHY_TEST_BBB_OBS_SEL, 1); ++ REG_CLR_BIT(ah, AR_PHY_TEST, AR_PHY_TEST_RX_OBS_SEL_BIT5); ++ REG_RMW_FIELD(ah, AR_PHY_TEST_CTL_STATUS, AR_PHY_TEST_CTL_RX_OBS_SEL, 0); + + memset(buf, 0, len); + for (i = 0; i < len; i++) { @@ -45,7 +45,7 @@ void ar9003_hw_attach_phy_ops(struct ath_hw *ah) { struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); -@@ -1951,6 +1971,7 @@ void ar9003_hw_attach_phy_ops(struct ath +@@ -1954,6 +1974,7 @@ void ar9003_hw_attach_phy_ops(struct ath priv_ops->set_radar_params = ar9003_hw_set_radar_params; priv_ops->fast_chan_change = ar9003_hw_fast_chan_change; @@ -55,7 +55,7 @@ ops->spectral_scan_config = ar9003_hw_spectral_scan_config; --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c -@@ -871,7 +871,8 @@ static void ath9k_init_txpower_limits(st +@@ -870,7 +870,8 @@ static void ath9k_init_txpower_limits(st if (ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) ath9k_init_band_txpower(sc, NL80211_BAND_5GHZ); @@ -65,7 +65,7 @@ } static const struct ieee80211_iface_limit if_limits[] = { -@@ -1049,6 +1050,18 @@ static void ath9k_set_hw_capab(struct at +@@ -1048,6 +1049,18 @@ static void ath9k_set_hw_capab(struct at wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_CAN_REPLACE_PTK0); } @@ -84,7 +84,7 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc, const struct ath_bus_ops *bus_ops) { -@@ -1096,6 +1109,8 @@ int ath9k_init_device(u16 devid, struct +@@ -1095,6 +1108,8 @@ int ath9k_init_device(u16 devid, struct wiphy_read_of_freq_limits(hw->wiphy); diff --git a/package/kernel/mac80211/patches/ath9k/545-ath9k_ani_ws_detect.patch b/package/kernel/mac80211/patches/ath9k/545-ath9k_ani_ws_detect.patch index 6027741cd..d3bf07ff9 100644 --- a/package/kernel/mac80211/patches/ath9k/545-ath9k_ani_ws_detect.patch +++ b/package/kernel/mac80211/patches/ath9k/545-ath9k_ani_ws_detect.patch @@ -79,7 +79,7 @@ static const u8 ofdm2pwr[] = { ALL_TARGET_LEGACY_6_24, ALL_TARGET_LEGACY_6_24, -@@ -1065,11 +1051,6 @@ static bool ar9003_hw_ani_control(struct +@@ -1068,11 +1054,6 @@ static bool ar9003_hw_ani_control(struct struct ath_common *common = ath9k_hw_common(ah); struct ath9k_channel *chan = ah->curchan; struct ar5416AniState *aniState = &ah->ani; @@ -91,7 +91,7 @@ s32 value, value2; switch (cmd & ah->ani_function) { -@@ -1083,61 +1064,6 @@ static bool ar9003_hw_ani_control(struct +@@ -1086,61 +1067,6 @@ static bool ar9003_hw_ani_control(struct */ u32 on = param ? 1 : 0; diff --git a/package/kernel/mac80211/patches/ath9k/548-ath9k_enable_gpio_chip.patch b/package/kernel/mac80211/patches/ath9k/548-ath9k_enable_gpio_chip.patch index 643d51285..78206d286 100644 --- a/package/kernel/mac80211/patches/ath9k/548-ath9k_enable_gpio_chip.patch +++ b/package/kernel/mac80211/patches/ath9k/548-ath9k_enable_gpio_chip.patch @@ -10,7 +10,7 @@ Signed-off-by: Felix Fietkau --- --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h -@@ -25,6 +25,7 @@ +@@ -24,6 +24,7 @@ #include #include #include @@ -18,7 +18,7 @@ Signed-off-by: Felix Fietkau #include "common.h" #include "debug.h" -@@ -990,6 +991,14 @@ struct ath_led { +@@ -989,6 +990,14 @@ struct ath_led { struct led_classdev cdev; }; @@ -33,7 +33,7 @@ Signed-off-by: Felix Fietkau struct ath_softc { struct ieee80211_hw *hw; struct device *dev; -@@ -1045,6 +1054,9 @@ struct ath_softc { +@@ -1044,6 +1053,9 @@ struct ath_softc { #ifdef CPTCFG_MAC80211_LEDS const char *led_default_trigger; struct list_head leds; @@ -91,7 +91,7 @@ Signed-off-by: Felix Fietkau + gchip); + struct ath_hw *ah = gc->sc->sc_ah; + -+ return !((REG_READ(ah, AR_GPIO_OE_OUT(ah)) >> (offset * 2)) & 3); ++ return !((REG_READ(ah, AR_GPIO_OE_OUT) >> (offset * 2)) & 3); +} + +/* gpio_chip handler : get GPIO pin value */ diff --git a/package/kernel/mac80211/patches/ath9k/549-ath9k_enable_gpio_buttons.patch b/package/kernel/mac80211/patches/ath9k/549-ath9k_enable_gpio_buttons.patch index 0b2acf8af..716e09f35 100644 --- a/package/kernel/mac80211/patches/ath9k/549-ath9k_enable_gpio_buttons.patch +++ b/package/kernel/mac80211/patches/ath9k/549-ath9k_enable_gpio_buttons.patch @@ -10,7 +10,7 @@ Signed-off-by: Felix Fietkau --- --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h -@@ -1056,6 +1056,7 @@ struct ath_softc { +@@ -1055,6 +1055,7 @@ struct ath_softc { struct list_head leds; #ifdef CONFIG_GPIOLIB struct ath9k_gpio_chip *gpiochip; @@ -128,3 +128,16 @@ Signed-off-by: Felix Fietkau if (pdata && pdata->leds && pdata->num_leds) for (i = 0; i < pdata->num_leds; i++) { +--- a/include/linux/ath9k_platform.h ++++ b/include/linux/ath9k_platform.h +@@ -49,6 +49,10 @@ struct ath9k_platform_data { + + int num_leds; + const struct gpio_led *leds; ++ ++ unsigned num_btns; ++ const struct gpio_keys_button *btns; ++ unsigned btn_poll_interval; + }; + + #endif /* _LINUX_ATH9K_PLATFORM_H */ diff --git a/package/kernel/mac80211/patches/ath9k/551-ath9k_ubnt_uap_plus_hsr.patch b/package/kernel/mac80211/patches/ath9k/551-ath9k_ubnt_uap_plus_hsr.patch index 4e4cab986..efc4b9187 100644 --- a/package/kernel/mac80211/patches/ath9k/551-ath9k_ubnt_uap_plus_hsr.patch +++ b/package/kernel/mac80211/patches/ath9k/551-ath9k_ubnt_uap_plus_hsr.patch @@ -339,7 +339,7 @@ static void ath9k_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u32 queues, bool drop); -@@ -658,6 +659,7 @@ void ath_reset_work(struct work_struct * +@@ -659,6 +660,7 @@ void ath_reset_work(struct work_struct * static int ath9k_start(struct ieee80211_hw *hw) { struct ath_softc *sc = hw->priv; @@ -347,7 +347,7 @@ struct ath_hw *ah = sc->sc_ah; struct ath_common *common = ath9k_hw_common(ah); struct ieee80211_channel *curchan = sc->cur_chan->chandef.chan; -@@ -736,6 +738,11 @@ static int ath9k_start(struct ieee80211_ +@@ -737,6 +739,11 @@ static int ath9k_start(struct ieee80211_ AR_GPIO_OUTPUT_MUX_AS_OUTPUT); } @@ -371,7 +371,7 @@ --- a/local-symbols +++ b/local-symbols -@@ -121,6 +121,7 @@ ATH9K_WOW= +@@ -129,6 +129,7 @@ ATH9K_WOW= ATH9K_RFKILL= ATH9K_CHANNEL_CONTEXT= ATH9K_PCOEM= @@ -400,4 +400,4 @@ + config ATH9K_DEBUGFS bool "Atheros ath9k debugging" - depends on ATH9K && DEBUG_FS && MAC80211_DEBUGFS + depends on ATH9K && DEBUG_FS diff --git a/package/kernel/mac80211/patches/ath9k/552-ath9k-ahb_of.patch b/package/kernel/mac80211/patches/ath9k/552-ath9k-ahb_of.patch index a4efdcd1b..57eef54e8 100644 --- a/package/kernel/mac80211/patches/ath9k/552-ath9k-ahb_of.patch +++ b/package/kernel/mac80211/patches/ath9k/552-ath9k-ahb_of.patch @@ -16,7 +16,7 @@ static const struct platform_device_id ath9k_platform_id_table[] = { { -@@ -69,6 +77,192 @@ static const struct ath_bus_ops ath_ahb_ +@@ -69,6 +77,236 @@ static const struct ath_bus_ops ath_ahb_ .eeprom_read = ath_ahb_eeprom_read, }; @@ -25,6 +25,47 @@ +#define QCA955X_DDR_CTL_CONFIG 0x108 +#define QCA955X_DDR_CTL_CONFIG_ACT_WMAC BIT(23) + ++static int of_get_wifi_cal(struct device_node *np, struct ath9k_platform_data *pdata) ++{ ++#ifdef CONFIG_MTD ++ struct device_node *mtd_np = NULL; ++ size_t retlen; ++ int size, ret; ++ struct mtd_info *mtd; ++ const char *part; ++ const __be32 *list; ++ phandle phandle; ++ ++ list = of_get_property(np, "mtd-cal-data", &size); ++ if (!list) ++ return 0; ++ ++ if (size != (2 * sizeof(*list))) ++ return 1; ++ ++ phandle = be32_to_cpup(list++); ++ if (phandle) ++ mtd_np = of_find_node_by_phandle(phandle); ++ ++ if (!mtd_np) ++ return 1; ++ ++ part = of_get_property(mtd_np, "label", NULL); ++ if (!part) ++ part = mtd_np->name; ++ ++ mtd = get_mtd_device_nm(part); ++ if (IS_ERR(mtd)) ++ return 1; ++ ++ ret = mtd_read(mtd, be32_to_cpup(list), sizeof(pdata->eeprom_data), ++ &retlen, (u8*)pdata->eeprom_data); ++ put_mtd_device(mtd); ++ ++#endif ++ return 0; ++} ++ +static int ar913x_wmac_reset(void) +{ + ath79_device_reset_set(AR913X_RESET_AMBA2WMAC); @@ -202,6 +243,9 @@ + + pdata->get_mac_revision = data->soc_revision; + ++ if (of_get_wifi_cal(pdev->dev.of_node, pdata)) ++ dev_err(&pdev->dev, "failed to load calibration data from mtd device\n"); ++ + return data->dev_id; +} +#endif @@ -209,7 +253,7 @@ static int ath_ahb_probe(struct platform_device *pdev) { void __iomem *mem; -@@ -80,6 +274,17 @@ static int ath_ahb_probe(struct platform +@@ -80,6 +318,17 @@ static int ath_ahb_probe(struct platform int ret = 0; struct ath_hw *ah; char hw_name[64]; @@ -227,7 +271,7 @@ if (!dev_get_platdata(&pdev->dev)) { dev_err(&pdev->dev, "no platform data specified\n"); -@@ -118,17 +323,23 @@ static int ath_ahb_probe(struct platform +@@ -118,13 +367,16 @@ static int ath_ahb_probe(struct platform sc->mem = mem; sc->irq = irq; @@ -245,15 +289,18 @@ if (ret) { dev_err(&pdev->dev, "failed to initialize device\n"); goto err_irq; +@@ -155,6 +407,9 @@ static int ath_ahb_remove(struct platfor + free_irq(sc->irq, sc); + ieee80211_free_hw(sc->hw); } +#ifdef CONFIG_OF + pdev->dev.platform_data = NULL; +#endif - ah = sc->sc_ah; - ath9k_hw_name(ah, hw_name, sizeof(hw_name)); -@@ -162,6 +373,9 @@ static struct platform_driver ath_ahb_dr - .remove_new = ath_ahb_remove, + return 0; + } +@@ -164,6 +419,9 @@ static struct platform_driver ath_ahb_dr + .remove = ath_ahb_remove, .driver = { .name = "ath9k", +#ifdef CONFIG_OF @@ -264,7 +311,7 @@ }; --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h -@@ -26,6 +26,7 @@ +@@ -25,6 +25,7 @@ #include #include #include @@ -272,7 +319,7 @@ #include "common.h" #include "debug.h" -@@ -1012,6 +1013,9 @@ struct ath_softc { +@@ -1011,6 +1012,9 @@ struct ath_softc { struct ath_hw *sc_ah; void __iomem *mem; int irq; diff --git a/package/kernel/mac80211/patches/ath9k/553-ath9k_of_gpio_mask.patch b/package/kernel/mac80211/patches/ath9k/553-ath9k_of_gpio_mask.patch index 752a4980a..6d1820ecb 100644 --- a/package/kernel/mac80211/patches/ath9k/553-ath9k_of_gpio_mask.patch +++ b/package/kernel/mac80211/patches/ath9k/553-ath9k_of_gpio_mask.patch @@ -13,7 +13,7 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, const struct ath_bus_ops *bus_ops) { -@@ -804,6 +810,9 @@ static int ath9k_init_softc(u16 devid, s +@@ -803,6 +809,9 @@ static int ath9k_init_softc(u16 devid, s if (ret) goto err_hw; diff --git a/package/kernel/mac80211/patches/brcm/810-b43-gpio-mask-module-option.patch b/package/kernel/mac80211/patches/brcm/810-b43-gpio-mask-module-option.patch index 295a4cca7..09ef50526 100644 --- a/package/kernel/mac80211/patches/brcm/810-b43-gpio-mask-module-option.patch +++ b/package/kernel/mac80211/patches/brcm/810-b43-gpio-mask-module-option.patch @@ -22,7 +22,7 @@ static int modparam_bad_frames_preempt; module_param_named(bad_frames_preempt, modparam_bad_frames_preempt, int, 0444); MODULE_PARM_DESC(bad_frames_preempt, -@@ -2870,10 +2875,10 @@ static int b43_gpio_init(struct b43_wlde +@@ -2869,10 +2874,10 @@ static int b43_gpio_init(struct b43_wlde u32 mask, set; b43_maskset32(dev, B43_MMIO_MACCTL, ~B43_MACCTL_GPOUTSMSK, 0); diff --git a/package/kernel/mac80211/patches/brcm/812-b43-add-antenna-control.patch b/package/kernel/mac80211/patches/brcm/812-b43-add-antenna-control.patch index e9f915d2d..22b67c49d 100644 --- a/package/kernel/mac80211/patches/brcm/812-b43-add-antenna-control.patch +++ b/package/kernel/mac80211/patches/brcm/812-b43-add-antenna-control.patch @@ -9,7 +9,7 @@ antenna = b43_antenna_to_phyctl(antenna); ctl = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_BEACPHYCTL); /* We can't send beacons with short preamble. Would get PHY errors. */ -@@ -3285,8 +3285,8 @@ static int b43_chip_init(struct b43_wlde +@@ -3284,8 +3284,8 @@ static int b43_chip_init(struct b43_wlde /* Select the antennae */ if (phy->ops->set_rx_antenna) @@ -20,7 +20,7 @@ if (phy->type == B43_PHYTYPE_B) { value16 = b43_read16(dev, 0x005E); -@@ -3988,7 +3988,6 @@ static int b43_op_config(struct ieee8021 +@@ -3986,7 +3986,6 @@ static int b43_op_config(struct ieee8021 struct b43_wldev *dev = wl->current_dev; struct b43_phy *phy = &dev->phy; struct ieee80211_conf *conf = &hw->conf; @@ -28,7 +28,7 @@ int err = 0; mutex_lock(&wl->mutex); -@@ -4031,11 +4030,9 @@ static int b43_op_config(struct ieee8021 +@@ -4029,11 +4028,9 @@ static int b43_op_config(struct ieee8021 } /* Antennas for RX and management frame TX. */ @@ -42,7 +42,7 @@ if (wl->radio_enabled != phy->radio_on) { if (wl->radio_enabled) { -@@ -5178,6 +5175,47 @@ static int b43_op_get_survey(struct ieee +@@ -5176,6 +5173,47 @@ static int b43_op_get_survey(struct ieee return 0; } @@ -88,9 +88,9 @@ +} + static const struct ieee80211_ops b43_hw_ops = { - .add_chanctx = ieee80211_emulate_add_chanctx, - .remove_chanctx = ieee80211_emulate_remove_chanctx, -@@ -5204,6 +5242,8 @@ static const struct ieee80211_ops b43_hw + .tx = b43_op_tx, + .wake_tx_queue = ieee80211_handle_wake_tx_queue, +@@ -5198,6 +5236,8 @@ static const struct ieee80211_ops b43_hw .sw_scan_complete = b43_op_sw_scan_complete_notifier, .get_survey = b43_op_get_survey, .rfkill_poll = b43_rfkill_poll, @@ -99,7 +99,7 @@ }; /* Hard-reset the chip. Do not call this directly. -@@ -5505,6 +5545,8 @@ static int b43_one_core_attach(struct b4 +@@ -5499,6 +5539,8 @@ static int b43_one_core_attach(struct b4 if (!wldev) goto out; @@ -108,7 +108,7 @@ wldev->use_pio = b43_modparam_pio; wldev->dev = dev; wldev->wl = wl; -@@ -5596,6 +5638,9 @@ static struct b43_wl *b43_wireless_init( +@@ -5590,6 +5632,9 @@ static struct b43_wl *b43_wireless_init( wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST); diff --git a/package/kernel/mac80211/patches/brcm/814-b43-only-use-gpio-0-1-for-led.patch b/package/kernel/mac80211/patches/brcm/814-b43-only-use-gpio-0-1-for-led.patch index f7aa41320..9cb0a32fd 100644 --- a/package/kernel/mac80211/patches/brcm/814-b43-only-use-gpio-0-1-for-led.patch +++ b/package/kernel/mac80211/patches/brcm/814-b43-only-use-gpio-0-1-for-led.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/broadcom/b43/main.c +++ b/drivers/net/wireless/broadcom/b43/main.c -@@ -2887,6 +2887,14 @@ static int b43_gpio_init(struct b43_wlde +@@ -2886,6 +2886,14 @@ static int b43_gpio_init(struct b43_wlde } else if (dev->dev->chip_id == 0x5354) { /* Don't allow overtaking buttons GPIOs */ set &= 0x2; /* 0x2 is LED GPIO on BCM5354 */ diff --git a/package/kernel/mac80211/patches/brcm/860-brcmfmac-register-wiphy-s-during-module_init.patch b/package/kernel/mac80211/patches/brcm/860-brcmfmac-register-wiphy-s-during-module_init.patch new file mode 100644 index 000000000..9d0f3e20b --- /dev/null +++ b/package/kernel/mac80211/patches/brcm/860-brcmfmac-register-wiphy-s-during-module_init.patch @@ -0,0 +1,64 @@ +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Mon, 8 Jun 2015 16:11:40 +0200 +Subject: [PATCH] brcmfmac: register wiphy(s) during module_init +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This is needed by OpenWrt which expects all PHYs to be created after +module loads successfully. + +Signed-off-by: Rafał Miłecki +--- + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c +@@ -459,6 +459,7 @@ struct brcmf_fw { + u32 curpos; + unsigned int board_index; + void (*done)(struct device *dev, int err, struct brcmf_fw_request *req); ++ struct completion *completion; + }; + + #ifdef CONFIG_EFI +@@ -686,6 +687,8 @@ static void brcmf_fw_request_done(const + fwctx->req = NULL; + } + fwctx->done(fwctx->dev, ret, fwctx->req); ++ if (fwctx->completion) ++ complete(fwctx->completion); + kfree(fwctx); + } + +@@ -751,6 +754,8 @@ int brcmf_fw_get_firmwares(struct device + { + struct brcmf_fw_item *first = &req->items[0]; + struct brcmf_fw *fwctx; ++ struct completion completion; ++ unsigned long time_left; + char *alt_path = NULL; + int ret; + +@@ -768,6 +773,9 @@ int brcmf_fw_get_firmwares(struct device + fwctx->dev = dev; + fwctx->req = req; + fwctx->done = fw_cb; ++ ++ init_completion(&completion); ++ fwctx->completion = &completion; + + /* First try alternative board-specific path if any */ + if (fwctx->req->board_types[0]) +@@ -787,6 +795,12 @@ int brcmf_fw_get_firmwares(struct device + if (ret < 0) + brcmf_fw_request_done(NULL, fwctx); + ++ ++ time_left = wait_for_completion_timeout(&completion, ++ msecs_to_jiffies(5000)); ++ if (!time_left && fwctx) ++ fwctx->completion = NULL; ++ + return 0; + } + diff --git a/package/kernel/mac80211/patches/brcm/861-brcmfmac-workaround-bug-with-some-inconsistent-BSSes.patch b/package/kernel/mac80211/patches/brcm/861-brcmfmac-workaround-bug-with-some-inconsistent-BSSes.patch index 84b989d85..b82b442a1 100644 --- a/package/kernel/mac80211/patches/brcm/861-brcmfmac-workaround-bug-with-some-inconsistent-BSSes.patch +++ b/package/kernel/mac80211/patches/brcm/861-brcmfmac-workaround-bug-with-some-inconsistent-BSSes.patch @@ -10,7 +10,7 @@ Signed-off-by: Rafał Miłecki --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c -@@ -980,8 +980,36 @@ static struct wireless_dev *brcmf_cfg802 +@@ -713,8 +713,36 @@ static struct wireless_dev *brcmf_cfg802 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); struct brcmf_pub *drvr = cfg->pub; struct wireless_dev *wdev; diff --git a/package/kernel/mac80211/patches/brcm/862-brcmfmac-Disable-power-management.patch b/package/kernel/mac80211/patches/brcm/862-brcmfmac-Disable-power-management.patch index 9f91b29c4..080ab8f7e 100644 --- a/package/kernel/mac80211/patches/brcm/862-brcmfmac-Disable-power-management.patch +++ b/package/kernel/mac80211/patches/brcm/862-brcmfmac-Disable-power-management.patch @@ -14,7 +14,7 @@ Signed-off-by: Phil Elwell --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c -@@ -3313,6 +3313,10 @@ brcmf_cfg80211_set_power_mgmt(struct wip +@@ -2976,6 +2976,10 @@ brcmf_cfg80211_set_power_mgmt(struct wip * preference in cfg struct to apply this to * FW later while initializing the dongle */ diff --git a/package/kernel/mac80211/patches/brcm/863-brcmfmac-add-in-driver-tables-with-country-codes.patch b/package/kernel/mac80211/patches/brcm/863-brcmfmac-add-in-driver-tables-with-country-codes.patch index f873528e2..25191b643 100644 --- a/package/kernel/mac80211/patches/brcm/863-brcmfmac-add-in-driver-tables-with-country-codes.patch +++ b/package/kernel/mac80211/patches/brcm/863-brcmfmac-add-in-driver-tables-with-country-codes.patch @@ -49,7 +49,7 @@ Signed-off-by: Rafał Miłecki void brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type, struct brcmf_mp_device *settings) { -@@ -113,6 +143,8 @@ void brcmf_of_probe(struct device *dev, +@@ -106,6 +136,8 @@ void brcmf_of_probe(struct device *dev, of_node_put(root); } diff --git a/package/kernel/mac80211/patches/brcm/865-brcmfmac-Read-alternative-firmware-names-from-DT.patch b/package/kernel/mac80211/patches/brcm/865-brcmfmac-Read-alternative-firmware-names-from-DT.patch new file mode 100644 index 000000000..8ed81f600 --- /dev/null +++ b/package/kernel/mac80211/patches/brcm/865-brcmfmac-Read-alternative-firmware-names-from-DT.patch @@ -0,0 +1,187 @@ +From 4e32024cbb14230af3048e249e84f8c2b25ce45a Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Thu, 28 Oct 2021 15:03:16 +0100 +Subject: [PATCH] brcmfmac: Read alternative firmware names from DT + +Add the ability to load the names of alternative firmwares from the +Device Tree node. This permits separate firmwares for 43436s and 43438 +and allows downstream firmwares to coexist with upstream. + +Signed-off-by: Phil Elwell +--- + .../wireless/broadcom/brcm80211/brcmfmac/of.c | 36 ++++++++++++++ + .../wireless/broadcom/brcm80211/brcmfmac/of.h | 7 +++ + .../broadcom/brcm80211/brcmfmac/sdio.c | 47 +++++++++++++++++-- + 3 files changed, 87 insertions(+), 3 deletions(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c +@@ -11,6 +11,7 @@ + #include "debug.h" + #include "core.h" + #include "common.h" ++#include "firmware.h" + #include "of.h" + + static int brcmf_of_get_country_codes(struct device *dev, +@@ -168,3 +169,38 @@ void brcmf_of_probe(struct device *dev, + sdio->oob_irq_nr = irq; + sdio->oob_irq_flags = irqf; + } ++ ++struct brcmf_firmware_mapping * ++brcmf_of_fwnames(struct device *dev, u32 *fwname_count) ++{ ++ struct device_node *np = dev->of_node; ++ struct brcmf_firmware_mapping *fwnames; ++ struct device_node *map_np, *fw_np; ++ int of_count; ++ int count = 0; ++ ++ map_np = of_get_child_by_name(np, "firmwares"); ++ of_count = of_get_child_count(map_np); ++ if (!of_count) ++ return NULL; ++ ++ fwnames = devm_kcalloc(dev, of_count, ++ sizeof(struct brcmf_firmware_mapping), ++ GFP_KERNEL); ++ ++ for_each_child_of_node(map_np, fw_np) ++ { ++ struct brcmf_firmware_mapping *cur = &fwnames[count]; ++ ++ if (of_property_read_u32(fw_np, "chipid", &cur->chipid) || ++ of_property_read_u32(fw_np, "revmask", &cur->revmask)) ++ continue; ++ cur->fw_base = of_get_property(fw_np, "fw_base", NULL); ++ if (cur->fw_base) ++ count++; ++ } ++ ++ *fwname_count = count; ++ ++ return count ? fwnames : NULL; ++} +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.h ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.h +@@ -5,9 +5,16 @@ + #ifdef CONFIG_OF + void brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type, + struct brcmf_mp_device *settings); ++struct brcmf_firmware_mapping * ++brcmf_of_fwnames(struct device *dev, u32 *map_count); + #else + static void brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type, + struct brcmf_mp_device *settings) + { + } ++static struct brcmf_firmware_mapping * ++brcmf_of_fwnames(struct device *dev, u32 *map_count) ++{ ++ return NULL; ++} + #endif /* CONFIG_OF */ +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +@@ -35,6 +35,7 @@ + #include "core.h" + #include "common.h" + #include "bcdc.h" ++#include "of.h" + + #define DCMD_RESP_TIMEOUT msecs_to_jiffies(2500) + #define CTL_DONE_TIMEOUT msecs_to_jiffies(2500) +@@ -634,7 +635,7 @@ MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "b + /* per-board firmware binaries */ + MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "brcmfmac*-sdio.*.bin"); + +-static const struct brcmf_firmware_mapping brcmf_sdio_fwnames[] = { ++static const struct brcmf_firmware_mapping sdio_fwnames[] = { + BRCMF_FW_ENTRY(BRCM_CC_43143_CHIP_ID, 0xFFFFFFFF, 43143), + BRCMF_FW_ENTRY(BRCM_CC_43241_CHIP_ID, 0x0000001F, 43241B0), + BRCMF_FW_ENTRY(BRCM_CC_43241_CHIP_ID, 0x00000020, 43241B4), +@@ -662,6 +663,9 @@ static const struct brcmf_firmware_mappi + BRCMF_FW_ENTRY(CY_CC_43752_CHIP_ID, 0xFFFFFFFF, 43752) + }; + ++static const struct brcmf_firmware_mapping *brcmf_sdio_fwnames = sdio_fwnames; ++static u32 brcmf_sdio_fwnames_count = ARRAY_SIZE(sdio_fwnames); ++ + #define TXCTL_CREDITS 2 + + static void pkt_align(struct sk_buff *p, int len, int align) +@@ -4193,6 +4197,9 @@ static const struct brcmf_bus_ops brcmf_ + #define BRCMF_SDIO_FW_NVRAM 1 + #define BRCMF_SDIO_FW_CLM 2 + ++static struct brcmf_fw_request * ++brcmf_sdio_prepare_fw_request(struct brcmf_sdio *bus); ++ + static void brcmf_sdio_firmware_callback(struct device *dev, int err, + struct brcmf_fw_request *fwreq) + { +@@ -4208,6 +4215,22 @@ static void brcmf_sdio_firmware_callback + + brcmf_dbg(TRACE, "Enter: dev=%s, err=%d\n", dev_name(dev), err); + ++ if (err && brcmf_sdio_fwnames != sdio_fwnames) { ++ /* Try again with the standard firmware names */ ++ brcmf_sdio_fwnames = sdio_fwnames; ++ brcmf_sdio_fwnames_count = ARRAY_SIZE(sdio_fwnames); ++ kfree(fwreq); ++ fwreq = brcmf_sdio_prepare_fw_request(bus); ++ if (!fwreq) { ++ err = -ENOMEM; ++ goto fail; ++ } ++ err = brcmf_fw_get_firmwares(dev, fwreq, ++ brcmf_sdio_firmware_callback); ++ if (!err) ++ return; ++ } ++ + if (err) + goto fail; + +@@ -4418,7 +4441,7 @@ brcmf_sdio_prepare_fw_request(struct brc + + fwreq = brcmf_fw_alloc_request(bus->ci->chip, bus->ci->chiprev, + brcmf_sdio_fwnames, +- ARRAY_SIZE(brcmf_sdio_fwnames), ++ brcmf_sdio_fwnames_count, + fwnames, ARRAY_SIZE(fwnames)); + if (!fwreq) + return NULL; +@@ -4438,6 +4461,9 @@ struct brcmf_sdio *brcmf_sdio_probe(stru + struct brcmf_sdio *bus; + struct workqueue_struct *wq; + struct brcmf_fw_request *fwreq; ++ struct brcmf_firmware_mapping *of_fwnames, *fwnames = NULL; ++ const int fwname_size = sizeof(struct brcmf_firmware_mapping); ++ u32 of_fw_count; + + brcmf_dbg(TRACE, "Enter\n"); + +@@ -4520,6 +4546,21 @@ struct brcmf_sdio *brcmf_sdio_probe(stru + + brcmf_dbg(INFO, "completed!!\n"); + ++ of_fwnames = brcmf_of_fwnames(sdiodev->dev, &of_fw_count); ++ if (of_fwnames) ++ fwnames = devm_kcalloc(sdiodev->dev, ++ of_fw_count + brcmf_sdio_fwnames_count, ++ fwname_size, GFP_KERNEL); ++ ++ if (fwnames) { ++ /* The array is scanned in order, so overrides come first */ ++ memcpy(fwnames, of_fwnames, of_fw_count * fwname_size); ++ memcpy(fwnames + of_fw_count, sdio_fwnames, ++ brcmf_sdio_fwnames_count * fwname_size); ++ brcmf_sdio_fwnames = fwnames; ++ brcmf_sdio_fwnames_count += of_fw_count; ++ } ++ + fwreq = brcmf_sdio_prepare_fw_request(bus); + if (!fwreq) { + ret = -ENOMEM; diff --git a/package/kernel/mac80211/patches/brcm/865-brcmfmac-disable-dump_survey-on-bcm2835.patch b/package/kernel/mac80211/patches/brcm/865-brcmfmac-disable-dump_survey-on-bcm2835.patch deleted file mode 100644 index 975647444..000000000 --- a/package/kernel/mac80211/patches/brcm/865-brcmfmac-disable-dump_survey-on-bcm2835.patch +++ /dev/null @@ -1,38 +0,0 @@ -brcmfmac: disable dump_survey on Raspberry Pi - -Enabling this causes slow iwinfo calls on Raspberry Pi and LuCI slows down -when wireless is enabled. -https://github.com/openwrt/openwrt/issues/14013 - -Signed-off-by: Álvaro Fernández Rojas ---- - ---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c -+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c -@@ -7979,6 +7979,7 @@ static s32 brcmf_translate_country_code( - return 0; - } - -+#if !defined(CONFIG_ARCH_BCM2835) - static int - brcmf_parse_dump_obss(char *buf, struct brcmf_dump_survey *survey) - { -@@ -8201,6 +8202,7 @@ exit: - brcmf_set_mpc(ifp, 1); - return err; - } -+#endif /* CONFIG_ARCH_BCM2835 */ - - static void brcmf_cfg80211_reg_notifier(struct wiphy *wiphy, - struct regulatory_request *req) -@@ -8353,8 +8355,10 @@ struct brcmf_cfg80211_info *brcmf_cfg802 - if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_WOWL_GTK)) - ops->set_rekey_data = brcmf_cfg80211_set_rekey_data; - #endif -+#if !defined(CONFIG_ARCH_BCM2835) - if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_DUMP_OBSS)) - ops->dump_survey = brcmf_cfg80211_dump_survey; -+#endif /* CONFIG_ARCH_BCM2835 */ - - err = wiphy_register(wiphy); - if (err < 0) { diff --git a/package/kernel/mac80211/patches/build/001-fix_build.patch b/package/kernel/mac80211/patches/build/001-fix_build.patch index 085eae3cd..8f63d36e2 100644 --- a/package/kernel/mac80211/patches/build/001-fix_build.patch +++ b/package/kernel/mac80211/patches/build/001-fix_build.patch @@ -27,7 +27,7 @@ @set -e ; test -f local-symbols || ( \ echo "/--------------" ;\ echo "| You shouldn't run make in the backports tree, but only in" ;\ -@@ -60,57 +62,62 @@ mrproper: +@@ -60,58 +62,62 @@ mrproper: echo "| (that isn't currently running.)" ;\ echo "\\--" ;\ false) @@ -56,12 +56,13 @@ - done \ - ) > Kconfig.kernel ;\ - kver=$$($(MAKE) --no-print-directory -C $(KLIB_BUILD) M=$(BACKPORT_DIR) \ -- kernelversion | sed 's/^\(\([3-6]\|2\.6\)\.[0-9]\+\).*/\1/;t;d');\ +- kernelversion | sed 's/^\(\([3-5]\|2\.6\)\.[0-9]\+\).*/\1/;t;d');\ - test "$$kver" != "" || echo "Kernel version parse failed!" ;\ - test "$$kver" != "" ;\ +- kvers="$$(seq 14 39 | sed 's/^/2.6./')" ;\ +- kvers="$$kvers $$(seq 0 19 | sed 's/^/3./')" ;\ - kvers="$$kvers $$(seq 0 20 | sed 's/^/4./')" ;\ -- kvers="$$kvers $$(seq 0 19 | sed 's/^/5./')" ;\ -- kvers="$$kvers $$(seq 0 20 | sed 's/^/6./')" ;\ +- kvers="$$kvers $$(seq 0 99 | sed 's/^/5./')" ;\ - print=0 ;\ - for v in $$kvers ; do \ - if [ "$$print" = "1" ] ; then \ @@ -111,13 +112,14 @@ + @echo " done." + +Kconfig.versions: Kconfig.kernel -+ @kver=$$($(MAKE) --no-print-directory -C $(KLIB_BUILD) M=$(BACKPORT_DIR) \ -+ kernelversion | sed 's/^\(\([3-6]\|2\.6\)\.[0-9]\+\).*/\1/;t;d');\ ++ @kver=$$($(MAKE) --no-print-directory -C $(KLIB_BUILD) M=$(BACKPORT_DIR) \ ++ kernelversion | sed 's/^\(\([3-5]\|2\.6\)\.[0-9]\+\).*/\1/;t;d');\ + test "$$kver" != "" || echo "Kernel version parse failed!" ;\ + test "$$kver" != "" ;\ ++ kvers="$$(seq 14 39 | sed 's/^/2.6./')" ;\ ++ kvers="$$kvers $$(seq 0 19 | sed 's/^/3./')" ;\ + kvers="$$kvers $$(seq 0 20 | sed 's/^/4./')" ;\ -+ kvers="$$kvers $$(seq 0 19 | sed 's/^/5./')" ;\ -+ kvers="$$kvers $$(seq 0 20 | sed 's/^/6./')" ;\ ++ kvers="$$kvers $$(seq 0 99 | sed 's/^/5./')" ;\ + print=0 ;\ + for v in $$kvers ; do \ + if [ "$$print" = "1" ] ; then \ @@ -125,9 +127,8 @@ + echo " def_bool y" ;\ + fi ;\ + if [ "$$v" = "$$kver" ] ; then print=1 ; fi ;\ -+ done > Kconfig.versions ;\ -+ # RHEL as well, sadly we need to grep for it ;\ -+ RHEL_MAJOR=$$(grep '^RHEL_MAJOR' $(KERNEL_MAKEFILE) | \ ++ done > $@ ++ @RHEL_MAJOR=$$(grep '^RHEL_MAJOR' $(KERNEL_MAKEFILE) | \ + sed 's/.*=\s*\([0-9]*\)/\1/;t;d') ;\ + RHEL_MINOR=$$(grep '^RHEL_MINOR' $(KERNEL_MAKEFILE) | \ + sed 's/.*=\s*\([0-9]*\)/\1/;t;d') ;\ diff --git a/package/kernel/mac80211/patches/build/004-fix-kconf-compiling.patch b/package/kernel/mac80211/patches/build/004-fix-kconf-compiling.patch deleted file mode 100644 index 8bae8367f..000000000 --- a/package/kernel/mac80211/patches/build/004-fix-kconf-compiling.patch +++ /dev/null @@ -1,47 +0,0 @@ ---- a/Makefile.real -+++ b/Makefile.real -@@ -6,6 +6,18 @@ else - export BACKPORTS_GIT_TRACKER_DEF= - endif - -+ifneq ($(LLVM),) -+ifneq ($(filter %/,$(LLVM)),) -+LLVM_PREFIX := $(LLVM) -+else ifneq ($(filter -%,$(LLVM)),) -+LLVM_SUFFIX := $(LLVM) -+endif -+ -+HOSTCC = $(LLVM_PREFIX)clang$(LLVM_SUFFIX) -+else -+HOSTCC = gcc -+endif -+ - # disable built-in rules for this file - .SUFFIXES: - -@@ -24,21 +36,21 @@ listnewconfig oldaskconfig oldconfig \ - silentoldconfig olddefconfig oldnoconfig \ - allnoconfig allyesconfig allmodconfig \ - alldefconfig randconfig: -- @$(MAKE) -C kconf conf -+ @$(MAKE) -C kconf CC=$(HOSTCC) conf - @./kconf/conf --$@ Kconfig - - .PHONY: usedefconfig - usedefconfig: -- @$(MAKE) -C kconf conf -+ @$(MAKE) -C kconf CC=$(HOSTCC) conf - @./kconf/conf --defconfig=defconfig Kconfig - - .PHONY: savedefconfig - savedefconfig: -- @$(MAKE) -C kconf conf -+ @$(MAKE) -C kconf CC=$(HOSTCC) conf - @./kconf/conf --savedefconfig=defconfig Kconfig - - defconfig-%:: -- @$(MAKE) -C kconf conf -+ @$(MAKE) -C kconf CC=$(HOSTCC) conf - @./kconf/conf --defconfig=defconfigs/$(@:defconfig-%=%) Kconfig - - .config: diff --git a/package/kernel/mac80211/patches/build/050-lib80211_option.patch b/package/kernel/mac80211/patches/build/050-lib80211_option.patch new file mode 100644 index 000000000..c1b1bc757 --- /dev/null +++ b/package/kernel/mac80211/patches/build/050-lib80211_option.patch @@ -0,0 +1,34 @@ +--- a/net/wireless/Kconfig ++++ b/net/wireless/Kconfig +@@ -188,7 +188,7 @@ config CFG80211_WEXT_EXPORT + endif # CFG80211 + + config LIB80211 +- tristate ++ tristate "lib80211" + depends on m + default n + help +@@ -198,19 +198,19 @@ config LIB80211 + Drivers should select this themselves if needed. + + config LIB80211_CRYPT_WEP +- tristate ++ tristate "lib80211 WEP support" + depends on m + select BPAUTO_CRYPTO_LIB_ARC4 + + config LIB80211_CRYPT_CCMP +- tristate ++ tristate "lib80211 CCMP support" + depends on m + depends on CRYPTO + depends on CRYPTO_AES + depends on CRYPTO_CCM + + config LIB80211_CRYPT_TKIP +- tristate ++ tristate "lib80211 TKIP support" + depends on m + select BPAUTO_CRYPTO_LIB_ARC4 + diff --git a/package/kernel/mac80211/patches/build/060-no_local_ssb_bcma.patch b/package/kernel/mac80211/patches/build/060-no_local_ssb_bcma.patch index 0dad745b4..4ad2ac081 100644 --- a/package/kernel/mac80211/patches/build/060-no_local_ssb_bcma.patch +++ b/package/kernel/mac80211/patches/build/060-no_local_ssb_bcma.patch @@ -1,6 +1,6 @@ --- a/local-symbols +++ b/local-symbols -@@ -471,43 +471,6 @@ USB_VL600= +@@ -470,43 +470,6 @@ USB_VL600= USB_NET_CH9200= USB_NET_AQC111= USB_RTL8153_ECM= @@ -90,7 +90,7 @@ config B43_PHY_G --- a/drivers/net/wireless/broadcom/b43/main.c +++ b/drivers/net/wireless/broadcom/b43/main.c -@@ -2854,7 +2854,7 @@ static struct ssb_device *b43_ssb_gpio_d +@@ -2853,7 +2853,7 @@ static struct ssb_device *b43_ssb_gpio_d { struct ssb_bus *bus = dev->dev->sdev->bus; @@ -99,7 +99,7 @@ return (bus->chipco.dev ? bus->chipco.dev : bus->pcicore.dev); #else return bus->chipco.dev; -@@ -4873,7 +4873,7 @@ static int b43_wireless_core_init(struct +@@ -4871,7 +4871,7 @@ static int b43_wireless_core_init(struct } if (sprom->boardflags_lo & B43_BFL_XTAL_NOSLOW) hf |= B43_HF_DSCRQ; /* Disable slowclock requests from ucode. */ @@ -171,7 +171,7 @@ depends on CORDIC --- a/Kconfig.local +++ b/Kconfig.local -@@ -1417,117 +1417,6 @@ config BACKPORTED_USB_NET_AQC111 +@@ -1414,117 +1414,6 @@ config BACKPORTED_USB_NET_AQC111 config BACKPORTED_USB_RTL8153_ECM tristate default USB_RTL8153_ECM @@ -303,7 +303,7 @@ source "$BACKPORT_DIR/drivers/staging/Kconfig" --- a/Makefile.kernel +++ b/Makefile.kernel -@@ -42,8 +42,6 @@ obj-$(CPTCFG_QRTR) += net/qrtr/ +@@ -43,8 +43,6 @@ obj-$(CPTCFG_QRTR) += net/qrtr/ obj-$(CPTCFG_QCOM_QMI_HELPERS) += drivers/soc/qcom/ obj-$(CPTCFG_MHI_BUS) += drivers/bus/mhi/ obj-$(CPTCFG_WLAN) += drivers/net/wireless/ diff --git a/package/kernel/mac80211/patches/build/080-resv_start_op.patch b/package/kernel/mac80211/patches/build/080-resv_start_op.patch new file mode 100644 index 000000000..40b8e94a2 --- /dev/null +++ b/package/kernel/mac80211/patches/build/080-resv_start_op.patch @@ -0,0 +1,24 @@ +--- a/drivers/net/wireless/mac80211_hwsim.c ++++ b/drivers/net/wireless/mac80211_hwsim.c +@@ -5363,7 +5363,9 @@ static struct genl_family hwsim_genl_fam + .module = THIS_MODULE, + .small_ops = hwsim_ops, + .n_small_ops = ARRAY_SIZE(hwsim_ops), ++#if LINUX_VERSION_IS_GEQ(6,1,0) + .resv_start_op = HWSIM_CMD_DEL_MAC_ADDR + 1, ++#endif + .mcgrps = hwsim_mcgrps, + .n_mcgrps = ARRAY_SIZE(hwsim_mcgrps), + }; +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -17233,7 +17233,9 @@ static struct genl_family nl80211_fam __ + .n_ops = ARRAY_SIZE(nl80211_ops), + .small_ops = nl80211_small_ops, + .n_small_ops = ARRAY_SIZE(nl80211_small_ops), ++#if LINUX_VERSION_IS_GEQ(6,1,0) + .resv_start_op = NL80211_CMD_REMOVE_LINK_STA + 1, ++#endif + .mcgrps = nl80211_mcgrps, + .n_mcgrps = ARRAY_SIZE(nl80211_mcgrps), + .parallel_ops = true, diff --git a/package/kernel/mac80211/patches/build/099-netlink-range.patch b/package/kernel/mac80211/patches/build/099-netlink-range.patch new file mode 100644 index 000000000..0df2b38fa --- /dev/null +++ b/package/kernel/mac80211/patches/build/099-netlink-range.patch @@ -0,0 +1,91 @@ +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -421,8 +421,13 @@ static const struct nla_policy + nl80211_fils_discovery_policy[NL80211_FILS_DISCOVERY_ATTR_MAX + 1] = { + [NL80211_FILS_DISCOVERY_ATTR_INT_MIN] = NLA_POLICY_MAX(NLA_U32, 10000), + [NL80211_FILS_DISCOVERY_ATTR_INT_MAX] = NLA_POLICY_MAX(NLA_U32, 10000), ++#if LINUX_VERSION_IS_GEQ(5,10,0) + [NL80211_FILS_DISCOVERY_ATTR_TMPL] = + NLA_POLICY_BINARY_RANGE(NL80211_FILS_DISCOVERY_TMPL_MIN_LEN, IEEE80211_MAX_DATA_LEN), ++#else ++ [NL80211_FILS_DISCOVERY_ATTR_TMPL] = { .type = NLA_BINARY, ++ .len = IEEE80211_MAX_DATA_LEN }, ++#endif + }; + + static const struct nla_policy +@@ -533,7 +538,11 @@ static const struct nla_policy nl80211_p + [NL80211_ATTR_MPATH_NEXT_HOP] = NLA_POLICY_ETH_ADDR_COMPAT, + + /* allow 3 for NUL-termination, we used to declare this NLA_STRING */ ++#if LINUX_VERSION_IS_GEQ(5,10,0) + [NL80211_ATTR_REG_ALPHA2] = NLA_POLICY_BINARY_RANGE(2, 3), ++#else ++ [NL80211_ATTR_REG_ALPHA2] = { .type = NLA_STRING, .len = 2 }, ++#endif + [NL80211_ATTR_REG_RULES] = { .type = NLA_NESTED }, + + [NL80211_ATTR_BSS_CTS_PROT] = { .type = NLA_U8 }, +@@ -679,14 +688,24 @@ static const struct nla_policy nl80211_p + * The value of the Length field of the Supported Operating + * Classes element is between 2 and 253. + */ ++#if LINUX_VERSION_IS_GEQ(5,10,0) + [NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES] = + NLA_POLICY_BINARY_RANGE(2, 253), ++#else ++ [NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES] = ++ { .type = NLA_BINARY }, ++#endif + [NL80211_ATTR_HANDLE_DFS] = { .type = NLA_FLAG }, + [NL80211_ATTR_OPMODE_NOTIF] = { .type = NLA_U8 }, + [NL80211_ATTR_VENDOR_ID] = { .type = NLA_U32 }, + [NL80211_ATTR_VENDOR_SUBCMD] = { .type = NLA_U32 }, + [NL80211_ATTR_VENDOR_DATA] = { .type = NLA_BINARY }, ++#if LINUX_VERSION_IS_GEQ(5,10,0) + [NL80211_ATTR_QOS_MAP] = NLA_POLICY_BINARY_RANGE(IEEE80211_QOS_MAP_LEN_MIN, IEEE80211_QOS_MAP_LEN_MAX), ++#else ++ [NL80211_ATTR_QOS_MAP] = { .type = NLA_BINARY, ++ .len = IEEE80211_QOS_MAP_LEN_MAX }, ++#endif + [NL80211_ATTR_MAC_HINT] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN), + [NL80211_ATTR_WIPHY_FREQ_HINT] = { .type = NLA_U32 }, + [NL80211_ATTR_TDLS_PEER_CAPABILITY] = { .type = NLA_U32 }, +@@ -741,9 +760,14 @@ static const struct nla_policy nl80211_p + [NL80211_ATTR_TXQ_LIMIT] = { .type = NLA_U32 }, + [NL80211_ATTR_TXQ_MEMORY_LIMIT] = { .type = NLA_U32 }, + [NL80211_ATTR_TXQ_QUANTUM] = { .type = NLA_U32 }, ++#if LINUX_VERSION_IS_GEQ(5,10,0) + [NL80211_ATTR_HE_CAPABILITY] = + NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_he_capa, + NL80211_HE_MAX_CAPABILITY_LEN), ++#else ++ [NL80211_ATTR_HE_CAPABILITY] = { .type = NLA_BINARY, ++ .len = NL80211_HE_MAX_CAPABILITY_LEN }, ++#endif + [NL80211_ATTR_FTM_RESPONDER] = + NLA_POLICY_NESTED(nl80211_ftm_responder_policy), + [NL80211_ATTR_TIMEOUT] = NLA_POLICY_MIN(NLA_U32, 1), +@@ -16392,9 +16416,11 @@ static const struct genl_ops nl80211_ops + /* can be retrieved by unprivileged users */ + .internal_flags = IFLAGS(NL80211_FLAG_NEED_WIPHY), + }, ++#if LINUX_VERSION_IS_GEQ(5,10,0) + }; + + static const struct genl_small_ops nl80211_small_ops[] = { ++#endif + { + .cmd = NL80211_CMD_SET_WIPHY, + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, +@@ -17231,8 +17257,10 @@ static struct genl_family nl80211_fam __ + .module = THIS_MODULE, + .ops = nl80211_ops, + .n_ops = ARRAY_SIZE(nl80211_ops), ++#if LINUX_VERSION_IS_GEQ(5,10,0) + .small_ops = nl80211_small_ops, + .n_small_ops = ARRAY_SIZE(nl80211_small_ops), ++#endif + #if LINUX_VERSION_IS_GEQ(6,1,0) + .resv_start_op = NL80211_CMD_REMOVE_LINK_STA + 1, + #endif diff --git a/package/kernel/mac80211/patches/build/100-backports-drop-QRTR-and-MHI.patch b/package/kernel/mac80211/patches/build/100-backports-drop-QRTR-and-MHI.patch index a3a65c2d2..b017a0ce1 100644 --- a/package/kernel/mac80211/patches/build/100-backports-drop-QRTR-and-MHI.patch +++ b/package/kernel/mac80211/patches/build/100-backports-drop-QRTR-and-MHI.patch @@ -32,7 +32,7 @@ Signed-off-by: Robert Marko source "$BACKPORT_DIR/drivers/net/usb/Kconfig" --- a/Makefile.kernel +++ b/Makefile.kernel -@@ -38,9 +38,7 @@ obj-y += compat/ +@@ -39,9 +39,7 @@ obj-y += compat/ obj-$(CPTCFG_CFG80211) += net/wireless/ obj-$(CPTCFG_MAC80211) += net/mac80211/ @@ -59,7 +59,7 @@ Signed-off-by: Robert Marko --- a/local-symbols +++ b/local-symbols -@@ -59,14 +59,6 @@ MAC80211_MESH_PS_DEBUG= +@@ -65,14 +65,6 @@ MAC80211_MESH_PS_DEBUG= MAC80211_TDLS_DEBUG= MAC80211_DEBUG_COUNTERS= MAC80211_STA_HASH_MAX_SIZE= @@ -73,4 +73,4 @@ Signed-off-by: Robert Marko -MHI_BUS_EP= QCOM_AOSS_QMP= QCOM_COMMAND_DB= - QCOM_GENI_SE= + QCOM_CPR= diff --git a/package/kernel/mac80211/patches/build/110-backport_namepace_const.patch b/package/kernel/mac80211/patches/build/110-backport_namepace_const.patch deleted file mode 100644 index 6dca708ed..000000000 --- a/package/kernel/mac80211/patches/build/110-backport_namepace_const.patch +++ /dev/null @@ -1,14 +0,0 @@ ---- a/net/wireless/sysfs.c -+++ b/net/wireless/sysfs.c -@@ -154,7 +154,11 @@ static SIMPLE_DEV_PM_OPS(wiphy_pm_ops, w - #define WIPHY_PM_OPS NULL - #endif - -+#if LINUX_VERSION_IS_GEQ(6,2,0) - static const void *wiphy_namespace(const struct device *d) -+#else -+static const void *wiphy_namespace(struct device *d) -+#endif - { - struct wiphy *wiphy = container_of(d, struct wiphy, dev); - diff --git a/package/kernel/mac80211/patches/build/110-backport_napi_build_skb.patch b/package/kernel/mac80211/patches/build/110-backport_napi_build_skb.patch new file mode 100644 index 000000000..1e152fece --- /dev/null +++ b/package/kernel/mac80211/patches/build/110-backport_napi_build_skb.patch @@ -0,0 +1,11 @@ +--- a/backport-include/linux/skbuff.h ++++ b/backport-include/linux/skbuff.h +@@ -144,4 +144,8 @@ static inline u64 skb_get_kcov_handle(st + #define napi_build_skb build_skb + #endif + ++#if LINUX_VERSION_IS_LESS(5,11,0) ++#define napi_build_skb build_skb ++#endif ++ + #endif /* __BACKPORT_SKBUFF_H */ diff --git a/package/kernel/mac80211/patches/build/120-headers_version_fix.patch b/package/kernel/mac80211/patches/build/120-headers_version_fix.patch deleted file mode 100644 index 21cf0b313..000000000 --- a/package/kernel/mac80211/patches/build/120-headers_version_fix.patch +++ /dev/null @@ -1,25 +0,0 @@ ---- a/backport-include/linux/random.h -+++ b/backport-include/linux/random.h -@@ -15,7 +15,7 @@ static inline u16 get_random_u16(void) - } - #endif - --#if LINUX_VERSION_IS_LESS(6,2,0) -+#if LINUX_VERSION_IS_LESS(6,1,4) - static inline u32 __get_random_u32_below(u32 ceil) - { - /* ---- a/backport-include/net/dropreason.h -+++ b/backport-include/net/dropreason.h -@@ -3,10 +3,9 @@ - - #include - -+#include - #if LINUX_VERSION_IS_GEQ(6,0,0) - #include_next --#else --#include - #endif - - #if LINUX_VERSION_IS_LESS(6,4,0) diff --git a/package/kernel/mac80211/patches/build/130-iommu_backport.patch b/package/kernel/mac80211/patches/build/130-iommu_backport.patch deleted file mode 100644 index 2d3ef88d6..000000000 --- a/package/kernel/mac80211/patches/build/130-iommu_backport.patch +++ /dev/null @@ -1,26 +0,0 @@ ---- /dev/null -+++ b/backport-include/linux/iommu.h -@@ -0,0 +1,23 @@ -+#ifndef __BACKPORT_LINUX_IOMMU_H -+#define __BACKPORT_LINUX_IOMMU_H -+ -+#include_next -+#include -+ -+#if LINUX_VERSION_IS_LESS(6,3,0) -+ -+static inline int LINUX_BACKPORT(iommu_map)(struct iommu_domain *domain, -+ unsigned long iova, -+ phys_addr_t paddr, size_t size, -+ int prot, gfp_t gfp) -+{ -+ if (gfp == GFP_ATOMIC) -+ return iommu_map_atomic(domain, iova, paddr, size, prot); -+ -+ return iommu_map(domain, iova, paddr, size, prot); -+} -+#define iommu_map LINUX_BACKPORT(iommu_map) -+ -+#endif /* < 6.3 */ -+ -+#endif diff --git a/package/kernel/mac80211/patches/build/200-iwlwifi_thermal_backport.patch b/package/kernel/mac80211/patches/build/200-iwlwifi_thermal_backport.patch deleted file mode 100644 index ad398d4d9..000000000 --- a/package/kernel/mac80211/patches/build/200-iwlwifi_thermal_backport.patch +++ /dev/null @@ -1,26 +0,0 @@ ---- a/drivers/net/wireless/intel/iwlwifi/mvm/tt.c -+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tt.c -@@ -689,13 +689,23 @@ static void iwl_mvm_thermal_zone_registe - for (i = 0 ; i < IWL_MAX_DTS_TRIPS; i++) { - mvm->tz_device.trips[i].temperature = THERMAL_TEMP_INVALID; - mvm->tz_device.trips[i].type = THERMAL_TRIP_PASSIVE; -+#if LINUX_VERSION_IS_GEQ(6,9,0) - mvm->tz_device.trips[i].flags = THERMAL_TRIP_FLAG_RW_TEMP; -+#endif - } -+#if LINUX_VERSION_IS_GEQ(6,9,0) - mvm->tz_device.tzone = thermal_zone_device_register_with_trips(name, - mvm->tz_device.trips, - IWL_MAX_DTS_TRIPS, - mvm, &tzone_ops, - NULL, 0, 0); -+#else -+ mvm->tz_device.tzone = thermal_zone_device_register_with_trips(name, -+ mvm->tz_device.trips, -+ IWL_MAX_DTS_TRIPS, 0, -+ mvm, &tzone_ops, -+ NULL, 0, 0); -+#endif - if (IS_ERR(mvm->tz_device.tzone)) { - IWL_DEBUG_TEMP(mvm, - "Failed to register to thermal zone (err = %ld)\n", diff --git a/package/kernel/mac80211/patches/build/210-backport_genl_split_ops.patch b/package/kernel/mac80211/patches/build/210-backport_genl_split_ops.patch deleted file mode 100644 index d9d6b8a75..000000000 --- a/package/kernel/mac80211/patches/build/210-backport_genl_split_ops.patch +++ /dev/null @@ -1,32 +0,0 @@ ---- a/net/wireless/nl80211.c -+++ b/net/wireless/nl80211.c -@@ -16383,9 +16383,14 @@ static u32 nl80211_internal_flags[] = { - #undef SELECTOR - }; - -+#if LINUX_VERSION_IS_LESS(6,2,0) -+static int nl80211_pre_doit(const struct genl_ops *ops, struct sk_buff *skb, -+ struct genl_info *info) -+#else - static int nl80211_pre_doit(const struct genl_split_ops *ops, - struct sk_buff *skb, - struct genl_info *info) -+#endif - { - struct cfg80211_registered_device *rdev = NULL; - struct wireless_dev *wdev = NULL; -@@ -16485,9 +16490,14 @@ out_unlock: - return err; - } - -+#if LINUX_VERSION_IS_LESS(6,2,0) -+static void nl80211_post_doit(const struct genl_ops *ops, struct sk_buff *skb, -+ struct genl_info *info) -+#else - static void nl80211_post_doit(const struct genl_split_ops *ops, - struct sk_buff *skb, - struct genl_info *info) -+#endif - { - u32 internal_flags = nl80211_internal_flags[ops->internal_flags]; - diff --git a/package/kernel/mac80211/patches/build/220-list-don-t-backport-list_count_nodes.patch b/package/kernel/mac80211/patches/build/220-list-don-t-backport-list_count_nodes.patch deleted file mode 100644 index 6d3000278..000000000 --- a/package/kernel/mac80211/patches/build/220-list-don-t-backport-list_count_nodes.patch +++ /dev/null @@ -1,26 +0,0 @@ -From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= -Date: Fri, 15 Dec 2023 10:17:21 +0100 -Subject: [PATCH] list: don't backport list_count_nodes() -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -It's redundant in OpenWrt as it backports it on its own. This fixes: -backport-include/linux/list.h:11:22: error: redefinition of 'list_count_nodes' - -Signed-off-by: Rafał Miłecki ---- - backport-include/linux/list.h | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/backport-include/linux/list.h -+++ b/backport-include/linux/list.h -@@ -3,7 +3,7 @@ - #include_next - #include - --#if LINUX_VERSION_IS_LESS(6,3,0) -+#if 0 /* OpenWrt backports list_count_nodes() on its own */ - /** - * list_count_nodes - count nodes in the list - * @head: the head for your list. diff --git a/package/kernel/mac80211/patches/build/230-brcmfmac_usb_driver_backport.patch b/package/kernel/mac80211/patches/build/230-brcmfmac_usb_driver_backport.patch deleted file mode 100644 index daeea3837..000000000 --- a/package/kernel/mac80211/patches/build/230-brcmfmac_usb_driver_backport.patch +++ /dev/null @@ -1,14 +0,0 @@ ---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c -+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c -@@ -1581,7 +1581,11 @@ static int brcmf_usb_reset_device(struct - - void brcmf_usb_exit(void) - { -+#if LINUX_VERSION_IS_GEQ(6,8,0) - struct device_driver *drv = &brcmf_usbdrvr.driver; -+#else -+ struct device_driver *drv = &brcmf_usbdrvr.drvwrap.driver; -+#endif - int ret; - - brcmf_dbg(USB, "Enter\n"); diff --git a/package/kernel/mac80211/patches/build/990-add_kernel_6.6_support.patch b/package/kernel/mac80211/patches/build/990-add_kernel_6.6_support.patch new file mode 100644 index 000000000..2ced0316d --- /dev/null +++ b/package/kernel/mac80211/patches/build/990-add_kernel_6.6_support.patch @@ -0,0 +1,113 @@ +--- a/net/wireless/sysfs.c ++++ b/net/wireless/sysfs.c +@@ -148,12 +148,21 @@ static SIMPLE_DEV_PM_OPS(wiphy_pm_ops, w + #define WIPHY_PM_OPS NULL + #endif + ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 4, 0) ++static const void *wiphy_namespace(const struct device *d) ++{ ++ struct wiphy *wiphy = container_of(d, struct wiphy, dev); ++ ++ return wiphy_net(wiphy); ++} ++#else + static const void *wiphy_namespace(struct device *d) + { + struct wiphy *wiphy = container_of(d, struct wiphy, dev); + + return wiphy_net(wiphy); + } ++#endif + + struct class ieee80211_class = { + .name = "ieee80211", +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -16158,8 +16158,14 @@ static u32 nl80211_internal_flags[] = { + #undef SELECTOR + }; + ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 4, 0) ++static int nl80211_pre_doit(const struct genl_split_ops *ops, ++ struct sk_buff *skb, ++ struct genl_info *info) ++#else + static int nl80211_pre_doit(const struct genl_ops *ops, struct sk_buff *skb, + struct genl_info *info) ++#endif + { + struct cfg80211_registered_device *rdev = NULL; + struct wireless_dev *wdev = NULL; +@@ -16259,8 +16265,14 @@ out_unlock: + return err; + } + ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 4, 0) ++static void nl80211_post_doit(const struct genl_split_ops *ops, ++ struct sk_buff *skb, ++ struct genl_info *info) ++#else + static void nl80211_post_doit(const struct genl_ops *ops, struct sk_buff *skb, + struct genl_info *info) ++#endif + { + u32 internal_flags = nl80211_internal_flags[ops->internal_flags]; + +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -27,6 +27,10 @@ + #include + #include + ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 4, 0) ++#include ++#endif ++ + #include "ieee80211_i.h" + #include "driver-ops.h" + #include "led.h" +--- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c +@@ -10,6 +10,10 @@ + #include + #include + ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 4, 0) ++#include ++#endif ++ + #include "iwl-trans.h" + #include "iwl-eeprom-parse.h" + #include "mvm.h" +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -1435,6 +1435,7 @@ enum mac80211_rx_encoding { + RX_ENC_HT, + RX_ENC_VHT, + RX_ENC_HE, ++ RX_ENC_EHT, + }; + + /** +@@ -1497,8 +1498,18 @@ struct ieee80211_rx_status { + u32 flag; + u16 freq: 13, freq_offset: 1; + u8 enc_flags; +- u8 encoding:2, bw:3, he_ru:3; +- u8 he_gi:2, he_dcm:1; ++ u8 encoding:3, bw:4; ++ union { ++ struct { ++ u8 he_ru:3; ++ u8 he_gi:2; ++ u8 he_dcm:1; ++ }; ++ struct { ++ u8 ru:4; ++ u8 gi:2; ++ } eht; ++ }; + u8 rate_idx; + u8 nss; + u8 rx_flags; diff --git a/package/kernel/mac80211/patches/mwl/700-mwl8k-missing-pci-id-for-WNR854T.patch b/package/kernel/mac80211/patches/mwl/700-mwl8k-missing-pci-id-for-WNR854T.patch index fb774b520..11536651b 100644 --- a/package/kernel/mac80211/patches/mwl/700-mwl8k-missing-pci-id-for-WNR854T.patch +++ b/package/kernel/mac80211/patches/mwl/700-mwl8k-missing-pci-id-for-WNR854T.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/marvell/mwl8k.c +++ b/drivers/net/wireless/marvell/mwl8k.c -@@ -5707,6 +5707,7 @@ MODULE_FIRMWARE("mwl8k/fmimage_8366.fw") +@@ -5703,6 +5703,7 @@ MODULE_FIRMWARE("mwl8k/fmimage_8366.fw") MODULE_FIRMWARE(MWL8K_8366_AP_FW(MWL8K_8366_AP_FW_API)); static const struct pci_device_id mwl8k_pci_id_table[] = { diff --git a/package/kernel/mac80211/patches/mwl/801-libertas-configure-sysfs-links.patch b/package/kernel/mac80211/patches/mwl/801-libertas-configure-sysfs-links.patch index 4d9d3de46..1dbcb1bfe 100644 --- a/package/kernel/mac80211/patches/mwl/801-libertas-configure-sysfs-links.patch +++ b/package/kernel/mac80211/patches/mwl/801-libertas-configure-sysfs-links.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/marvell/libertas/cfg.c +++ b/drivers/net/wireless/marvell/libertas/cfg.c -@@ -2101,6 +2101,8 @@ struct wireless_dev *lbs_cfg_alloc(struc +@@ -2052,6 +2052,8 @@ struct wireless_dev *lbs_cfg_alloc(struc goto err_wiphy_new; } diff --git a/package/kernel/mac80211/patches/mwl/802-libertas-set-wireless-macaddr.patch b/package/kernel/mac80211/patches/mwl/802-libertas-set-wireless-macaddr.patch index 9aa559979..b47aee549 100644 --- a/package/kernel/mac80211/patches/mwl/802-libertas-set-wireless-macaddr.patch +++ b/package/kernel/mac80211/patches/mwl/802-libertas-set-wireless-macaddr.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/marvell/libertas/cfg.c +++ b/drivers/net/wireless/marvell/libertas/cfg.c -@@ -2178,6 +2178,8 @@ int lbs_cfg_register(struct lbs_private +@@ -2128,6 +2128,8 @@ int lbs_cfg_register(struct lbs_private wdev->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); wdev->wiphy->reg_notifier = lbs_reg_notifier; diff --git a/package/kernel/mac80211/patches/mwl/940-mwl8k_init_devices_synchronously.patch b/package/kernel/mac80211/patches/mwl/940-mwl8k_init_devices_synchronously.patch index 06edc441e..c8d24283a 100644 --- a/package/kernel/mac80211/patches/mwl/940-mwl8k_init_devices_synchronously.patch +++ b/package/kernel/mac80211/patches/mwl/940-mwl8k_init_devices_synchronously.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/marvell/mwl8k.c +++ b/drivers/net/wireless/marvell/mwl8k.c -@@ -6293,6 +6293,8 @@ static int mwl8k_probe(struct pci_dev *p +@@ -6289,6 +6289,8 @@ static int mwl8k_probe(struct pci_dev *p priv->running_bsses = 0; @@ -9,7 +9,7 @@ return rc; err_stop_firmware: -@@ -6326,8 +6328,6 @@ static void mwl8k_remove(struct pci_dev +@@ -6322,8 +6324,6 @@ static void mwl8k_remove(struct pci_dev return; priv = hw->priv; diff --git a/package/kernel/mac80211/patches/mwl/950-mwifiex-Print-stringified-name-of-command-in-error-l.patch b/package/kernel/mac80211/patches/mwl/950-mwifiex-Print-stringified-name-of-command-in-error-l.patch index a7ecabde8..98ed9e60e 100644 --- a/package/kernel/mac80211/patches/mwl/950-mwifiex-Print-stringified-name-of-command-in-error-l.patch +++ b/package/kernel/mac80211/patches/mwl/950-mwifiex-Print-stringified-name-of-command-in-error-l.patch @@ -139,7 +139,7 @@ Signed-off-by: Pali Rohár mwifiex_init_fw_complete(adapter); return -1; } else if (adapter->last_init_cmd == cmdresp_no) -@@ -1265,8 +1345,8 @@ mwifiex_process_sleep_confirm_resp(struc +@@ -1273,8 +1353,8 @@ mwifiex_process_sleep_confirm_resp(struc if (command != HostCmd_CMD_802_11_PS_MODE_ENH) { mwifiex_dbg(adapter, ERROR, @@ -152,7 +152,7 @@ Signed-off-by: Pali Rohár --- a/drivers/net/wireless/marvell/mwifiex/main.h +++ b/drivers/net/wireless/marvell/mwifiex/main.h -@@ -1084,6 +1084,8 @@ void mwifiex_cancel_all_pending_cmd(stru +@@ -1099,6 +1099,8 @@ void mwifiex_cancel_all_pending_cmd(stru void mwifiex_cancel_pending_scan_cmd(struct mwifiex_adapter *adapter); void mwifiex_cancel_scan(struct mwifiex_adapter *adapter); @@ -177,7 +177,7 @@ Signed-off-by: Pali Rohár adapter->cmd_wait_q.status = -1; --- a/drivers/net/wireless/marvell/mwifiex/uap_cmd.c +++ b/drivers/net/wireless/marvell/mwifiex/uap_cmd.c -@@ -802,7 +802,8 @@ int mwifiex_uap_prepare_cmd(struct mwifi +@@ -794,7 +794,8 @@ int mwifiex_uap_prepare_cmd(struct mwifi break; default: mwifiex_dbg(priv->adapter, ERROR, diff --git a/package/kernel/mac80211/patches/rt2x00/602-02-wifi-rt2x00-Add-option-to-pass-EEPROM-file-name-from.patch b/package/kernel/mac80211/patches/rt2x00/602-02-wifi-rt2x00-Add-option-to-pass-EEPROM-file-name-from.patch deleted file mode 100644 index 90055b911..000000000 --- a/package/kernel/mac80211/patches/rt2x00/602-02-wifi-rt2x00-Add-option-to-pass-EEPROM-file-name-from.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 15329d8b206d9c04ffad49aecd37f5d0bfb85768 Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Sun, 15 Oct 2023 14:23:19 +0200 -Subject: [PATCH 2/5] wifi: rt2x00: Add option to pass EEPROM file name from DT - -Add option to pass EEPROM file name from DT using ralink,eeprom binding. - -Signed-off-by: Christian Marangi ---- - drivers/net/wireless/ralink/rt2x00/rt2x00eeprom.c | 11 +++++++++++ - 1 file changed, 11 insertions(+) - ---- a/drivers/net/wireless/ralink/rt2x00/rt2x00eeprom.c -+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00eeprom.c -@@ -10,6 +10,7 @@ - - #include - #include -+#include - - #include "rt2x00.h" - #include "rt2x00soc.h" -@@ -18,10 +19,20 @@ static const char * - rt2x00lib_get_eeprom_file_name(struct rt2x00_dev *rt2x00dev) - { - struct rt2x00_platform_data *pdata = rt2x00dev->dev->platform_data; -+#ifdef CONFIG_OF -+ struct device_node *np; -+ const char *eep; -+#endif - - if (pdata && pdata->eeprom_file_name) - return pdata->eeprom_file_name; - -+#ifdef CONFIG_OF -+ np = rt2x00dev->dev->of_node; -+ if (np && !of_property_read_string(np, "ralink,eeprom", &eep)) -+ return eep; -+#endif -+ - return NULL; - } - diff --git a/package/kernel/mac80211/patches/rt2x00/602-04-wifi-rt2x00-Support-EEPROM-swap-binding.patch b/package/kernel/mac80211/patches/rt2x00/602-04-wifi-rt2x00-Support-EEPROM-swap-binding.patch deleted file mode 100644 index 392910d22..000000000 --- a/package/kernel/mac80211/patches/rt2x00/602-04-wifi-rt2x00-Support-EEPROM-swap-binding.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 9c9a3c27b96e057f3c3f47151d7a170d84e3bb5f Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Sun, 15 Oct 2023 15:31:47 +0200 -Subject: [PATCH 4/5] wifi: rt2x00: Support EEPROM swap binding - -Add binding "ralink,eeprom-swap" to swap bytes of EEPROM before using -it. - -Signed-off-by: Christian Marangi ---- - drivers/net/wireless/ralink/rt2x00/rt2x00eeprom.c | 15 +++++++++++++++ - 1 file changed, 15 insertions(+) - ---- a/drivers/net/wireless/ralink/rt2x00/rt2x00eeprom.c -+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00eeprom.c -@@ -20,6 +20,19 @@ - #include "rt2x00soc.h" - - #if IS_ENABLED(CONFIG_MTD) -+static void rt2800lib_eeprom_swap(struct rt2x00_dev *rt2x00dev) -+{ -+ struct device_node *np = rt2x00dev->dev->of_node; -+ size_t len = rt2x00dev->ops->eeprom_size; -+ int i; -+ -+ if (!of_find_property(np, "ralink,eeprom-swap", NULL)) -+ return; -+ -+ for (i = 0; i < len / sizeof(u16); i++) -+ rt2x00dev->eeprom[i] = swab16(rt2x00dev->eeprom[i]); -+} -+ - static int rt2800lib_read_eeprom_mtd(struct rt2x00_dev *rt2x00dev) - { - int ret = -EINVAL; -@@ -66,6 +79,8 @@ static int rt2800lib_read_eeprom_mtd(str - return ret; - } - -+ rt2800lib_eeprom_swap(rt2x00dev); -+ - dev_info(rt2x00dev->dev, "loaded eeprom from mtd device \"%s\"\n", part); - #endif - diff --git a/package/kernel/mac80211/patches/rt2x00/602-05-wifi-rt2x00-support-loading-eeprom-from-NVMEM-cells.patch b/package/kernel/mac80211/patches/rt2x00/602-05-wifi-rt2x00-support-loading-eeprom-from-NVMEM-cells.patch deleted file mode 100644 index e6633363b..000000000 --- a/package/kernel/mac80211/patches/rt2x00/602-05-wifi-rt2x00-support-loading-eeprom-from-NVMEM-cells.patch +++ /dev/null @@ -1,97 +0,0 @@ -From 9008cdacdc41f8233f4444b86cf3a17201686e2d Mon Sep 17 00:00:00 2001 -From: Shiji Yang -Date: Tue, 18 Jul 2023 20:18:16 +0800 -Subject: [PATCH 5/5] wifi: rt2x00: support loading eeprom from NVMEM cells - -This patch allows rt2x00 to load eeprom from "eeprom" NVMEM cell. - -Example: - -/* load eeprom from NVMEM provider 'eep' */ -&wmac { - nvmem-cells = <&eep>; - nvmem-cell-names = "eeprom"; -}; - -Signed-off-by: Shiji Yang -Signed-off-by: Christian Marangi ---- - .../net/wireless/ralink/rt2x00/rt2x00eeprom.c | 41 ++++++++++++++++++- - 1 file changed, 40 insertions(+), 1 deletion(-) - ---- a/drivers/net/wireless/ralink/rt2x00/rt2x00eeprom.c -+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00eeprom.c -@@ -14,12 +14,12 @@ - #include - #include - #endif -+#include - #include - - #include "rt2x00.h" - #include "rt2x00soc.h" - --#if IS_ENABLED(CONFIG_MTD) - static void rt2800lib_eeprom_swap(struct rt2x00_dev *rt2x00dev) - { - struct device_node *np = rt2x00dev->dev->of_node; -@@ -33,6 +33,7 @@ static void rt2800lib_eeprom_swap(struct - rt2x00dev->eeprom[i] = swab16(rt2x00dev->eeprom[i]); - } - -+#if IS_ENABLED(CONFIG_MTD) - static int rt2800lib_read_eeprom_mtd(struct rt2x00_dev *rt2x00dev) - { - int ret = -EINVAL; -@@ -88,6 +89,40 @@ static int rt2800lib_read_eeprom_mtd(str - } - #endif - -+static int rt2800lib_read_eeprom_nvmem(struct rt2x00_dev *rt2x00dev) -+{ -+ struct device_node *np = rt2x00dev->dev->of_node; -+ unsigned int len = rt2x00dev->ops->eeprom_size; -+ struct nvmem_cell *cell; -+ const void *data; -+ size_t retlen; -+ int ret = 0; -+ -+ cell = of_nvmem_cell_get(np, "eeprom"); -+ if (IS_ERR(cell)) -+ return PTR_ERR(cell); -+ -+ data = nvmem_cell_read(cell, &retlen); -+ nvmem_cell_put(cell); -+ -+ if (IS_ERR(data)) -+ return PTR_ERR(data); -+ -+ if (retlen != len) { -+ dev_err(rt2x00dev->dev, "invalid eeprom size, required: 0x%04x\n", len); -+ ret = -EINVAL; -+ goto exit; -+ } -+ -+ memcpy(rt2x00dev->eeprom, data, len); -+ -+ rt2800lib_eeprom_swap(rt2x00dev); -+ -+exit: -+ kfree(data); -+ return ret; -+} -+ - static const char * - rt2x00lib_get_eeprom_file_name(struct rt2x00_dev *rt2x00dev) - { -@@ -164,6 +199,10 @@ int rt2x00lib_read_eeprom(struct rt2x00_ - return 0; - #endif - -+ ret = rt2800lib_read_eeprom_nvmem(rt2x00dev); -+ if (!ret) -+ return 0; -+ - return rt2x00lib_read_eeprom_file(rt2x00dev); - } - EXPORT_SYMBOL_GPL(rt2x00lib_read_eeprom); diff --git a/package/kernel/mac80211/patches/rt2x00/602-01-wifi-rt2x00-Add-support-for-loading-EEPROM-from-user.patch b/package/kernel/mac80211/patches/rt2x00/602-rt2x00-introduce-rt2x00eeprom.patch similarity index 53% rename from package/kernel/mac80211/patches/rt2x00/602-01-wifi-rt2x00-Add-support-for-loading-EEPROM-from-user.patch rename to package/kernel/mac80211/patches/rt2x00/602-rt2x00-introduce-rt2x00eeprom.patch index f90e109a8..ab0fa3670 100644 --- a/package/kernel/mac80211/patches/rt2x00/602-01-wifi-rt2x00-Add-support-for-loading-EEPROM-from-user.patch +++ b/package/kernel/mac80211/patches/rt2x00/602-rt2x00-introduce-rt2x00eeprom.patch @@ -1,27 +1,6 @@ -From 1046fc9e98936991aeb0b0656c84833d96a63c0f Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Sun, 15 Oct 2023 14:22:49 +0200 -Subject: [PATCH 1/5] wifi: rt2x00: Add support for loading EEPROM from - userspace - -Add support for loading EEPROM from userspace. - -Signed-off-by: Christian Marangi ---- - drivers/net/wireless/ralink/rt2x00/Kconfig | 5 ++ - drivers/net/wireless/ralink/rt2x00/Makefile | 1 + - .../net/wireless/ralink/rt2x00/rt2800soc.c | 15 +--- - drivers/net/wireless/ralink/rt2x00/rt2x00.h | 1 + - .../net/wireless/ralink/rt2x00/rt2x00dev.c | 9 +++ - .../net/wireless/ralink/rt2x00/rt2x00eeprom.c | 75 +++++++++++++++++++ - .../net/wireless/ralink/rt2x00/rt2x00soc.c | 1 + - .../net/wireless/ralink/rt2x00/rt2x00soc.h | 9 +++ - 8 files changed, 102 insertions(+), 14 deletions(-) - create mode 100644 drivers/net/wireless/ralink/rt2x00/rt2x00eeprom.c - --- a/local-symbols +++ b/local-symbols -@@ -334,6 +334,7 @@ RT2X00_LIB_FIRMWARE= +@@ -347,6 +347,7 @@ RT2X00_LIB_FIRMWARE= RT2X00_LIB_CRYPTO= RT2X00_LIB_LEDS= RT2X00_LIB_DEBUGFS= @@ -67,6 +46,33 @@ Signed-off-by: Christian Marangi obj-$(CPTCFG_RT2X00_LIB) += rt2x00lib.o obj-$(CPTCFG_RT2X00_LIB_MMIO) += rt2x00mmio.o +--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h ++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h +@@ -47,6 +47,8 @@ struct rt2800_drv_data { + struct ieee80211_sta *wcid_to_sta[STA_IDS_SIZE]; + }; + ++#include "rt2800.h" ++ + struct rt2800_ops { + u32 (*register_read)(struct rt2x00_dev *rt2x00dev, + const unsigned int offset); +@@ -145,6 +147,15 @@ static inline int rt2800_read_eeprom(str + { + const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv; + ++ if (rt2x00dev->eeprom_file) { ++ memcpy(rt2x00dev->eeprom, rt2x00dev->eeprom_file->data, ++ EEPROM_SIZE); ++ return 0; ++ } ++ ++ if (!rt2800ops->read_eeprom) ++ return -EINVAL; ++ + return rt2800ops->read_eeprom(rt2x00dev); + } + --- a/drivers/net/wireless/ralink/rt2x00/rt2800soc.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2800soc.c @@ -90,19 +90,6 @@ static int rt2800soc_set_device_state(st @@ -89,12 +95,11 @@ Signed-off-by: Christian Marangi /* Firmware functions */ static char *rt2800soc_get_firmware_name(struct rt2x00_dev *rt2x00dev) { -@@ -172,7 +159,7 @@ static const struct rt2800_ops rt2800soc +@@ -168,7 +155,6 @@ static const struct rt2800_ops rt2800soc .register_multiread = rt2x00mmio_register_multiread, .register_multiwrite = rt2x00mmio_register_multiwrite, .regbusy_read = rt2x00mmio_regbusy_read, - .read_eeprom = rt2800soc_read_eeprom, -+ .read_eeprom = rt2x00lib_read_eeprom, .hwcrypt_disabled = rt2800soc_hwcrypt_disabled, .drv_write_firmware = rt2800soc_write_firmware, .drv_init_registers = rt2800mmio_init_registers, @@ -108,24 +113,77 @@ Signed-off-by: Christian Marangi /* * Capabilities +@@ -980,6 +981,11 @@ struct rt2x00_dev { + const struct firmware *fw; + + /* ++ * EEPROM image. ++ */ ++ const struct firmware *eeprom_file; ++ ++ /* + * FIFO for storing tx status reports between isr and tasklet. + */ + DECLARE_KFIFO_PTR(txstatus_fifo, u32); +--- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c +@@ -1419,6 +1419,10 @@ int rt2x00lib_probe_dev(struct rt2x00_de + INIT_DELAYED_WORK(&rt2x00dev->autowakeup_work, rt2x00lib_autowakeup); + INIT_WORK(&rt2x00dev->sleep_work, rt2x00lib_sleep); + ++ retval = rt2x00lib_load_eeprom_file(rt2x00dev); ++ if (retval) ++ goto exit; ++ + /* + * Let the driver probe the device to detect the capabilities. + */ +@@ -1559,6 +1563,11 @@ void rt2x00lib_remove_dev(struct rt2x00_ + * Free the driver data. + */ + kfree(rt2x00dev->drv_data); ++ ++ /* ++ * Free EEPROM image. ++ */ ++ rt2x00lib_free_eeprom_file(rt2x00dev); + } + EXPORT_SYMBOL_GPL(rt2x00lib_remove_dev); + --- /dev/null +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00eeprom.c -@@ -0,0 +1,77 @@ -+// SPDX-License-Identifier: GPL-2.0-or-later -+/* Copyright (C) 2004 - 2009 Ivo van Doorn -+ * Copyright (C) 2004 - 2009 Gertjan van Wingerde -+ * +@@ -0,0 +1,106 @@ ++/* ++ Copyright (C) 2004 - 2009 Ivo van Doorn ++ Copyright (C) 2004 - 2009 Gertjan van Wingerde ++ ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 2 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program; if not, write to the ++ Free Software Foundation, Inc., ++ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + -+/* Module: rt2x00lib -+ * Abstract: rt2x00 eeprom file loading routines. ++/* ++ Module: rt2x00lib ++ Abstract: rt2x00 eeprom file loading routines. + */ + +#include +#include + +#include "rt2x00.h" -+#include "rt2x00soc.h" ++#include "rt2x00lib.h" + +static const char * +rt2x00lib_get_eeprom_file_name(struct rt2x00_dev *rt2x00dev) @@ -138,7 +196,7 @@ Signed-off-by: Christian Marangi + return NULL; +} + -+static int rt2x00lib_read_eeprom_file(struct rt2x00_dev *rt2x00dev) ++static int rt2x00lib_request_eeprom_file(struct rt2x00_dev *rt2x00dev) +{ + const struct firmware *ee; + const char *ee_name; @@ -175,7 +233,8 @@ Signed-off-by: Christian Marangi + goto err_release_ee; + } + -+ memcpy(rt2x00dev->eeprom, ee->data, rt2x00dev->ops->eeprom_size); ++ rt2x00dev->eeprom_file = ee; ++ return 0; + +err_release_ee: + release_firmware(ee); @@ -183,11 +242,48 @@ Signed-off-by: Christian Marangi + return retval; +} + -+int rt2x00lib_read_eeprom(struct rt2x00_dev *rt2x00dev) ++int rt2x00lib_load_eeprom_file(struct rt2x00_dev *rt2x00dev) +{ -+ return rt2x00lib_read_eeprom_file(rt2x00dev); ++ int retval; ++ ++ retval = rt2x00lib_request_eeprom_file(rt2x00dev); ++ if (retval) ++ return retval; ++ ++ return 0; +} -+EXPORT_SYMBOL_GPL(rt2x00lib_read_eeprom); ++ ++void rt2x00lib_free_eeprom_file(struct rt2x00_dev *rt2x00dev) ++{ ++ if (rt2x00dev->eeprom_file && rt2x00dev->eeprom_file->size) ++ release_firmware(rt2x00dev->eeprom_file); ++ rt2x00dev->eeprom_file = NULL; ++} +--- a/drivers/net/wireless/ralink/rt2x00/rt2x00lib.h ++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00lib.h +@@ -286,6 +286,22 @@ static inline void rt2x00lib_free_firmwa + #endif /* CPTCFG_RT2X00_LIB_FIRMWARE */ + + /* ++ * EEPROM file handlers. ++ */ ++#ifdef CPTCFG_RT2X00_LIB_EEPROM ++int rt2x00lib_load_eeprom_file(struct rt2x00_dev *rt2x00dev); ++void rt2x00lib_free_eeprom_file(struct rt2x00_dev *rt2x00dev); ++#else ++static inline int rt2x00lib_load_eeprom_file(struct rt2x00_dev *rt2x00dev) ++{ ++ return 0; ++} ++static inline void rt2x00lib_free_eeprom_file(struct rt2x00_dev *rt2x00dev) ++{ ++} ++#endif /* CPTCFG_RT2X00_LIB_EEPROM */ ++ ++/* + * Debugfs handlers. + */ + #ifdef CPTCFG_RT2X00_LIB_DEBUGFS --- a/drivers/net/wireless/ralink/rt2x00/rt2x00soc.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00soc.c @@ -86,6 +86,7 @@ int rt2x00soc_probe(struct platform_devi @@ -198,19 +294,3 @@ Signed-off-by: Christian Marangi rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_SOC); retval = rt2x00soc_alloc_reg(rt2x00dev); ---- a/drivers/net/wireless/ralink/rt2x00/rt2x00soc.h -+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00soc.h -@@ -26,4 +26,13 @@ int rt2x00soc_resume(struct platform_dev - #define rt2x00soc_resume NULL - #endif /* CONFIG_PM */ - -+/* -+ * EEPROM file handlers. -+ */ -+#ifdef CPTCFG_RT2X00_LIB_EEPROM -+int rt2x00lib_read_eeprom(struct rt2x00_dev *rt2x00dev); -+#else -+#define rt2x00lib_read_eeprom NULL -+#endif /* CPTCFG_RT2X00_LIB_EEPROM */ -+ - #endif /* RT2X00SOC_H */ diff --git a/package/kernel/mac80211/patches/rt2x00/603-rt2x00-of_load_eeprom_filename.patch b/package/kernel/mac80211/patches/rt2x00/603-rt2x00-of_load_eeprom_filename.patch new file mode 100644 index 000000000..431e09023 --- /dev/null +++ b/package/kernel/mac80211/patches/rt2x00/603-rt2x00-of_load_eeprom_filename.patch @@ -0,0 +1,31 @@ +--- a/drivers/net/wireless/ralink/rt2x00/rt2x00eeprom.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00eeprom.c +@@ -26,6 +26,7 @@ + + #include + #include ++#include + + #include "rt2x00.h" + #include "rt2x00lib.h" +@@ -34,10 +35,20 @@ static const char * + rt2x00lib_get_eeprom_file_name(struct rt2x00_dev *rt2x00dev) + { + struct rt2x00_platform_data *pdata = rt2x00dev->dev->platform_data; ++#ifdef CONFIG_OF ++ struct device_node *np; ++ const char *eep; ++#endif + + if (pdata && pdata->eeprom_file_name) + return pdata->eeprom_file_name; + ++#ifdef CONFIG_OF ++ np = rt2x00dev->dev->of_node; ++ if (np && of_property_read_string(np, "ralink,eeprom", &eep) == 0) ++ return eep; ++#endif ++ + return NULL; + } + diff --git a/package/kernel/mac80211/patches/rt2x00/602-03-wifi-rt2x00-Add-support-for-loading-EEPROM-from-MTD.patch b/package/kernel/mac80211/patches/rt2x00/604-rt2x00-load-eeprom-on-SoC-from-a-mtd-device-defines-.patch similarity index 63% rename from package/kernel/mac80211/patches/rt2x00/602-03-wifi-rt2x00-Add-support-for-loading-EEPROM-from-MTD.patch rename to package/kernel/mac80211/patches/rt2x00/604-rt2x00-load-eeprom-on-SoC-from-a-mtd-device-defines-.patch index fab4bf39c..7338eb15b 100644 --- a/package/kernel/mac80211/patches/rt2x00/602-03-wifi-rt2x00-Add-support-for-loading-EEPROM-from-MTD.patch +++ b/package/kernel/mac80211/patches/rt2x00/604-rt2x00-load-eeprom-on-SoC-from-a-mtd-device-defines-.patch @@ -1,16 +1,14 @@ -From 71261ca81b491a4c3b08690347c12e96a75ad0d0 Mon Sep 17 00:00:00 2001 +From 339fe73f340161a624cc08e738d2244814852c3e Mon Sep 17 00:00:00 2001 From: John Crispin Date: Sun, 17 Mar 2013 00:55:04 +0100 -Subject: [PATCH 3/5] wifi: rt2x00: Add support for loading EEPROM from MTD - -Add support for loading EEPROM from MTD. +Subject: [PATCH] rt2x00: load eeprom on SoC from a mtd device defines inside + OF Signed-off-by: John Crispin -Signed-off-by: Christian Marangi --- - drivers/net/wireless/ralink/rt2x00/Kconfig | 1 + - .../net/wireless/ralink/rt2x00/rt2x00eeprom.c | 66 +++++++++++++++++++ - 2 files changed, 67 insertions(+) + drivers/net/wireless/ralink/rt2x00/Kconfig | 1 + + drivers/net/wireless/ralink/rt2x00/rt2x00eeprom.c | 65 +++++++++++++++++++++++ + 2 files changed, 66 insertions(+) --- a/drivers/net/wireless/ralink/rt2x00/Kconfig +++ b/drivers/net/wireless/ralink/rt2x00/Kconfig @@ -24,7 +22,7 @@ Signed-off-by: Christian Marangi Supported chips: RT2880, RT3050, RT3052, RT3350, RT3352. --- a/drivers/net/wireless/ralink/rt2x00/rt2x00eeprom.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00eeprom.c -@@ -10,11 +10,69 @@ +@@ -26,11 +26,76 @@ #include #include @@ -35,20 +33,21 @@ Signed-off-by: Christian Marangi #include #include "rt2x00.h" - #include "rt2x00soc.h" + #include "rt2x00lib.h" +#if IS_ENABLED(CONFIG_MTD) +static int rt2800lib_read_eeprom_mtd(struct rt2x00_dev *rt2x00dev) +{ + int ret = -EINVAL; +#ifdef CONFIG_OF ++ static struct firmware mtd_fw; + struct device_node *np = rt2x00dev->dev->of_node, *mtd_np = NULL; -+ int size, offset = 0; ++ size_t retlen, len = rt2x00dev->ops->eeprom_size; ++ int i, size, offset = 0; + struct mtd_info *mtd; + const char *part; + const __be32 *list; + phandle phandle; -+ size_t retlen; + + list = of_get_property(np, "ralink,mtd-eeprom", &size); + if (!list) @@ -75,15 +74,21 @@ Signed-off-by: Christian Marangi + if (size > sizeof(*list)) + offset = be32_to_cpup(list); + -+ ret = mtd_read(mtd, offset, rt2x00dev->ops->eeprom_size, -+ &retlen, (u_char *)rt2x00dev->eeprom); ++ ret = mtd_read(mtd, offset, len, &retlen, (u_char *) rt2x00dev->eeprom); + put_mtd_device(mtd); + -+ if (retlen != rt2x00dev->ops->eeprom_size || ret) { ++ if ((retlen != rt2x00dev->ops->eeprom_size) || ret) { + dev_err(rt2x00dev->dev, "failed to load eeprom from device \"%s\"\n", part); + return ret; + } + ++ if (of_find_property(np, "ralink,mtd-eeprom-swap", NULL)) ++ for (i = 0; i < len/sizeof(u16); i++) ++ rt2x00dev->eeprom[i] = swab16(rt2x00dev->eeprom[i]); ++ ++ rt2x00dev->eeprom_file = &mtd_fw; ++ mtd_fw.data = (const u8 *) rt2x00dev->eeprom; ++ + dev_info(rt2x00dev->dev, "loaded eeprom from mtd device \"%s\"\n", part); +#endif + @@ -94,18 +99,15 @@ Signed-off-by: Christian Marangi static const char * rt2x00lib_get_eeprom_file_name(struct rt2x00_dev *rt2x00dev) { -@@ -83,6 +141,14 @@ err_exit: +@@ -58,6 +123,11 @@ static int rt2x00lib_request_eeprom_file + const char *ee_name; + int retval; - int rt2x00lib_read_eeprom(struct rt2x00_dev *rt2x00dev) - { -+ int ret; -+ +#if IS_ENABLED(CONFIG_MTD) -+ ret = rt2800lib_read_eeprom_mtd(rt2x00dev); -+ if (!ret) ++ if (!rt2800lib_read_eeprom_mtd(rt2x00dev)) + return 0; +#endif + - return rt2x00lib_read_eeprom_file(rt2x00dev); - } - EXPORT_SYMBOL_GPL(rt2x00lib_read_eeprom); + ee_name = rt2x00lib_get_eeprom_file_name(rt2x00dev); + if (!ee_name && test_bit(REQUIRE_EEPROM_FILE, &rt2x00dev->cap_flags)) { + rt2x00_err(rt2x00dev, "Required EEPROM name is missing."); diff --git a/package/kernel/mac80211/patches/rt2x00/606-rt2x00-allow_disabling_bands_through_platform_data.patch b/package/kernel/mac80211/patches/rt2x00/606-rt2x00-allow_disabling_bands_through_platform_data.patch index ab09a6829..ffee2189d 100644 --- a/package/kernel/mac80211/patches/rt2x00/606-rt2x00-allow_disabling_bands_through_platform_data.patch +++ b/package/kernel/mac80211/patches/rt2x00/606-rt2x00-allow_disabling_bands_through_platform_data.patch @@ -12,7 +12,7 @@ #endif /* _RT2X00_PLATFORM_H */ --- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c -@@ -1008,6 +1008,22 @@ static int rt2x00lib_probe_hw_modes(stru +@@ -1007,6 +1007,22 @@ static int rt2x00lib_probe_hw_modes(stru unsigned int num_rates; unsigned int i; diff --git a/package/kernel/mac80211/patches/rt2x00/607-rt2x00-add_platform_data_mac_addr.patch b/package/kernel/mac80211/patches/rt2x00/607-rt2x00-add_platform_data_mac_addr.patch index 79f99ffdf..37553bb80 100644 --- a/package/kernel/mac80211/patches/rt2x00/607-rt2x00-add_platform_data_mac_addr.patch +++ b/package/kernel/mac80211/patches/rt2x00/607-rt2x00-add_platform_data_mac_addr.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c -@@ -990,6 +990,12 @@ static void rt2x00lib_rate(struct ieee80 +@@ -989,6 +989,12 @@ static void rt2x00lib_rate(struct ieee80 void rt2x00lib_set_mac_address(struct rt2x00_dev *rt2x00dev, u8 *eeprom_mac_addr) { diff --git a/package/kernel/mac80211/patches/rt2x00/608-rt2x00-allow_disabling_bands_through_dts.patch b/package/kernel/mac80211/patches/rt2x00/608-rt2x00-allow_disabling_bands_through_dts.patch index 31f2f0261..6211809c0 100644 --- a/package/kernel/mac80211/patches/rt2x00/608-rt2x00-allow_disabling_bands_through_dts.patch +++ b/package/kernel/mac80211/patches/rt2x00/608-rt2x00-allow_disabling_bands_through_dts.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c -@@ -1013,6 +1013,16 @@ static int rt2x00lib_probe_hw_modes(stru +@@ -1012,6 +1012,16 @@ static int rt2x00lib_probe_hw_modes(stru struct ieee80211_rate *rates; unsigned int num_rates; unsigned int i; diff --git a/package/kernel/mac80211/patches/rt2x00/609-rt2x00-make-wmac-loadable-via-OF-on-rt288x-305x-SoC.patch b/package/kernel/mac80211/patches/rt2x00/609-rt2x00-make-wmac-loadable-via-OF-on-rt288x-305x-SoC.patch index de2cf2dca..8964f8bf1 100644 --- a/package/kernel/mac80211/patches/rt2x00/609-rt2x00-make-wmac-loadable-via-OF-on-rt288x-305x-SoC.patch +++ b/package/kernel/mac80211/patches/rt2x00/609-rt2x00-make-wmac-loadable-via-OF-on-rt288x-305x-SoC.patch @@ -13,7 +13,7 @@ Signed-off-by: John Crispin --- a/drivers/net/wireless/ralink/rt2x00/rt2800soc.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2800soc.c -@@ -230,10 +230,17 @@ static int rt2800soc_probe(struct platfo +@@ -225,10 +225,17 @@ static int rt2800soc_probe(struct platfo return rt2x00soc_probe(pdev, &rt2800soc_ops); } diff --git a/package/kernel/mac80211/patches/rt2x00/610-rt2x00-change-led-polarity-from-OF.patch b/package/kernel/mac80211/patches/rt2x00/610-rt2x00-change-led-polarity-from-OF.patch index 4a819039d..acc8a8edb 100644 --- a/package/kernel/mac80211/patches/rt2x00/610-rt2x00-change-led-polarity-from-OF.patch +++ b/package/kernel/mac80211/patches/rt2x00/610-rt2x00-change-led-polarity-from-OF.patch @@ -8,7 +8,7 @@ #include "rt2x00.h" #include "rt2800lib.h" -@@ -11282,6 +11283,17 @@ static int rt2800_init_eeprom(struct rt2 +@@ -11131,6 +11132,17 @@ static int rt2800_init_eeprom(struct rt2 rt2800_init_led(rt2x00dev, &rt2x00dev->led_assoc, LED_TYPE_ASSOC); rt2800_init_led(rt2x00dev, &rt2x00dev->led_qual, LED_TYPE_QUALITY); diff --git a/package/kernel/mac80211/patches/rt2x00/611-rt2x00-add-AP+STA-support.patch b/package/kernel/mac80211/patches/rt2x00/611-rt2x00-add-AP+STA-support.patch index 9564f02ed..5ef5fc8de 100644 --- a/package/kernel/mac80211/patches/rt2x00/611-rt2x00-add-AP+STA-support.patch +++ b/package/kernel/mac80211/patches/rt2x00/611-rt2x00-add-AP+STA-support.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c -@@ -1362,7 +1362,7 @@ static inline void rt2x00lib_set_if_comb +@@ -1358,7 +1358,7 @@ static inline void rt2x00lib_set_if_comb */ if_limit = &rt2x00dev->if_limits_ap; if_limit->max = rt2x00dev->ops->max_ap_intf; diff --git a/package/kernel/mac80211/patches/rt2x00/994-rt2x00-import-support-for-external-LNA-on-MT7620.patch b/package/kernel/mac80211/patches/rt2x00/994-rt2x00-import-support-for-external-LNA-on-MT7620.patch index 5b950539b..deaa03be6 100644 --- a/package/kernel/mac80211/patches/rt2x00/994-rt2x00-import-support-for-external-LNA-on-MT7620.patch +++ b/package/kernel/mac80211/patches/rt2x00/994-rt2x00-import-support-for-external-LNA-on-MT7620.patch @@ -27,7 +27,7 @@ Signed-off-by: Daniel Golle --- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c -@@ -305,6 +305,24 @@ static void rt2800_rf_write(struct rt2x0 +@@ -304,6 +304,24 @@ static void rt2800_rf_write(struct rt2x0 mutex_unlock(&rt2x00dev->csr_mutex); } @@ -52,27 +52,67 @@ Signed-off-by: Daniel Golle static const unsigned int rt2800_eeprom_map[EEPROM_WORD_COUNT] = { [EEPROM_CHIP_ID] = 0x0000, [EEPROM_VERSION] = 0x0001, -@@ -10404,8 +10422,10 @@ static void rt2800_calibration_rt6352(st - u32 reg; +@@ -4469,6 +4487,29 @@ static void rt2800_config_channel(struct + rt2800_register_write(rt2x00dev, TX1_RF_GAIN_ATTEN, + 0x6C6C6B6C); + } ++ ++ if (rt2x00_has_cap_external_lna_bg(rt2x00dev)) { ++ reg = rt2800_register_read(rt2x00dev, RF_CONTROL3); ++ reg |= 0x00000101; ++ rt2800_register_write(rt2x00dev, RF_CONTROL3, reg); ++ ++ reg = rt2800_register_read(rt2x00dev, RF_BYPASS3); ++ reg |= 0x00000101; ++ rt2800_register_write(rt2x00dev, RF_BYPASS3, reg); ++ ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 14, 0x66); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 17, 0x20); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 18, 0x42); ++ rt2800_bbp_write(rt2x00dev, 75, 0x68); ++ rt2800_bbp_write(rt2x00dev, 76, 0x4C); ++ rt2800_bbp_write(rt2x00dev, 79, 0x1C); ++ rt2800_bbp_write(rt2x00dev, 80, 0x0C); ++ rt2800_bbp_write(rt2x00dev, 82, 0xB6); ++ /* bank 0 RF reg 42 and glrt BBP reg 141 will be set in ++ * config channel function in dependence of channel and ++ * HT20/HT40 so don't touch it ++ */ ++ } + } - if (rt2x00_has_cap_external_pa(rt2x00dev) || -- rt2x00_has_cap_external_lna_bg(rt2x00dev)) -+ rt2x00_has_cap_external_lna_bg(rt2x00dev)) { -+ rt6352_enable_pa_pin(rt2x00dev, 0); - rt2800_restore_rf_bbp_rt6352(rt2x00dev); -+ } + bbp = rt2800_bbp_read(rt2x00dev, 4); +@@ -10583,6 +10624,7 @@ static void rt2800_init_rfcsr_6352(struc + rt2800_rfcsr_write_dccal(rt2x00dev, 5, 0x00); + rt2800_rfcsr_write_dccal(rt2x00dev, 17, 0x7C); ++ rt6352_enable_pa_pin(rt2x00dev, 0); rt2800_r_calibration(rt2x00dev); rt2800_rf_self_txdc_cal(rt2x00dev); -@@ -10423,6 +10443,8 @@ static void rt2800_calibration_rt6352(st - !rt2x00_has_cap_external_lna_bg(rt2x00dev)) - return; - + rt2800_rxdcoc_calibration(rt2x00dev); +@@ -10590,6 +10632,22 @@ static void rt2800_init_rfcsr_6352(struc + rt2800_bw_filter_calibration(rt2x00dev, false); + rt2800_loft_iq_calibration(rt2x00dev); + rt2800_rxiq_calibration(rt2x00dev); + rt6352_enable_pa_pin(rt2x00dev, 1); + - if (rt2x00_has_cap_external_pa(rt2x00dev)) { - reg = rt2800_register_read(rt2x00dev, RF_CONTROL3); - reg |= 0x00000101; ++ if (rt2x00_has_cap_external_lna_bg(rt2x00dev)) { ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 14, 0x66); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 17, 0x20); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 18, 0x42); ++ rt2800_bbp_write(rt2x00dev, 75, 0x68); ++ rt2800_bbp_write(rt2x00dev, 76, 0x4C); ++ rt2800_bbp_write(rt2x00dev, 79, 0x1C); ++ rt2800_bbp_write(rt2x00dev, 80, 0x0C); ++ rt2800_bbp_write(rt2x00dev, 82, 0xB6); ++ /* bank 0 RF reg 42 and glrt BBP reg 141 will be set in config ++ * channel function in dependence of channel and HT20/HT40, ++ * so don't touch them here. ++ */ ++ } + } + + static void rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) --- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h @@ -28,6 +28,7 @@ @@ -83,7 +123,7 @@ Signed-off-by: Daniel Golle #include #include -@@ -1027,6 +1028,11 @@ struct rt2x00_dev { +@@ -1029,6 +1030,11 @@ struct rt2x00_dev { /* Clock for System On Chip devices. */ struct clk *clk; diff --git a/package/kernel/mac80211/patches/rt2x00/995-rt2x00-mt7620-introduce-accessors-for-CHIP_VER-register.patch b/package/kernel/mac80211/patches/rt2x00/995-rt2x00-mt7620-introduce-accessors-for-CHIP_VER-register.patch index b3828052e..97a56de2b 100644 --- a/package/kernel/mac80211/patches/rt2x00/995-rt2x00-mt7620-introduce-accessors-for-CHIP_VER-register.patch +++ b/package/kernel/mac80211/patches/rt2x00/995-rt2x00-mt7620-introduce-accessors-for-CHIP_VER-register.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h +++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h -@@ -76,6 +76,9 @@ struct rt2800_ops { +@@ -78,6 +78,9 @@ struct rt2800_ops { int (*drv_init_registers)(struct rt2x00_dev *rt2x00dev); __le32 *(*drv_get_txwi)(struct queue_entry *entry); unsigned int (*drv_get_dma_done)(struct data_queue *queue); @@ -10,7 +10,7 @@ }; static inline u32 rt2800_register_read(struct rt2x00_dev *rt2x00dev, -@@ -184,6 +187,27 @@ static inline unsigned int rt2800_drv_ge +@@ -195,6 +198,27 @@ static inline unsigned int rt2800_drv_ge return rt2800ops->drv_get_dma_done(queue); } @@ -49,9 +49,9 @@ +static int rt2800pci_get_chipeco(void) { return 0; } + static const struct ieee80211_ops rt2800pci_mac80211_ops = { - .add_chanctx = ieee80211_emulate_add_chanctx, - .remove_chanctx = ieee80211_emulate_remove_chanctx, -@@ -333,6 +337,9 @@ static const struct rt2800_ops rt2800pci + .tx = rt2x00mac_tx, + .wake_tx_queue = ieee80211_handle_wake_tx_queue, +@@ -329,6 +333,9 @@ static const struct rt2800_ops rt2800pci .drv_init_registers = rt2800mmio_init_registers, .drv_get_txwi = rt2800mmio_get_txwi, .drv_get_dma_done = rt2800mmio_get_dma_done, @@ -102,9 +102,9 @@ +#endif + static const struct ieee80211_ops rt2800soc_mac80211_ops = { - .add_chanctx = ieee80211_emulate_add_chanctx, - .remove_chanctx = ieee80211_emulate_remove_chanctx, -@@ -165,6 +192,9 @@ static const struct rt2800_ops rt2800soc + .tx = rt2x00mac_tx, + .wake_tx_queue = ieee80211_handle_wake_tx_queue, +@@ -160,6 +187,9 @@ static const struct rt2800_ops rt2800soc .drv_init_registers = rt2800mmio_init_registers, .drv_get_txwi = rt2800mmio_get_txwi, .drv_get_dma_done = rt2800mmio_get_dma_done, @@ -125,9 +125,9 @@ +static int rt2800usb_get_chipeco(void) { return 0; } + static const struct ieee80211_ops rt2800usb_mac80211_ops = { - .add_chanctx = ieee80211_emulate_add_chanctx, - .remove_chanctx = ieee80211_emulate_remove_chanctx, -@@ -676,6 +680,9 @@ static const struct rt2800_ops rt2800usb + .tx = rt2x00mac_tx, + .wake_tx_queue = ieee80211_handle_wake_tx_queue, +@@ -672,6 +676,9 @@ static const struct rt2800_ops rt2800usb .drv_init_registers = rt2800usb_init_registers, .drv_get_txwi = rt2800usb_get_txwi, .drv_get_dma_done = rt2800usb_get_dma_done, diff --git a/package/kernel/mac80211/patches/rt2x00/996-rt2x00-mt7620-differentiate-based-on-SoC-CHIP_VER.patch b/package/kernel/mac80211/patches/rt2x00/996-rt2x00-mt7620-differentiate-based-on-SoC-CHIP_VER.patch index 4c07a1059..dab6e05ff 100644 --- a/package/kernel/mac80211/patches/rt2x00/996-rt2x00-mt7620-differentiate-based-on-SoC-CHIP_VER.patch +++ b/package/kernel/mac80211/patches/rt2x00/996-rt2x00-mt7620-differentiate-based-on-SoC-CHIP_VER.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/ralink/rt2x00/rt2800.h +++ b/drivers/net/wireless/ralink/rt2x00/rt2800.h -@@ -1056,6 +1056,11 @@ +@@ -1044,6 +1044,11 @@ #define MIMO_PS_CFG_RX_STBY_POL FIELD32(0x00000010) #define MIMO_PS_CFG_RX_RX_STBY0 FIELD32(0x00000020) @@ -14,7 +14,7 @@ */ --- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c -@@ -3836,14 +3836,16 @@ static void rt2800_config_channel_rf7620 +@@ -3778,14 +3778,16 @@ static void rt2800_config_channel_rf7620 rt2x00_set_field8(&rfcsr, RFCSR19_K, rf->rf4); rt2800_rfcsr_write(rt2x00dev, 19, rfcsr); @@ -39,7 +39,7 @@ rfcsr = rt2800_rfcsr_read(rt2x00dev, 1); rt2x00_set_field8(&rfcsr, RFCSR1_TX2_EN_MT7620, -@@ -3877,18 +3879,23 @@ static void rt2800_config_channel_rf7620 +@@ -3819,18 +3821,23 @@ static void rt2800_config_channel_rf7620 rt2800_rfcsr_write_dccal(rt2x00dev, 59, 0x20); } @@ -73,7 +73,7 @@ if (!test_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags)) { if (conf_is_ht40(conf)) { -@@ -4002,25 +4009,29 @@ static void rt2800_config_alc_rt6352(str +@@ -3929,25 +3936,29 @@ static void rt2800_config_alc(struct rt2 if (unlikely(rt2800_wait_bbp_rf_ready(rt2x00dev, MAC_STATUS_CFG_BBP_RF_BUSY))) rt2x00_warn(rt2x00dev, "RF busy while configuring ALC\n"); @@ -121,17 +121,7 @@ rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, mac_sys_ctrl); rt2800_vco_calibration(rt2x00dev); -@@ -4513,7 +4524,8 @@ static void rt2800_config_channel(struct - if (rt2x00_rt(rt2x00dev, RT6352)) { - /* BBP for GLRT BW */ - bbp = conf_is_ht40(conf) ? -- 0x10 : rt2x00_has_cap_external_lna_bg(rt2x00dev) ? -+ 0x10 : !rt2x00_has_cap_external_lna_bg(rt2x00dev) ? -+ 0x1a : rt2800_hw_get_chippkg(rt2x00dev) == 1 ? - 0x15 : 0x1a; - rt2800_bbp_glrt_write(rt2x00dev, 141, bbp); - -@@ -6017,18 +6029,33 @@ static int rt2800_init_registers(struct +@@ -6011,18 +6022,33 @@ static int rt2800_init_registers(struct } else if (rt2x00_rt(rt2x00dev, RT5350)) { rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000404); } else if (rt2x00_rt(rt2x00dev, RT6352)) { @@ -177,7 +167,7 @@ reg = rt2800_register_read(rt2x00dev, TX_ALC_CFG_1); rt2x00_set_field32(®, TX_ALC_CFG_1_ROS_BUSY_EN, 0); rt2800_register_write(rt2x00dev, TX_ALC_CFG_1, reg); -@@ -7141,14 +7168,16 @@ static void rt2800_init_bbp_6352(struct +@@ -7127,14 +7153,16 @@ static void rt2800_init_bbp_6352(struct rt2800_bbp_write(rt2x00dev, 188, 0x00); rt2800_bbp_write(rt2x00dev, 189, 0x00); @@ -202,27 +192,7 @@ /* BBP for G band GLRT function (BBP_128 ~ BBP_221) */ rt2800_bbp_glrt_write(rt2x00dev, 0, 0x00); -@@ -10378,6 +10407,9 @@ static void rt2800_restore_rf_bbp_rt6352 - rt2800_register_write(rt2x00dev, RF_BYPASS3, 0x0); - } - -+ if (rt2800_hw_get_chippkg(rt2x00dev) != 1) -+ return; -+ - if (rt2x00_has_cap_external_lna_bg(rt2x00dev)) { - rt2800_rfcsr_write_chanreg(rt2x00dev, 14, 0x16); - rt2800_rfcsr_write_chanreg(rt2x00dev, 17, 0x23); -@@ -10455,6 +10487,9 @@ static void rt2800_calibration_rt6352(st - rt2800_register_write(rt2x00dev, RF_BYPASS3, reg); - } - -+ if (rt2800_hw_get_chippkg(rt2x00dev) != 1) -+ return; -+ - if (rt2x00_has_cap_external_lna_bg(rt2x00dev)) { - rt2800_rfcsr_write_chanreg(rt2x00dev, 14, 0x66); - rt2800_rfcsr_write_chanreg(rt2x00dev, 17, 0x20); -@@ -10545,31 +10580,36 @@ static void rt2800_init_rfcsr_6352(struc +@@ -10408,31 +10436,36 @@ static void rt2800_init_rfcsr_6352(struc rt2800_rfcsr_write(rt2x00dev, 42, 0x5B); rt2800_rfcsr_write(rt2x00dev, 43, 0x00); @@ -284,7 +254,7 @@ /* Initialize RF channel register to default value */ rt2800_rfcsr_write_chanreg(rt2x00dev, 0, 0x03); -@@ -10635,63 +10675,71 @@ static void rt2800_init_rfcsr_6352(struc +@@ -10498,63 +10531,71 @@ static void rt2800_init_rfcsr_6352(struc rt2800_rfcsr_write_bank(rt2x00dev, 6, 45, 0xC5); @@ -318,6 +288,33 @@ - rt2800_rfcsr_write_chanreg(rt2x00dev, 59, 0x6B); - rt2800_rfcsr_write_chanreg(rt2x00dev, 60, 0xF7); - rt2800_rfcsr_write_chanreg(rt2x00dev, 61, 0x09); +- +- rt2800_rfcsr_write_chanreg(rt2x00dev, 10, 0x51); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 14, 0x06); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 19, 0xA7); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 28, 0x2C); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 55, 0x64); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 8, 0x51); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 9, 0x36); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 11, 0x53); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 14, 0x16); +- +- rt2800_rfcsr_write_chanreg(rt2x00dev, 47, 0x6C); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 48, 0xFC); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 49, 0x1F); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 54, 0x27); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 55, 0x66); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 59, 0x6B); +- +- /* Initialize RF channel register for DRQFN */ +- rt2800_rfcsr_write_chanreg(rt2x00dev, 43, 0xD3); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 44, 0xE3); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 45, 0xE5); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 47, 0x28); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 55, 0x68); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 56, 0xF7); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 58, 0x02); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 60, 0xC7); + if (rt2800_hw_get_chipver(rt2x00dev) > 1) { + rt2800_rfcsr_write_chanreg(rt2x00dev, 9, 0x47); + rt2800_rfcsr_write_chanreg(rt2x00dev, 10, 0x71); @@ -350,16 +347,7 @@ + rt2800_rfcsr_write_chanreg(rt2x00dev, 60, 0xF7); + rt2800_rfcsr_write_chanreg(rt2x00dev, 61, 0x09); + } - -- rt2800_rfcsr_write_chanreg(rt2x00dev, 10, 0x51); -- rt2800_rfcsr_write_chanreg(rt2x00dev, 14, 0x06); -- rt2800_rfcsr_write_chanreg(rt2x00dev, 19, 0xA7); -- rt2800_rfcsr_write_chanreg(rt2x00dev, 28, 0x2C); -- rt2800_rfcsr_write_chanreg(rt2x00dev, 55, 0x64); -- rt2800_rfcsr_write_chanreg(rt2x00dev, 8, 0x51); -- rt2800_rfcsr_write_chanreg(rt2x00dev, 9, 0x36); -- rt2800_rfcsr_write_chanreg(rt2x00dev, 11, 0x53); -- rt2800_rfcsr_write_chanreg(rt2x00dev, 14, 0x16); ++ + if (rt2800_hw_get_chipver(rt2x00dev) > 1 && + rt2800_hw_get_chipeco(rt2x00dev) >= 2) { + rt2800_rfcsr_write_chanreg(rt2x00dev, 10, 0x51); @@ -379,23 +367,7 @@ + rt2800_rfcsr_write_chanreg(rt2x00dev, 55, 0x66); + rt2800_rfcsr_write_chanreg(rt2x00dev, 59, 0x6B); + } - -- rt2800_rfcsr_write_chanreg(rt2x00dev, 47, 0x6C); -- rt2800_rfcsr_write_chanreg(rt2x00dev, 48, 0xFC); -- rt2800_rfcsr_write_chanreg(rt2x00dev, 49, 0x1F); -- rt2800_rfcsr_write_chanreg(rt2x00dev, 54, 0x27); -- rt2800_rfcsr_write_chanreg(rt2x00dev, 55, 0x66); -- rt2800_rfcsr_write_chanreg(rt2x00dev, 59, 0x6B); -- -- /* Initialize RF channel register for DRQFN */ -- rt2800_rfcsr_write_chanreg(rt2x00dev, 43, 0xD3); -- rt2800_rfcsr_write_chanreg(rt2x00dev, 44, 0xE3); -- rt2800_rfcsr_write_chanreg(rt2x00dev, 45, 0xE5); -- rt2800_rfcsr_write_chanreg(rt2x00dev, 47, 0x28); -- rt2800_rfcsr_write_chanreg(rt2x00dev, 55, 0x68); -- rt2800_rfcsr_write_chanreg(rt2x00dev, 56, 0xF7); -- rt2800_rfcsr_write_chanreg(rt2x00dev, 58, 0x02); -- rt2800_rfcsr_write_chanreg(rt2x00dev, 60, 0xC7); ++ + if (rt2800_hw_get_chippkg(rt2x00dev) == 0 && + rt2800_hw_get_chipver(rt2x00dev) == 1) { + /* Initialize RF channel register for DRQFN */ @@ -411,7 +383,7 @@ /* Initialize RF DC calibration register to default value */ rt2800_rfcsr_write_dccal(rt2x00dev, 0, 0x47); -@@ -10754,12 +10802,17 @@ static void rt2800_init_rfcsr_6352(struc +@@ -10617,12 +10658,17 @@ static void rt2800_init_rfcsr_6352(struc rt2800_rfcsr_write_dccal(rt2x00dev, 62, 0x00); rt2800_rfcsr_write_dccal(rt2x00dev, 63, 0x00); @@ -432,5 +404,5 @@ + rt2800_rfcsr_write_dccal(rt2x00dev, 17, 0x7C); + } - /* Do calibration and init PA/LNA */ - rt2800_calibration_rt6352(rt2x00dev); + rt6352_enable_pa_pin(rt2x00dev, 0); + rt2800_r_calibration(rt2x00dev); diff --git a/package/kernel/mac80211/patches/subsys/110-mac80211_keep_keys_on_stop_ap.patch b/package/kernel/mac80211/patches/subsys/110-mac80211_keep_keys_on_stop_ap.patch index c71f1f2ff..4d4a2a8f5 100644 --- a/package/kernel/mac80211/patches/subsys/110-mac80211_keep_keys_on_stop_ap.patch +++ b/package/kernel/mac80211/patches/subsys/110-mac80211_keep_keys_on_stop_ap.patch @@ -9,16 +9,11 @@ Used for AP+STA support in OpenWrt - preserve AP mode keys across STA reconnect --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c -@@ -1647,12 +1647,6 @@ static int ieee80211_stop_ap(struct wiph +@@ -1519,7 +1519,6 @@ static int ieee80211_stop_ap(struct wiph + link_conf->bssid_indicator = 0; - __sta_info_flush(sdata, true, link_id); + __sta_info_flush(sdata, true); +- ieee80211_free_keys(sdata, true); -- ieee80211_remove_link_keys(link, &keys); -- if (!list_empty(&keys)) { -- synchronize_net(); -- ieee80211_free_key_list(local, &keys); -- } -- link_conf->enable_beacon = false; sdata->beacon_rate_set = false; - sdata->vif.cfg.ssid_len = 0; diff --git a/package/kernel/mac80211/patches/subsys/130-disable_auto_vif.patch b/package/kernel/mac80211/patches/subsys/130-disable_auto_vif.patch deleted file mode 100644 index d4341a135..000000000 --- a/package/kernel/mac80211/patches/subsys/130-disable_auto_vif.patch +++ /dev/null @@ -1,27 +0,0 @@ ---- a/net/mac80211/main.c -+++ b/net/mac80211/main.c -@@ -1564,24 +1564,6 @@ int ieee80211_register_hw(struct ieee802 - - ieee80211_check_wbrf_support(local); - -- rtnl_lock(); -- wiphy_lock(hw->wiphy); -- -- /* add one default STA interface if supported */ -- if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION) && -- !ieee80211_hw_check(hw, NO_AUTO_VIF)) { -- struct vif_params params = {0}; -- -- result = ieee80211_if_add(local, "wlan%d", NET_NAME_ENUM, NULL, -- NL80211_IFTYPE_STATION, ¶ms); -- if (result) -- wiphy_warn(local->hw.wiphy, -- "Failed to add default virtual iface\n"); -- } -- -- wiphy_unlock(hw->wiphy); -- rtnl_unlock(); -- - #ifdef CONFIG_INET - local->ifa_notifier.notifier_call = ieee80211_ifa_changed; - result = register_inetaddr_notifier(&local->ifa_notifier); diff --git a/package/kernel/mac80211/patches/subsys/210-ap_scan.patch b/package/kernel/mac80211/patches/subsys/210-ap_scan.patch index a1f96cb3a..10b842d9a 100644 --- a/package/kernel/mac80211/patches/subsys/210-ap_scan.patch +++ b/package/kernel/mac80211/patches/subsys/210-ap_scan.patch @@ -8,7 +8,7 @@ Subject: [PATCH] mac80211: allow scans in access point mode (for site survey) --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c -@@ -2844,6 +2844,8 @@ static int ieee80211_scan(struct wiphy * +@@ -2727,6 +2727,8 @@ static int ieee80211_scan(struct wiphy * */ fallthrough; case NL80211_IFTYPE_AP: diff --git a/package/kernel/mac80211/patches/subsys/301-mac80211-sta-randomize-BA-session-dialog-token-alloc.patch b/package/kernel/mac80211/patches/subsys/301-mac80211-sta-randomize-BA-session-dialog-token-alloc.patch index d576661bd..63b217747 100644 --- a/package/kernel/mac80211/patches/subsys/301-mac80211-sta-randomize-BA-session-dialog-token-alloc.patch +++ b/package/kernel/mac80211/patches/subsys/301-mac80211-sta-randomize-BA-session-dialog-token-alloc.patch @@ -28,15 +28,11 @@ Signed-off-by: Johannes Berg --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c -@@ -565,6 +565,11 @@ __sta_info_alloc(struct ieee80211_sub_if - spin_lock_init(&sta->ps_lock); +@@ -554,6 +554,7 @@ __sta_info_alloc(struct ieee80211_sub_if INIT_WORK(&sta->drv_deliver_wk, sta_deliver_ps_frames); - wiphy_work_init(&sta->ampdu_mlme.work, ieee80211_ba_session_work); -+#if LINUX_VERSION_IS_LESS(6,2,0) + INIT_WORK(&sta->ampdu_mlme.work, ieee80211_ba_session_work); + mutex_init(&sta->ampdu_mlme.mtx); + sta->ampdu_mlme.dialog_token_allocator = prandom_u32_max(U8_MAX); -+#else -+ sta->ampdu_mlme.dialog_token_allocator = get_random_u32_below(U8_MAX); -+#endif #ifdef CPTCFG_MAC80211_MESH if (ieee80211_vif_is_mesh(&sdata->vif)) { sta->mesh = kzalloc(sizeof(*sta->mesh), gfp); diff --git a/package/kernel/mac80211/patches/subsys/305-mac80211-increase-quantum-for-airtime-scheduler.patch b/package/kernel/mac80211/patches/subsys/305-mac80211-increase-quantum-for-airtime-scheduler.patch index 71ce340d3..0ac972955 100644 --- a/package/kernel/mac80211/patches/subsys/305-mac80211-increase-quantum-for-airtime-scheduler.patch +++ b/package/kernel/mac80211/patches/subsys/305-mac80211-increase-quantum-for-airtime-scheduler.patch @@ -12,9 +12,9 @@ Signed-off-by: Felix Fietkau --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h -@@ -101,6 +101,8 @@ ieee80211_sta_keep_active(struct sta_inf - return time_before_eq(jiffies, sta->airtime[ac].last_active + HZ / 10); - } +@@ -90,6 +90,8 @@ extern const u8 ieee80211_ac_to_qos_mask + */ + #define AIRTIME_ACTIVE_DURATION (HZ / 10) +#define AIRTIME_QUANTUM_SHIFT 3 + @@ -23,7 +23,7 @@ Signed-off-by: Felix Fietkau --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c -@@ -4082,7 +4082,7 @@ struct ieee80211_txq *ieee80211_next_txq +@@ -3984,7 +3984,7 @@ struct ieee80211_txq *ieee80211_next_txq if (deficit < 0) sta->airtime[txqi->txq.ac].deficit += @@ -32,7 +32,7 @@ Signed-off-by: Felix Fietkau if (deficit < 0 || !aql_check) { list_move_tail(&txqi->schedule_order, -@@ -4225,7 +4225,8 @@ bool ieee80211_txq_may_transmit(struct i +@@ -4127,7 +4127,8 @@ bool ieee80211_txq_may_transmit(struct i } sta = container_of(iter->txq.sta, struct sta_info, sta); if (ieee80211_sta_deficit(sta, ac) < 0) @@ -42,7 +42,7 @@ Signed-off-by: Felix Fietkau list_move_tail(&iter->schedule_order, &local->active_txqs[ac]); } -@@ -4233,7 +4234,7 @@ bool ieee80211_txq_may_transmit(struct i +@@ -4135,7 +4136,7 @@ bool ieee80211_txq_may_transmit(struct i if (sta->airtime[ac].deficit >= 0) goto out; diff --git a/package/kernel/mac80211/patches/subsys/306-01-v6.2-wifi-mac80211-add-internal-handler-for-wake_tx_queue.patch b/package/kernel/mac80211/patches/subsys/306-01-v6.2-wifi-mac80211-add-internal-handler-for-wake_tx_queue.patch new file mode 100644 index 000000000..d14ba05e6 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/306-01-v6.2-wifi-mac80211-add-internal-handler-for-wake_tx_queue.patch @@ -0,0 +1,183 @@ +From: Alexander Wetzel +Date: Sun, 9 Oct 2022 18:30:38 +0200 +Subject: [PATCH] wifi: mac80211: add internal handler for wake_tx_queue + +Start to align the TX handling to only use internal TX queues (iTXQs): + +Provide a handler for drivers not having a custom wake_tx_queue +callback and update the documentation. + +Signed-off-by: Alexander Wetzel +Signed-off-by: Johannes Berg +--- + +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -89,15 +89,13 @@ + /** + * DOC: mac80211 software tx queueing + * +- * mac80211 provides an optional intermediate queueing implementation designed +- * to allow the driver to keep hardware queues short and provide some fairness +- * between different stations/interfaces. +- * In this model, the driver pulls data frames from the mac80211 queue instead +- * of letting mac80211 push them via drv_tx(). +- * Other frames (e.g. control or management) are still pushed using drv_tx(). ++ * mac80211 uses an intermediate queueing implementation, designed to allow the ++ * driver to keep hardware queues short and to provide some fairness between ++ * different stations/interfaces. + * +- * Drivers indicate that they use this model by implementing the .wake_tx_queue +- * driver operation. ++ * Drivers must provide the .wake_tx_queue driver operation by either ++ * linking it to ieee80211_handle_wake_tx_queue() or implementing a custom ++ * handler. + * + * Intermediate queues (struct ieee80211_txq) are kept per-sta per-tid, with + * another per-sta for non-data/non-mgmt and bufferable management frames, and +@@ -106,9 +104,12 @@ + * The driver is expected to initialize its private per-queue data for stations + * and interfaces in the .add_interface and .sta_add ops. + * +- * The driver can't access the queue directly. To dequeue a frame from a +- * txq, it calls ieee80211_tx_dequeue(). Whenever mac80211 adds a new frame to a +- * queue, it calls the .wake_tx_queue driver op. ++ * The driver can't access the internal TX queues (iTXQs) directly. ++ * Whenever mac80211 adds a new frame to a queue, it calls the .wake_tx_queue ++ * driver op. ++ * Drivers implementing a custom .wake_tx_queue op can get them by calling ++ * ieee80211_tx_dequeue(). Drivers using ieee80211_handle_wake_tx_queue() will ++ * simply get the individual frames pushed via the .tx driver operation. + * + * Drivers can optionally delegate responsibility for scheduling queues to + * mac80211, to take advantage of airtime fairness accounting. In this case, to +@@ -2248,8 +2249,8 @@ struct ieee80211_link_sta { + * For non MLO STA it will point to the deflink data. For MLO STA + * ieee80211_sta_recalc_aggregates() must be called to update it. + * @support_p2p_ps: indicates whether the STA supports P2P PS mechanism or not. +- * @txq: per-TID data TX queues (if driver uses the TXQ abstraction); note that +- * the last entry (%IEEE80211_NUM_TIDS) is used for non-data frames ++ * @txq: per-TID data TX queues; note that the last entry (%IEEE80211_NUM_TIDS) ++ * is used for non-data frames + * @deflink: This holds the default link STA information, for non MLO STA all link + * specific STA information is accessed through @deflink or through + * link[0] which points to address of @deflink. For MLO Link STA +@@ -5687,7 +5688,7 @@ void ieee80211_key_replay(struct ieee802 + * @hw: pointer as obtained from ieee80211_alloc_hw(). + * @queue: queue number (counted from zero). + * +- * Drivers should use this function instead of netif_wake_queue. ++ * Drivers must use this function instead of netif_wake_queue. + */ + void ieee80211_wake_queue(struct ieee80211_hw *hw, int queue); + +@@ -5696,7 +5697,7 @@ void ieee80211_wake_queue(struct ieee802 + * @hw: pointer as obtained from ieee80211_alloc_hw(). + * @queue: queue number (counted from zero). + * +- * Drivers should use this function instead of netif_stop_queue. ++ * Drivers must use this function instead of netif_stop_queue. + */ + void ieee80211_stop_queue(struct ieee80211_hw *hw, int queue); + +@@ -5705,7 +5706,7 @@ void ieee80211_stop_queue(struct ieee802 + * @hw: pointer as obtained from ieee80211_alloc_hw(). + * @queue: queue number (counted from zero). + * +- * Drivers should use this function instead of netif_stop_queue. ++ * Drivers must use this function instead of netif_queue_stopped. + * + * Return: %true if the queue is stopped. %false otherwise. + */ +@@ -5716,7 +5717,7 @@ int ieee80211_queue_stopped(struct ieee8 + * ieee80211_stop_queues - stop all queues + * @hw: pointer as obtained from ieee80211_alloc_hw(). + * +- * Drivers should use this function instead of netif_stop_queue. ++ * Drivers must use this function instead of netif_tx_stop_all_queues. + */ + void ieee80211_stop_queues(struct ieee80211_hw *hw); + +@@ -5724,7 +5725,7 @@ void ieee80211_stop_queues(struct ieee80 + * ieee80211_wake_queues - wake all queues + * @hw: pointer as obtained from ieee80211_alloc_hw(). + * +- * Drivers should use this function instead of netif_wake_queue. ++ * Drivers must use this function instead of netif_tx_wake_all_queues. + */ + void ieee80211_wake_queues(struct ieee80211_hw *hw); + +@@ -6946,6 +6947,18 @@ static inline struct sk_buff *ieee80211_ + } + + /** ++ * ieee80211_handle_wake_tx_queue - mac80211 handler for wake_tx_queue callback ++ * ++ * @hw: pointer as obtained from wake_tx_queue() callback(). ++ * @txq: pointer as obtained from wake_tx_queue() callback(). ++ * ++ * Drivers can use this function for the mandatory mac80211 wake_tx_queue ++ * callback in struct ieee80211_ops. They should not call this function. ++ */ ++void ieee80211_handle_wake_tx_queue(struct ieee80211_hw *hw, ++ struct ieee80211_txq *txq); ++ ++/** + * ieee80211_next_txq - get next tx queue to pull packets from + * + * @hw: pointer as obtained from ieee80211_alloc_hw() +--- a/net/mac80211/util.c ++++ b/net/mac80211/util.c +@@ -288,6 +288,52 @@ __le16 ieee80211_ctstoself_duration(stru + } + EXPORT_SYMBOL(ieee80211_ctstoself_duration); + ++static void wake_tx_push_queue(struct ieee80211_local *local, ++ struct ieee80211_sub_if_data *sdata, ++ struct ieee80211_txq *queue) ++{ ++ int q = sdata->vif.hw_queue[queue->ac]; ++ struct ieee80211_tx_control control = { ++ .sta = queue->sta, ++ }; ++ struct sk_buff *skb; ++ unsigned long flags; ++ bool q_stopped; ++ ++ while (1) { ++ spin_lock_irqsave(&local->queue_stop_reason_lock, flags); ++ q_stopped = local->queue_stop_reasons[q]; ++ spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); ++ ++ if (q_stopped) ++ break; ++ ++ skb = ieee80211_tx_dequeue(&local->hw, queue); ++ if (!skb) ++ break; ++ ++ drv_tx(local, &control, skb); ++ } ++} ++ ++/* wake_tx_queue handler for driver not implementing a custom one*/ ++void ieee80211_handle_wake_tx_queue(struct ieee80211_hw *hw, ++ struct ieee80211_txq *txq) ++{ ++ struct ieee80211_local *local = hw_to_local(hw); ++ struct ieee80211_sub_if_data *sdata = vif_to_sdata(txq->vif); ++ struct ieee80211_txq *queue; ++ ++ /* Use ieee80211_next_txq() for airtime fairness accounting */ ++ ieee80211_txq_schedule_start(hw, txq->ac); ++ while ((queue = ieee80211_next_txq(hw, txq->ac))) { ++ wake_tx_push_queue(local, sdata, queue); ++ ieee80211_return_txq(hw, queue, false); ++ } ++ ieee80211_txq_schedule_end(hw, txq->ac); ++} ++EXPORT_SYMBOL(ieee80211_handle_wake_tx_queue); ++ + static void __ieee80211_wake_txqs(struct ieee80211_sub_if_data *sdata, int ac) + { + struct ieee80211_local *local = sdata->local; diff --git a/package/kernel/mac80211/patches/subsys/306-02-v6.2-wifi-mac80211-add-wake_tx_queue-callback-to-drivers.patch b/package/kernel/mac80211/patches/subsys/306-02-v6.2-wifi-mac80211-add-wake_tx_queue-callback-to-drivers.patch new file mode 100644 index 000000000..fee038d90 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/306-02-v6.2-wifi-mac80211-add-wake_tx_queue-callback-to-drivers.patch @@ -0,0 +1,396 @@ +From: Alexander Wetzel +Date: Sun, 9 Oct 2022 18:30:39 +0200 +Subject: [PATCH] wifi: mac80211: add wake_tx_queue callback to drivers + +mac80211 is fully switching over to the internal TX queue (iTXQ) +implementation. Update all drivers not yet providing the now mandatory +wake_tx_queue() callback. + +As an side effect the netdev interfaces of all updated drivers will +switch to the noqueue qdisc. + +Signed-off-by: Alexander Wetzel +[add staging drivers] +Signed-off-by: Johannes Berg +--- + +--- a/drivers/net/wireless/admtek/adm8211.c ++++ b/drivers/net/wireless/admtek/adm8211.c +@@ -1760,6 +1760,7 @@ static int adm8211_alloc_rings(struct ie + + static const struct ieee80211_ops adm8211_ops = { + .tx = adm8211_tx, ++ .wake_tx_queue = ieee80211_handle_wake_tx_queue, + .start = adm8211_start, + .stop = adm8211_stop, + .add_interface = adm8211_add_interface, +--- a/drivers/net/wireless/ath/ar5523/ar5523.c ++++ b/drivers/net/wireless/ath/ar5523/ar5523.c +@@ -1361,6 +1361,7 @@ static const struct ieee80211_ops ar5523 + .start = ar5523_start, + .stop = ar5523_stop, + .tx = ar5523_tx, ++ .wake_tx_queue = ieee80211_handle_wake_tx_queue, + .set_rts_threshold = ar5523_set_rts_threshold, + .add_interface = ar5523_add_interface, + .remove_interface = ar5523_remove_interface, +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -8587,6 +8587,7 @@ err_fallback: + + static const struct ieee80211_ops ath11k_ops = { + .tx = ath11k_mac_op_tx, ++ .wake_tx_queue = ieee80211_handle_wake_tx_queue, + .start = ath11k_mac_op_start, + .stop = ath11k_mac_op_stop, + .reconfig_complete = ath11k_mac_op_reconfig_complete, +--- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c ++++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c +@@ -781,6 +781,7 @@ static int ath5k_set_ringparam(struct ie + + const struct ieee80211_ops ath5k_hw_ops = { + .tx = ath5k_tx, ++ .wake_tx_queue = ieee80211_handle_wake_tx_queue, + .start = ath5k_start, + .stop = ath5k_stop, + .add_interface = ath5k_add_interface, +--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c ++++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c +@@ -1870,6 +1870,7 @@ static void ath9k_htc_channel_switch_bea + + struct ieee80211_ops ath9k_htc_ops = { + .tx = ath9k_htc_tx, ++ .wake_tx_queue = ieee80211_handle_wake_tx_queue, + .start = ath9k_htc_start, + .stop = ath9k_htc_stop, + .add_interface = ath9k_htc_add_interface, +--- a/drivers/net/wireless/ath/carl9170/main.c ++++ b/drivers/net/wireless/ath/carl9170/main.c +@@ -1715,6 +1715,7 @@ static const struct ieee80211_ops carl91 + .start = carl9170_op_start, + .stop = carl9170_op_stop, + .tx = carl9170_op_tx, ++ .wake_tx_queue = ieee80211_handle_wake_tx_queue, + .flush = carl9170_op_flush, + .add_interface = carl9170_op_add_interface, + .remove_interface = carl9170_op_remove_interface, +--- a/drivers/net/wireless/ath/wcn36xx/main.c ++++ b/drivers/net/wireless/ath/wcn36xx/main.c +@@ -1362,6 +1362,7 @@ static const struct ieee80211_ops wcn36x + .prepare_multicast = wcn36xx_prepare_multicast, + .configure_filter = wcn36xx_configure_filter, + .tx = wcn36xx_tx, ++ .wake_tx_queue = ieee80211_handle_wake_tx_queue, + .set_key = wcn36xx_set_key, + .hw_scan = wcn36xx_hw_scan, + .cancel_hw_scan = wcn36xx_cancel_hw_scan, +--- a/drivers/net/wireless/atmel/at76c50x-usb.c ++++ b/drivers/net/wireless/atmel/at76c50x-usb.c +@@ -2187,6 +2187,7 @@ static int at76_set_key(struct ieee80211 + + static const struct ieee80211_ops at76_ops = { + .tx = at76_mac80211_tx, ++ .wake_tx_queue = ieee80211_handle_wake_tx_queue, + .add_interface = at76_add_interface, + .remove_interface = at76_remove_interface, + .config = at76_config, +--- a/drivers/net/wireless/broadcom/b43/main.c ++++ b/drivers/net/wireless/broadcom/b43/main.c +@@ -5171,6 +5171,7 @@ static int b43_op_get_survey(struct ieee + + static const struct ieee80211_ops b43_hw_ops = { + .tx = b43_op_tx, ++ .wake_tx_queue = ieee80211_handle_wake_tx_queue, + .conf_tx = b43_op_conf_tx, + .add_interface = b43_op_add_interface, + .remove_interface = b43_op_remove_interface, +--- a/drivers/net/wireless/broadcom/b43legacy/main.c ++++ b/drivers/net/wireless/broadcom/b43legacy/main.c +@@ -3532,6 +3532,7 @@ static int b43legacy_op_get_survey(struc + + static const struct ieee80211_ops b43legacy_hw_ops = { + .tx = b43legacy_op_tx, ++ .wake_tx_queue = ieee80211_handle_wake_tx_queue, + .conf_tx = b43legacy_op_conf_tx, + .add_interface = b43legacy_op_add_interface, + .remove_interface = b43legacy_op_remove_interface, +--- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/mac80211_if.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/mac80211_if.c +@@ -962,6 +962,7 @@ static int brcms_ops_beacon_set_tim(stru + + static const struct ieee80211_ops brcms_ops = { + .tx = brcms_ops_tx, ++ .wake_tx_queue = ieee80211_handle_wake_tx_queue, + .start = brcms_ops_start, + .stop = brcms_ops_stop, + .add_interface = brcms_ops_add_interface, +--- a/drivers/net/wireless/intel/iwlegacy/3945-mac.c ++++ b/drivers/net/wireless/intel/iwlegacy/3945-mac.c +@@ -3439,6 +3439,7 @@ static const struct attribute_group il39 + + static struct ieee80211_ops il3945_mac_ops __ro_after_init = { + .tx = il3945_mac_tx, ++ .wake_tx_queue = ieee80211_handle_wake_tx_queue, + .start = il3945_mac_start, + .stop = il3945_mac_stop, + .add_interface = il_mac_add_interface, +--- a/drivers/net/wireless/intel/iwlegacy/4965-mac.c ++++ b/drivers/net/wireless/intel/iwlegacy/4965-mac.c +@@ -6308,6 +6308,7 @@ il4965_tx_queue_set_status(struct il_pri + + static const struct ieee80211_ops il4965_mac_ops = { + .tx = il4965_mac_tx, ++ .wake_tx_queue = ieee80211_handle_wake_tx_queue, + .start = il4965_mac_start, + .stop = il4965_mac_stop, + .add_interface = il_mac_add_interface, +--- a/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c ++++ b/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c +@@ -1571,6 +1571,7 @@ static void iwlagn_mac_sta_notify(struct + + const struct ieee80211_ops iwlagn_hw_ops = { + .tx = iwlagn_mac_tx, ++ .wake_tx_queue = ieee80211_handle_wake_tx_queue, + .start = iwlagn_mac_start, + .stop = iwlagn_mac_stop, + #ifdef CONFIG_PM_SLEEP +--- a/drivers/net/wireless/intersil/p54/main.c ++++ b/drivers/net/wireless/intersil/p54/main.c +@@ -705,6 +705,7 @@ static void p54_set_coverage_class(struc + + static const struct ieee80211_ops p54_ops = { + .tx = p54_tx_80211, ++ .wake_tx_queue = ieee80211_handle_wake_tx_queue, + .start = p54_start, + .stop = p54_stop, + .add_interface = p54_add_interface, +--- a/drivers/net/wireless/mac80211_hwsim.c ++++ b/drivers/net/wireless/mac80211_hwsim.c +@@ -3109,6 +3109,7 @@ static int mac80211_hwsim_change_sta_lin + + #define HWSIM_COMMON_OPS \ + .tx = mac80211_hwsim_tx, \ ++ .wake_tx_queue = ieee80211_handle_wake_tx_queue, \ + .start = mac80211_hwsim_start, \ + .stop = mac80211_hwsim_stop, \ + .add_interface = mac80211_hwsim_add_interface, \ +--- a/drivers/net/wireless/marvell/libertas_tf/main.c ++++ b/drivers/net/wireless/marvell/libertas_tf/main.c +@@ -474,6 +474,7 @@ static int lbtf_op_get_survey(struct iee + + static const struct ieee80211_ops lbtf_ops = { + .tx = lbtf_op_tx, ++ .wake_tx_queue = ieee80211_handle_wake_tx_queue, + .start = lbtf_op_start, + .stop = lbtf_op_stop, + .add_interface = lbtf_op_add_interface, +--- a/drivers/net/wireless/marvell/mwl8k.c ++++ b/drivers/net/wireless/marvell/mwl8k.c +@@ -5611,6 +5611,7 @@ static void mwl8k_sw_scan_complete(struc + + static const struct ieee80211_ops mwl8k_ops = { + .tx = mwl8k_tx, ++ .wake_tx_queue = ieee80211_handle_wake_tx_queue, + .start = mwl8k_start, + .stop = mwl8k_stop, + .add_interface = mwl8k_add_interface, +--- a/drivers/net/wireless/mediatek/mt7601u/main.c ++++ b/drivers/net/wireless/mediatek/mt7601u/main.c +@@ -406,6 +406,7 @@ out: + + const struct ieee80211_ops mt7601u_ops = { + .tx = mt7601u_tx, ++ .wake_tx_queue = ieee80211_handle_wake_tx_queue, + .start = mt7601u_start, + .stop = mt7601u_stop, + .add_interface = mt7601u_add_interface, +--- a/drivers/net/wireless/ralink/rt2x00/rt2400pci.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2400pci.c +@@ -1706,6 +1706,7 @@ static int rt2400pci_tx_last_beacon(stru + + static const struct ieee80211_ops rt2400pci_mac80211_ops = { + .tx = rt2x00mac_tx, ++ .wake_tx_queue = ieee80211_handle_wake_tx_queue, + .start = rt2x00mac_start, + .stop = rt2x00mac_stop, + .add_interface = rt2x00mac_add_interface, +--- a/drivers/net/wireless/ralink/rt2x00/rt2500pci.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2500pci.c +@@ -2004,6 +2004,7 @@ static int rt2500pci_tx_last_beacon(stru + + static const struct ieee80211_ops rt2500pci_mac80211_ops = { + .tx = rt2x00mac_tx, ++ .wake_tx_queue = ieee80211_handle_wake_tx_queue, + .start = rt2x00mac_start, + .stop = rt2x00mac_stop, + .add_interface = rt2x00mac_add_interface, +--- a/drivers/net/wireless/ralink/rt2x00/rt2500usb.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2500usb.c +@@ -1795,6 +1795,7 @@ static int rt2500usb_probe_hw(struct rt2 + + static const struct ieee80211_ops rt2500usb_mac80211_ops = { + .tx = rt2x00mac_tx, ++ .wake_tx_queue = ieee80211_handle_wake_tx_queue, + .start = rt2x00mac_start, + .stop = rt2x00mac_stop, + .add_interface = rt2x00mac_add_interface, +--- a/drivers/net/wireless/ralink/rt2x00/rt2800pci.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2800pci.c +@@ -288,6 +288,7 @@ static int rt2800pci_read_eeprom(struct + + static const struct ieee80211_ops rt2800pci_mac80211_ops = { + .tx = rt2x00mac_tx, ++ .wake_tx_queue = ieee80211_handle_wake_tx_queue, + .start = rt2x00mac_start, + .stop = rt2x00mac_stop, + .add_interface = rt2x00mac_add_interface, +--- a/drivers/net/wireless/ralink/rt2x00/rt2800soc.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2800soc.c +@@ -133,6 +133,7 @@ static int rt2800soc_write_firmware(stru + + static const struct ieee80211_ops rt2800soc_mac80211_ops = { + .tx = rt2x00mac_tx, ++ .wake_tx_queue = ieee80211_handle_wake_tx_queue, + .start = rt2x00mac_start, + .stop = rt2x00mac_stop, + .add_interface = rt2x00mac_add_interface, +--- a/drivers/net/wireless/ralink/rt2x00/rt2800usb.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2800usb.c +@@ -630,6 +630,7 @@ static int rt2800usb_probe_hw(struct rt2 + + static const struct ieee80211_ops rt2800usb_mac80211_ops = { + .tx = rt2x00mac_tx, ++ .wake_tx_queue = ieee80211_handle_wake_tx_queue, + .start = rt2x00mac_start, + .stop = rt2x00mac_stop, + .add_interface = rt2x00mac_add_interface, +--- a/drivers/net/wireless/ralink/rt2x00/rt61pci.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt61pci.c +@@ -2873,6 +2873,7 @@ static u64 rt61pci_get_tsf(struct ieee80 + + static const struct ieee80211_ops rt61pci_mac80211_ops = { + .tx = rt2x00mac_tx, ++ .wake_tx_queue = ieee80211_handle_wake_tx_queue, + .start = rt2x00mac_start, + .stop = rt2x00mac_stop, + .add_interface = rt2x00mac_add_interface, +--- a/drivers/net/wireless/ralink/rt2x00/rt73usb.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt73usb.c +@@ -2292,6 +2292,7 @@ static u64 rt73usb_get_tsf(struct ieee80 + + static const struct ieee80211_ops rt73usb_mac80211_ops = { + .tx = rt2x00mac_tx, ++ .wake_tx_queue = ieee80211_handle_wake_tx_queue, + .start = rt2x00mac_start, + .stop = rt2x00mac_stop, + .add_interface = rt2x00mac_add_interface, +--- a/drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c ++++ b/drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c +@@ -1608,6 +1608,7 @@ static void rtl8180_configure_filter(str + + static const struct ieee80211_ops rtl8180_ops = { + .tx = rtl8180_tx, ++ .wake_tx_queue = ieee80211_handle_wake_tx_queue, + .start = rtl8180_start, + .stop = rtl8180_stop, + .add_interface = rtl8180_add_interface, +--- a/drivers/net/wireless/realtek/rtl818x/rtl8187/dev.c ++++ b/drivers/net/wireless/realtek/rtl818x/rtl8187/dev.c +@@ -1378,6 +1378,7 @@ static int rtl8187_conf_tx(struct ieee80 + + static const struct ieee80211_ops rtl8187_ops = { + .tx = rtl8187_tx, ++ .wake_tx_queue = ieee80211_handle_wake_tx_queue, + .start = rtl8187_start, + .stop = rtl8187_stop, + .add_interface = rtl8187_add_interface, +--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c ++++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c +@@ -6548,6 +6548,7 @@ static void rtl8xxxu_stop(struct ieee802 + + static const struct ieee80211_ops rtl8xxxu_ops = { + .tx = rtl8xxxu_tx, ++ .wake_tx_queue = ieee80211_handle_wake_tx_queue, + .add_interface = rtl8xxxu_add_interface, + .remove_interface = rtl8xxxu_remove_interface, + .config = rtl8xxxu_config, +--- a/drivers/net/wireless/realtek/rtlwifi/core.c ++++ b/drivers/net/wireless/realtek/rtlwifi/core.c +@@ -1912,6 +1912,7 @@ const struct ieee80211_ops rtl_ops = { + .start = rtl_op_start, + .stop = rtl_op_stop, + .tx = rtl_op_tx, ++ .wake_tx_queue = ieee80211_handle_wake_tx_queue, + .add_interface = rtl_op_add_interface, + .remove_interface = rtl_op_remove_interface, + .change_interface = rtl_op_change_interface, +--- a/drivers/net/wireless/realtek/rtw88/mac80211.c ++++ b/drivers/net/wireless/realtek/rtw88/mac80211.c +@@ -896,6 +896,7 @@ static void rtw_ops_sta_rc_update(struct + + const struct ieee80211_ops rtw_ops = { + .tx = rtw_ops_tx, ++ .wake_tx_queue = ieee80211_handle_wake_tx_queue, + .wake_tx_queue = rtw_ops_wake_tx_queue, + .start = rtw_ops_start, + .stop = rtw_ops_stop, +--- a/drivers/net/wireless/realtek/rtw89/mac80211.c ++++ b/drivers/net/wireless/realtek/rtw89/mac80211.c +@@ -918,6 +918,7 @@ static int rtw89_ops_set_tid_config(stru + + const struct ieee80211_ops rtw89_ops = { + .tx = rtw89_ops_tx, ++ .wake_tx_queue = ieee80211_handle_wake_tx_queue, + .wake_tx_queue = rtw89_ops_wake_tx_queue, + .start = rtw89_ops_start, + .stop = rtw89_ops_stop, +--- a/drivers/net/wireless/rsi/rsi_91x_mac80211.c ++++ b/drivers/net/wireless/rsi/rsi_91x_mac80211.c +@@ -1958,6 +1958,7 @@ static int rsi_mac80211_resume(struct ie + + static const struct ieee80211_ops mac80211_ops = { + .tx = rsi_mac80211_tx, ++ .wake_tx_queue = ieee80211_handle_wake_tx_queue, + .start = rsi_mac80211_start, + .stop = rsi_mac80211_stop, + .add_interface = rsi_mac80211_add_interface, +--- a/drivers/net/wireless/st/cw1200/main.c ++++ b/drivers/net/wireless/st/cw1200/main.c +@@ -209,6 +209,7 @@ static const struct ieee80211_ops cw1200 + .remove_interface = cw1200_remove_interface, + .change_interface = cw1200_change_interface, + .tx = cw1200_tx, ++ .wake_tx_queue = ieee80211_handle_wake_tx_queue, + .hw_scan = cw1200_hw_scan, + .set_tim = cw1200_set_tim, + .sta_notify = cw1200_sta_notify, +--- a/drivers/net/wireless/ti/wl1251/main.c ++++ b/drivers/net/wireless/ti/wl1251/main.c +@@ -1359,6 +1359,7 @@ static const struct ieee80211_ops wl1251 + .prepare_multicast = wl1251_op_prepare_multicast, + .configure_filter = wl1251_op_configure_filter, + .tx = wl1251_op_tx, ++ .wake_tx_queue = ieee80211_handle_wake_tx_queue, + .set_key = wl1251_op_set_key, + .hw_scan = wl1251_op_hw_scan, + .bss_info_changed = wl1251_op_bss_info_changed, +--- a/drivers/net/wireless/ti/wlcore/main.c ++++ b/drivers/net/wireless/ti/wlcore/main.c +@@ -5942,6 +5942,7 @@ static const struct ieee80211_ops wl1271 + .prepare_multicast = wl1271_op_prepare_multicast, + .configure_filter = wl1271_op_configure_filter, + .tx = wl1271_op_tx, ++ .wake_tx_queue = ieee80211_handle_wake_tx_queue, + .set_key = wlcore_op_set_key, + .hw_scan = wl1271_op_hw_scan, + .cancel_hw_scan = wl1271_op_cancel_hw_scan, +--- a/drivers/net/wireless/zydas/zd1211rw/zd_mac.c ++++ b/drivers/net/wireless/zydas/zd1211rw/zd_mac.c +@@ -1344,6 +1344,7 @@ static u64 zd_op_get_tsf(struct ieee8021 + + static const struct ieee80211_ops zd_ops = { + .tx = zd_op_tx, ++ .wake_tx_queue = ieee80211_handle_wake_tx_queue, + .start = zd_op_start, + .stop = zd_op_stop, + .add_interface = zd_op_add_interface, diff --git a/package/kernel/mac80211/patches/subsys/306-03-v6.2-wifi-mac80211-Drop-support-for-TX-push-path.patch b/package/kernel/mac80211/patches/subsys/306-03-v6.2-wifi-mac80211-Drop-support-for-TX-push-path.patch new file mode 100644 index 000000000..f9f9977ce --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/306-03-v6.2-wifi-mac80211-Drop-support-for-TX-push-path.patch @@ -0,0 +1,683 @@ +From: Alexander Wetzel +Date: Sun, 9 Oct 2022 18:30:40 +0200 +Subject: [PATCH] wifi: mac80211: Drop support for TX push path + +All drivers are now using mac80211 internal queues (iTXQs). +Drop mac80211 internal support for the old push path. + +Signed-off-by: Alexander Wetzel +Signed-off-by: Johannes Berg +--- + +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -4346,9 +4346,6 @@ static int ieee80211_get_txq_stats(struc + struct ieee80211_sub_if_data *sdata; + int ret = 0; + +- if (!local->ops->wake_tx_queue) +- return 1; +- + spin_lock_bh(&local->fq.lock); + rcu_read_lock(); + +--- a/net/mac80211/debugfs.c ++++ b/net/mac80211/debugfs.c +@@ -663,9 +663,7 @@ void debugfs_hw_add(struct ieee80211_loc + DEBUGFS_ADD_MODE(force_tx_status, 0600); + DEBUGFS_ADD_MODE(aql_enable, 0600); + DEBUGFS_ADD(aql_pending); +- +- if (local->ops->wake_tx_queue) +- DEBUGFS_ADD_MODE(aqm, 0600); ++ DEBUGFS_ADD_MODE(aqm, 0600); + + DEBUGFS_ADD_MODE(airtime_flags, 0600); + +--- a/net/mac80211/debugfs_netdev.c ++++ b/net/mac80211/debugfs_netdev.c +@@ -677,8 +677,7 @@ static void add_common_files(struct ieee + DEBUGFS_ADD(rc_rateidx_vht_mcs_mask_5ghz); + DEBUGFS_ADD(hw_queues); + +- if (sdata->local->ops->wake_tx_queue && +- sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE && ++ if (sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE && + sdata->vif.type != NL80211_IFTYPE_NAN) + DEBUGFS_ADD(aqm); + } +--- a/net/mac80211/debugfs_sta.c ++++ b/net/mac80211/debugfs_sta.c +@@ -1057,10 +1057,8 @@ void ieee80211_sta_debugfs_add(struct st + DEBUGFS_ADD_COUNTER(rx_fragments, deflink.rx_stats.fragments); + DEBUGFS_ADD_COUNTER(tx_filtered, deflink.status_stats.filtered); + +- if (local->ops->wake_tx_queue) { +- DEBUGFS_ADD(aqm); +- DEBUGFS_ADD(airtime); +- } ++ DEBUGFS_ADD(aqm); ++ DEBUGFS_ADD(airtime); + + if (wiphy_ext_feature_isset(local->hw.wiphy, + NL80211_EXT_FEATURE_AQL)) +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -2294,7 +2294,6 @@ void ieee80211_wake_queue_by_reason(stru + void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue, + enum queue_stop_reason reason, + bool refcounted); +-void ieee80211_propagate_queue_wake(struct ieee80211_local *local, int queue); + void ieee80211_add_pending_skb(struct ieee80211_local *local, + struct sk_buff *skb); + void ieee80211_add_pending_skbs(struct ieee80211_local *local, +--- a/net/mac80211/iface.c ++++ b/net/mac80211/iface.c +@@ -460,12 +460,6 @@ static void ieee80211_do_stop(struct iee + if (cancel_scan) + ieee80211_scan_cancel(local); + +- /* +- * Stop TX on this interface first. +- */ +- if (!local->ops->wake_tx_queue && sdata->dev) +- netif_tx_stop_all_queues(sdata->dev); +- + ieee80211_roc_purge(local, sdata); + + switch (sdata->vif.type) { +@@ -813,13 +807,6 @@ static void ieee80211_uninit(struct net_ + ieee80211_teardown_sdata(IEEE80211_DEV_TO_SUB_IF(dev)); + } + +-static u16 ieee80211_netdev_select_queue(struct net_device *dev, +- struct sk_buff *skb, +- struct net_device *sb_dev) +-{ +- return ieee80211_select_queue(IEEE80211_DEV_TO_SUB_IF(dev), skb); +-} +- + static void + ieee80211_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) + { +@@ -833,7 +820,6 @@ static const struct net_device_ops ieee8 + .ndo_start_xmit = ieee80211_subif_start_xmit, + .ndo_set_rx_mode = ieee80211_set_multicast_list, + .ndo_set_mac_address = ieee80211_change_mac, +- .ndo_select_queue = ieee80211_netdev_select_queue, + .ndo_get_stats64 = ieee80211_get_stats64, + }; + +@@ -941,7 +927,6 @@ static const struct net_device_ops ieee8 + .ndo_start_xmit = ieee80211_subif_start_xmit_8023, + .ndo_set_rx_mode = ieee80211_set_multicast_list, + .ndo_set_mac_address = ieee80211_change_mac, +- .ndo_select_queue = ieee80211_netdev_select_queue, + .ndo_get_stats64 = ieee80211_get_stats64, + .ndo_fill_forward_path = ieee80211_netdev_fill_forward_path, + }; +@@ -1443,35 +1428,6 @@ int ieee80211_do_open(struct wireless_de + + ieee80211_recalc_ps(local); + +- if (sdata->vif.type == NL80211_IFTYPE_MONITOR || +- sdata->vif.type == NL80211_IFTYPE_AP_VLAN || +- local->ops->wake_tx_queue) { +- /* XXX: for AP_VLAN, actually track AP queues */ +- if (dev) +- netif_tx_start_all_queues(dev); +- } else if (dev) { +- unsigned long flags; +- int n_acs = IEEE80211_NUM_ACS; +- int ac; +- +- if (local->hw.queues < IEEE80211_NUM_ACS) +- n_acs = 1; +- +- spin_lock_irqsave(&local->queue_stop_reason_lock, flags); +- if (sdata->vif.cab_queue == IEEE80211_INVAL_HW_QUEUE || +- (local->queue_stop_reasons[sdata->vif.cab_queue] == 0 && +- skb_queue_empty(&local->pending[sdata->vif.cab_queue]))) { +- for (ac = 0; ac < n_acs; ac++) { +- int ac_queue = sdata->vif.hw_queue[ac]; +- +- if (local->queue_stop_reasons[ac_queue] == 0 && +- skb_queue_empty(&local->pending[ac_queue])) +- netif_start_subqueue(dev, ac); +- } +- } +- spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); +- } +- + set_bit(SDATA_STATE_RUNNING, &sdata->state); + + return 0; +@@ -1501,17 +1457,12 @@ static void ieee80211_if_setup(struct ne + { + ether_setup(dev); + dev->priv_flags &= ~IFF_TX_SKB_SHARING; ++ dev->priv_flags |= IFF_NO_QUEUE; + dev->netdev_ops = &ieee80211_dataif_ops; + dev->needs_free_netdev = true; + dev->priv_destructor = ieee80211_if_free; + } + +-static void ieee80211_if_setup_no_queue(struct net_device *dev) +-{ +- ieee80211_if_setup(dev); +- dev->priv_flags |= IFF_NO_QUEUE; +-} +- + static void ieee80211_iface_process_skb(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata, + struct sk_buff *skb) +@@ -2096,9 +2047,7 @@ int ieee80211_if_add(struct ieee80211_lo + struct net_device *ndev = NULL; + struct ieee80211_sub_if_data *sdata = NULL; + struct txq_info *txqi; +- void (*if_setup)(struct net_device *dev); + int ret, i; +- int txqs = 1; + + ASSERT_RTNL(); + +@@ -2121,30 +2070,18 @@ int ieee80211_if_add(struct ieee80211_lo + sizeof(void *)); + int txq_size = 0; + +- if (local->ops->wake_tx_queue && +- type != NL80211_IFTYPE_AP_VLAN && ++ if (type != NL80211_IFTYPE_AP_VLAN && + (type != NL80211_IFTYPE_MONITOR || + (params->flags & MONITOR_FLAG_ACTIVE))) + txq_size += sizeof(struct txq_info) + + local->hw.txq_data_size; + +- if (local->ops->wake_tx_queue) { +- if_setup = ieee80211_if_setup_no_queue; +- } else { +- if_setup = ieee80211_if_setup; +- if (local->hw.queues >= IEEE80211_NUM_ACS) +- txqs = IEEE80211_NUM_ACS; +- } +- + ndev = alloc_netdev_mqs(size + txq_size, + name, name_assign_type, +- if_setup, txqs, 1); ++ ieee80211_if_setup, 1, 1); + if (!ndev) + return -ENOMEM; + +- if (!local->ops->wake_tx_queue && local->hw.wiphy->tx_queue_len) +- ndev->tx_queue_len = local->hw.wiphy->tx_queue_len; +- + dev_net_set(ndev, wiphy_net(local->hw.wiphy)); + + ndev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); +--- a/net/mac80211/main.c ++++ b/net/mac80211/main.c +@@ -630,7 +630,7 @@ struct ieee80211_hw *ieee80211_alloc_hw_ + + if (WARN_ON(!ops->tx || !ops->start || !ops->stop || !ops->config || + !ops->add_interface || !ops->remove_interface || +- !ops->configure_filter)) ++ !ops->configure_filter || !ops->wake_tx_queue)) + return NULL; + + if (WARN_ON(ops->sta_state && (ops->sta_add || ops->sta_remove))) +@@ -719,9 +719,7 @@ struct ieee80211_hw *ieee80211_alloc_hw_ + if (!ops->set_key) + wiphy->flags |= WIPHY_FLAG_IBSS_RSN; + +- if (ops->wake_tx_queue) +- wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_TXQS); +- ++ wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_TXQS); + wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_RRM); + + wiphy->bss_priv_size = sizeof(struct ieee80211_bss); +@@ -834,10 +832,7 @@ struct ieee80211_hw *ieee80211_alloc_hw_ + atomic_set(&local->agg_queue_stop[i], 0); + } + tasklet_setup(&local->tx_pending_tasklet, ieee80211_tx_pending); +- +- if (ops->wake_tx_queue) +- tasklet_setup(&local->wake_txqs_tasklet, ieee80211_wake_txqs); +- ++ tasklet_setup(&local->wake_txqs_tasklet, ieee80211_wake_txqs); + tasklet_setup(&local->tasklet, ieee80211_tasklet_handler); + + skb_queue_head_init(&local->skb_queue); +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -1571,9 +1571,6 @@ static void sta_ps_start(struct sta_info + + ieee80211_clear_fast_xmit(sta); + +- if (!sta->sta.txq[0]) +- return; +- + for (tid = 0; tid < IEEE80211_NUM_TIDS; tid++) { + struct ieee80211_txq *txq = sta->sta.txq[tid]; + struct txq_info *txqi = to_txq_info(txq); +--- a/net/mac80211/sta_info.c ++++ b/net/mac80211/sta_info.c +@@ -140,17 +140,15 @@ static void __cleanup_single_sta(struct + atomic_dec(&ps->num_sta_ps); + } + +- if (sta->sta.txq[0]) { +- for (i = 0; i < ARRAY_SIZE(sta->sta.txq); i++) { +- struct txq_info *txqi; ++ for (i = 0; i < ARRAY_SIZE(sta->sta.txq); i++) { ++ struct txq_info *txqi; + +- if (!sta->sta.txq[i]) +- continue; ++ if (!sta->sta.txq[i]) ++ continue; + +- txqi = to_txq_info(sta->sta.txq[i]); ++ txqi = to_txq_info(sta->sta.txq[i]); + +- ieee80211_txq_purge(local, txqi); +- } ++ ieee80211_txq_purge(local, txqi); + } + + for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { +@@ -425,8 +423,7 @@ void sta_info_free(struct ieee80211_loca + + sta_dbg(sta->sdata, "Destroyed STA %pM\n", sta->sta.addr); + +- if (sta->sta.txq[0]) +- kfree(to_txq_info(sta->sta.txq[0])); ++ kfree(to_txq_info(sta->sta.txq[0])); + kfree(rcu_dereference_raw(sta->sta.rates)); + #ifdef CPTCFG_MAC80211_MESH + kfree(sta->mesh); +@@ -527,6 +524,8 @@ __sta_info_alloc(struct ieee80211_sub_if + struct ieee80211_local *local = sdata->local; + struct ieee80211_hw *hw = &local->hw; + struct sta_info *sta; ++ void *txq_data; ++ int size; + int i; + + sta = kzalloc(sizeof(*sta) + hw->sta_data_size, gfp); +@@ -597,21 +596,18 @@ __sta_info_alloc(struct ieee80211_sub_if + + sta->last_connected = ktime_get_seconds(); + +- if (local->ops->wake_tx_queue) { +- void *txq_data; +- int size = sizeof(struct txq_info) + +- ALIGN(hw->txq_data_size, sizeof(void *)); ++ size = sizeof(struct txq_info) + ++ ALIGN(hw->txq_data_size, sizeof(void *)); + +- txq_data = kcalloc(ARRAY_SIZE(sta->sta.txq), size, gfp); +- if (!txq_data) +- goto free; ++ txq_data = kcalloc(ARRAY_SIZE(sta->sta.txq), size, gfp); ++ if (!txq_data) ++ goto free; + +- for (i = 0; i < ARRAY_SIZE(sta->sta.txq); i++) { +- struct txq_info *txq = txq_data + i * size; ++ for (i = 0; i < ARRAY_SIZE(sta->sta.txq); i++) { ++ struct txq_info *txq = txq_data + i * size; + +- /* might not do anything for the bufferable MMPDU TXQ */ +- ieee80211_txq_init(sdata, sta, txq, i); +- } ++ /* might not do anything for the (bufferable) MMPDU TXQ */ ++ ieee80211_txq_init(sdata, sta, txq, i); + } + + if (sta_prepare_rate_control(local, sta, gfp)) +@@ -685,8 +681,7 @@ __sta_info_alloc(struct ieee80211_sub_if + return sta; + + free_txq: +- if (sta->sta.txq[0]) +- kfree(to_txq_info(sta->sta.txq[0])); ++ kfree(to_txq_info(sta->sta.txq[0])); + free: + sta_info_free_link(&sta->deflink); + #ifdef CPTCFG_MAC80211_MESH +@@ -1960,9 +1955,6 @@ ieee80211_sta_ps_deliver_response(struct + * TIM recalculation. + */ + +- if (!sta->sta.txq[0]) +- return; +- + for (tid = 0; tid < ARRAY_SIZE(sta->sta.txq); tid++) { + if (!sta->sta.txq[tid] || + !(driver_release_tids & BIT(tid)) || +@@ -2447,7 +2439,7 @@ static void sta_set_tidstats(struct sta_ + tidstats->tx_msdu_failed = sta->deflink.status_stats.msdu_failed[tid]; + } + +- if (local->ops->wake_tx_queue && tid < IEEE80211_NUM_TIDS) { ++ if (tid < IEEE80211_NUM_TIDS) { + spin_lock_bh(&local->fq.lock); + rcu_read_lock(); + +@@ -2775,9 +2767,6 @@ unsigned long ieee80211_sta_last_active( + + static void sta_update_codel_params(struct sta_info *sta, u32 thr) + { +- if (!sta->sdata->local->ops->wake_tx_queue) +- return; +- + if (thr && thr < STA_SLOW_THRESHOLD * sta->local->num_sta) { + sta->cparams.target = MS2TIME(50); + sta->cparams.interval = MS2TIME(300); +--- a/net/mac80211/tdls.c ++++ b/net/mac80211/tdls.c +@@ -1016,7 +1016,6 @@ ieee80211_tdls_prep_mgmt_packet(struct w + skb->priority = 256 + 5; + break; + } +- skb_set_queue_mapping(skb, ieee80211_select_queue(sdata, skb)); + + /* + * Set the WLAN_TDLS_TEARDOWN flag to indicate a teardown in progress. +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -1600,9 +1600,6 @@ int ieee80211_txq_setup_flows(struct iee + bool supp_vht = false; + enum nl80211_band band; + +- if (!local->ops->wake_tx_queue) +- return 0; +- + ret = fq_init(fq, 4096); + if (ret) + return ret; +@@ -1650,9 +1647,6 @@ void ieee80211_txq_teardown_flows(struct + { + struct fq *fq = &local->fq; + +- if (!local->ops->wake_tx_queue) +- return; +- + kfree(local->cvars); + local->cvars = NULL; + +@@ -1669,8 +1663,7 @@ static bool ieee80211_queue_skb(struct i + struct ieee80211_vif *vif; + struct txq_info *txqi; + +- if (!local->ops->wake_tx_queue || +- sdata->vif.type == NL80211_IFTYPE_MONITOR) ++ if (sdata->vif.type == NL80211_IFTYPE_MONITOR) + return false; + + if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) +@@ -4193,12 +4186,7 @@ void __ieee80211_subif_start_xmit(struct + if (IS_ERR(sta)) + sta = NULL; + +- if (local->ops->wake_tx_queue) { +- u16 queue = __ieee80211_select_queue(sdata, sta, skb); +- skb_set_queue_mapping(skb, queue); +- skb_get_hash(skb); +- } +- ++ skb_set_queue_mapping(skb, ieee80211_select_queue(sdata, sta, skb)); + ieee80211_aggr_check(sdata, sta, skb); + + sk_pacing_shift_update(skb->sk, sdata->local->hw.tx_sk_pacing_shift); +@@ -4509,11 +4497,7 @@ static void ieee80211_8023_xmit(struct i + struct tid_ampdu_tx *tid_tx; + u8 tid; + +- if (local->ops->wake_tx_queue) { +- u16 queue = __ieee80211_select_queue(sdata, sta, skb); +- skb_set_queue_mapping(skb, queue); +- skb_get_hash(skb); +- } ++ skb_set_queue_mapping(skb, ieee80211_select_queue(sdata, sta, skb)); + + if (unlikely(test_bit(SCAN_SW_SCANNING, &local->scanning)) && + test_bit(SDATA_STATE_OFFCHANNEL, &sdata->state)) +@@ -4767,9 +4751,6 @@ void ieee80211_tx_pending(struct tasklet + if (!txok) + break; + } +- +- if (skb_queue_empty(&local->pending[i])) +- ieee80211_propagate_queue_wake(local, i); + } + spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); + +@@ -5962,10 +5943,9 @@ int ieee80211_tx_control_port(struct wip + } + + if (!IS_ERR(sta)) { +- u16 queue = __ieee80211_select_queue(sdata, sta, skb); ++ u16 queue = ieee80211_select_queue(sdata, sta, skb); + + skb_set_queue_mapping(skb, queue); +- skb_get_hash(skb); + + /* + * for MLO STA, the SA should be the AP MLD address, but +--- a/net/mac80211/util.c ++++ b/net/mac80211/util.c +@@ -444,39 +444,6 @@ void ieee80211_wake_txqs(struct tasklet_ + spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); + } + +-void ieee80211_propagate_queue_wake(struct ieee80211_local *local, int queue) +-{ +- struct ieee80211_sub_if_data *sdata; +- int n_acs = IEEE80211_NUM_ACS; +- +- if (local->ops->wake_tx_queue) +- return; +- +- if (local->hw.queues < IEEE80211_NUM_ACS) +- n_acs = 1; +- +- list_for_each_entry_rcu(sdata, &local->interfaces, list) { +- int ac; +- +- if (!sdata->dev) +- continue; +- +- if (sdata->vif.cab_queue != IEEE80211_INVAL_HW_QUEUE && +- local->queue_stop_reasons[sdata->vif.cab_queue] != 0) +- continue; +- +- for (ac = 0; ac < n_acs; ac++) { +- int ac_queue = sdata->vif.hw_queue[ac]; +- +- if (ac_queue == queue || +- (sdata->vif.cab_queue == queue && +- local->queue_stop_reasons[ac_queue] == 0 && +- skb_queue_empty(&local->pending[ac_queue]))) +- netif_wake_subqueue(sdata->dev, ac); +- } +- } +-} +- + static void __ieee80211_wake_queue(struct ieee80211_hw *hw, int queue, + enum queue_stop_reason reason, + bool refcounted, +@@ -507,11 +474,7 @@ static void __ieee80211_wake_queue(struc + /* someone still has this queue stopped */ + return; + +- if (skb_queue_empty(&local->pending[queue])) { +- rcu_read_lock(); +- ieee80211_propagate_queue_wake(local, queue); +- rcu_read_unlock(); +- } else ++ if (!skb_queue_empty(&local->pending[queue])) + tasklet_schedule(&local->tx_pending_tasklet); + + /* +@@ -521,12 +484,10 @@ static void __ieee80211_wake_queue(struc + * release someone's lock, but it is fine because all the callers of + * __ieee80211_wake_queue call it right before releasing the lock. + */ +- if (local->ops->wake_tx_queue) { +- if (reason == IEEE80211_QUEUE_STOP_REASON_DRIVER) +- tasklet_schedule(&local->wake_txqs_tasklet); +- else +- _ieee80211_wake_txqs(local, flags); +- } ++ if (reason == IEEE80211_QUEUE_STOP_REASON_DRIVER) ++ tasklet_schedule(&local->wake_txqs_tasklet); ++ else ++ _ieee80211_wake_txqs(local, flags); + } + + void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue, +@@ -554,8 +515,6 @@ static void __ieee80211_stop_queue(struc + bool refcounted) + { + struct ieee80211_local *local = hw_to_local(hw); +- struct ieee80211_sub_if_data *sdata; +- int n_acs = IEEE80211_NUM_ACS; + + trace_stop_queue(local, queue, reason); + +@@ -567,27 +526,7 @@ static void __ieee80211_stop_queue(struc + else + local->q_stop_reasons[queue][reason]++; + +- if (__test_and_set_bit(reason, &local->queue_stop_reasons[queue])) +- return; +- +- if (local->hw.queues < IEEE80211_NUM_ACS) +- n_acs = 1; +- +- rcu_read_lock(); +- list_for_each_entry_rcu(sdata, &local->interfaces, list) { +- int ac; +- +- if (!sdata->dev) +- continue; +- +- for (ac = 0; ac < n_acs; ac++) { +- if (!local->ops->wake_tx_queue && +- (sdata->vif.hw_queue[ac] == queue || +- sdata->vif.cab_queue == queue)) +- netif_stop_subqueue(sdata->dev, ac); +- } +- } +- rcu_read_unlock(); ++ set_bit(reason, &local->queue_stop_reasons[queue]); + } + + void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue, +--- a/net/mac80211/wme.c ++++ b/net/mac80211/wme.c +@@ -122,6 +122,9 @@ u16 ieee80211_select_queue_80211(struct + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + u8 *p; + ++ /* Ensure hash is set prior to potential SW encryption */ ++ skb_get_hash(skb); ++ + if ((info->control.flags & IEEE80211_TX_CTRL_DONT_REORDER) || + local->hw.queues < IEEE80211_NUM_ACS) + return 0; +@@ -141,13 +144,16 @@ u16 ieee80211_select_queue_80211(struct + return ieee80211_downgrade_queue(sdata, NULL, skb); + } + +-u16 __ieee80211_select_queue(struct ieee80211_sub_if_data *sdata, +- struct sta_info *sta, struct sk_buff *skb) ++u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata, ++ struct sta_info *sta, struct sk_buff *skb) + { + const struct ethhdr *eth = (void *)skb->data; + struct mac80211_qos_map *qos_map; + bool qos; + ++ /* Ensure hash is set prior to potential SW encryption */ ++ skb_get_hash(skb); ++ + /* all mesh/ocb stations are required to support WME */ + if ((sdata->vif.type == NL80211_IFTYPE_MESH_POINT && + !is_multicast_ether_addr(eth->h_dest)) || +@@ -178,59 +184,6 @@ u16 __ieee80211_select_queue(struct ieee + return ieee80211_downgrade_queue(sdata, sta, skb); + } + +- +-/* Indicate which queue to use. */ +-u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata, +- struct sk_buff *skb) +-{ +- struct ieee80211_local *local = sdata->local; +- struct sta_info *sta = NULL; +- const u8 *ra = NULL; +- u16 ret; +- +- /* when using iTXQ, we can do this later */ +- if (local->ops->wake_tx_queue) +- return 0; +- +- if (local->hw.queues < IEEE80211_NUM_ACS || skb->len < 6) { +- skb->priority = 0; /* required for correct WPA/11i MIC */ +- return 0; +- } +- +- rcu_read_lock(); +- switch (sdata->vif.type) { +- case NL80211_IFTYPE_AP_VLAN: +- sta = rcu_dereference(sdata->u.vlan.sta); +- if (sta) +- break; +- fallthrough; +- case NL80211_IFTYPE_AP: +- ra = skb->data; +- break; +- case NL80211_IFTYPE_STATION: +- /* might be a TDLS station */ +- sta = sta_info_get(sdata, skb->data); +- if (sta) +- break; +- +- ra = sdata->deflink.u.mgd.bssid; +- break; +- case NL80211_IFTYPE_ADHOC: +- ra = skb->data; +- break; +- default: +- break; +- } +- +- if (!sta && ra && !is_multicast_ether_addr(ra)) +- sta = sta_info_get(sdata, ra); +- +- ret = __ieee80211_select_queue(sdata, sta, skb); +- +- rcu_read_unlock(); +- return ret; +-} +- + /** + * ieee80211_set_qos_hdr - Fill in the QoS header if there is one. + * +--- a/net/mac80211/wme.h ++++ b/net/mac80211/wme.h +@@ -13,10 +13,8 @@ + u16 ieee80211_select_queue_80211(struct ieee80211_sub_if_data *sdata, + struct sk_buff *skb, + struct ieee80211_hdr *hdr); +-u16 __ieee80211_select_queue(struct ieee80211_sub_if_data *sdata, +- struct sta_info *sta, struct sk_buff *skb); + u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata, +- struct sk_buff *skb); ++ struct sta_info *sta, struct sk_buff *skb); + void ieee80211_set_qos_hdr(struct ieee80211_sub_if_data *sdata, + struct sk_buff *skb); + diff --git a/package/kernel/mac80211/patches/subsys/306-04-v6.2-wifi-realtek-remove-duplicated-wake_tx_queue.patch b/package/kernel/mac80211/patches/subsys/306-04-v6.2-wifi-realtek-remove-duplicated-wake_tx_queue.patch new file mode 100644 index 000000000..f0dfc75a7 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/306-04-v6.2-wifi-realtek-remove-duplicated-wake_tx_queue.patch @@ -0,0 +1,32 @@ +From: Johannes Berg +Date: Mon, 10 Oct 2022 19:17:46 +0200 +Subject: [PATCH] wifi: realtek: remove duplicated wake_tx_queue + +By accident, the previous patch duplicated the initialization +of the wake_tx_queue callback. Fix that by removing the new +initializations. + +Fixes: a790cc3a4fad ("wifi: mac80211: add wake_tx_queue callback to drivers") +Signed-off-by: Johannes Berg +--- + +--- a/drivers/net/wireless/realtek/rtw88/mac80211.c ++++ b/drivers/net/wireless/realtek/rtw88/mac80211.c +@@ -896,7 +896,6 @@ static void rtw_ops_sta_rc_update(struct + + const struct ieee80211_ops rtw_ops = { + .tx = rtw_ops_tx, +- .wake_tx_queue = ieee80211_handle_wake_tx_queue, + .wake_tx_queue = rtw_ops_wake_tx_queue, + .start = rtw_ops_start, + .stop = rtw_ops_stop, +--- a/drivers/net/wireless/realtek/rtw89/mac80211.c ++++ b/drivers/net/wireless/realtek/rtw89/mac80211.c +@@ -918,7 +918,6 @@ static int rtw89_ops_set_tid_config(stru + + const struct ieee80211_ops rtw89_ops = { + .tx = rtw89_ops_tx, +- .wake_tx_queue = ieee80211_handle_wake_tx_queue, + .wake_tx_queue = rtw89_ops_wake_tx_queue, + .start = rtw89_ops_start, + .stop = rtw89_ops_stop, diff --git a/package/kernel/mac80211/patches/subsys/306-wifi-mac80211-clear-vif-drv_priv-after-calling-remov.patch b/package/kernel/mac80211/patches/subsys/306-wifi-mac80211-clear-vif-drv_priv-after-calling-remov.patch deleted file mode 100644 index b0119988d..000000000 --- a/package/kernel/mac80211/patches/subsys/306-wifi-mac80211-clear-vif-drv_priv-after-calling-remov.patch +++ /dev/null @@ -1,29 +0,0 @@ -From: Felix Fietkau -Date: Wed, 3 Jul 2024 12:10:01 +0200 -Subject: [PATCH] wifi: mac80211: clear vif drv_priv after calling - remove_interface - -Avoid reusing stale driver data when an interface is brought down and up -again. In order to avoid having to duplicate the memset in every single -driver, do it here. - -Signed-off-by: Felix Fietkau ---- - ---- a/net/mac80211/iface.c -+++ b/net/mac80211/iface.c -@@ -693,8 +693,12 @@ static void ieee80211_do_stop(struct iee - - fallthrough; - default: -- if (going_down) -- drv_remove_interface(local, sdata); -+ if (!going_down) -+ break; -+ drv_remove_interface(local, sdata); -+ -+ /* Clear private driver data to prevent reuse */ -+ memset(sdata->vif.drv_priv, 0, local->hw.vif_data_size); - } - - ieee80211_recalc_ps(local); diff --git a/package/kernel/mac80211/patches/subsys/310-v6.2-mac80211-add-support-for-restricting-netdev-features.patch b/package/kernel/mac80211/patches/subsys/310-v6.2-mac80211-add-support-for-restricting-netdev-features.patch new file mode 100644 index 000000000..812b12189 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/310-v6.2-mac80211-add-support-for-restricting-netdev-features.patch @@ -0,0 +1,506 @@ +From: Felix Fietkau +Date: Sun, 9 Oct 2022 20:15:46 +0200 +Subject: [PATCH] mac80211: add support for restricting netdev features per vif + +This can be used to selectively disable feature flags for checksum offload, +scatter/gather or GSO by changing vif->netdev_features. +Removing features from vif->netdev_features does not affect the netdev +features themselves, but instead fixes up skbs in the tx path so that the +offloads are not needed in the driver. + +Aside from making it easier to deal with vif type based hardware limitations, +this also makes it possible to optimize performance on hardware without native +GSO support by declaring GSO support in hw->netdev_features and removing it +from vif->netdev_features. This allows mac80211 to handle GSO segmentation +after the sta lookup, but before itxq enqueue, thus reducing the number of +unnecessary sta lookups, as well as some other per-packet processing. + +Signed-off-by: Felix Fietkau +--- + +--- a/include/net/fq_impl.h ++++ b/include/net/fq_impl.h +@@ -200,6 +200,7 @@ static void fq_tin_enqueue(struct fq *fq + fq_skb_free_t free_func) + { + struct fq_flow *flow; ++ struct sk_buff *next; + bool oom; + + lockdep_assert_held(&fq->lock); +@@ -214,11 +215,15 @@ static void fq_tin_enqueue(struct fq *fq + } + + flow->tin = tin; +- flow->backlog += skb->len; +- tin->backlog_bytes += skb->len; +- tin->backlog_packets++; +- fq->memory_usage += skb->truesize; +- fq->backlog++; ++ skb_list_walk_safe(skb, skb, next) { ++ skb_mark_not_on_list(skb); ++ flow->backlog += skb->len; ++ tin->backlog_bytes += skb->len; ++ tin->backlog_packets++; ++ fq->memory_usage += skb->truesize; ++ fq->backlog++; ++ __skb_queue_tail(&flow->queue, skb); ++ } + + if (list_empty(&flow->flowchain)) { + flow->deficit = fq->quantum; +@@ -226,7 +231,6 @@ static void fq_tin_enqueue(struct fq *fq + &tin->new_flows); + } + +- __skb_queue_tail(&flow->queue, skb); + oom = (fq->memory_usage > fq->memory_limit); + while (fq->backlog > fq->limit || oom) { + flow = fq_find_fattest_flow(fq); +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -1807,6 +1807,10 @@ struct ieee80211_vif_cfg { + * @addr: address of this interface + * @p2p: indicates whether this AP or STA interface is a p2p + * interface, i.e. a GO or p2p-sta respectively ++ * @netdev_features: tx netdev features supported by the hardware for this ++ * vif. mac80211 initializes this to hw->netdev_features, and the driver ++ * can mask out specific tx features. mac80211 will handle software fixup ++ * for masked offloads (GSO, CSUM) + * @driver_flags: flags/capabilities the driver has for this interface, + * these need to be set (or cleared) when the interface is added + * or, if supported by the driver, the interface type is changed +@@ -1846,6 +1850,7 @@ struct ieee80211_vif { + + struct ieee80211_txq *txq; + ++ netdev_features_t netdev_features; + u32 driver_flags; + u32 offload_flags; + +--- a/net/mac80211/iface.c ++++ b/net/mac80211/iface.c +@@ -2181,6 +2181,7 @@ int ieee80211_if_add(struct ieee80211_lo + ndev->priv_flags |= IFF_LIVE_ADDR_CHANGE; + ndev->hw_features |= ndev->features & + MAC80211_SUPPORTED_FEATURES_TX; ++ sdata->vif.netdev_features = local->hw.netdev_features; + + netdev_set_default_ethtool_ops(ndev, &ieee80211_ethtool_ops); + +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -1356,7 +1356,11 @@ static struct txq_info *ieee80211_get_tx + + static void ieee80211_set_skb_enqueue_time(struct sk_buff *skb) + { +- IEEE80211_SKB_CB(skb)->control.enqueue_time = codel_get_time(); ++ struct sk_buff *next; ++ codel_time_t now = codel_get_time(); ++ ++ skb_list_walk_safe(skb, skb, next) ++ IEEE80211_SKB_CB(skb)->control.enqueue_time = now; + } + + static u32 codel_skb_len_func(const struct sk_buff *skb) +@@ -3579,55 +3583,79 @@ ieee80211_xmit_fast_finish(struct ieee80 + return TX_CONTINUE; + } + +-static bool ieee80211_xmit_fast(struct ieee80211_sub_if_data *sdata, +- struct sta_info *sta, +- struct ieee80211_fast_tx *fast_tx, +- struct sk_buff *skb) ++static netdev_features_t ++ieee80211_sdata_netdev_features(struct ieee80211_sub_if_data *sdata) + { +- struct ieee80211_local *local = sdata->local; +- u16 ethertype = (skb->data[12] << 8) | skb->data[13]; +- int extra_head = fast_tx->hdr_len - (ETH_HLEN - 2); +- int hw_headroom = sdata->local->hw.extra_tx_headroom; +- struct ethhdr eth; +- struct ieee80211_tx_info *info; +- struct ieee80211_hdr *hdr = (void *)fast_tx->hdr; +- struct ieee80211_tx_data tx; +- ieee80211_tx_result r; +- struct tid_ampdu_tx *tid_tx = NULL; +- u8 tid = IEEE80211_NUM_TIDS; ++ if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN) ++ return sdata->vif.netdev_features; + +- /* control port protocol needs a lot of special handling */ +- if (cpu_to_be16(ethertype) == sdata->control_port_protocol) +- return false; ++ if (!sdata->bss) ++ return 0; + +- /* only RFC 1042 SNAP */ +- if (ethertype < ETH_P_802_3_MIN) +- return false; ++ sdata = container_of(sdata->bss, struct ieee80211_sub_if_data, u.ap); ++ return sdata->vif.netdev_features; ++} + +- /* don't handle TX status request here either */ +- if (skb->sk && skb_shinfo(skb)->tx_flags & SKBTX_WIFI_STATUS) +- return false; ++static struct sk_buff * ++ieee80211_tx_skb_fixup(struct sk_buff *skb, netdev_features_t features) ++{ ++ if (skb_is_gso(skb)) { ++ struct sk_buff *segs; + +- if (hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_QOS_DATA)) { +- tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK; +- tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[tid]); +- if (tid_tx) { +- if (!test_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state)) +- return false; +- if (tid_tx->timeout) +- tid_tx->last_tx = jiffies; +- } ++ segs = skb_gso_segment(skb, features); ++ if (!segs) ++ return skb; ++ if (IS_ERR(segs)) ++ goto free; ++ ++ consume_skb(skb); ++ return segs; + } + +- /* after this point (skb is modified) we cannot return false */ ++ if (skb_needs_linearize(skb, features) && __skb_linearize(skb)) ++ goto free; ++ ++ if (skb->ip_summed == CHECKSUM_PARTIAL) { ++ int ofs = skb_checksum_start_offset(skb); ++ ++ if (skb->encapsulation) ++ skb_set_inner_transport_header(skb, ofs); ++ else ++ skb_set_transport_header(skb, ofs); ++ ++ if (skb_csum_hwoffload_help(skb, features)) ++ goto free; ++ } ++ ++ skb_mark_not_on_list(skb); ++ return skb; ++ ++free: ++ kfree_skb(skb); ++ return NULL; ++} ++ ++static void __ieee80211_xmit_fast(struct ieee80211_sub_if_data *sdata, ++ struct sta_info *sta, ++ struct ieee80211_fast_tx *fast_tx, ++ struct sk_buff *skb, u8 tid, bool ampdu) ++{ ++ struct ieee80211_local *local = sdata->local; ++ struct ieee80211_hdr *hdr = (void *)fast_tx->hdr; ++ struct ieee80211_tx_info *info; ++ struct ieee80211_tx_data tx; ++ ieee80211_tx_result r; ++ int hw_headroom = sdata->local->hw.extra_tx_headroom; ++ int extra_head = fast_tx->hdr_len - (ETH_HLEN - 2); ++ struct ethhdr eth; + + skb = skb_share_check(skb, GFP_ATOMIC); + if (unlikely(!skb)) +- return true; ++ return; + + if ((hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_QOS_DATA)) && + ieee80211_amsdu_aggregate(sdata, sta, fast_tx, skb)) +- return true; ++ return; + + /* will not be crypto-handled beyond what we do here, so use false + * as the may-encrypt argument for the resize to not account for +@@ -3636,10 +3664,8 @@ static bool ieee80211_xmit_fast(struct i + if (unlikely(ieee80211_skb_resize(sdata, skb, + max_t(int, extra_head + hw_headroom - + skb_headroom(skb), 0), +- ENCRYPT_NO))) { +- kfree_skb(skb); +- return true; +- } ++ ENCRYPT_NO))) ++ goto free; + + memcpy(ð, skb->data, ETH_HLEN - 2); + hdr = skb_push(skb, extra_head); +@@ -3653,7 +3679,7 @@ static bool ieee80211_xmit_fast(struct i + info->control.vif = &sdata->vif; + info->flags = IEEE80211_TX_CTL_FIRST_FRAGMENT | + IEEE80211_TX_CTL_DONTFRAG | +- (tid_tx ? IEEE80211_TX_CTL_AMPDU : 0); ++ (ampdu ? IEEE80211_TX_CTL_AMPDU : 0); + info->control.flags = IEEE80211_TX_CTRL_FAST_XMIT | + u32_encode_bits(IEEE80211_LINK_UNSPECIFIED, + IEEE80211_TX_CTRL_MLO_LINK); +@@ -3677,16 +3703,14 @@ static bool ieee80211_xmit_fast(struct i + tx.key = fast_tx->key; + + if (ieee80211_queue_skb(local, sdata, sta, skb)) +- return true; ++ return; + + tx.skb = skb; + r = ieee80211_xmit_fast_finish(sdata, sta, fast_tx->pn_offs, + fast_tx->key, &tx); + tx.skb = NULL; +- if (r == TX_DROP) { +- kfree_skb(skb); +- return true; +- } ++ if (r == TX_DROP) ++ goto free; + + if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) + sdata = container_of(sdata->bss, +@@ -3694,6 +3718,56 @@ static bool ieee80211_xmit_fast(struct i + + __skb_queue_tail(&tx.skbs, skb); + ieee80211_tx_frags(local, &sdata->vif, sta, &tx.skbs, false); ++ return; ++ ++free: ++ kfree_skb(skb); ++} ++ ++static bool ieee80211_xmit_fast(struct ieee80211_sub_if_data *sdata, ++ struct sta_info *sta, ++ struct ieee80211_fast_tx *fast_tx, ++ struct sk_buff *skb) ++{ ++ u16 ethertype = (skb->data[12] << 8) | skb->data[13]; ++ struct ieee80211_hdr *hdr = (void *)fast_tx->hdr; ++ struct tid_ampdu_tx *tid_tx = NULL; ++ struct sk_buff *next; ++ u8 tid = IEEE80211_NUM_TIDS; ++ ++ /* control port protocol needs a lot of special handling */ ++ if (cpu_to_be16(ethertype) == sdata->control_port_protocol) ++ return false; ++ ++ /* only RFC 1042 SNAP */ ++ if (ethertype < ETH_P_802_3_MIN) ++ return false; ++ ++ /* don't handle TX status request here either */ ++ if (skb->sk && skb_shinfo(skb)->tx_flags & SKBTX_WIFI_STATUS) ++ return false; ++ ++ if (hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_QOS_DATA)) { ++ tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK; ++ tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[tid]); ++ if (tid_tx) { ++ if (!test_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state)) ++ return false; ++ if (tid_tx->timeout) ++ tid_tx->last_tx = jiffies; ++ } ++ } ++ ++ /* after this point (skb is modified) we cannot return false */ ++ skb = ieee80211_tx_skb_fixup(skb, ieee80211_sdata_netdev_features(sdata)); ++ if (!skb) ++ return true; ++ ++ skb_list_walk_safe(skb, skb, next) { ++ skb_mark_not_on_list(skb); ++ __ieee80211_xmit_fast(sdata, sta, fast_tx, skb, tid, tid_tx); ++ } ++ + return true; + } + +@@ -4201,31 +4275,14 @@ void __ieee80211_subif_start_xmit(struct + goto out; + } + +- if (skb_is_gso(skb)) { +- struct sk_buff *segs; +- +- segs = skb_gso_segment(skb, 0); +- if (IS_ERR(segs)) { +- goto out_free; +- } else if (segs) { +- consume_skb(skb); +- skb = segs; +- } +- } else { +- /* we cannot process non-linear frames on this path */ +- if (skb_linearize(skb)) +- goto out_free; +- +- /* the frame could be fragmented, software-encrypted, and other +- * things so we cannot really handle checksum offload with it - +- * fix it up in software before we handle anything else. +- */ +- if (skb->ip_summed == CHECKSUM_PARTIAL) { +- skb_set_transport_header(skb, +- skb_checksum_start_offset(skb)); +- if (skb_checksum_help(skb)) +- goto out_free; +- } ++ /* the frame could be fragmented, software-encrypted, and other ++ * things so we cannot really handle checksum or GSO offload. ++ * fix it up in software before we handle anything else. ++ */ ++ skb = ieee80211_tx_skb_fixup(skb, 0); ++ if (!skb) { ++ len = 0; ++ goto out; + } + + skb_list_walk_safe(skb, skb, next) { +@@ -4443,9 +4500,11 @@ normal: + return NETDEV_TX_OK; + } + +-static bool ieee80211_tx_8023(struct ieee80211_sub_if_data *sdata, +- struct sk_buff *skb, struct sta_info *sta, +- bool txpending) ++ ++ ++static bool __ieee80211_tx_8023(struct ieee80211_sub_if_data *sdata, ++ struct sk_buff *skb, struct sta_info *sta, ++ bool txpending) + { + struct ieee80211_local *local = sdata->local; + struct ieee80211_tx_control control = {}; +@@ -4454,14 +4513,6 @@ static bool ieee80211_tx_8023(struct iee + unsigned long flags; + int q = info->hw_queue; + +- if (sta) +- sk_pacing_shift_update(skb->sk, local->hw.tx_sk_pacing_shift); +- +- ieee80211_tpt_led_trig_tx(local, skb->len); +- +- if (ieee80211_queue_skb(local, sdata, sta, skb)) +- return true; +- + spin_lock_irqsave(&local->queue_stop_reason_lock, flags); + + if (local->queue_stop_reasons[q] || +@@ -4488,6 +4539,26 @@ static bool ieee80211_tx_8023(struct iee + return true; + } + ++static bool ieee80211_tx_8023(struct ieee80211_sub_if_data *sdata, ++ struct sk_buff *skb, struct sta_info *sta, ++ bool txpending) ++{ ++ struct ieee80211_local *local = sdata->local; ++ struct sk_buff *next; ++ bool ret = true; ++ ++ if (ieee80211_queue_skb(local, sdata, sta, skb)) ++ return true; ++ ++ skb_list_walk_safe(skb, skb, next) { ++ skb_mark_not_on_list(skb); ++ if (!__ieee80211_tx_8023(sdata, skb, sta, txpending)) ++ ret = false; ++ } ++ ++ return ret; ++} ++ + static void ieee80211_8023_xmit(struct ieee80211_sub_if_data *sdata, + struct net_device *dev, struct sta_info *sta, + struct ieee80211_key *key, struct sk_buff *skb) +@@ -4495,9 +4566,13 @@ static void ieee80211_8023_xmit(struct i + struct ieee80211_tx_info *info; + struct ieee80211_local *local = sdata->local; + struct tid_ampdu_tx *tid_tx; ++ struct sk_buff *seg, *next; ++ unsigned int skbs = 0, len = 0; ++ u16 queue; + u8 tid; + +- skb_set_queue_mapping(skb, ieee80211_select_queue(sdata, sta, skb)); ++ queue = ieee80211_select_queue(sdata, sta, skb); ++ skb_set_queue_mapping(skb, queue); + + if (unlikely(test_bit(SCAN_SW_SCANNING, &local->scanning)) && + test_bit(SDATA_STATE_OFFCHANNEL, &sdata->state)) +@@ -4507,9 +4582,6 @@ static void ieee80211_8023_xmit(struct i + if (unlikely(!skb)) + return; + +- info = IEEE80211_SKB_CB(skb); +- memset(info, 0, sizeof(*info)); +- + ieee80211_aggr_check(sdata, sta, skb); + + tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK; +@@ -4523,22 +4595,20 @@ static void ieee80211_8023_xmit(struct i + return; + } + +- info->flags |= IEEE80211_TX_CTL_AMPDU; + if (tid_tx->timeout) + tid_tx->last_tx = jiffies; + } + +- if (unlikely(skb->sk && +- skb_shinfo(skb)->tx_flags & SKBTX_WIFI_STATUS)) +- info->ack_frame_id = ieee80211_store_ack_skb(local, skb, +- &info->flags, NULL); ++ skb = ieee80211_tx_skb_fixup(skb, ieee80211_sdata_netdev_features(sdata)); ++ if (!skb) ++ return; + +- info->hw_queue = sdata->vif.hw_queue[skb_get_queue_mapping(skb)]; ++ info = IEEE80211_SKB_CB(skb); ++ memset(info, 0, sizeof(*info)); ++ if (tid_tx) ++ info->flags |= IEEE80211_TX_CTL_AMPDU; + +- dev_sw_netstats_tx_add(dev, 1, skb->len); +- +- sta->deflink.tx_stats.bytes[skb_get_queue_mapping(skb)] += skb->len; +- sta->deflink.tx_stats.packets[skb_get_queue_mapping(skb)]++; ++ info->hw_queue = sdata->vif.hw_queue[queue]; + + if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) + sdata = container_of(sdata->bss, +@@ -4550,6 +4620,24 @@ static void ieee80211_8023_xmit(struct i + if (key) + info->control.hw_key = &key->conf; + ++ skb_list_walk_safe(skb, seg, next) { ++ skbs++; ++ len += seg->len; ++ if (seg != skb) ++ memcpy(IEEE80211_SKB_CB(seg), info, sizeof(*info)); ++ } ++ ++ if (unlikely(skb->sk && ++ skb_shinfo(skb)->tx_flags & SKBTX_WIFI_STATUS)) ++ info->ack_frame_id = ieee80211_store_ack_skb(local, skb, ++ &info->flags, NULL); ++ ++ dev_sw_netstats_tx_add(dev, skbs, len); ++ sta->deflink.tx_stats.packets[queue] += skbs; ++ sta->deflink.tx_stats.bytes[queue] += len; ++ ++ ieee80211_tpt_led_trig_tx(local, len); ++ + ieee80211_tx_8023(sdata, skb, sta, false); + + return; +@@ -4591,6 +4679,7 @@ netdev_tx_t ieee80211_subif_start_xmit_8 + key->conf.cipher == WLAN_CIPHER_SUITE_TKIP)) + goto skip_offload; + ++ sk_pacing_shift_update(skb->sk, sdata->local->hw.tx_sk_pacing_shift); + ieee80211_8023_xmit(sdata, dev, sta, key, skb); + goto out; + diff --git a/package/kernel/mac80211/patches/subsys/311-v6.2-wifi-mac80211-fix-and-simplify-unencrypted-drop-chec.patch b/package/kernel/mac80211/patches/subsys/311-v6.2-wifi-mac80211-fix-and-simplify-unencrypted-drop-chec.patch new file mode 100644 index 000000000..804b02eb3 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/311-v6.2-wifi-mac80211-fix-and-simplify-unencrypted-drop-chec.patch @@ -0,0 +1,87 @@ +From: Felix Fietkau +Date: Thu, 1 Dec 2022 14:57:30 +0100 +Subject: [PATCH] wifi: mac80211: fix and simplify unencrypted drop check for + mesh + +ieee80211_drop_unencrypted is called from ieee80211_rx_h_mesh_fwding and +ieee80211_frame_allowed. + +Since ieee80211_rx_h_mesh_fwding can forward packets for other mesh nodes +and is called earlier, it needs to check the decryptions status and if the +packet is using the control protocol on its own, instead of deferring to +the later call from ieee80211_frame_allowed. + +Because of that, ieee80211_drop_unencrypted has a mesh specific check +that skips over the mesh header in order to check the payload protocol. +This code is invalid when called from ieee80211_frame_allowed, since that +happens after the 802.11->802.3 conversion. + +Fix this by moving the mesh specific check directly into +ieee80211_rx_h_mesh_fwding. + +Signed-off-by: Felix Fietkau +Link: https://lore.kernel.org/r/20221201135730.19723-1-nbd@nbd.name +Signed-off-by: Johannes Berg +--- + +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -2403,7 +2403,6 @@ static int ieee80211_802_1x_port_control + + static int ieee80211_drop_unencrypted(struct ieee80211_rx_data *rx, __le16 fc) + { +- struct ieee80211_hdr *hdr = (void *)rx->skb->data; + struct sk_buff *skb = rx->skb; + struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); + +@@ -2414,31 +2413,6 @@ static int ieee80211_drop_unencrypted(st + if (status->flag & RX_FLAG_DECRYPTED) + return 0; + +- /* check mesh EAPOL frames first */ +- if (unlikely(rx->sta && ieee80211_vif_is_mesh(&rx->sdata->vif) && +- ieee80211_is_data(fc))) { +- struct ieee80211s_hdr *mesh_hdr; +- u16 hdr_len = ieee80211_hdrlen(fc); +- u16 ethertype_offset; +- __be16 ethertype; +- +- if (!ether_addr_equal(hdr->addr1, rx->sdata->vif.addr)) +- goto drop_check; +- +- /* make sure fixed part of mesh header is there, also checks skb len */ +- if (!pskb_may_pull(rx->skb, hdr_len + 6)) +- goto drop_check; +- +- mesh_hdr = (struct ieee80211s_hdr *)(skb->data + hdr_len); +- ethertype_offset = hdr_len + ieee80211_get_mesh_hdrlen(mesh_hdr) + +- sizeof(rfc1042_header); +- +- if (skb_copy_bits(rx->skb, ethertype_offset, ðertype, 2) == 0 && +- ethertype == rx->sdata->control_port_protocol) +- return 0; +- } +- +-drop_check: + /* Drop unencrypted frames if key is set. */ + if (unlikely(!ieee80211_has_protected(fc) && + !ieee80211_is_any_nullfunc(fc) && +@@ -2892,8 +2866,16 @@ ieee80211_rx_h_mesh_fwding(struct ieee80 + hdr = (struct ieee80211_hdr *) skb->data; + mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen); + +- if (ieee80211_drop_unencrypted(rx, hdr->frame_control)) +- return RX_DROP_MONITOR; ++ if (ieee80211_drop_unencrypted(rx, hdr->frame_control)) { ++ int offset = hdrlen + ieee80211_get_mesh_hdrlen(mesh_hdr) + ++ sizeof(rfc1042_header); ++ __be16 ethertype; ++ ++ if (!ether_addr_equal(hdr->addr1, rx->sdata->vif.addr) || ++ skb_copy_bits(rx->skb, offset, ðertype, 2) != 0 || ++ ethertype != rx->sdata->control_port_protocol) ++ return RX_DROP_MONITOR; ++ } + + /* frame is in RMC, don't forward */ + if (ieee80211_is_data(hdr->frame_control) && diff --git a/package/kernel/mac80211/patches/subsys/312-v6.3-wifi-cfg80211-move-A-MSDU-check-in-ieee80211_data_to.patch b/package/kernel/mac80211/patches/subsys/312-v6.3-wifi-cfg80211-move-A-MSDU-check-in-ieee80211_data_to.patch new file mode 100644 index 000000000..f668905cc --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/312-v6.3-wifi-cfg80211-move-A-MSDU-check-in-ieee80211_data_to.patch @@ -0,0 +1,25 @@ +From: Felix Fietkau +Date: Fri, 2 Dec 2022 13:53:11 +0100 +Subject: [PATCH] wifi: cfg80211: move A-MSDU check in + ieee80211_data_to_8023_exthdr + +When parsing the outer A-MSDU header, don't check for inner bridge tunnel +or RFC1042 headers. This is handled by ieee80211_amsdu_to_8023s already. + +Signed-off-by: Felix Fietkau +--- + +--- a/net/wireless/util.c ++++ b/net/wireless/util.c +@@ -631,8 +631,9 @@ int ieee80211_data_to_8023_exthdr(struct + break; + } + +- if (likely(skb_copy_bits(skb, hdrlen, &payload, sizeof(payload)) == 0 && +- ((!is_amsdu && ether_addr_equal(payload.hdr, rfc1042_header) && ++ if (likely(!is_amsdu && ++ skb_copy_bits(skb, hdrlen, &payload, sizeof(payload)) == 0 && ++ ((ether_addr_equal(payload.hdr, rfc1042_header) && + payload.proto != htons(ETH_P_AARP) && + payload.proto != htons(ETH_P_IPX)) || + ether_addr_equal(payload.hdr, bridge_tunnel_header)))) { diff --git a/package/kernel/mac80211/patches/subsys/313-v6.3-wifi-cfg80211-factor-out-bridge-tunnel-RFC1042-heade.patch b/package/kernel/mac80211/patches/subsys/313-v6.3-wifi-cfg80211-factor-out-bridge-tunnel-RFC1042-heade.patch new file mode 100644 index 000000000..864105786 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/313-v6.3-wifi-cfg80211-factor-out-bridge-tunnel-RFC1042-heade.patch @@ -0,0 +1,76 @@ +From: Felix Fietkau +Date: Fri, 2 Dec 2022 13:54:15 +0100 +Subject: [PATCH] wifi: cfg80211: factor out bridge tunnel / RFC1042 header + check + +The same check is done in multiple places, unify it. + +Signed-off-by: Felix Fietkau +--- + +--- a/net/wireless/util.c ++++ b/net/wireless/util.c +@@ -542,6 +542,21 @@ unsigned int ieee80211_get_mesh_hdrlen(s + } + EXPORT_SYMBOL(ieee80211_get_mesh_hdrlen); + ++static bool ieee80211_get_8023_tunnel_proto(const void *hdr, __be16 *proto) ++{ ++ const __be16 *hdr_proto = hdr + ETH_ALEN; ++ ++ if (!(ether_addr_equal(hdr, rfc1042_header) && ++ *hdr_proto != htons(ETH_P_AARP) && ++ *hdr_proto != htons(ETH_P_IPX)) && ++ !ether_addr_equal(hdr, bridge_tunnel_header)) ++ return false; ++ ++ *proto = *hdr_proto; ++ ++ return true; ++} ++ + int ieee80211_data_to_8023_exthdr(struct sk_buff *skb, struct ethhdr *ehdr, + const u8 *addr, enum nl80211_iftype iftype, + u8 data_offset, bool is_amsdu) +@@ -633,14 +648,9 @@ int ieee80211_data_to_8023_exthdr(struct + + if (likely(!is_amsdu && + skb_copy_bits(skb, hdrlen, &payload, sizeof(payload)) == 0 && +- ((ether_addr_equal(payload.hdr, rfc1042_header) && +- payload.proto != htons(ETH_P_AARP) && +- payload.proto != htons(ETH_P_IPX)) || +- ether_addr_equal(payload.hdr, bridge_tunnel_header)))) { +- /* remove RFC1042 or Bridge-Tunnel encapsulation and +- * replace EtherType */ ++ ieee80211_get_8023_tunnel_proto(&payload, &tmp.h_proto))) { ++ /* remove RFC1042 or Bridge-Tunnel encapsulation */ + hdrlen += ETH_ALEN + 2; +- tmp.h_proto = payload.proto; + skb_postpull_rcsum(skb, &payload, ETH_ALEN + 2); + } else { + tmp.h_proto = htons(skb->len - hdrlen); +@@ -756,8 +766,6 @@ void ieee80211_amsdu_to_8023s(struct sk_ + { + unsigned int hlen = ALIGN(extra_headroom, 4); + struct sk_buff *frame = NULL; +- u16 ethertype; +- u8 *payload; + int offset = 0, remaining; + struct ethhdr eth; + bool reuse_frag = skb->head_frag && !skb_has_frag_list(skb); +@@ -811,14 +819,8 @@ void ieee80211_amsdu_to_8023s(struct sk_ + frame->dev = skb->dev; + frame->priority = skb->priority; + +- payload = frame->data; +- ethertype = (payload[6] << 8) | payload[7]; +- if (likely((ether_addr_equal(payload, rfc1042_header) && +- ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) || +- ether_addr_equal(payload, bridge_tunnel_header))) { +- eth.h_proto = htons(ethertype); ++ if (likely(ieee80211_get_8023_tunnel_proto(frame->data, ð.h_proto))) + skb_pull(frame, ETH_ALEN + 2); +- } + + memcpy(skb_push(frame, sizeof(eth)), ð, sizeof(eth)); + __skb_queue_tail(list, frame); diff --git a/package/kernel/mac80211/patches/subsys/314-v6.3-wifi-mac80211-remove-mesh-forwarding-congestion-chec.patch b/package/kernel/mac80211/patches/subsys/314-v6.3-wifi-mac80211-remove-mesh-forwarding-congestion-chec.patch new file mode 100644 index 000000000..515176f0d --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/314-v6.3-wifi-mac80211-remove-mesh-forwarding-congestion-chec.patch @@ -0,0 +1,54 @@ +From: Felix Fietkau +Date: Fri, 2 Dec 2022 17:01:46 +0100 +Subject: [PATCH] wifi: mac80211: remove mesh forwarding congestion check + +Now that all drivers use iTXQ, it does not make sense to check to drop +tx forwarding packets when the driver has stopped the queues. +fq_codel will take care of dropping packets when the queues fill up + +Signed-off-by: Felix Fietkau +--- + +--- a/net/mac80211/debugfs_netdev.c ++++ b/net/mac80211/debugfs_netdev.c +@@ -603,8 +603,6 @@ IEEE80211_IF_FILE(fwded_mcast, u.mesh.ms + IEEE80211_IF_FILE(fwded_unicast, u.mesh.mshstats.fwded_unicast, DEC); + IEEE80211_IF_FILE(fwded_frames, u.mesh.mshstats.fwded_frames, DEC); + IEEE80211_IF_FILE(dropped_frames_ttl, u.mesh.mshstats.dropped_frames_ttl, DEC); +-IEEE80211_IF_FILE(dropped_frames_congestion, +- u.mesh.mshstats.dropped_frames_congestion, DEC); + IEEE80211_IF_FILE(dropped_frames_no_route, + u.mesh.mshstats.dropped_frames_no_route, DEC); + +@@ -740,7 +738,6 @@ static void add_mesh_stats(struct ieee80 + MESHSTATS_ADD(fwded_frames); + MESHSTATS_ADD(dropped_frames_ttl); + MESHSTATS_ADD(dropped_frames_no_route); +- MESHSTATS_ADD(dropped_frames_congestion); + #undef MESHSTATS_ADD + } + +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -329,7 +329,6 @@ struct mesh_stats { + __u32 fwded_frames; /* Mesh total forwarded frames */ + __u32 dropped_frames_ttl; /* Not transmitted since mesh_ttl == 0*/ + __u32 dropped_frames_no_route; /* Not transmitted, no route found */ +- __u32 dropped_frames_congestion;/* Not forwarded due to congestion */ + }; + + #define PREQ_Q_F_START 0x1 +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -2926,11 +2926,6 @@ ieee80211_rx_h_mesh_fwding(struct ieee80 + return RX_CONTINUE; + + ac = ieee802_1d_to_ac[skb->priority]; +- q = sdata->vif.hw_queue[ac]; +- if (ieee80211_queue_stopped(&local->hw, q)) { +- IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_congestion); +- return RX_DROP_MONITOR; +- } + skb_set_queue_mapping(skb, ac); + + if (!--mesh_hdr->ttl) { diff --git a/package/kernel/mac80211/patches/subsys/315-v6.3-wifi-mac80211-fix-receiving-A-MSDU-frames-on-mesh-in.patch b/package/kernel/mac80211/patches/subsys/315-v6.3-wifi-mac80211-fix-receiving-A-MSDU-frames-on-mesh-in.patch new file mode 100644 index 000000000..59b799b6b --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/315-v6.3-wifi-mac80211-fix-receiving-A-MSDU-frames-on-mesh-in.patch @@ -0,0 +1,762 @@ +From 986e43b19ae9176093da35e0a844e65c8bf9ede7 Mon Sep 17 00:00:00 2001 +From: Felix Fietkau +Date: Mon, 13 Feb 2023 11:08:54 +0100 +Subject: [PATCH] wifi: mac80211: fix receiving A-MSDU frames on mesh + interfaces + +The current mac80211 mesh A-MSDU receive path fails to parse A-MSDU packets +on mesh interfaces, because it assumes that the Mesh Control field is always +directly after the 802.11 header. +802.11-2020 9.3.2.2.2 Figure 9-70 shows that the Mesh Control field is +actually part of the A-MSDU subframe header. +This makes more sense, since it allows packets for multiple different +destinations to be included in the same A-MSDU, as long as RA and TID are +still the same. +Another issue is the fact that the A-MSDU subframe length field was apparently +accidentally defined as little-endian in the standard. + +In order to fix this, the mesh forwarding path needs happen at a different +point in the receive path. + +ieee80211_data_to_8023_exthdr is changed to ignore the mesh control field +and leave it in after the ethernet header. This also affects the source/dest +MAC address fields, which now in the case of mesh point to the mesh SA/DA. + +ieee80211_amsdu_to_8023s is changed to deal with the endian difference and +to add the Mesh Control length to the subframe length, since it's not covered +by the MSDU length field. + +With these changes, the mac80211 will get the same packet structure for +converted regular data packets and unpacked A-MSDU subframes. + +The mesh forwarding checks are now only performed after the A-MSDU decap. +For locally received packets, the Mesh Control header is stripped away. +For forwarded packets, a new 802.11 header gets added. + +Signed-off-by: Felix Fietkau +Link: https://lore.kernel.org/r/20230213100855.34315-4-nbd@nbd.name +[fix fortify build error] +Signed-off-by: Johannes Berg +--- + .../wireless/marvell/mwifiex/11n_rxreorder.c | 2 +- + include/net/cfg80211.h | 27 +- + net/mac80211/rx.c | 350 ++++++++++-------- + net/wireless/util.c | 120 +++--- + 4 files changed, 297 insertions(+), 202 deletions(-) + +--- a/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c ++++ b/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c +@@ -33,7 +33,7 @@ static int mwifiex_11n_dispatch_amsdu_pk + skb_trim(skb, le16_to_cpu(local_rx_pd->rx_pkt_length)); + + ieee80211_amsdu_to_8023s(skb, &list, priv->curr_addr, +- priv->wdev.iftype, 0, NULL, NULL); ++ priv->wdev.iftype, 0, NULL, NULL, false); + + while (!skb_queue_empty(&list)) { + struct rx_packet_hdr *rx_hdr; +--- a/include/net/cfg80211.h ++++ b/include/net/cfg80211.h +@@ -6208,11 +6208,36 @@ static inline int ieee80211_data_to_8023 + * @extra_headroom: The hardware extra headroom for SKBs in the @list. + * @check_da: DA to check in the inner ethernet header, or NULL + * @check_sa: SA to check in the inner ethernet header, or NULL ++ * @mesh_control: A-MSDU subframe header includes the mesh control field + */ + void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list, + const u8 *addr, enum nl80211_iftype iftype, + const unsigned int extra_headroom, +- const u8 *check_da, const u8 *check_sa); ++ const u8 *check_da, const u8 *check_sa, ++ bool mesh_control); ++ ++/** ++ * ieee80211_get_8023_tunnel_proto - get RFC1042 or bridge tunnel encap protocol ++ * ++ * Check for RFC1042 or bridge tunnel header and fetch the encapsulated ++ * protocol. ++ * ++ * @hdr: pointer to the MSDU payload ++ * @proto: destination pointer to store the protocol ++ * Return: true if encapsulation was found ++ */ ++bool ieee80211_get_8023_tunnel_proto(const void *hdr, __be16 *proto); ++ ++/** ++ * ieee80211_strip_8023_mesh_hdr - strip mesh header from converted 802.3 frames ++ * ++ * Strip the mesh header, which was left in by ieee80211_data_to_8023 as part ++ * of the MSDU data. Also move any source/destination addresses from the mesh ++ * header to the ethernet header (if present). ++ * ++ * @skb: The 802.3 frame with embedded mesh header ++ */ ++int ieee80211_strip_8023_mesh_hdr(struct sk_buff *skb); + + /** + * cfg80211_classify8021d - determine the 802.1p/1d tag for a data frame +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -2720,6 +2720,174 @@ ieee80211_deliver_skb(struct ieee80211_r + } + } + ++static ieee80211_rx_result ++ieee80211_rx_mesh_data(struct ieee80211_sub_if_data *sdata, struct sta_info *sta, ++ struct sk_buff *skb) ++{ ++#ifdef CPTCFG_MAC80211_MESH ++ struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; ++ struct ieee80211_local *local = sdata->local; ++ uint16_t fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_DATA; ++ struct ieee80211_hdr hdr = { ++ .frame_control = cpu_to_le16(fc) ++ }; ++ struct ieee80211_hdr *fwd_hdr; ++ struct ieee80211s_hdr *mesh_hdr; ++ struct ieee80211_tx_info *info; ++ struct sk_buff *fwd_skb; ++ struct ethhdr *eth; ++ bool multicast; ++ int tailroom = 0; ++ int hdrlen, mesh_hdrlen; ++ u8 *qos; ++ ++ if (!ieee80211_vif_is_mesh(&sdata->vif)) ++ return RX_CONTINUE; ++ ++ if (!pskb_may_pull(skb, sizeof(*eth) + 6)) ++ return RX_DROP_MONITOR; ++ ++ mesh_hdr = (struct ieee80211s_hdr *)(skb->data + sizeof(*eth)); ++ mesh_hdrlen = ieee80211_get_mesh_hdrlen(mesh_hdr); ++ ++ if (!pskb_may_pull(skb, sizeof(*eth) + mesh_hdrlen)) ++ return RX_DROP_MONITOR; ++ ++ eth = (struct ethhdr *)skb->data; ++ multicast = is_multicast_ether_addr(eth->h_dest); ++ ++ mesh_hdr = (struct ieee80211s_hdr *)(eth + 1); ++ if (!mesh_hdr->ttl) ++ return RX_DROP_MONITOR; ++ ++ /* frame is in RMC, don't forward */ ++ if (is_multicast_ether_addr(eth->h_dest) && ++ mesh_rmc_check(sdata, eth->h_source, mesh_hdr)) ++ return RX_DROP_MONITOR; ++ ++ /* Frame has reached destination. Don't forward */ ++ if (ether_addr_equal(sdata->vif.addr, eth->h_dest)) ++ goto rx_accept; ++ ++ if (!ifmsh->mshcfg.dot11MeshForwarding) { ++ if (is_multicast_ether_addr(eth->h_dest)) ++ goto rx_accept; ++ ++ return RX_DROP_MONITOR; ++ } ++ ++ /* forward packet */ ++ if (sdata->crypto_tx_tailroom_needed_cnt) ++ tailroom = IEEE80211_ENCRYPT_TAILROOM; ++ ++ if (!--mesh_hdr->ttl) { ++ if (multicast) ++ goto rx_accept; ++ ++ IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_ttl); ++ return RX_DROP_MONITOR; ++ } ++ ++ if (mesh_hdr->flags & MESH_FLAGS_AE) { ++ struct mesh_path *mppath; ++ char *proxied_addr; ++ ++ if (multicast) ++ proxied_addr = mesh_hdr->eaddr1; ++ else if ((mesh_hdr->flags & MESH_FLAGS_AE) == MESH_FLAGS_AE_A5_A6) ++ /* has_a4 already checked in ieee80211_rx_mesh_check */ ++ proxied_addr = mesh_hdr->eaddr2; ++ else ++ return RX_DROP_MONITOR; ++ ++ rcu_read_lock(); ++ mppath = mpp_path_lookup(sdata, proxied_addr); ++ if (!mppath) { ++ mpp_path_add(sdata, proxied_addr, eth->h_source); ++ } else { ++ spin_lock_bh(&mppath->state_lock); ++ if (!ether_addr_equal(mppath->mpp, eth->h_source)) ++ memcpy(mppath->mpp, eth->h_source, ETH_ALEN); ++ mppath->exp_time = jiffies; ++ spin_unlock_bh(&mppath->state_lock); ++ } ++ rcu_read_unlock(); ++ } ++ ++ skb_set_queue_mapping(skb, ieee802_1d_to_ac[skb->priority]); ++ ++ ieee80211_fill_mesh_addresses(&hdr, &hdr.frame_control, ++ eth->h_dest, eth->h_source); ++ hdrlen = ieee80211_hdrlen(hdr.frame_control); ++ if (multicast) { ++ int extra_head = sizeof(struct ieee80211_hdr) - sizeof(*eth); ++ ++ fwd_skb = skb_copy_expand(skb, local->tx_headroom + extra_head + ++ IEEE80211_ENCRYPT_HEADROOM, ++ tailroom, GFP_ATOMIC); ++ if (!fwd_skb) ++ goto rx_accept; ++ } else { ++ fwd_skb = skb; ++ skb = NULL; ++ ++ if (skb_cow_head(fwd_skb, hdrlen - sizeof(struct ethhdr))) ++ return RX_DROP_UNUSABLE; ++ } ++ ++ fwd_hdr = skb_push(fwd_skb, hdrlen - sizeof(struct ethhdr)); ++ memcpy(fwd_hdr, &hdr, hdrlen - 2); ++ qos = ieee80211_get_qos_ctl(fwd_hdr); ++ qos[0] = qos[1] = 0; ++ ++ skb_reset_mac_header(fwd_skb); ++ hdrlen += mesh_hdrlen; ++ if (ieee80211_get_8023_tunnel_proto(fwd_skb->data + hdrlen, ++ &fwd_skb->protocol)) ++ hdrlen += ETH_ALEN; ++ else ++ fwd_skb->protocol = htons(fwd_skb->len - hdrlen); ++ skb_set_network_header(fwd_skb, hdrlen); ++ ++ info = IEEE80211_SKB_CB(fwd_skb); ++ memset(info, 0, sizeof(*info)); ++ info->control.flags |= IEEE80211_TX_INTCFL_NEED_TXPROCESSING; ++ info->control.vif = &sdata->vif; ++ info->control.jiffies = jiffies; ++ if (multicast) { ++ IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_mcast); ++ memcpy(fwd_hdr->addr2, sdata->vif.addr, ETH_ALEN); ++ /* update power mode indication when forwarding */ ++ ieee80211_mps_set_frame_flags(sdata, NULL, fwd_hdr); ++ } else if (!mesh_nexthop_lookup(sdata, fwd_skb)) { ++ /* mesh power mode flags updated in mesh_nexthop_lookup */ ++ IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_unicast); ++ } else { ++ /* unable to resolve next hop */ ++ if (sta) ++ mesh_path_error_tx(sdata, ifmsh->mshcfg.element_ttl, ++ hdr.addr3, 0, ++ WLAN_REASON_MESH_PATH_NOFORWARD, ++ sta->sta.addr); ++ IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_no_route); ++ kfree_skb(fwd_skb); ++ goto rx_accept; ++ } ++ ++ IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_frames); ++ fwd_skb->dev = sdata->dev; ++ ieee80211_add_pending_skb(local, fwd_skb); ++ ++rx_accept: ++ if (!skb) ++ return RX_QUEUED; ++ ++ ieee80211_strip_8023_mesh_hdr(skb); ++#endif ++ ++ return RX_CONTINUE; ++} ++ + static ieee80211_rx_result debug_noinline + __ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx, u8 data_offset) + { +@@ -2728,8 +2896,10 @@ __ieee80211_rx_h_amsdu(struct ieee80211_ + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + __le16 fc = hdr->frame_control; + struct sk_buff_head frame_list; ++ static ieee80211_rx_result res; + struct ethhdr ethhdr; + const u8 *check_da = ethhdr.h_dest, *check_sa = ethhdr.h_source; ++ bool mesh = false; + + if (unlikely(ieee80211_has_a4(hdr->frame_control))) { + check_da = NULL; +@@ -2746,6 +2916,8 @@ __ieee80211_rx_h_amsdu(struct ieee80211_ + break; + case NL80211_IFTYPE_MESH_POINT: + check_sa = NULL; ++ check_da = NULL; ++ mesh = true; + break; + default: + break; +@@ -2763,17 +2935,29 @@ __ieee80211_rx_h_amsdu(struct ieee80211_ + ieee80211_amsdu_to_8023s(skb, &frame_list, dev->dev_addr, + rx->sdata->vif.type, + rx->local->hw.extra_tx_headroom, +- check_da, check_sa); ++ check_da, check_sa, mesh); + + while (!skb_queue_empty(&frame_list)) { + rx->skb = __skb_dequeue(&frame_list); + +- if (!ieee80211_frame_allowed(rx, fc)) { +- dev_kfree_skb(rx->skb); ++ res = ieee80211_rx_mesh_data(rx->sdata, rx->sta, rx->skb); ++ switch (res) { ++ case RX_QUEUED: + continue; ++ case RX_CONTINUE: ++ break; ++ default: ++ goto free; + } + ++ if (!ieee80211_frame_allowed(rx, fc)) ++ goto free; ++ + ieee80211_deliver_skb(rx); ++ continue; ++ ++free: ++ dev_kfree_skb(rx->skb); + } + + return RX_QUEUED; +@@ -2806,6 +2990,8 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx + if (!rx->sdata->u.mgd.use_4addr) + return RX_DROP_UNUSABLE; + break; ++ case NL80211_IFTYPE_MESH_POINT: ++ break; + default: + return RX_DROP_UNUSABLE; + } +@@ -2834,155 +3020,6 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx + return __ieee80211_rx_h_amsdu(rx, 0); + } + +-#ifdef CPTCFG_MAC80211_MESH +-static ieee80211_rx_result +-ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) +-{ +- struct ieee80211_hdr *fwd_hdr, *hdr; +- struct ieee80211_tx_info *info; +- struct ieee80211s_hdr *mesh_hdr; +- struct sk_buff *skb = rx->skb, *fwd_skb; +- struct ieee80211_local *local = rx->local; +- struct ieee80211_sub_if_data *sdata = rx->sdata; +- struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; +- u16 ac, q, hdrlen; +- int tailroom = 0; +- +- hdr = (struct ieee80211_hdr *) skb->data; +- hdrlen = ieee80211_hdrlen(hdr->frame_control); +- +- /* make sure fixed part of mesh header is there, also checks skb len */ +- if (!pskb_may_pull(rx->skb, hdrlen + 6)) +- return RX_DROP_MONITOR; +- +- mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen); +- +- /* make sure full mesh header is there, also checks skb len */ +- if (!pskb_may_pull(rx->skb, +- hdrlen + ieee80211_get_mesh_hdrlen(mesh_hdr))) +- return RX_DROP_MONITOR; +- +- /* reload pointers */ +- hdr = (struct ieee80211_hdr *) skb->data; +- mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen); +- +- if (ieee80211_drop_unencrypted(rx, hdr->frame_control)) { +- int offset = hdrlen + ieee80211_get_mesh_hdrlen(mesh_hdr) + +- sizeof(rfc1042_header); +- __be16 ethertype; +- +- if (!ether_addr_equal(hdr->addr1, rx->sdata->vif.addr) || +- skb_copy_bits(rx->skb, offset, ðertype, 2) != 0 || +- ethertype != rx->sdata->control_port_protocol) +- return RX_DROP_MONITOR; +- } +- +- /* frame is in RMC, don't forward */ +- if (ieee80211_is_data(hdr->frame_control) && +- is_multicast_ether_addr(hdr->addr1) && +- mesh_rmc_check(rx->sdata, hdr->addr3, mesh_hdr)) +- return RX_DROP_MONITOR; +- +- if (!ieee80211_is_data(hdr->frame_control)) +- return RX_CONTINUE; +- +- if (!mesh_hdr->ttl) +- return RX_DROP_MONITOR; +- +- if (mesh_hdr->flags & MESH_FLAGS_AE) { +- struct mesh_path *mppath; +- char *proxied_addr; +- char *mpp_addr; +- +- if (is_multicast_ether_addr(hdr->addr1)) { +- mpp_addr = hdr->addr3; +- proxied_addr = mesh_hdr->eaddr1; +- } else if ((mesh_hdr->flags & MESH_FLAGS_AE) == +- MESH_FLAGS_AE_A5_A6) { +- /* has_a4 already checked in ieee80211_rx_mesh_check */ +- mpp_addr = hdr->addr4; +- proxied_addr = mesh_hdr->eaddr2; +- } else { +- return RX_DROP_MONITOR; +- } +- +- rcu_read_lock(); +- mppath = mpp_path_lookup(sdata, proxied_addr); +- if (!mppath) { +- mpp_path_add(sdata, proxied_addr, mpp_addr); +- } else { +- spin_lock_bh(&mppath->state_lock); +- if (!ether_addr_equal(mppath->mpp, mpp_addr)) +- memcpy(mppath->mpp, mpp_addr, ETH_ALEN); +- mppath->exp_time = jiffies; +- spin_unlock_bh(&mppath->state_lock); +- } +- rcu_read_unlock(); +- } +- +- /* Frame has reached destination. Don't forward */ +- if (!is_multicast_ether_addr(hdr->addr1) && +- ether_addr_equal(sdata->vif.addr, hdr->addr3)) +- return RX_CONTINUE; +- +- ac = ieee802_1d_to_ac[skb->priority]; +- skb_set_queue_mapping(skb, ac); +- +- if (!--mesh_hdr->ttl) { +- if (!is_multicast_ether_addr(hdr->addr1)) +- IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, +- dropped_frames_ttl); +- goto out; +- } +- +- if (!ifmsh->mshcfg.dot11MeshForwarding) +- goto out; +- +- if (sdata->crypto_tx_tailroom_needed_cnt) +- tailroom = IEEE80211_ENCRYPT_TAILROOM; +- +- fwd_skb = skb_copy_expand(skb, local->tx_headroom + +- IEEE80211_ENCRYPT_HEADROOM, +- tailroom, GFP_ATOMIC); +- if (!fwd_skb) +- goto out; +- +- fwd_skb->dev = sdata->dev; +- fwd_hdr = (struct ieee80211_hdr *) fwd_skb->data; +- fwd_hdr->frame_control &= ~cpu_to_le16(IEEE80211_FCTL_RETRY); +- info = IEEE80211_SKB_CB(fwd_skb); +- memset(info, 0, sizeof(*info)); +- info->control.flags |= IEEE80211_TX_INTCFL_NEED_TXPROCESSING; +- info->control.vif = &rx->sdata->vif; +- info->control.jiffies = jiffies; +- if (is_multicast_ether_addr(fwd_hdr->addr1)) { +- IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_mcast); +- memcpy(fwd_hdr->addr2, sdata->vif.addr, ETH_ALEN); +- /* update power mode indication when forwarding */ +- ieee80211_mps_set_frame_flags(sdata, NULL, fwd_hdr); +- } else if (!mesh_nexthop_lookup(sdata, fwd_skb)) { +- /* mesh power mode flags updated in mesh_nexthop_lookup */ +- IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_unicast); +- } else { +- /* unable to resolve next hop */ +- mesh_path_error_tx(sdata, ifmsh->mshcfg.element_ttl, +- fwd_hdr->addr3, 0, +- WLAN_REASON_MESH_PATH_NOFORWARD, +- fwd_hdr->addr2); +- IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_no_route); +- kfree_skb(fwd_skb); +- return RX_DROP_MONITOR; +- } +- +- IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_frames); +- ieee80211_add_pending_skb(local, fwd_skb); +- out: +- if (is_multicast_ether_addr(hdr->addr1)) +- return RX_CONTINUE; +- return RX_DROP_MONITOR; +-} +-#endif +- + static ieee80211_rx_result debug_noinline + ieee80211_rx_h_data(struct ieee80211_rx_data *rx) + { +@@ -2991,6 +3028,7 @@ ieee80211_rx_h_data(struct ieee80211_rx_ + struct net_device *dev = sdata->dev; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; + __le16 fc = hdr->frame_control; ++ static ieee80211_rx_result res; + bool port_control; + int err; + +@@ -3017,6 +3055,10 @@ ieee80211_rx_h_data(struct ieee80211_rx_ + if (unlikely(err)) + return RX_DROP_UNUSABLE; + ++ res = ieee80211_rx_mesh_data(rx->sdata, rx->sta, rx->skb); ++ if (res != RX_CONTINUE) ++ return res; ++ + if (!ieee80211_frame_allowed(rx, fc)) + return RX_DROP_MONITOR; + +@@ -3987,10 +4029,6 @@ static void ieee80211_rx_handlers(struct + CALL_RXH(ieee80211_rx_h_defragment); + CALL_RXH(ieee80211_rx_h_michael_mic_verify); + /* must be after MMIC verify so header is counted in MPDU mic */ +-#ifdef CPTCFG_MAC80211_MESH +- if (ieee80211_vif_is_mesh(&rx->sdata->vif)) +- CALL_RXH(ieee80211_rx_h_mesh_fwding); +-#endif + CALL_RXH(ieee80211_rx_h_amsdu); + CALL_RXH(ieee80211_rx_h_data); + +--- a/net/wireless/util.c ++++ b/net/wireless/util.c +@@ -542,7 +542,7 @@ unsigned int ieee80211_get_mesh_hdrlen(s + } + EXPORT_SYMBOL(ieee80211_get_mesh_hdrlen); + +-static bool ieee80211_get_8023_tunnel_proto(const void *hdr, __be16 *proto) ++bool ieee80211_get_8023_tunnel_proto(const void *hdr, __be16 *proto) + { + const __be16 *hdr_proto = hdr + ETH_ALEN; + +@@ -556,6 +556,49 @@ static bool ieee80211_get_8023_tunnel_pr + + return true; + } ++EXPORT_SYMBOL(ieee80211_get_8023_tunnel_proto); ++ ++int ieee80211_strip_8023_mesh_hdr(struct sk_buff *skb) ++{ ++ const void *mesh_addr; ++ struct { ++ struct ethhdr eth; ++ u8 flags; ++ } payload; ++ int hdrlen; ++ int ret; ++ ++ ret = skb_copy_bits(skb, 0, &payload, sizeof(payload)); ++ if (ret) ++ return ret; ++ ++ hdrlen = sizeof(payload.eth) + __ieee80211_get_mesh_hdrlen(payload.flags); ++ ++ if (likely(pskb_may_pull(skb, hdrlen + 8) && ++ ieee80211_get_8023_tunnel_proto(skb->data + hdrlen, ++ &payload.eth.h_proto))) ++ hdrlen += ETH_ALEN + 2; ++ else if (!pskb_may_pull(skb, hdrlen)) ++ return -EINVAL; ++ ++ mesh_addr = skb->data + sizeof(payload.eth) + ETH_ALEN; ++ switch (payload.flags & MESH_FLAGS_AE) { ++ case MESH_FLAGS_AE_A4: ++ memcpy(&payload.eth.h_source, mesh_addr, ETH_ALEN); ++ break; ++ case MESH_FLAGS_AE_A5_A6: ++ memcpy(&payload.eth, mesh_addr, 2 * ETH_ALEN); ++ break; ++ default: ++ break; ++ } ++ ++ pskb_pull(skb, hdrlen - sizeof(payload.eth)); ++ memcpy(skb->data, &payload.eth, sizeof(payload.eth)); ++ ++ return 0; ++} ++EXPORT_SYMBOL(ieee80211_strip_8023_mesh_hdr); + + int ieee80211_data_to_8023_exthdr(struct sk_buff *skb, struct ethhdr *ehdr, + const u8 *addr, enum nl80211_iftype iftype, +@@ -568,7 +611,6 @@ int ieee80211_data_to_8023_exthdr(struct + } payload; + struct ethhdr tmp; + u16 hdrlen; +- u8 mesh_flags = 0; + + if (unlikely(!ieee80211_is_data_present(hdr->frame_control))) + return -1; +@@ -589,12 +631,6 @@ int ieee80211_data_to_8023_exthdr(struct + memcpy(tmp.h_dest, ieee80211_get_DA(hdr), ETH_ALEN); + memcpy(tmp.h_source, ieee80211_get_SA(hdr), ETH_ALEN); + +- if (iftype == NL80211_IFTYPE_MESH_POINT && +- skb_copy_bits(skb, hdrlen, &mesh_flags, 1) < 0) +- return -1; +- +- mesh_flags &= MESH_FLAGS_AE; +- + switch (hdr->frame_control & + cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) { + case cpu_to_le16(IEEE80211_FCTL_TODS): +@@ -608,17 +644,6 @@ int ieee80211_data_to_8023_exthdr(struct + iftype != NL80211_IFTYPE_AP_VLAN && + iftype != NL80211_IFTYPE_STATION)) + return -1; +- if (iftype == NL80211_IFTYPE_MESH_POINT) { +- if (mesh_flags == MESH_FLAGS_AE_A4) +- return -1; +- if (mesh_flags == MESH_FLAGS_AE_A5_A6 && +- skb_copy_bits(skb, hdrlen + +- offsetof(struct ieee80211s_hdr, eaddr1), +- tmp.h_dest, 2 * ETH_ALEN) < 0) +- return -1; +- +- hdrlen += __ieee80211_get_mesh_hdrlen(mesh_flags); +- } + break; + case cpu_to_le16(IEEE80211_FCTL_FROMDS): + if ((iftype != NL80211_IFTYPE_STATION && +@@ -627,16 +652,6 @@ int ieee80211_data_to_8023_exthdr(struct + (is_multicast_ether_addr(tmp.h_dest) && + ether_addr_equal(tmp.h_source, addr))) + return -1; +- if (iftype == NL80211_IFTYPE_MESH_POINT) { +- if (mesh_flags == MESH_FLAGS_AE_A5_A6) +- return -1; +- if (mesh_flags == MESH_FLAGS_AE_A4 && +- skb_copy_bits(skb, hdrlen + +- offsetof(struct ieee80211s_hdr, eaddr1), +- tmp.h_source, ETH_ALEN) < 0) +- return -1; +- hdrlen += __ieee80211_get_mesh_hdrlen(mesh_flags); +- } + break; + case cpu_to_le16(0): + if (iftype != NL80211_IFTYPE_ADHOC && +@@ -646,7 +661,7 @@ int ieee80211_data_to_8023_exthdr(struct + break; + } + +- if (likely(!is_amsdu && ++ if (likely(!is_amsdu && iftype != NL80211_IFTYPE_MESH_POINT && + skb_copy_bits(skb, hdrlen, &payload, sizeof(payload)) == 0 && + ieee80211_get_8023_tunnel_proto(&payload, &tmp.h_proto))) { + /* remove RFC1042 or Bridge-Tunnel encapsulation */ +@@ -722,7 +737,8 @@ __ieee80211_amsdu_copy_frag(struct sk_bu + + static struct sk_buff * + __ieee80211_amsdu_copy(struct sk_buff *skb, unsigned int hlen, +- int offset, int len, bool reuse_frag) ++ int offset, int len, bool reuse_frag, ++ int min_len) + { + struct sk_buff *frame; + int cur_len = len; +@@ -736,7 +752,7 @@ __ieee80211_amsdu_copy(struct sk_buff *s + * in the stack later. + */ + if (reuse_frag) +- cur_len = min_t(int, len, 32); ++ cur_len = min_t(int, len, min_len); + + /* + * Allocate and reserve two bytes more for payload +@@ -746,6 +762,7 @@ __ieee80211_amsdu_copy(struct sk_buff *s + if (!frame) + return NULL; + ++ frame->priority = skb->priority; + skb_reserve(frame, hlen + sizeof(struct ethhdr) + 2); + skb_copy_bits(skb, offset, skb_put(frame, cur_len), cur_len); + +@@ -762,23 +779,37 @@ __ieee80211_amsdu_copy(struct sk_buff *s + void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list, + const u8 *addr, enum nl80211_iftype iftype, + const unsigned int extra_headroom, +- const u8 *check_da, const u8 *check_sa) ++ const u8 *check_da, const u8 *check_sa, ++ bool mesh_control) + { + unsigned int hlen = ALIGN(extra_headroom, 4); + struct sk_buff *frame = NULL; + int offset = 0, remaining; +- struct ethhdr eth; ++ struct { ++ struct ethhdr eth; ++ uint8_t flags; ++ } hdr; + bool reuse_frag = skb->head_frag && !skb_has_frag_list(skb); + bool reuse_skb = false; + bool last = false; ++ int copy_len = sizeof(hdr.eth); ++ ++ if (iftype == NL80211_IFTYPE_MESH_POINT) ++ copy_len = sizeof(hdr); + + while (!last) { + unsigned int subframe_len; +- int len; ++ int len, mesh_len = 0; + u8 padding; + +- skb_copy_bits(skb, offset, ð, sizeof(eth)); +- len = ntohs(eth.h_proto); ++ skb_copy_bits(skb, offset, &hdr, copy_len); ++ if (iftype == NL80211_IFTYPE_MESH_POINT) ++ mesh_len = __ieee80211_get_mesh_hdrlen(hdr.flags); ++ if (mesh_control) ++ len = le16_to_cpu(*(__le16 *)&hdr.eth.h_proto) + mesh_len; ++ else ++ len = ntohs(hdr.eth.h_proto); ++ + subframe_len = sizeof(struct ethhdr) + len; + padding = (4 - subframe_len) & 0x3; + +@@ -787,16 +818,16 @@ void ieee80211_amsdu_to_8023s(struct sk_ + if (subframe_len > remaining) + goto purge; + /* mitigate A-MSDU aggregation injection attacks */ +- if (ether_addr_equal(eth.h_dest, rfc1042_header)) ++ if (ether_addr_equal(hdr.eth.h_dest, rfc1042_header)) + goto purge; + + offset += sizeof(struct ethhdr); + last = remaining <= subframe_len + padding; + + /* FIXME: should we really accept multicast DA? */ +- if ((check_da && !is_multicast_ether_addr(eth.h_dest) && +- !ether_addr_equal(check_da, eth.h_dest)) || +- (check_sa && !ether_addr_equal(check_sa, eth.h_source))) { ++ if ((check_da && !is_multicast_ether_addr(hdr.eth.h_dest) && ++ !ether_addr_equal(check_da, hdr.eth.h_dest)) || ++ (check_sa && !ether_addr_equal(check_sa, hdr.eth.h_source))) { + offset += len + padding; + continue; + } +@@ -808,7 +839,7 @@ void ieee80211_amsdu_to_8023s(struct sk_ + reuse_skb = true; + } else { + frame = __ieee80211_amsdu_copy(skb, hlen, offset, len, +- reuse_frag); ++ reuse_frag, 32 + mesh_len); + if (!frame) + goto purge; + +@@ -819,10 +850,11 @@ void ieee80211_amsdu_to_8023s(struct sk_ + frame->dev = skb->dev; + frame->priority = skb->priority; + +- if (likely(ieee80211_get_8023_tunnel_proto(frame->data, ð.h_proto))) ++ if (likely(iftype != NL80211_IFTYPE_MESH_POINT && ++ ieee80211_get_8023_tunnel_proto(frame->data, &hdr.eth.h_proto))) + skb_pull(frame, ETH_ALEN + 2); + +- memcpy(skb_push(frame, sizeof(eth)), ð, sizeof(eth)); ++ memcpy(skb_push(frame, sizeof(hdr.eth)), &hdr.eth, sizeof(hdr.eth)); + __skb_queue_tail(list, frame); + } + diff --git a/package/kernel/mac80211/patches/subsys/316-v6.3-wifi-mac80211-add-a-workaround-for-receiving-non-sta.patch b/package/kernel/mac80211/patches/subsys/316-v6.3-wifi-mac80211-add-a-workaround-for-receiving-non-sta.patch new file mode 100644 index 000000000..6dc98ae16 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/316-v6.3-wifi-mac80211-add-a-workaround-for-receiving-non-sta.patch @@ -0,0 +1,145 @@ +From: Felix Fietkau +Date: Fri, 9 Dec 2022 21:15:04 +0100 +Subject: [PATCH] wifi: mac80211: add a workaround for receiving + non-standard mesh A-MSDU + +At least ath10k and ath11k supported hardware (maybe more) does not implement +mesh A-MSDU aggregation in a standard compliant way. +802.11-2020 9.3.2.2.2 declares that the Mesh Control field is part of the +A-MSDU header. As such, its length must not be included in the subframe +length field. +Hardware affected by this bug treats the mesh control field as part of the +MSDU data and sets the length accordingly. +In order to avoid packet loss, keep track of which stations are affected +by this and take it into account when converting A-MSDU to 802.3 + mesh control +packets. + +Signed-off-by: Felix Fietkau +--- + +--- a/include/net/cfg80211.h ++++ b/include/net/cfg80211.h +@@ -6194,6 +6194,19 @@ static inline int ieee80211_data_to_8023 + } + + /** ++ * ieee80211_is_valid_amsdu - check if subframe lengths of an A-MSDU are valid ++ * ++ * This is used to detect non-standard A-MSDU frames, e.g. the ones generated ++ * by ath10k and ath11k, where the subframe length includes the length of the ++ * mesh control field. ++ * ++ * @skb: The input A-MSDU frame without any headers. ++ * @mesh_hdr: use standard compliant mesh A-MSDU subframe header ++ * Returns: true if subframe header lengths are valid for the @mesh_hdr mode ++ */ ++bool ieee80211_is_valid_amsdu(struct sk_buff *skb, bool mesh_hdr); ++ ++/** + * ieee80211_amsdu_to_8023s - decode an IEEE 802.11n A-MSDU frame + * + * Decode an IEEE 802.11 A-MSDU and convert it to a list of 802.3 frames. +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -2899,7 +2899,6 @@ __ieee80211_rx_h_amsdu(struct ieee80211_ + static ieee80211_rx_result res; + struct ethhdr ethhdr; + const u8 *check_da = ethhdr.h_dest, *check_sa = ethhdr.h_source; +- bool mesh = false; + + if (unlikely(ieee80211_has_a4(hdr->frame_control))) { + check_da = NULL; +@@ -2917,7 +2916,6 @@ __ieee80211_rx_h_amsdu(struct ieee80211_ + case NL80211_IFTYPE_MESH_POINT: + check_sa = NULL; + check_da = NULL; +- mesh = true; + break; + default: + break; +@@ -2932,10 +2930,21 @@ __ieee80211_rx_h_amsdu(struct ieee80211_ + data_offset, true)) + return RX_DROP_UNUSABLE; + ++ if (rx->sta && rx->sta->amsdu_mesh_control < 0) { ++ bool valid_std = ieee80211_is_valid_amsdu(skb, true); ++ bool valid_nonstd = ieee80211_is_valid_amsdu(skb, false); ++ ++ if (valid_std && !valid_nonstd) ++ rx->sta->amsdu_mesh_control = 1; ++ else if (valid_nonstd && !valid_std) ++ rx->sta->amsdu_mesh_control = 0; ++ } ++ + ieee80211_amsdu_to_8023s(skb, &frame_list, dev->dev_addr, + rx->sdata->vif.type, + rx->local->hw.extra_tx_headroom, +- check_da, check_sa, mesh); ++ check_da, check_sa, ++ rx->sta->amsdu_mesh_control); + + while (!skb_queue_empty(&frame_list)) { + rx->skb = __skb_dequeue(&frame_list); +--- a/net/mac80211/sta_info.c ++++ b/net/mac80211/sta_info.c +@@ -591,6 +591,9 @@ __sta_info_alloc(struct ieee80211_sub_if + + sta->sta_state = IEEE80211_STA_NONE; + ++ if (sdata->vif.type == NL80211_IFTYPE_MESH_POINT) ++ sta->amsdu_mesh_control = -1; ++ + /* Mark TID as unreserved */ + sta->reserved_tid = IEEE80211_TID_UNRESERVED; + +--- a/net/mac80211/sta_info.h ++++ b/net/mac80211/sta_info.h +@@ -702,6 +702,7 @@ struct sta_info { + struct codel_params cparams; + + u8 reserved_tid; ++ s8 amsdu_mesh_control; + + struct cfg80211_chan_def tdls_chandef; + +--- a/net/wireless/util.c ++++ b/net/wireless/util.c +@@ -776,6 +776,38 @@ __ieee80211_amsdu_copy(struct sk_buff *s + return frame; + } + ++bool ieee80211_is_valid_amsdu(struct sk_buff *skb, bool mesh_hdr) ++{ ++ int offset = 0, remaining, subframe_len, padding; ++ ++ for (offset = 0; offset < skb->len; offset += subframe_len + padding) { ++ struct { ++ __be16 len; ++ u8 mesh_flags; ++ } hdr; ++ u16 len; ++ ++ if (skb_copy_bits(skb, offset + 2 * ETH_ALEN, &hdr, sizeof(hdr)) < 0) ++ return false; ++ ++ if (mesh_hdr) ++ len = le16_to_cpu(*(__le16 *)&hdr.len) + ++ __ieee80211_get_mesh_hdrlen(hdr.mesh_flags); ++ else ++ len = ntohs(hdr.len); ++ ++ subframe_len = sizeof(struct ethhdr) + len; ++ padding = (4 - subframe_len) & 0x3; ++ remaining = skb->len - offset; ++ ++ if (subframe_len > remaining) ++ return false; ++ } ++ ++ return true; ++} ++EXPORT_SYMBOL(ieee80211_is_valid_amsdu); ++ + void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list, + const u8 *addr, enum nl80211_iftype iftype, + const unsigned int extra_headroom, diff --git a/package/kernel/mac80211/patches/subsys/318-wifi-mac80211-fix-race-in-mesh-sequence-number-assig.patch b/package/kernel/mac80211/patches/subsys/318-wifi-mac80211-fix-race-in-mesh-sequence-number-assig.patch new file mode 100644 index 000000000..7d01ffdff --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/318-wifi-mac80211-fix-race-in-mesh-sequence-number-assig.patch @@ -0,0 +1,37 @@ +From: Felix Fietkau +Date: Wed, 15 Feb 2023 15:21:37 +0100 +Subject: [PATCH] wifi: mac80211: fix race in mesh sequence number + assignment + +Since the sequence number is shared across different tx queues, it needs +to be atomic in order to avoid accidental duplicate assignment + +Signed-off-by: Felix Fietkau +--- + +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -696,7 +696,7 @@ struct ieee80211_if_mesh { + struct mesh_stats mshstats; + struct mesh_config mshcfg; + atomic_t estab_plinks; +- u32 mesh_seqnum; ++ atomic_t mesh_seqnum; + bool accepting_plinks; + int num_gates; + struct beacon_data __rcu *beacon; +--- a/net/mac80211/mesh.c ++++ b/net/mac80211/mesh.c +@@ -752,10 +752,8 @@ unsigned int ieee80211_new_mesh_header(s + + meshhdr->ttl = sdata->u.mesh.mshcfg.dot11MeshTTL; + +- /* FIXME: racy -- TX on multiple queues can be concurrent */ +- put_unaligned(cpu_to_le32(sdata->u.mesh.mesh_seqnum), &meshhdr->seqnum); +- sdata->u.mesh.mesh_seqnum++; +- ++ put_unaligned_le32(atomic_inc_return(&sdata->u.mesh.mesh_seqnum), ++ &meshhdr->seqnum); + if (addr4or5 && !addr6) { + meshhdr->flags |= MESH_FLAGS_AE_A4; + memcpy(meshhdr->eaddr1, addr4or5, ETH_ALEN); diff --git a/package/kernel/mac80211/patches/subsys/319-wifi-mac80211-mesh-fast-xmit-support.patch b/package/kernel/mac80211/patches/subsys/319-wifi-mac80211-mesh-fast-xmit-support.patch new file mode 100644 index 000000000..968d2885f --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/319-wifi-mac80211-mesh-fast-xmit-support.patch @@ -0,0 +1,850 @@ +From: Felix Fietkau +Date: Sun, 26 Feb 2023 13:53:08 +0100 +Subject: [PATCH] wifi: mac80211: mesh fast xmit support + +Previously, fast xmit only worked on interface types where initially a +sta lookup is performed, and a cached header can be attached to the sta, +requiring only some fields to be updated at runtime. + +This technique is not directly applicable for a mesh device type due +to the dynamic nature of the topology and protocol. There are more +addresses that need to be filled, and there is an extra header with a +dynamic length based on the addressing mode. + +Change the code to cache entries contain a copy of the mesh subframe header + +bridge tunnel header, as well as an embedded struct ieee80211_fast_tx, which +contains the information for building the 802.11 header. + +Add a mesh specific early fast xmit call, which looks up a cached entry and +adds only the mesh subframe header, before passing it over to the generic +fast xmit code. + +To ensure the changes in network are reflected in these cached headers, +flush affected cached entries on path changes, as well as other conditions +that currently trigger a fast xmit check in other modes (key changes etc.) + +This code is loosely based on a previous implementation by: +Sriram R + +Signed-off-by: Ryder Lee +Signed-off-by: Felix Fietkau +--- + +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -37,6 +37,7 @@ + extern const struct cfg80211_ops mac80211_config_ops; + + struct ieee80211_local; ++struct ieee80211_mesh_fast_tx; + + /* Maximum number of broadcast/multicast frames to buffer when some of the + * associated stations are using power saving. */ +@@ -656,6 +657,19 @@ struct mesh_table { + atomic_t entries; /* Up to MAX_MESH_NEIGHBOURS */ + }; + ++/** ++ * struct mesh_tx_cache - mesh fast xmit header cache ++ * ++ * @rht: hash table containing struct ieee80211_mesh_fast_tx, using skb DA as key ++ * @walk_head: linked list containing all ieee80211_mesh_fast_tx objects ++ * @walk_lock: lock protecting walk_head and rht ++ */ ++struct mesh_tx_cache { ++ struct rhashtable rht; ++ struct hlist_head walk_head; ++ spinlock_t walk_lock; ++}; ++ + struct ieee80211_if_mesh { + struct timer_list housekeeping_timer; + struct timer_list mesh_path_timer; +@@ -734,6 +748,7 @@ struct ieee80211_if_mesh { + struct mesh_table mpp_paths; /* Store paths for MPP&MAP */ + int mesh_paths_generation; + int mpp_paths_generation; ++ struct mesh_tx_cache tx_cache; + }; + + #ifdef CPTCFG_MAC80211_MESH +@@ -2002,6 +2017,11 @@ int ieee80211_tx_control_port(struct wip + int link_id, u64 *cookie); + int ieee80211_probe_mesh_link(struct wiphy *wiphy, struct net_device *dev, + const u8 *buf, size_t len); ++void __ieee80211_xmit_fast(struct ieee80211_sub_if_data *sdata, ++ struct sta_info *sta, ++ struct ieee80211_fast_tx *fast_tx, ++ struct sk_buff *skb, bool ampdu, ++ const u8 *da, const u8 *sa); + + /* HT */ + void ieee80211_apply_htcap_overrides(struct ieee80211_sub_if_data *sdata, +--- a/net/mac80211/mesh.c ++++ b/net/mac80211/mesh.c +@@ -10,6 +10,7 @@ + #include + #include "ieee80211_i.h" + #include "mesh.h" ++#include "wme.h" + #include "driver-ops.h" + + static int mesh_allocated; +@@ -698,6 +699,95 @@ ieee80211_mesh_update_bss_params(struct + __le32_to_cpu(he_oper->he_oper_params); + } + ++bool ieee80211_mesh_xmit_fast(struct ieee80211_sub_if_data *sdata, ++ struct sk_buff *skb, u32 ctrl_flags) ++{ ++ struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; ++ struct ieee80211_mesh_fast_tx *entry; ++ struct ieee80211s_hdr *meshhdr; ++ u8 sa[ETH_ALEN] __aligned(2); ++ struct tid_ampdu_tx *tid_tx; ++ struct sta_info *sta; ++ bool copy_sa = false; ++ u16 ethertype; ++ u8 tid; ++ ++ if (ctrl_flags & IEEE80211_TX_CTRL_SKIP_MPATH_LOOKUP) ++ return false; ++ ++ if (ifmsh->mshcfg.dot11MeshNolearn) ++ return false; ++ ++ /* Add support for these cases later */ ++ if (ifmsh->ps_peers_light_sleep || ifmsh->ps_peers_deep_sleep) ++ return false; ++ ++ if (is_multicast_ether_addr(skb->data)) ++ return false; ++ ++ ethertype = (skb->data[12] << 8) | skb->data[13]; ++ if (ethertype < ETH_P_802_3_MIN) ++ return false; ++ ++ if (skb->sk && skb_shinfo(skb)->tx_flags & SKBTX_WIFI_STATUS) ++ return false; ++ ++ if (skb->ip_summed == CHECKSUM_PARTIAL) { ++ skb_set_transport_header(skb, skb_checksum_start_offset(skb)); ++ if (skb_checksum_help(skb)) ++ return false; ++ } ++ ++ entry = mesh_fast_tx_get(sdata, skb->data); ++ if (!entry) ++ return false; ++ ++ if (skb_headroom(skb) < entry->hdrlen + entry->fast_tx.hdr_len) ++ return false; ++ ++ sta = rcu_dereference(entry->mpath->next_hop); ++ if (!sta) ++ return false; ++ ++ tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK; ++ tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[tid]); ++ if (tid_tx) { ++ if (!test_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state)) ++ return false; ++ if (tid_tx->timeout) ++ tid_tx->last_tx = jiffies; ++ } ++ ++ skb = skb_share_check(skb, GFP_ATOMIC); ++ if (!skb) ++ return true; ++ ++ skb_set_queue_mapping(skb, ieee80211_select_queue(sdata, sta, skb)); ++ ++ meshhdr = (struct ieee80211s_hdr *)entry->hdr; ++ if ((meshhdr->flags & MESH_FLAGS_AE) == MESH_FLAGS_AE_A5_A6) { ++ /* preserve SA from eth header for 6-addr frames */ ++ ether_addr_copy(sa, skb->data + ETH_ALEN); ++ copy_sa = true; ++ } ++ ++ memcpy(skb_push(skb, entry->hdrlen - 2 * ETH_ALEN), entry->hdr, ++ entry->hdrlen); ++ ++ meshhdr = (struct ieee80211s_hdr *)skb->data; ++ put_unaligned_le32(atomic_inc_return(&sdata->u.mesh.mesh_seqnum), ++ &meshhdr->seqnum); ++ meshhdr->ttl = sdata->u.mesh.mshcfg.dot11MeshTTL; ++ if (copy_sa) ++ ether_addr_copy(meshhdr->eaddr2, sa); ++ ++ skb_push(skb, 2 * ETH_ALEN); ++ __ieee80211_xmit_fast(sdata, sta, &entry->fast_tx, skb, tid_tx, ++ entry->mpath->dst, sdata->vif.addr); ++ ++ return true; ++} ++ + /** + * ieee80211_fill_mesh_addresses - fill addresses of a locally originated mesh frame + * @hdr: 802.11 frame header +@@ -780,6 +870,8 @@ static void ieee80211_mesh_housekeeping( + changed = mesh_accept_plinks_update(sdata); + ieee80211_mbss_info_change_notify(sdata, changed); + ++ mesh_fast_tx_gc(sdata); ++ + mod_timer(&ifmsh->housekeeping_timer, + round_jiffies(jiffies + + IEEE80211_MESH_HOUSEKEEPING_INTERVAL)); +--- a/net/mac80211/mesh.h ++++ b/net/mac80211/mesh.h +@@ -122,11 +122,41 @@ struct mesh_path { + u8 rann_snd_addr[ETH_ALEN]; + u32 rann_metric; + unsigned long last_preq_to_root; ++ unsigned long fast_tx_check; + bool is_root; + bool is_gate; + u32 path_change_count; + }; + ++#define MESH_FAST_TX_CACHE_MAX_SIZE 512 ++#define MESH_FAST_TX_CACHE_THRESHOLD_SIZE 384 ++#define MESH_FAST_TX_CACHE_TIMEOUT 8000 /* msecs */ ++ ++/** ++ * struct ieee80211_mesh_fast_tx - cached mesh fast tx entry ++ * @rhash: rhashtable pointer ++ * @addr_key: The Ethernet DA which is the key for this entry ++ * @fast_tx: base fast_tx data ++ * @hdr: cached mesh and rfc1042 headers ++ * @hdrlen: length of mesh + rfc1042 ++ * @walk_list: list containing all the fast tx entries ++ * @mpath: mesh path corresponding to the Mesh DA ++ * @mppath: MPP entry corresponding to this DA ++ * @timestamp: Last used time of this entry ++ */ ++struct ieee80211_mesh_fast_tx { ++ struct rhash_head rhash; ++ u8 addr_key[ETH_ALEN] __aligned(2); ++ ++ struct ieee80211_fast_tx fast_tx; ++ u8 hdr[sizeof(struct ieee80211s_hdr) + sizeof(rfc1042_header)]; ++ u16 hdrlen; ++ ++ struct mesh_path *mpath, *mppath; ++ struct hlist_node walk_list; ++ unsigned long timestamp; ++}; ++ + /* Recent multicast cache */ + /* RMC_BUCKETS must be a power of 2, maximum 256 */ + #define RMC_BUCKETS 256 +@@ -298,6 +328,20 @@ void mesh_path_discard_frame(struct ieee + void mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata); + + bool mesh_action_is_path_sel(struct ieee80211_mgmt *mgmt); ++struct ieee80211_mesh_fast_tx * ++mesh_fast_tx_get(struct ieee80211_sub_if_data *sdata, const u8 *addr); ++bool ieee80211_mesh_xmit_fast(struct ieee80211_sub_if_data *sdata, ++ struct sk_buff *skb, u32 ctrl_flags); ++void mesh_fast_tx_cache(struct ieee80211_sub_if_data *sdata, ++ struct sk_buff *skb, struct mesh_path *mpath); ++void mesh_fast_tx_gc(struct ieee80211_sub_if_data *sdata); ++void mesh_fast_tx_flush_addr(struct ieee80211_sub_if_data *sdata, ++ const u8 *addr); ++void mesh_fast_tx_flush_mpath(struct mesh_path *mpath); ++void mesh_fast_tx_flush_sta(struct ieee80211_sub_if_data *sdata, ++ struct sta_info *sta); ++void mesh_path_refresh(struct ieee80211_sub_if_data *sdata, ++ struct mesh_path *mpath, const u8 *addr); + + #ifdef CPTCFG_MAC80211_MESH + static inline +--- a/net/mac80211/mesh_hwmp.c ++++ b/net/mac80211/mesh_hwmp.c +@@ -394,6 +394,7 @@ static u32 hwmp_route_info_get(struct ie + u32 orig_sn, orig_metric; + unsigned long orig_lifetime, exp_time; + u32 last_hop_metric, new_metric; ++ bool flush_mpath = false; + bool process = true; + u8 hopcount; + +@@ -491,8 +492,10 @@ static u32 hwmp_route_info_get(struct ie + } + + if (fresh_info) { +- if (rcu_access_pointer(mpath->next_hop) != sta) ++ if (rcu_access_pointer(mpath->next_hop) != sta) { + mpath->path_change_count++; ++ flush_mpath = true; ++ } + mesh_path_assign_nexthop(mpath, sta); + mpath->flags |= MESH_PATH_SN_VALID; + mpath->metric = new_metric; +@@ -502,6 +505,8 @@ static u32 hwmp_route_info_get(struct ie + mpath->hop_count = hopcount; + mesh_path_activate(mpath); + spin_unlock_bh(&mpath->state_lock); ++ if (flush_mpath) ++ mesh_fast_tx_flush_mpath(mpath); + ewma_mesh_fail_avg_init(&sta->mesh->fail_avg); + /* init it at a low value - 0 start is tricky */ + ewma_mesh_fail_avg_add(&sta->mesh->fail_avg, 1); +@@ -539,8 +544,10 @@ static u32 hwmp_route_info_get(struct ie + } + + if (fresh_info) { +- if (rcu_access_pointer(mpath->next_hop) != sta) ++ if (rcu_access_pointer(mpath->next_hop) != sta) { + mpath->path_change_count++; ++ flush_mpath = true; ++ } + mesh_path_assign_nexthop(mpath, sta); + mpath->metric = last_hop_metric; + mpath->exp_time = time_after(mpath->exp_time, exp_time) +@@ -548,6 +555,8 @@ static u32 hwmp_route_info_get(struct ie + mpath->hop_count = 1; + mesh_path_activate(mpath); + spin_unlock_bh(&mpath->state_lock); ++ if (flush_mpath) ++ mesh_fast_tx_flush_mpath(mpath); + ewma_mesh_fail_avg_init(&sta->mesh->fail_avg); + /* init it at a low value - 0 start is tricky */ + ewma_mesh_fail_avg_add(&sta->mesh->fail_avg, 1); +@@ -1215,6 +1224,20 @@ static int mesh_nexthop_lookup_nolearn(s + return 0; + } + ++void mesh_path_refresh(struct ieee80211_sub_if_data *sdata, ++ struct mesh_path *mpath, const u8 *addr) ++{ ++ if (mpath->flags & (MESH_PATH_REQ_QUEUED | MESH_PATH_FIXED | ++ MESH_PATH_RESOLVING)) ++ return; ++ ++ if (time_after(jiffies, ++ mpath->exp_time - ++ msecs_to_jiffies(sdata->u.mesh.mshcfg.path_refresh_time)) && ++ (!addr || ether_addr_equal(sdata->vif.addr, addr))) ++ mesh_queue_preq(mpath, PREQ_Q_F_START | PREQ_Q_F_REFRESH); ++} ++ + /** + * mesh_nexthop_lookup - put the appropriate next hop on a mesh frame. Calling + * this function is considered "using" the associated mpath, so preempt a path +@@ -1242,19 +1265,15 @@ int mesh_nexthop_lookup(struct ieee80211 + if (!mpath || !(mpath->flags & MESH_PATH_ACTIVE)) + return -ENOENT; + +- if (time_after(jiffies, +- mpath->exp_time - +- msecs_to_jiffies(sdata->u.mesh.mshcfg.path_refresh_time)) && +- ether_addr_equal(sdata->vif.addr, hdr->addr4) && +- !(mpath->flags & MESH_PATH_RESOLVING) && +- !(mpath->flags & MESH_PATH_FIXED)) +- mesh_queue_preq(mpath, PREQ_Q_F_START | PREQ_Q_F_REFRESH); ++ mesh_path_refresh(sdata, mpath, hdr->addr4); + + next_hop = rcu_dereference(mpath->next_hop); + if (next_hop) { + memcpy(hdr->addr1, next_hop->sta.addr, ETH_ALEN); + memcpy(hdr->addr2, sdata->vif.addr, ETH_ALEN); + ieee80211_mps_set_frame_flags(sdata, next_hop, hdr); ++ if (ieee80211_hw_check(&sdata->local->hw, SUPPORT_FAST_XMIT)) ++ mesh_fast_tx_cache(sdata, skb, mpath); + return 0; + } + +--- a/net/mac80211/mesh_pathtbl.c ++++ b/net/mac80211/mesh_pathtbl.c +@@ -14,6 +14,7 @@ + #include "wme.h" + #include "ieee80211_i.h" + #include "mesh.h" ++#include + + static void mesh_path_free_rcu(struct mesh_table *tbl, struct mesh_path *mpath); + +@@ -32,6 +33,41 @@ static const struct rhashtable_params me + .hashfn = mesh_table_hash, + }; + ++static const struct rhashtable_params fast_tx_rht_params = { ++ .nelem_hint = 10, ++ .automatic_shrinking = true, ++ .key_len = ETH_ALEN, ++ .key_offset = offsetof(struct ieee80211_mesh_fast_tx, addr_key), ++ .head_offset = offsetof(struct ieee80211_mesh_fast_tx, rhash), ++ .hashfn = mesh_table_hash, ++}; ++ ++static void __mesh_fast_tx_entry_free(void *ptr, void *tblptr) ++{ ++ struct ieee80211_mesh_fast_tx *entry = ptr; ++ ++ kfree_rcu(entry, fast_tx.rcu_head); ++} ++ ++static void mesh_fast_tx_deinit(struct ieee80211_sub_if_data *sdata) ++{ ++ struct mesh_tx_cache *cache; ++ ++ cache = &sdata->u.mesh.tx_cache; ++ rhashtable_free_and_destroy(&cache->rht, ++ __mesh_fast_tx_entry_free, NULL); ++} ++ ++static void mesh_fast_tx_init(struct ieee80211_sub_if_data *sdata) ++{ ++ struct mesh_tx_cache *cache; ++ ++ cache = &sdata->u.mesh.tx_cache; ++ rhashtable_init(&cache->rht, &fast_tx_rht_params); ++ INIT_HLIST_HEAD(&cache->walk_head); ++ spin_lock_init(&cache->walk_lock); ++} ++ + static inline bool mpath_expired(struct mesh_path *mpath) + { + return (mpath->flags & MESH_PATH_ACTIVE) && +@@ -381,6 +417,243 @@ struct mesh_path *mesh_path_new(struct i + return new_mpath; + } + ++static void mesh_fast_tx_entry_free(struct mesh_tx_cache *cache, ++ struct ieee80211_mesh_fast_tx *entry) ++{ ++ hlist_del_rcu(&entry->walk_list); ++ rhashtable_remove_fast(&cache->rht, &entry->rhash, fast_tx_rht_params); ++ kfree_rcu(entry, fast_tx.rcu_head); ++} ++ ++struct ieee80211_mesh_fast_tx * ++mesh_fast_tx_get(struct ieee80211_sub_if_data *sdata, const u8 *addr) ++{ ++ struct ieee80211_mesh_fast_tx *entry; ++ struct mesh_tx_cache *cache; ++ ++ cache = &sdata->u.mesh.tx_cache; ++ entry = rhashtable_lookup(&cache->rht, addr, fast_tx_rht_params); ++ if (!entry) ++ return NULL; ++ ++ if (!(entry->mpath->flags & MESH_PATH_ACTIVE) || ++ mpath_expired(entry->mpath)) { ++ spin_lock_bh(&cache->walk_lock); ++ entry = rhashtable_lookup(&cache->rht, addr, fast_tx_rht_params); ++ if (entry) ++ mesh_fast_tx_entry_free(cache, entry); ++ spin_unlock_bh(&cache->walk_lock); ++ return NULL; ++ } ++ ++ mesh_path_refresh(sdata, entry->mpath, NULL); ++ if (entry->mppath) ++ entry->mppath->exp_time = jiffies; ++ entry->timestamp = jiffies; ++ ++ return entry; ++} ++ ++void mesh_fast_tx_cache(struct ieee80211_sub_if_data *sdata, ++ struct sk_buff *skb, struct mesh_path *mpath) ++{ ++ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; ++ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); ++ struct ieee80211_mesh_fast_tx *entry, *prev; ++ struct ieee80211_mesh_fast_tx build = {}; ++ struct ieee80211s_hdr *meshhdr; ++ struct mesh_tx_cache *cache; ++ struct ieee80211_key *key; ++ struct mesh_path *mppath; ++ struct sta_info *sta; ++ u8 *qc; ++ ++ if (sdata->noack_map || ++ !ieee80211_is_data_qos(hdr->frame_control)) ++ return; ++ ++ build.fast_tx.hdr_len = ieee80211_hdrlen(hdr->frame_control); ++ meshhdr = (struct ieee80211s_hdr *)(skb->data + build.fast_tx.hdr_len); ++ build.hdrlen = ieee80211_get_mesh_hdrlen(meshhdr); ++ ++ cache = &sdata->u.mesh.tx_cache; ++ if (atomic_read(&cache->rht.nelems) >= MESH_FAST_TX_CACHE_MAX_SIZE) ++ return; ++ ++ sta = rcu_dereference(mpath->next_hop); ++ if (!sta) ++ return; ++ ++ if ((meshhdr->flags & MESH_FLAGS_AE) == MESH_FLAGS_AE_A5_A6) { ++ /* This is required to keep the mppath alive */ ++ mppath = mpp_path_lookup(sdata, meshhdr->eaddr1); ++ if (!mppath) ++ return; ++ build.mppath = mppath; ++ } else if (ieee80211_has_a4(hdr->frame_control)) { ++ mppath = mpath; ++ } else { ++ return; ++ } ++ ++ /* rate limit, in case fast xmit can't be enabled */ ++ if (mppath->fast_tx_check == jiffies) ++ return; ++ ++ mppath->fast_tx_check = jiffies; ++ ++ /* ++ * Same use of the sta lock as in ieee80211_check_fast_xmit, in order ++ * to protect against concurrent sta key updates. ++ */ ++ spin_lock_bh(&sta->lock); ++ key = rcu_access_pointer(sta->ptk[sta->ptk_idx]); ++ if (!key) ++ key = rcu_access_pointer(sdata->default_unicast_key); ++ build.fast_tx.key = key; ++ ++ if (key) { ++ bool gen_iv, iv_spc; ++ ++ gen_iv = key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV; ++ iv_spc = key->conf.flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE; ++ ++ if (!(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) || ++ (key->flags & KEY_FLAG_TAINTED)) ++ goto unlock_sta; ++ ++ switch (key->conf.cipher) { ++ case WLAN_CIPHER_SUITE_CCMP: ++ case WLAN_CIPHER_SUITE_CCMP_256: ++ if (gen_iv) ++ build.fast_tx.pn_offs = build.fast_tx.hdr_len; ++ if (gen_iv || iv_spc) ++ build.fast_tx.hdr_len += IEEE80211_CCMP_HDR_LEN; ++ break; ++ case WLAN_CIPHER_SUITE_GCMP: ++ case WLAN_CIPHER_SUITE_GCMP_256: ++ if (gen_iv) ++ build.fast_tx.pn_offs = build.fast_tx.hdr_len; ++ if (gen_iv || iv_spc) ++ build.fast_tx.hdr_len += IEEE80211_GCMP_HDR_LEN; ++ break; ++ default: ++ goto unlock_sta; ++ } ++ } ++ ++ memcpy(build.addr_key, mppath->dst, ETH_ALEN); ++ build.timestamp = jiffies; ++ build.fast_tx.band = info->band; ++ build.fast_tx.da_offs = offsetof(struct ieee80211_hdr, addr3); ++ build.fast_tx.sa_offs = offsetof(struct ieee80211_hdr, addr4); ++ build.mpath = mpath; ++ memcpy(build.hdr, meshhdr, build.hdrlen); ++ memcpy(build.hdr + build.hdrlen, rfc1042_header, sizeof(rfc1042_header)); ++ build.hdrlen += sizeof(rfc1042_header); ++ memcpy(build.fast_tx.hdr, hdr, build.fast_tx.hdr_len); ++ ++ hdr = (struct ieee80211_hdr *)build.fast_tx.hdr; ++ if (build.fast_tx.key) ++ hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); ++ ++ qc = ieee80211_get_qos_ctl(hdr); ++ qc[1] |= IEEE80211_QOS_CTL_MESH_CONTROL_PRESENT >> 8; ++ ++ entry = kmemdup(&build, sizeof(build), GFP_ATOMIC); ++ if (!entry) ++ goto unlock_sta; ++ ++ spin_lock(&cache->walk_lock); ++ prev = rhashtable_lookup_get_insert_fast(&cache->rht, ++ &entry->rhash, ++ fast_tx_rht_params); ++ if (unlikely(IS_ERR(prev))) { ++ kfree(entry); ++ goto unlock_cache; ++ } ++ ++ /* ++ * replace any previous entry in the hash table, in case we're ++ * replacing it with a different type (e.g. mpath -> mpp) ++ */ ++ if (unlikely(prev)) { ++ rhashtable_replace_fast(&cache->rht, &prev->rhash, ++ &entry->rhash, fast_tx_rht_params); ++ hlist_del_rcu(&prev->walk_list); ++ kfree_rcu(prev, fast_tx.rcu_head); ++ } ++ ++ hlist_add_head(&entry->walk_list, &cache->walk_head); ++ ++unlock_cache: ++ spin_unlock(&cache->walk_lock); ++unlock_sta: ++ spin_unlock_bh(&sta->lock); ++} ++ ++void mesh_fast_tx_gc(struct ieee80211_sub_if_data *sdata) ++{ ++ unsigned long timeout = msecs_to_jiffies(MESH_FAST_TX_CACHE_TIMEOUT); ++ struct mesh_tx_cache *cache; ++ struct ieee80211_mesh_fast_tx *entry; ++ struct hlist_node *n; ++ ++ cache = &sdata->u.mesh.tx_cache; ++ if (atomic_read(&cache->rht.nelems) < MESH_FAST_TX_CACHE_THRESHOLD_SIZE) ++ return; ++ ++ spin_lock_bh(&cache->walk_lock); ++ hlist_for_each_entry_safe(entry, n, &cache->walk_head, walk_list) ++ if (!time_is_after_jiffies(entry->timestamp + timeout)) ++ mesh_fast_tx_entry_free(cache, entry); ++ spin_unlock_bh(&cache->walk_lock); ++} ++ ++void mesh_fast_tx_flush_mpath(struct mesh_path *mpath) ++{ ++ struct ieee80211_sub_if_data *sdata = mpath->sdata; ++ struct mesh_tx_cache *cache = &sdata->u.mesh.tx_cache; ++ struct ieee80211_mesh_fast_tx *entry; ++ struct hlist_node *n; ++ ++ cache = &sdata->u.mesh.tx_cache; ++ spin_lock_bh(&cache->walk_lock); ++ hlist_for_each_entry_safe(entry, n, &cache->walk_head, walk_list) ++ if (entry->mpath == mpath) ++ mesh_fast_tx_entry_free(cache, entry); ++ spin_unlock_bh(&cache->walk_lock); ++} ++ ++void mesh_fast_tx_flush_sta(struct ieee80211_sub_if_data *sdata, ++ struct sta_info *sta) ++{ ++ struct mesh_tx_cache *cache = &sdata->u.mesh.tx_cache; ++ struct ieee80211_mesh_fast_tx *entry; ++ struct hlist_node *n; ++ ++ cache = &sdata->u.mesh.tx_cache; ++ spin_lock_bh(&cache->walk_lock); ++ hlist_for_each_entry_safe(entry, n, &cache->walk_head, walk_list) ++ if (rcu_access_pointer(entry->mpath->next_hop) == sta) ++ mesh_fast_tx_entry_free(cache, entry); ++ spin_unlock_bh(&cache->walk_lock); ++} ++ ++void mesh_fast_tx_flush_addr(struct ieee80211_sub_if_data *sdata, ++ const u8 *addr) ++{ ++ struct mesh_tx_cache *cache = &sdata->u.mesh.tx_cache; ++ struct ieee80211_mesh_fast_tx *entry; ++ ++ cache = &sdata->u.mesh.tx_cache; ++ spin_lock_bh(&cache->walk_lock); ++ entry = rhashtable_lookup(&cache->rht, addr, fast_tx_rht_params); ++ if (entry) ++ mesh_fast_tx_entry_free(cache, entry); ++ spin_unlock_bh(&cache->walk_lock); ++} ++ + /** + * mesh_path_add - allocate and add a new path to the mesh path table + * @dst: destination address of the path (ETH_ALEN length) +@@ -464,6 +737,8 @@ int mpp_path_add(struct ieee80211_sub_if + + if (ret) + kfree(new_mpath); ++ else ++ mesh_fast_tx_flush_addr(sdata, dst); + + sdata->u.mesh.mpp_paths_generation++; + return ret; +@@ -523,6 +798,10 @@ static void __mesh_path_del(struct mesh_ + { + hlist_del_rcu(&mpath->walk_list); + rhashtable_remove_fast(&tbl->rhead, &mpath->rhash, mesh_rht_params); ++ if (tbl == &mpath->sdata->u.mesh.mpp_paths) ++ mesh_fast_tx_flush_addr(mpath->sdata, mpath->dst); ++ else ++ mesh_fast_tx_flush_mpath(mpath); + mesh_path_free_rcu(tbl, mpath); + } + +@@ -747,6 +1026,7 @@ void mesh_path_fix_nexthop(struct mesh_p + mpath->exp_time = 0; + mpath->flags = MESH_PATH_FIXED | MESH_PATH_SN_VALID; + mesh_path_activate(mpath); ++ mesh_fast_tx_flush_mpath(mpath); + spin_unlock_bh(&mpath->state_lock); + ewma_mesh_fail_avg_init(&next_hop->mesh->fail_avg); + /* init it at a low value - 0 start is tricky */ +@@ -758,6 +1038,7 @@ void mesh_pathtbl_init(struct ieee80211_ + { + mesh_table_init(&sdata->u.mesh.mesh_paths); + mesh_table_init(&sdata->u.mesh.mpp_paths); ++ mesh_fast_tx_init(sdata); + } + + static +@@ -785,6 +1066,7 @@ void mesh_path_expire(struct ieee80211_s + + void mesh_pathtbl_unregister(struct ieee80211_sub_if_data *sdata) + { ++ mesh_fast_tx_deinit(sdata); + mesh_table_free(&sdata->u.mesh.mesh_paths); + mesh_table_free(&sdata->u.mesh.mpp_paths); + } +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -2791,6 +2791,7 @@ ieee80211_rx_mesh_data(struct ieee80211_ + if (mesh_hdr->flags & MESH_FLAGS_AE) { + struct mesh_path *mppath; + char *proxied_addr; ++ bool update = false; + + if (multicast) + proxied_addr = mesh_hdr->eaddr1; +@@ -2806,11 +2807,18 @@ ieee80211_rx_mesh_data(struct ieee80211_ + mpp_path_add(sdata, proxied_addr, eth->h_source); + } else { + spin_lock_bh(&mppath->state_lock); +- if (!ether_addr_equal(mppath->mpp, eth->h_source)) ++ if (!ether_addr_equal(mppath->mpp, eth->h_source)) { + memcpy(mppath->mpp, eth->h_source, ETH_ALEN); ++ update = true; ++ } + mppath->exp_time = jiffies; + spin_unlock_bh(&mppath->state_lock); + } ++ ++ /* flush fast xmit cache if the address path changed */ ++ if (update) ++ mesh_fast_tx_flush_addr(sdata, proxied_addr); ++ + rcu_read_unlock(); + } + +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -3022,6 +3022,9 @@ void ieee80211_check_fast_xmit(struct st + if (!ieee80211_hw_check(&local->hw, SUPPORT_FAST_XMIT)) + return; + ++ if (ieee80211_vif_is_mesh(&sdata->vif)) ++ mesh_fast_tx_flush_sta(sdata, sta); ++ + /* Locking here protects both the pointer itself, and against concurrent + * invocations winning data access races to, e.g., the key pointer that + * is used. +@@ -3403,6 +3406,9 @@ static bool ieee80211_amsdu_aggregate(st + if (sdata->vif.offload_flags & IEEE80211_OFFLOAD_ENCAP_ENABLED) + return false; + ++ if (ieee80211_vif_is_mesh(&sdata->vif)) ++ return false; ++ + if (skb_is_gso(skb)) + return false; + +@@ -3635,10 +3641,11 @@ free: + return NULL; + } + +-static void __ieee80211_xmit_fast(struct ieee80211_sub_if_data *sdata, +- struct sta_info *sta, +- struct ieee80211_fast_tx *fast_tx, +- struct sk_buff *skb, u8 tid, bool ampdu) ++void __ieee80211_xmit_fast(struct ieee80211_sub_if_data *sdata, ++ struct sta_info *sta, ++ struct ieee80211_fast_tx *fast_tx, ++ struct sk_buff *skb, bool ampdu, ++ const u8 *da, const u8 *sa) + { + struct ieee80211_local *local = sdata->local; + struct ieee80211_hdr *hdr = (void *)fast_tx->hdr; +@@ -3647,7 +3654,6 @@ static void __ieee80211_xmit_fast(struct + ieee80211_tx_result r; + int hw_headroom = sdata->local->hw.extra_tx_headroom; + int extra_head = fast_tx->hdr_len - (ETH_HLEN - 2); +- struct ethhdr eth; + + skb = skb_share_check(skb, GFP_ATOMIC); + if (unlikely(!skb)) +@@ -3667,11 +3673,10 @@ static void __ieee80211_xmit_fast(struct + ENCRYPT_NO))) + goto free; + +- memcpy(ð, skb->data, ETH_HLEN - 2); + hdr = skb_push(skb, extra_head); + memcpy(skb->data, fast_tx->hdr, fast_tx->hdr_len); +- memcpy(skb->data + fast_tx->da_offs, eth.h_dest, ETH_ALEN); +- memcpy(skb->data + fast_tx->sa_offs, eth.h_source, ETH_ALEN); ++ memcpy(skb->data + fast_tx->da_offs, da, ETH_ALEN); ++ memcpy(skb->data + fast_tx->sa_offs, sa, ETH_ALEN); + + info = IEEE80211_SKB_CB(skb); + memset(info, 0, sizeof(*info)); +@@ -3690,7 +3695,8 @@ static void __ieee80211_xmit_fast(struct + #endif + + if (hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_QOS_DATA)) { +- tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK; ++ u8 tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK; ++ + *ieee80211_get_qos_ctl(hdr) = tid; + } + +@@ -3733,6 +3739,7 @@ static bool ieee80211_xmit_fast(struct i + struct ieee80211_hdr *hdr = (void *)fast_tx->hdr; + struct tid_ampdu_tx *tid_tx = NULL; + struct sk_buff *next; ++ struct ethhdr eth; + u8 tid = IEEE80211_NUM_TIDS; + + /* control port protocol needs a lot of special handling */ +@@ -3758,6 +3765,8 @@ static bool ieee80211_xmit_fast(struct i + } + } + ++ memcpy(ð, skb->data, ETH_HLEN - 2); ++ + /* after this point (skb is modified) we cannot return false */ + skb = ieee80211_tx_skb_fixup(skb, ieee80211_sdata_netdev_features(sdata)); + if (!skb) +@@ -3765,7 +3774,8 @@ static bool ieee80211_xmit_fast(struct i + + skb_list_walk_safe(skb, skb, next) { + skb_mark_not_on_list(skb); +- __ieee80211_xmit_fast(sdata, sta, fast_tx, skb, tid, tid_tx); ++ __ieee80211_xmit_fast(sdata, sta, fast_tx, skb, tid_tx, ++ eth.h_dest, eth.h_source); + } + + return true; +@@ -4252,8 +4262,15 @@ void __ieee80211_subif_start_xmit(struct + return; + } + ++ sk_pacing_shift_update(skb->sk, sdata->local->hw.tx_sk_pacing_shift); ++ + rcu_read_lock(); + ++ if (ieee80211_vif_is_mesh(&sdata->vif) && ++ ieee80211_hw_check(&local->hw, SUPPORT_FAST_XMIT) && ++ ieee80211_mesh_xmit_fast(sdata, skb, ctrl_flags)) ++ goto out; ++ + if (ieee80211_lookup_ra_sta(sdata, skb, &sta)) + goto out_free; + +@@ -4263,8 +4280,6 @@ void __ieee80211_subif_start_xmit(struct + skb_set_queue_mapping(skb, ieee80211_select_queue(sdata, sta, skb)); + ieee80211_aggr_check(sdata, sta, skb); + +- sk_pacing_shift_update(skb->sk, sdata->local->hw.tx_sk_pacing_shift); +- + if (sta) { + struct ieee80211_fast_tx *fast_tx; + diff --git a/package/kernel/mac80211/patches/subsys/320-cfg80211-allow-grace-period-for-DFS-available-after-.patch b/package/kernel/mac80211/patches/subsys/320-cfg80211-allow-grace-period-for-DFS-available-after-.patch deleted file mode 100644 index 39f23f783..000000000 --- a/package/kernel/mac80211/patches/subsys/320-cfg80211-allow-grace-period-for-DFS-available-after-.patch +++ /dev/null @@ -1,149 +0,0 @@ -From: Felix Fietkau -Date: Thu, 14 Sep 2023 13:17:16 +0200 -Subject: [PATCH] cfg80211: allow grace period for DFS available after beacon - shutdown - -Fixes reconfiguring an AP on a DFS channel in non-ETSI regdomain - -Fixes: b35a51c7dd25 ("cfg80211: Make pre-CAC results valid only for ETSI domain") -Signed-off-by: Felix Fietkau ---- - ---- a/include/net/cfg80211.h -+++ b/include/net/cfg80211.h -@@ -189,6 +189,8 @@ enum ieee80211_channel_flags { - * @dfs_state: current state of this channel. Only relevant if radar is required - * on this channel. - * @dfs_state_entered: timestamp (jiffies) when the dfs state was entered. -+ * @dfs_state_last_available: timestamp (jiffies) of the last time when the -+ * channel was available. - * @dfs_cac_ms: DFS CAC time in milliseconds, this is valid for DFS channels. - * @psd: power spectral density (in dBm) - */ -@@ -206,6 +208,7 @@ struct ieee80211_channel { - int orig_mag, orig_mpwr; - enum nl80211_dfs_state dfs_state; - unsigned long dfs_state_entered; -+ unsigned long dfs_state_last_available; - unsigned int dfs_cac_ms; - s8 psd; - }; ---- a/net/wireless/ap.c -+++ b/net/wireless/ap.c -@@ -30,6 +30,9 @@ static int ___cfg80211_stop_ap(struct cf - if (!wdev->links[link_id].ap.beacon_interval) - return -ENOENT; - -+ cfg80211_update_last_available(wdev->wiphy, -+ &wdev->links[link_id].ap.chandef); -+ - err = rdev_stop_ap(rdev, dev, link_id); - if (!err) { - wdev->conn_owner_nlportid = 0; -@@ -41,9 +44,6 @@ static int ___cfg80211_stop_ap(struct cf - if (notify) - nl80211_send_ap_stopped(wdev, link_id); - -- /* Should we apply the grace period during beaconing interface -- * shutdown also? -- */ - cfg80211_sched_dfs_chan_update(rdev); - } - ---- a/net/wireless/chan.c -+++ b/net/wireless/chan.c -@@ -560,6 +560,8 @@ static void cfg80211_set_chans_dfs_state - - c->dfs_state = dfs_state; - c->dfs_state_entered = jiffies; -+ if (dfs_state == NL80211_DFS_AVAILABLE) -+ c->dfs_state_last_available = jiffies; - } - } - -@@ -1049,6 +1051,49 @@ static bool cfg80211_get_chans_dfs_avail - return true; - } - -+static void -+__cfg80211_update_last_available(struct wiphy *wiphy, -+ u32 center_freq, -+ u32 bandwidth) -+{ -+ struct ieee80211_channel *c; -+ u32 freq, start_freq, end_freq; -+ -+ start_freq = cfg80211_get_start_freq(center_freq, bandwidth); -+ end_freq = cfg80211_get_end_freq(center_freq, bandwidth); -+ -+ /* -+ * Check entire range of channels for the bandwidth. -+ * If any channel in between is disabled or has not -+ * had gone through CAC return false -+ */ -+ for (freq = start_freq; freq <= end_freq; freq += MHZ_TO_KHZ(20)) { -+ c = ieee80211_get_channel_khz(wiphy, freq); -+ if (!c) -+ return; -+ -+ c->dfs_state_last_available = jiffies; -+ } -+} -+ -+void cfg80211_update_last_available(struct wiphy *wiphy, -+ const struct cfg80211_chan_def *chandef) -+{ -+ int width; -+ -+ width = cfg80211_chandef_get_width(chandef); -+ if (width < 0) -+ return; -+ -+ __cfg80211_update_last_available(wiphy, MHZ_TO_KHZ(chandef->center_freq1), -+ width); -+ if (chandef->width != NL80211_CHAN_WIDTH_80P80) -+ return; -+ -+ __cfg80211_update_last_available(wiphy, MHZ_TO_KHZ(chandef->center_freq2), -+ width); -+} -+ - static bool cfg80211_chandef_dfs_available(struct wiphy *wiphy, - const struct cfg80211_chan_def *chandef) - { ---- a/net/wireless/core.h -+++ b/net/wireless/core.h -@@ -467,6 +467,8 @@ void cfg80211_set_dfs_state(struct wiphy - enum nl80211_dfs_state dfs_state); - - void cfg80211_dfs_channels_update_work(struct work_struct *work); -+void cfg80211_update_last_available(struct wiphy *wiphy, -+ const struct cfg80211_chan_def *chandef); - - void cfg80211_sched_dfs_chan_update(struct cfg80211_registered_device *rdev); - ---- a/net/wireless/mlme.c -+++ b/net/wireless/mlme.c -@@ -1037,6 +1037,8 @@ void cfg80211_dfs_channels_update_work(s - if (c->dfs_state == NL80211_DFS_UNAVAILABLE) { - time_dfs_update = IEEE80211_DFS_MIN_NOP_TIME_MS; - radar_event = NL80211_RADAR_NOP_FINISHED; -+ timeout = c->dfs_state_entered + -+ msecs_to_jiffies(time_dfs_update); - } else { - if (regulatory_pre_cac_allowed(wiphy) || - cfg80211_any_wiphy_oper_chan(wiphy, c)) -@@ -1044,11 +1046,10 @@ void cfg80211_dfs_channels_update_work(s - - time_dfs_update = REG_PRE_CAC_EXPIRY_GRACE_MS; - radar_event = NL80211_RADAR_PRE_CAC_EXPIRED; -+ timeout = c->dfs_state_last_available + -+ msecs_to_jiffies(time_dfs_update); - } - -- timeout = c->dfs_state_entered + -- msecs_to_jiffies(time_dfs_update); -- - if (time_after_eq(jiffies, timeout)) { - c->dfs_state = NL80211_DFS_USABLE; - c->dfs_state_entered = jiffies; diff --git a/package/kernel/mac80211/patches/subsys/320-wifi-mac80211-use-mesh-header-cache-to-speed-up-mesh.patch b/package/kernel/mac80211/patches/subsys/320-wifi-mac80211-use-mesh-header-cache-to-speed-up-mesh.patch new file mode 100644 index 000000000..28b1ff110 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/320-wifi-mac80211-use-mesh-header-cache-to-speed-up-mesh.patch @@ -0,0 +1,132 @@ +From: Felix Fietkau +Date: Thu, 16 Feb 2023 11:07:30 +0100 +Subject: [PATCH] wifi: mac80211: use mesh header cache to speed up mesh + forwarding + +Significantly reduces mesh forwarding path CPU usage and enables the +direct use of iTXQ. + +Signed-off-by: Felix Fietkau +--- + +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -2720,6 +2720,65 @@ ieee80211_deliver_skb(struct ieee80211_r + } + } + ++#ifdef CPTCFG_MAC80211_MESH ++static bool ++ieee80211_rx_mesh_fast_forward(struct ieee80211_sub_if_data *sdata, ++ struct sk_buff *skb, int hdrlen) ++{ ++ struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; ++ struct ieee80211_mesh_fast_tx *entry = NULL; ++ struct ieee80211s_hdr *mesh_hdr; ++ struct tid_ampdu_tx *tid_tx; ++ struct sta_info *sta; ++ struct ethhdr eth; ++ u8 tid; ++ ++ mesh_hdr = (struct ieee80211s_hdr *)(skb->data + sizeof(eth)); ++ if ((mesh_hdr->flags & MESH_FLAGS_AE) == MESH_FLAGS_AE_A5_A6) ++ entry = mesh_fast_tx_get(sdata, mesh_hdr->eaddr1); ++ else if (!(mesh_hdr->flags & MESH_FLAGS_AE)) ++ entry = mesh_fast_tx_get(sdata, skb->data); ++ if (!entry) ++ return false; ++ ++ sta = rcu_dereference(entry->mpath->next_hop); ++ if (!sta) ++ return false; ++ ++ if (skb_linearize(skb)) ++ return false; ++ ++ tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK; ++ tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[tid]); ++ if (tid_tx) { ++ if (!test_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state)) ++ return false; ++ ++ if (tid_tx->timeout) ++ tid_tx->last_tx = jiffies; ++ } ++ ++ ieee80211_aggr_check(sdata, sta, skb); ++ ++ if (ieee80211_get_8023_tunnel_proto(skb->data + hdrlen, ++ &skb->protocol)) ++ hdrlen += ETH_ALEN; ++ else ++ skb->protocol = htons(skb->len - hdrlen); ++ skb_set_network_header(skb, hdrlen + 2); ++ ++ skb->dev = sdata->dev; ++ memcpy(ð, skb->data, ETH_HLEN - 2); ++ skb_pull(skb, 2); ++ __ieee80211_xmit_fast(sdata, sta, &entry->fast_tx, skb, tid_tx, ++ eth.h_dest, eth.h_source); ++ IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_unicast); ++ IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_frames); ++ ++ return true; ++} ++#endif ++ + static ieee80211_rx_result + ieee80211_rx_mesh_data(struct ieee80211_sub_if_data *sdata, struct sta_info *sta, + struct sk_buff *skb) +@@ -2824,6 +2883,10 @@ ieee80211_rx_mesh_data(struct ieee80211_ + + skb_set_queue_mapping(skb, ieee802_1d_to_ac[skb->priority]); + ++ if (!multicast && ++ ieee80211_rx_mesh_fast_forward(sdata, skb, mesh_hdrlen)) ++ return RX_QUEUED; ++ + ieee80211_fill_mesh_addresses(&hdr, &hdr.frame_control, + eth->h_dest, eth->h_source); + hdrlen = ieee80211_hdrlen(hdr.frame_control); +@@ -2862,6 +2925,7 @@ ieee80211_rx_mesh_data(struct ieee80211_ + info->control.flags |= IEEE80211_TX_INTCFL_NEED_TXPROCESSING; + info->control.vif = &sdata->vif; + info->control.jiffies = jiffies; ++ fwd_skb->dev = sdata->dev; + if (multicast) { + IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_mcast); + memcpy(fwd_hdr->addr2, sdata->vif.addr, ETH_ALEN); +@@ -2883,7 +2947,6 @@ ieee80211_rx_mesh_data(struct ieee80211_ + } + + IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_frames); +- fwd_skb->dev = sdata->dev; + ieee80211_add_pending_skb(local, fwd_skb); + + rx_accept: +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -2022,6 +2022,8 @@ void __ieee80211_xmit_fast(struct ieee80 + struct ieee80211_fast_tx *fast_tx, + struct sk_buff *skb, bool ampdu, + const u8 *da, const u8 *sa); ++void ieee80211_aggr_check(struct ieee80211_sub_if_data *sdata, ++ struct sta_info *sta, struct sk_buff *skb); + + /* HT */ + void ieee80211_apply_htcap_overrides(struct ieee80211_sub_if_data *sdata, +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -1191,10 +1191,8 @@ static bool ieee80211_tx_prep_agg(struct + return queued; + } + +-static void +-ieee80211_aggr_check(struct ieee80211_sub_if_data *sdata, +- struct sta_info *sta, +- struct sk_buff *skb) ++void ieee80211_aggr_check(struct ieee80211_sub_if_data *sdata, ++ struct sta_info *sta, struct sk_buff *skb) + { + struct rate_control_ref *ref = sdata->local->rate_ctrl; + u16 tid; diff --git a/package/kernel/mac80211/patches/subsys/321-mac80211-fix-mesh-forwarding.patch b/package/kernel/mac80211/patches/subsys/321-mac80211-fix-mesh-forwarding.patch new file mode 100644 index 000000000..e2b268ae4 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/321-mac80211-fix-mesh-forwarding.patch @@ -0,0 +1,32 @@ +From: Felix Fietkau +Date: Mon, 20 Feb 2023 12:50:50 +0100 +Subject: [PATCH] mac80211: fix mesh forwarding + +Linearize packets (needed for forwarding A-MSDU subframes). +Fix network header offset to fix flow dissector (and fair queueing). + +Fixes: 986e43b19ae9 ("wifi: mac80211: fix receiving A-MSDU frames on mesh interfaces") +Signed-off-by: Felix Fietkau +--- + +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -2904,6 +2904,9 @@ ieee80211_rx_mesh_data(struct ieee80211_ + + if (skb_cow_head(fwd_skb, hdrlen - sizeof(struct ethhdr))) + return RX_DROP_UNUSABLE; ++ ++ if (skb_linearize(fwd_skb)) ++ return RX_DROP_UNUSABLE; + } + + fwd_hdr = skb_push(fwd_skb, hdrlen - sizeof(struct ethhdr)); +@@ -2918,7 +2921,7 @@ ieee80211_rx_mesh_data(struct ieee80211_ + hdrlen += ETH_ALEN; + else + fwd_skb->protocol = htons(fwd_skb->len - hdrlen); +- skb_set_network_header(fwd_skb, hdrlen); ++ skb_set_network_header(fwd_skb, hdrlen + 2); + + info = IEEE80211_SKB_CB(fwd_skb); + memset(info, 0, sizeof(*info)); diff --git a/package/kernel/mac80211/patches/subsys/322-wifi-mac80211-fix-mesh-path-discovery-based-on-unica.patch b/package/kernel/mac80211/patches/subsys/322-wifi-mac80211-fix-mesh-path-discovery-based-on-unica.patch new file mode 100644 index 000000000..292a89ef9 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/322-wifi-mac80211-fix-mesh-path-discovery-based-on-unica.patch @@ -0,0 +1,52 @@ +From: Felix Fietkau +Date: Sun, 26 Feb 2023 20:30:20 +0100 +Subject: [PATCH] wifi: mac80211: fix mesh path discovery based on unicast + packets + +If a packet has reached its intended destination, it was bumped to the code +that accepts it, without first checking if a mesh_path needs to be created +based on the discovered source. +Fix this by moving the destination address check further down + +Fixes: 986e43b19ae9 ("wifi: mac80211: fix receiving A-MSDU frames on mesh interfaces") +Signed-off-by: Felix Fietkau +--- + +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -2824,17 +2824,6 @@ ieee80211_rx_mesh_data(struct ieee80211_ + mesh_rmc_check(sdata, eth->h_source, mesh_hdr)) + return RX_DROP_MONITOR; + +- /* Frame has reached destination. Don't forward */ +- if (ether_addr_equal(sdata->vif.addr, eth->h_dest)) +- goto rx_accept; +- +- if (!ifmsh->mshcfg.dot11MeshForwarding) { +- if (is_multicast_ether_addr(eth->h_dest)) +- goto rx_accept; +- +- return RX_DROP_MONITOR; +- } +- + /* forward packet */ + if (sdata->crypto_tx_tailroom_needed_cnt) + tailroom = IEEE80211_ENCRYPT_TAILROOM; +@@ -2881,6 +2870,17 @@ ieee80211_rx_mesh_data(struct ieee80211_ + rcu_read_unlock(); + } + ++ /* Frame has reached destination. Don't forward */ ++ if (ether_addr_equal(sdata->vif.addr, eth->h_dest)) ++ goto rx_accept; ++ ++ if (!ifmsh->mshcfg.dot11MeshForwarding) { ++ if (is_multicast_ether_addr(eth->h_dest)) ++ goto rx_accept; ++ ++ return RX_DROP_MONITOR; ++ } ++ + skb_set_queue_mapping(skb, ieee802_1d_to_ac[skb->priority]); + + if (!multicast && diff --git a/package/kernel/mac80211/patches/subsys/323-v6.3-wifi-mac80211-Add-VHT-MU-MIMO-related-flags-in-ieee8.patch b/package/kernel/mac80211/patches/subsys/323-v6.3-wifi-mac80211-Add-VHT-MU-MIMO-related-flags-in-ieee8.patch new file mode 100644 index 000000000..e23dc4d22 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/323-v6.3-wifi-mac80211-Add-VHT-MU-MIMO-related-flags-in-ieee8.patch @@ -0,0 +1,68 @@ +From: Muna Sinada +Date: Wed, 5 Oct 2022 14:54:45 -0700 +Subject: [PATCH] wifi: mac80211: Add VHT MU-MIMO related flags in + ieee80211_bss_conf + +Adding flags for SU Beamformer, SU Beamformee, MU Beamformer and +MU Beamformee for VHT. This is utilized to pass MU-MIMO +configurations from user space to driver in AP mode. + +Signed-off-by: Muna Sinada +Link: https://lore.kernel.org/r/1665006886-23874-1-git-send-email-quic_msinada@quicinc.com +[fixed indentation, removed redundant !!] +Signed-off-by: Johannes Berg +--- + +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -653,6 +653,14 @@ struct ieee80211_fils_discovery { + * write-protected by sdata_lock and local->mtx so holding either is fine + * for read access. + * @color_change_color: the bss color that will be used after the change. ++ * @vht_su_beamformer: in AP mode, does this BSS support operation as an VHT SU ++ * beamformer ++ * @vht_su_beamformee: in AP mode, does this BSS support operation as an VHT SU ++ * beamformee ++ * @vht_mu_beamformer: in AP mode, does this BSS support operation as an VHT MU ++ * beamformer ++ * @vht_mu_beamformee: in AP mode, does this BSS support operation as an VHT MU ++ * beamformee + */ + struct ieee80211_bss_conf { + const u8 *bssid; +@@ -726,6 +734,11 @@ struct ieee80211_bss_conf { + + bool color_change_active; + u8 color_change_color; ++ ++ bool vht_su_beamformer; ++ bool vht_su_beamformee; ++ bool vht_mu_beamformer; ++ bool vht_mu_beamformee; + }; + + /** +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -1252,6 +1252,21 @@ static int ieee80211_start_ap(struct wip + prev_beacon_int = link_conf->beacon_int; + link_conf->beacon_int = params->beacon_interval; + ++ if (params->vht_cap) { ++ link_conf->vht_su_beamformer = ++ params->vht_cap->vht_cap_info & ++ cpu_to_le32(IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE); ++ link_conf->vht_su_beamformee = ++ params->vht_cap->vht_cap_info & ++ cpu_to_le32(IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE); ++ link_conf->vht_mu_beamformer = ++ params->vht_cap->vht_cap_info & ++ cpu_to_le32(IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE); ++ link_conf->vht_mu_beamformee = ++ params->vht_cap->vht_cap_info & ++ cpu_to_le32(IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE); ++ } ++ + if (params->he_cap && params->he_oper) { + link_conf->he_support = true; + link_conf->htc_trig_based_pkt_ext = diff --git a/package/kernel/mac80211/patches/subsys/324-v6.3-wifi-mac80211-Add-HE-MU-MIMO-related-flags-in-ieee80.patch b/package/kernel/mac80211/patches/subsys/324-v6.3-wifi-mac80211-Add-HE-MU-MIMO-related-flags-in-ieee80.patch new file mode 100644 index 000000000..f843dba12 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/324-v6.3-wifi-mac80211-Add-HE-MU-MIMO-related-flags-in-ieee80.patch @@ -0,0 +1,68 @@ +From: Muna Sinada +Date: Wed, 5 Oct 2022 14:54:46 -0700 +Subject: [PATCH] wifi: mac80211: Add HE MU-MIMO related flags in + ieee80211_bss_conf + +Adding flags for SU Beamformer, SU Beamformee, MU Beamformer and Full +Bandwidth UL MU-MIMO for HE. This is utilized to pass MU-MIMO +configurations from user space to driver in AP mode. + +Signed-off-by: Muna Sinada +Link: https://lore.kernel.org/r/1665006886-23874-2-git-send-email-quic_msinada@quicinc.com +[fixed indentation, removed redundant !!] +Signed-off-by: Johannes Berg +--- + +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -661,6 +661,15 @@ struct ieee80211_fils_discovery { + * beamformer + * @vht_mu_beamformee: in AP mode, does this BSS support operation as an VHT MU + * beamformee ++ * @he_su_beamformer: in AP-mode, does this BSS support operation as an HE SU ++ * beamformer ++ * @he_su_beamformee: in AP-mode, does this BSS support operation as an HE SU ++ * beamformee ++ * @he_mu_beamformer: in AP-mode, does this BSS support operation as an HE MU ++ * beamformer ++ * @he_full_ul_mumimo: does this BSS support the reception (AP) or transmission ++ * (non-AP STA) of an HE TB PPDU on an RU that spans the entire PPDU ++ * bandwidth + */ + struct ieee80211_bss_conf { + const u8 *bssid; +@@ -739,6 +748,10 @@ struct ieee80211_bss_conf { + bool vht_su_beamformee; + bool vht_mu_beamformer; + bool vht_mu_beamformee; ++ bool he_su_beamformer; ++ bool he_su_beamformee; ++ bool he_mu_beamformer; ++ bool he_full_ul_mumimo; + }; + + /** +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -1281,6 +1281,21 @@ static int ieee80211_start_ap(struct wip + changed |= BSS_CHANGED_HE_BSS_COLOR; + } + ++ if (params->he_cap) { ++ link_conf->he_su_beamformer = ++ params->he_cap->phy_cap_info[3] & ++ IEEE80211_HE_PHY_CAP3_SU_BEAMFORMER; ++ link_conf->he_su_beamformee = ++ params->he_cap->phy_cap_info[4] & ++ IEEE80211_HE_PHY_CAP4_SU_BEAMFORMEE; ++ link_conf->he_mu_beamformer = ++ params->he_cap->phy_cap_info[4] & ++ IEEE80211_HE_PHY_CAP4_MU_BEAMFORMER; ++ link_conf->he_full_ul_mumimo = ++ params->he_cap->phy_cap_info[2] & ++ IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO; ++ } ++ + if (sdata->vif.type == NL80211_IFTYPE_AP && + params->mbssid_config.tx_wdev) { + err = ieee80211_set_ap_mbssid_options(sdata, diff --git a/package/kernel/mac80211/patches/subsys/325-wifi-mac80211-introduce-ieee80211_refresh_tx_agg_ses.patch b/package/kernel/mac80211/patches/subsys/325-wifi-mac80211-introduce-ieee80211_refresh_tx_agg_ses.patch new file mode 100644 index 000000000..1be5fcfbf --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/325-wifi-mac80211-introduce-ieee80211_refresh_tx_agg_ses.patch @@ -0,0 +1,60 @@ +From: Ryder Lee +Date: Sat, 18 Feb 2023 01:50:05 +0800 +Subject: [PATCH] wifi: mac80211: introduce + ieee80211_refresh_tx_agg_session_timer() + +This allows low level drivers to refresh the tx agg session timer, based on +querying stats from the firmware usually. Especially for some mt76 devices +support .net_fill_forward_path would bypass mac80211, which leads to tx BA +session timeout for certain clients. + +Signed-off-by: Ryder Lee +--- + +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -5964,6 +5964,18 @@ void ieee80211_queue_delayed_work(struct + unsigned long delay); + + /** ++ * ieee80211_refresh_tx_agg_session_timer - Refresh a tx agg session timer. ++ * @sta: the station for which to start a BA session ++ * @tid: the TID to BA on. ++ * ++ * This function allows low level driver to refresh tx agg session timer ++ * to maintain BA session, the session level will still be managed by the ++ * mac80211. ++ */ ++void ieee80211_refresh_tx_agg_session_timer(struct ieee80211_sta *sta, ++ u16 tid); ++ ++/** + * ieee80211_start_tx_ba_session - Start a tx Block Ack session. + * @sta: the station for which to start a BA session + * @tid: the TID to BA on. +--- a/net/mac80211/agg-tx.c ++++ b/net/mac80211/agg-tx.c +@@ -554,6 +554,23 @@ void ieee80211_tx_ba_session_handle_star + ieee80211_send_addba_with_timeout(sta, tid_tx); + } + ++void ieee80211_refresh_tx_agg_session_timer(struct ieee80211_sta *pubsta, ++ u16 tid) ++{ ++ struct sta_info *sta = container_of(pubsta, struct sta_info, sta); ++ struct tid_ampdu_tx *tid_tx; ++ ++ if (WARN_ON_ONCE(tid >= IEEE80211_NUM_TIDS)) ++ return; ++ ++ tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[tid]); ++ if (!tid_tx) ++ return; ++ ++ tid_tx->last_tx = jiffies; ++} ++EXPORT_SYMBOL(ieee80211_refresh_tx_agg_session_timer); ++ + /* + * After accepting the AddBA Response we activated a timer, + * resetting it after each frame that we send. diff --git a/package/kernel/mac80211/patches/subsys/326-wifi-mac80211-add-mesh-fast-rx-support.patch b/package/kernel/mac80211/patches/subsys/326-wifi-mac80211-add-mesh-fast-rx-support.patch new file mode 100644 index 000000000..11f39c2d1 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/326-wifi-mac80211-add-mesh-fast-rx-support.patch @@ -0,0 +1,77 @@ +From: Felix Fietkau +Date: Thu, 2 Mar 2023 13:52:29 +0100 +Subject: [PATCH] wifi: mac80211: add mesh fast-rx support + +This helps bring down rx CPU usage by avoiding calls to the rx handlers in +the slow path. Supports forwarding and local rx, including A-MSDU. + +Signed-off-by: Felix Fietkau +--- + +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -4564,6 +4564,12 @@ void ieee80211_check_fast_rx(struct sta_ + } + + break; ++ case NL80211_IFTYPE_MESH_POINT: ++ fastrx.expected_ds_bits = cpu_to_le16(IEEE80211_FCTL_FROMDS | ++ IEEE80211_FCTL_TODS); ++ fastrx.da_offs = offsetof(struct ieee80211_hdr, addr3); ++ fastrx.sa_offs = offsetof(struct ieee80211_hdr, addr4); ++ break; + default: + goto clear; + } +@@ -4772,6 +4778,7 @@ static bool ieee80211_invoke_fast_rx(str + struct sk_buff *skb = rx->skb; + struct ieee80211_hdr *hdr = (void *)skb->data; + struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); ++ static ieee80211_rx_result res; + int orig_len = skb->len; + int hdrlen = ieee80211_hdrlen(hdr->frame_control); + int snap_offs = hdrlen; +@@ -4833,7 +4840,8 @@ static bool ieee80211_invoke_fast_rx(str + snap_offs += IEEE80211_CCMP_HDR_LEN; + } + +- if (!(status->rx_flags & IEEE80211_RX_AMSDU)) { ++ if (!ieee80211_vif_is_mesh(&rx->sdata->vif) && ++ !(status->rx_flags & IEEE80211_RX_AMSDU)) { + if (!pskb_may_pull(skb, snap_offs + sizeof(*payload))) + return false; + +@@ -4872,13 +4880,29 @@ static bool ieee80211_invoke_fast_rx(str + /* do the header conversion - first grab the addresses */ + ether_addr_copy(addrs.da, skb->data + fast_rx->da_offs); + ether_addr_copy(addrs.sa, skb->data + fast_rx->sa_offs); +- skb_postpull_rcsum(skb, skb->data + snap_offs, +- sizeof(rfc1042_header) + 2); +- /* remove the SNAP but leave the ethertype */ +- skb_pull(skb, snap_offs + sizeof(rfc1042_header)); ++ if (ieee80211_vif_is_mesh(&rx->sdata->vif)) { ++ skb_pull(skb, snap_offs - 2); ++ put_unaligned_be16(skb->len - 2, skb->data); ++ } else { ++ skb_postpull_rcsum(skb, skb->data + snap_offs, ++ sizeof(rfc1042_header) + 2); ++ ++ /* remove the SNAP but leave the ethertype */ ++ skb_pull(skb, snap_offs + sizeof(rfc1042_header)); ++ } + /* push the addresses in front */ + memcpy(skb_push(skb, sizeof(addrs)), &addrs, sizeof(addrs)); + ++ res = ieee80211_rx_mesh_data(rx->sdata, rx->sta, rx->skb); ++ switch (res) { ++ case RX_QUEUED: ++ return true; ++ case RX_CONTINUE: ++ break; ++ default: ++ goto drop; ++ } ++ + ieee80211_rx_8023(rx, fast_rx, orig_len); + + return true; diff --git a/package/kernel/mac80211/patches/subsys/327-wifi-mac80211-add-support-for-letting-drivers-regist.patch b/package/kernel/mac80211/patches/subsys/327-wifi-mac80211-add-support-for-letting-drivers-regist.patch new file mode 100644 index 000000000..ac290b536 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/327-wifi-mac80211-add-support-for-letting-drivers-regist.patch @@ -0,0 +1,149 @@ +From: Felix Fietkau +Date: Mon, 20 Mar 2023 14:28:08 +0100 +Subject: [PATCH] wifi: mac80211: add support for letting drivers register tc + offload support + +On newer MediaTek SoCs (e.g. MT7986), WLAN->WLAN or WLAN->Ethernet flows can +be offloaded by the SoC. In order to support that, the .ndo_setup_tc op is +needed. + +Signed-off-by: Felix Fietkau +--- + +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -4192,6 +4192,10 @@ struct ieee80211_prep_tx_info { + * Note that a sta can also be inserted or removed with valid links, + * i.e. passed to @sta_add/@sta_state with sta->valid_links not zero. + * In fact, cannot change from having valid_links and not having them. ++ * @net_setup_tc: Called from .ndo_setup_tc in order to prepare hardware ++ * flow offloading for flows originating from the vif. ++ * Note that the driver must not assume that the vif driver_data is valid ++ * at this point, since the callback can be called during netdev teardown. + */ + struct ieee80211_ops { + void (*tx)(struct ieee80211_hw *hw, +@@ -4547,6 +4551,11 @@ struct ieee80211_ops { + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + u16 old_links, u16 new_links); ++ int (*net_setup_tc)(struct ieee80211_hw *hw, ++ struct ieee80211_vif *vif, ++ struct net_device *dev, ++ enum tc_setup_type type, ++ void *type_data); + }; + + /** +--- a/net/mac80211/driver-ops.h ++++ b/net/mac80211/driver-ops.h +@@ -1470,6 +1470,23 @@ static inline int drv_net_fill_forward_p + return ret; + } + ++static inline int drv_net_setup_tc(struct ieee80211_local *local, ++ struct ieee80211_sub_if_data *sdata, ++ struct net_device *dev, ++ enum tc_setup_type type, void *type_data) ++{ ++ int ret = -EOPNOTSUPP; ++ ++ sdata = get_bss_sdata(sdata); ++ trace_drv_net_setup_tc(local, sdata, type); ++ if (local->ops->net_setup_tc) ++ ret = local->ops->net_setup_tc(&local->hw, &sdata->vif, dev, ++ type, type_data); ++ trace_drv_return_int(local, ret); ++ ++ return ret; ++} ++ + int drv_change_vif_links(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata, + u16 old_links, u16 new_links, +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -1939,7 +1939,8 @@ void ieee80211_color_collision_detection + /* interface handling */ + #define MAC80211_SUPPORTED_FEATURES_TX (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | \ + NETIF_F_HW_CSUM | NETIF_F_SG | \ +- NETIF_F_HIGHDMA | NETIF_F_GSO_SOFTWARE) ++ NETIF_F_HIGHDMA | NETIF_F_GSO_SOFTWARE | \ ++ NETIF_F_HW_TC) + #define MAC80211_SUPPORTED_FEATURES_RX (NETIF_F_RXCSUM) + #define MAC80211_SUPPORTED_FEATURES (MAC80211_SUPPORTED_FEATURES_TX | \ + MAC80211_SUPPORTED_FEATURES_RX) +--- a/net/mac80211/iface.c ++++ b/net/mac80211/iface.c +@@ -813,6 +813,21 @@ ieee80211_get_stats64(struct net_device + dev_fetch_sw_netstats(stats, dev->tstats); + } + ++static int ieee80211_netdev_setup_tc(struct net_device *dev, ++ enum tc_setup_type type, void *type_data) ++{ ++ struct ieee80211_sub_if_data *sdata; ++ struct ieee80211_local *local; ++ ++ sdata = IEEE80211_DEV_TO_SUB_IF(dev); ++ local = sdata->local; ++ ++ if (!local->ops->net_setup_tc) ++ return -EOPNOTSUPP; ++ ++ return drv_net_setup_tc(local, sdata, dev, type, type_data); ++} ++ + static const struct net_device_ops ieee80211_dataif_ops = { + .ndo_open = ieee80211_open, + .ndo_stop = ieee80211_stop, +@@ -821,6 +836,7 @@ static const struct net_device_ops ieee8 + .ndo_set_rx_mode = ieee80211_set_multicast_list, + .ndo_set_mac_address = ieee80211_change_mac, + .ndo_get_stats64 = ieee80211_get_stats64, ++ .ndo_setup_tc = ieee80211_netdev_setup_tc, + }; + + static u16 ieee80211_monitor_select_queue(struct net_device *dev, +@@ -929,6 +945,7 @@ static const struct net_device_ops ieee8 + .ndo_set_mac_address = ieee80211_change_mac, + .ndo_get_stats64 = ieee80211_get_stats64, + .ndo_fill_forward_path = ieee80211_netdev_fill_forward_path, ++ .ndo_setup_tc = ieee80211_netdev_setup_tc, + }; + + static bool ieee80211_iftype_supports_hdr_offload(enum nl80211_iftype iftype) +--- a/net/mac80211/trace.h ++++ b/net/mac80211/trace.h +@@ -2478,6 +2478,31 @@ DEFINE_EVENT(sta_event, drv_net_fill_for + TP_ARGS(local, sdata, sta) + ); + ++TRACE_EVENT(drv_net_setup_tc, ++ TP_PROTO(struct ieee80211_local *local, ++ struct ieee80211_sub_if_data *sdata, ++ u8 type), ++ ++ TP_ARGS(local, sdata, type), ++ ++ TP_STRUCT__entry( ++ LOCAL_ENTRY ++ VIF_ENTRY ++ __field(u8, type) ++ ), ++ ++ TP_fast_assign( ++ LOCAL_ASSIGN; ++ VIF_ASSIGN; ++ __entry->type = type; ++ ), ++ ++ TP_printk( ++ LOCAL_PR_FMT VIF_PR_FMT " type:%d\n", ++ LOCAL_PR_ARG, VIF_PR_ARG, __entry->type ++ ) ++); ++ + TRACE_EVENT(drv_change_vif_links, + TP_PROTO(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata, diff --git a/package/kernel/mac80211/patches/subsys/329-wifi-mac80211-fix-receiving-mesh-packets-in-forwardi.patch b/package/kernel/mac80211/patches/subsys/329-wifi-mac80211-fix-receiving-mesh-packets-in-forwardi.patch new file mode 100644 index 000000000..6882694da --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/329-wifi-mac80211-fix-receiving-mesh-packets-in-forwardi.patch @@ -0,0 +1,50 @@ +From: Felix Fietkau +Date: Sun, 26 Mar 2023 17:11:34 +0200 +Subject: [PATCH] wifi: mac80211: fix receiving mesh packets in forwarding=0 + networks +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +When forwarding is set to 0, frames are typically sent with ttl=1. +Move the ttl decrement check below the check for local receive in order to +fix packet drops. + +Reported-by: Thomas Hühn +Reported-by: Nick Hainke +Fixes: 986e43b19ae9 ("wifi: mac80211: fix receiving A-MSDU frames on mesh interfaces") +Signed-off-by: Felix Fietkau +--- + +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -2828,14 +2828,6 @@ ieee80211_rx_mesh_data(struct ieee80211_ + if (sdata->crypto_tx_tailroom_needed_cnt) + tailroom = IEEE80211_ENCRYPT_TAILROOM; + +- if (!--mesh_hdr->ttl) { +- if (multicast) +- goto rx_accept; +- +- IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_ttl); +- return RX_DROP_MONITOR; +- } +- + if (mesh_hdr->flags & MESH_FLAGS_AE) { + struct mesh_path *mppath; + char *proxied_addr; +@@ -2874,6 +2866,14 @@ ieee80211_rx_mesh_data(struct ieee80211_ + if (ether_addr_equal(sdata->vif.addr, eth->h_dest)) + goto rx_accept; + ++ if (!--mesh_hdr->ttl) { ++ if (multicast) ++ goto rx_accept; ++ ++ IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_ttl); ++ return RX_DROP_MONITOR; ++ } ++ + if (!ifmsh->mshcfg.dot11MeshForwarding) { + if (is_multicast_ether_addr(eth->h_dest)) + goto rx_accept; diff --git a/package/kernel/mac80211/patches/subsys/330-mac80211-add-AQL-support-for-broadcast-packets.patch b/package/kernel/mac80211/patches/subsys/330-mac80211-add-AQL-support-for-broadcast-packets.patch deleted file mode 100644 index d822e4535..000000000 --- a/package/kernel/mac80211/patches/subsys/330-mac80211-add-AQL-support-for-broadcast-packets.patch +++ /dev/null @@ -1,293 +0,0 @@ -From: Felix Fietkau -Date: Fri, 9 Feb 2024 19:43:40 +0100 -Subject: [PATCH] mac80211: add AQL support for broadcast packets - -Excessive broadcast traffic with little competing unicast traffic can easily -flood hardware queues, leading to throughput issues. Additionally, filling -the hardware queues with too many packets breaks FQ for broadcast data. -Fix this by enabling AQL for broadcast packets. - -Signed-off-by: Felix Fietkau ---- - ---- a/include/net/cfg80211.h -+++ b/include/net/cfg80211.h -@@ -3416,6 +3416,7 @@ enum wiphy_params_flags { - /* The per TXQ device queue limit in airtime */ - #define IEEE80211_DEFAULT_AQL_TXQ_LIMIT_L 5000 - #define IEEE80211_DEFAULT_AQL_TXQ_LIMIT_H 12000 -+#define IEEE80211_DEFAULT_AQL_TXQ_LIMIT_BC 50000 - - /* The per interface airtime threshold to switch to lower queue limit */ - #define IEEE80211_AQL_THRESHOLD 24000 ---- a/net/mac80211/debugfs.c -+++ b/net/mac80211/debugfs.c -@@ -215,11 +215,13 @@ static ssize_t aql_pending_read(struct f - "VI %u us\n" - "BE %u us\n" - "BK %u us\n" -+ "BC/MC %u us\n" - "total %u us\n", - atomic_read(&local->aql_ac_pending_airtime[IEEE80211_AC_VO]), - atomic_read(&local->aql_ac_pending_airtime[IEEE80211_AC_VI]), - atomic_read(&local->aql_ac_pending_airtime[IEEE80211_AC_BE]), - atomic_read(&local->aql_ac_pending_airtime[IEEE80211_AC_BK]), -+ atomic_read(&local->aql_bc_pending_airtime), - atomic_read(&local->aql_total_pending_airtime)); - return simple_read_from_buffer(user_buf, count, ppos, - buf, len); -@@ -245,7 +247,8 @@ static ssize_t aql_txq_limit_read(struct - "VO %u %u\n" - "VI %u %u\n" - "BE %u %u\n" -- "BK %u %u\n", -+ "BK %u %u\n" -+ "BC/MC %u\n", - local->aql_txq_limit_low[IEEE80211_AC_VO], - local->aql_txq_limit_high[IEEE80211_AC_VO], - local->aql_txq_limit_low[IEEE80211_AC_VI], -@@ -253,7 +256,8 @@ static ssize_t aql_txq_limit_read(struct - local->aql_txq_limit_low[IEEE80211_AC_BE], - local->aql_txq_limit_high[IEEE80211_AC_BE], - local->aql_txq_limit_low[IEEE80211_AC_BK], -- local->aql_txq_limit_high[IEEE80211_AC_BK]); -+ local->aql_txq_limit_high[IEEE80211_AC_BK], -+ local->aql_txq_limit_bc); - return simple_read_from_buffer(user_buf, count, ppos, - buf, len); - } -@@ -279,6 +283,11 @@ static ssize_t aql_txq_limit_write(struc - else - buf[count] = '\0'; - -+ if (sscanf(buf, "mcast %u", &q_limit_low) == 1) { -+ local->aql_txq_limit_bc = q_limit_low; -+ return count; -+ } -+ - if (sscanf(buf, "%u %u %u", &ac, &q_limit_low, &q_limit_high) != 3) - return -EINVAL; - ---- a/net/mac80211/ieee80211_i.h -+++ b/net/mac80211/ieee80211_i.h -@@ -1338,10 +1338,12 @@ struct ieee80211_local { - spinlock_t handle_wake_tx_queue_lock; - - u16 airtime_flags; -+ u32 aql_txq_limit_bc; - u32 aql_txq_limit_low[IEEE80211_NUM_ACS]; - u32 aql_txq_limit_high[IEEE80211_NUM_ACS]; - u32 aql_threshold; - atomic_t aql_total_pending_airtime; -+ atomic_t aql_bc_pending_airtime; - atomic_t aql_ac_pending_airtime[IEEE80211_NUM_ACS]; - - const struct ieee80211_ops *ops; ---- a/net/mac80211/main.c -+++ b/net/mac80211/main.c -@@ -944,6 +944,7 @@ struct ieee80211_hw *ieee80211_alloc_hw_ - spin_lock_init(&local->rx_path_lock); - spin_lock_init(&local->queue_stop_reason_lock); - -+ local->aql_txq_limit_bc = IEEE80211_DEFAULT_AQL_TXQ_LIMIT_BC; - for (i = 0; i < IEEE80211_NUM_ACS; i++) { - INIT_LIST_HEAD(&local->active_txqs[i]); - spin_lock_init(&local->active_txq_lock[i]); ---- a/net/mac80211/sta_info.c -+++ b/net/mac80211/sta_info.c -@@ -2357,13 +2357,28 @@ EXPORT_SYMBOL(ieee80211_sta_recalc_aggre - - void ieee80211_sta_update_pending_airtime(struct ieee80211_local *local, - struct sta_info *sta, u8 ac, -- u16 tx_airtime, bool tx_completed) -+ u16 tx_airtime, bool tx_completed, -+ bool mcast) - { - int tx_pending; - - if (!wiphy_ext_feature_isset(local->hw.wiphy, NL80211_EXT_FEATURE_AQL)) - return; - -+ if (mcast) { -+ if (!tx_completed) { -+ atomic_add(tx_airtime, &local->aql_bc_pending_airtime); -+ return; -+ } -+ -+ tx_pending = atomic_sub_return(tx_airtime, -+ &local->aql_bc_pending_airtime); -+ if (tx_pending < 0) -+ atomic_cmpxchg(&local->aql_bc_pending_airtime, -+ tx_pending, 0); -+ return; -+ } -+ - if (!tx_completed) { - if (sta) - atomic_add(tx_airtime, ---- a/net/mac80211/tx.c -+++ b/net/mac80211/tx.c -@@ -2554,7 +2554,7 @@ static u16 ieee80211_store_ack_skb(struc - - spin_lock_irqsave(&local->ack_status_lock, flags); - id = idr_alloc(&local->ack_status_frames, ack_skb, -- 1, 0x2000, GFP_ATOMIC); -+ 1, 0x1000, GFP_ATOMIC); - spin_unlock_irqrestore(&local->ack_status_lock, flags); - - if (id >= 0) { -@@ -3983,20 +3983,20 @@ begin: - encap_out: - info->control.vif = vif; - -- if (tx.sta && -- wiphy_ext_feature_isset(local->hw.wiphy, NL80211_EXT_FEATURE_AQL)) { -- bool ampdu = txq->ac != IEEE80211_AC_VO; -+ if (wiphy_ext_feature_isset(local->hw.wiphy, NL80211_EXT_FEATURE_AQL)) { -+ bool ampdu = txq->sta && txq->ac != IEEE80211_AC_VO; - u32 airtime; - - airtime = ieee80211_calc_expected_tx_airtime(hw, vif, txq->sta, - skb->len, ampdu); -- if (airtime) { -- airtime = ieee80211_info_set_tx_time_est(info, airtime); -- ieee80211_sta_update_pending_airtime(local, tx.sta, -- txq->ac, -- airtime, -- false); -- } -+ if (!airtime) -+ return skb; -+ -+ airtime = ieee80211_info_set_tx_time_est(info, airtime); -+ info->tx_time_mc = !tx.sta; -+ ieee80211_sta_update_pending_airtime(local, tx.sta, txq->ac, -+ airtime, false, -+ info->tx_time_mc); - } - - return skb; -@@ -4048,6 +4048,7 @@ struct ieee80211_txq *ieee80211_next_txq - struct ieee80211_txq *ret = NULL; - struct txq_info *txqi = NULL, *head = NULL; - bool found_eligible_txq = false; -+ bool aql_check; - - spin_lock_bh(&local->active_txq_lock[ac]); - -@@ -4071,26 +4072,26 @@ struct ieee80211_txq *ieee80211_next_txq - if (!head) - head = txqi; - -+ aql_check = ieee80211_txq_airtime_check(hw, &txqi->txq); -+ if (aql_check) -+ found_eligible_txq = true; -+ - if (txqi->txq.sta) { - struct sta_info *sta = container_of(txqi->txq.sta, - struct sta_info, sta); -- bool aql_check = ieee80211_txq_airtime_check(hw, &txqi->txq); -- s32 deficit = ieee80211_sta_deficit(sta, txqi->txq.ac); -- -- if (aql_check) -- found_eligible_txq = true; -- -- if (deficit < 0) -+ if (ieee80211_sta_deficit(sta, txqi->txq.ac) < 0) { - sta->airtime[txqi->txq.ac].deficit += - sta->airtime_weight << AIRTIME_QUANTUM_SHIFT; -- -- if (deficit < 0 || !aql_check) { -- list_move_tail(&txqi->schedule_order, -- &local->active_txqs[txqi->txq.ac]); -- goto begin; -+ aql_check = false; - } - } - -+ if (!aql_check) { -+ list_move_tail(&txqi->schedule_order, -+ &local->active_txqs[txqi->txq.ac]); -+ goto begin; -+ } -+ - if (txqi->schedule_round == local->schedule_round[ac]) - goto out; - -@@ -4155,7 +4156,8 @@ bool ieee80211_txq_airtime_check(struct - return true; - - if (!txq->sta) -- return true; -+ return atomic_read(&local->aql_bc_pending_airtime) < -+ local->aql_txq_limit_bc; - - if (unlikely(txq->tid == IEEE80211_NUM_TIDS)) - return true; -@@ -4204,15 +4206,15 @@ bool ieee80211_txq_may_transmit(struct i - - spin_lock_bh(&local->active_txq_lock[ac]); - -- if (!txqi->txq.sta) -- goto out; -- - if (list_empty(&txqi->schedule_order)) - goto out; - - if (!ieee80211_txq_schedule_airtime_check(local, ac)) - goto out; - -+ if (!txqi->txq.sta) -+ goto out; -+ - list_for_each_entry_safe(iter, tmp, &local->active_txqs[ac], - schedule_order) { - if (iter == txqi) ---- a/include/net/mac80211.h -+++ b/include/net/mac80211.h -@@ -1180,8 +1180,8 @@ struct ieee80211_tx_info { - status_data_idr:1, - status_data:13, - hw_queue:4, -+ tx_time_mc:1, - tx_time_est:10; -- /* 1 free bit */ - - union { - struct { ---- a/net/mac80211/sta_info.h -+++ b/net/mac80211/sta_info.h -@@ -147,7 +147,8 @@ struct airtime_info { - - void ieee80211_sta_update_pending_airtime(struct ieee80211_local *local, - struct sta_info *sta, u8 ac, -- u16 tx_airtime, bool tx_completed); -+ u16 tx_airtime, bool tx_completed, -+ bool mcast); - - struct sta_info; - ---- a/net/mac80211/status.c -+++ b/net/mac80211/status.c -@@ -717,7 +717,7 @@ static void ieee80211_report_used_skb(st - ieee80211_sta_update_pending_airtime(local, sta, - skb_get_queue_mapping(skb), - tx_time_est, -- true); -+ true, info->tx_time_mc); - rcu_read_unlock(); - } - -@@ -1138,10 +1138,11 @@ void ieee80211_tx_status_ext(struct ieee - /* Do this here to avoid the expensive lookup of the sta - * in ieee80211_report_used_skb(). - */ -+ bool mcast = IEEE80211_SKB_CB(skb)->tx_time_mc; - ieee80211_sta_update_pending_airtime(local, sta, - skb_get_queue_mapping(skb), - tx_time_est, -- true); -+ true, mcast); - ieee80211_info_set_tx_time_est(IEEE80211_SKB_CB(skb), 0); - } - diff --git a/package/kernel/mac80211/patches/subsys/330-wifi-ieee80211-correctly-mark-FTM-frames-non-buffera.patch b/package/kernel/mac80211/patches/subsys/330-wifi-ieee80211-correctly-mark-FTM-frames-non-buffera.patch new file mode 100644 index 000000000..079dd2a86 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/330-wifi-ieee80211-correctly-mark-FTM-frames-non-buffera.patch @@ -0,0 +1,134 @@ +From: Johannes Berg +Date: Wed, 29 Mar 2023 16:46:26 +0200 +Subject: [PATCH] wifi: ieee80211: correctly mark FTM frames non-bufferable + +The checks of whether or not a frame is bufferable were not +taking into account that some action frames aren't, such as +FTM. Check this, which requires some changes to the function +ieee80211_is_bufferable_mmpdu() since we need the whole skb +for the checks now. + +Signed-off-by: Johannes Berg +Reviewed-by: Greenman, Gregory +Reviewed-by: Peer, Ilan +--- + +--- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c +@@ -601,8 +601,9 @@ static void iwl_mvm_skb_prepare_status(s + + static int iwl_mvm_get_ctrl_vif_queue(struct iwl_mvm *mvm, + struct ieee80211_tx_info *info, +- struct ieee80211_hdr *hdr) ++ struct sk_buff *skb) + { ++ struct ieee80211_hdr *hdr = (void *)skb->data; + struct iwl_mvm_vif *mvmvif = + iwl_mvm_vif_from_mac80211(info->control.vif); + __le16 fc = hdr->frame_control; +@@ -621,7 +622,7 @@ static int iwl_mvm_get_ctrl_vif_queue(st + * reason 7 ("Class 3 frame received from nonassociated STA"). + */ + if (ieee80211_is_mgmt(fc) && +- (!ieee80211_is_bufferable_mmpdu(fc) || ++ (!ieee80211_is_bufferable_mmpdu(skb) || + ieee80211_is_deauth(fc) || ieee80211_is_disassoc(fc))) + return mvm->probe_queue; + +@@ -740,7 +741,7 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mv + else + sta_id = mvmvif->mcast_sta.sta_id; + +- queue = iwl_mvm_get_ctrl_vif_queue(mvm, &info, hdr); ++ queue = iwl_mvm_get_ctrl_vif_queue(mvm, &info, skb); + } else if (info.control.vif->type == NL80211_IFTYPE_MONITOR) { + queue = mvm->snif_queue; + sta_id = mvm->snif_sta.sta_id; +--- a/include/linux/ieee80211.h ++++ b/include/linux/ieee80211.h +@@ -772,20 +772,6 @@ static inline bool ieee80211_is_any_null + } + + /** +- * ieee80211_is_bufferable_mmpdu - check if frame is bufferable MMPDU +- * @fc: frame control field in little-endian byteorder +- */ +-static inline bool ieee80211_is_bufferable_mmpdu(__le16 fc) +-{ +- /* IEEE 802.11-2012, definition of "bufferable management frame"; +- * note that this ignores the IBSS special case. */ +- return ieee80211_is_mgmt(fc) && +- (ieee80211_is_action(fc) || +- ieee80211_is_disassoc(fc) || +- ieee80211_is_deauth(fc)); +-} +- +-/** + * ieee80211_is_first_frag - check if IEEE80211_SCTL_FRAG is not set + * @seq_ctrl: frame sequence control bytes in little-endian byteorder + */ +@@ -4121,6 +4107,44 @@ static inline u8 *ieee80211_get_DA(struc + } + + /** ++ * ieee80211_is_bufferable_mmpdu - check if frame is bufferable MMPDU ++ * @skb: the skb to check, starting with the 802.11 header ++ */ ++static inline bool ieee80211_is_bufferable_mmpdu(struct sk_buff *skb) ++{ ++ struct ieee80211_mgmt *mgmt = (void *)skb->data; ++ __le16 fc = mgmt->frame_control; ++ ++ /* ++ * IEEE 802.11 REVme D2.0 definition of bufferable MMPDU; ++ * note that this ignores the IBSS special case. ++ */ ++ if (!ieee80211_is_mgmt(fc)) ++ return false; ++ ++ if (ieee80211_is_disassoc(fc) || ieee80211_is_deauth(fc)) ++ return true; ++ ++ if (!ieee80211_is_action(fc)) ++ return false; ++ ++ if (skb->len < offsetofend(typeof(*mgmt), u.action.u.ftm.action_code)) ++ return true; ++ ++ /* action frame - additionally check for non-bufferable FTM */ ++ ++ if (mgmt->u.action.category != WLAN_CATEGORY_PUBLIC && ++ mgmt->u.action.category != WLAN_CATEGORY_PROTECTED_DUAL_OF_ACTION) ++ return true; ++ ++ if (mgmt->u.action.u.ftm.action_code == WLAN_PUB_ACTION_FTM_REQUEST || ++ mgmt->u.action.u.ftm.action_code == WLAN_PUBLIC_ACTION_FTM_RESPONSE) ++ return false; ++ ++ return true; ++} ++ ++/** + * _ieee80211_is_robust_mgmt_frame - check if frame is a robust management frame + * @hdr: the frame (buffer must include at least the first octet of payload) + */ +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -488,7 +488,7 @@ ieee80211_tx_h_unicast_ps_buf(struct iee + int ac = skb_get_queue_mapping(tx->skb); + + if (ieee80211_is_mgmt(hdr->frame_control) && +- !ieee80211_is_bufferable_mmpdu(hdr->frame_control)) { ++ !ieee80211_is_bufferable_mmpdu(tx->skb)) { + info->flags |= IEEE80211_TX_CTL_NO_PS_BUFFER; + return TX_CONTINUE; + } +@@ -1326,7 +1326,7 @@ static struct txq_info *ieee80211_get_tx + if (!(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) && + unlikely(!ieee80211_is_data_present(hdr->frame_control))) { + if ((!ieee80211_is_mgmt(hdr->frame_control) || +- ieee80211_is_bufferable_mmpdu(hdr->frame_control) || ++ ieee80211_is_bufferable_mmpdu(skb) || + vif->type == NL80211_IFTYPE_STATION) && + sta && sta->uploaded) { + /* diff --git a/package/kernel/mac80211/patches/subsys/331-wifi-mac80211-extend-IEEE80211_KEY_FLAG_GENERATE_MMI.patch b/package/kernel/mac80211/patches/subsys/331-wifi-mac80211-extend-IEEE80211_KEY_FLAG_GENERATE_MMI.patch deleted file mode 100644 index 5c202c26c..000000000 --- a/package/kernel/mac80211/patches/subsys/331-wifi-mac80211-extend-IEEE80211_KEY_FLAG_GENERATE_MMI.patch +++ /dev/null @@ -1,70 +0,0 @@ -From: Michael-CY Lee -Date: Tue, 26 Mar 2024 08:30:36 +0800 -Subject: [PATCH] wifi: mac80211: extend IEEE80211_KEY_FLAG_GENERATE_MMIE to - other ciphers - -Extend the flag IEEE80211_KEY_FLAG_GENERATE_MMIE to BIP-CMAC-256, -BIP-GMAC-128 and BIP-GMAC-256 for the same reason and in the same -way that the flag was added originally in commit a0b4496a4368 -("mac80211: add IEEE80211_KEY_FLAG_GENERATE_MMIE to ieee80211_key_flags"). - -Signed-off-by: Michael-CY Lee -Link: https://msgid.link/20240326003036.15215-1-michael-cy.lee@mediatek.com -Signed-off-by: Johannes Berg ---- - ---- a/include/net/mac80211.h -+++ b/include/net/mac80211.h -@@ -2123,8 +2123,8 @@ static inline bool lockdep_vif_wiphy_mut - * @IEEE80211_KEY_FLAG_GENERATE_MMIC on the same key. - * @IEEE80211_KEY_FLAG_NO_AUTO_TX: Key needs explicit Tx activation. - * @IEEE80211_KEY_FLAG_GENERATE_MMIE: This flag should be set by the driver -- * for a AES_CMAC key to indicate that it requires sequence number -- * generation only -+ * for a AES_CMAC or a AES_GMAC key to indicate that it requires sequence -+ * number generation only - * @IEEE80211_KEY_FLAG_SPP_AMSDU: SPP A-MSDUs can be used with this key - * (set by mac80211 from the sta->spp_amsdu flag) - */ ---- a/net/mac80211/wpa.c -+++ b/net/mac80211/wpa.c -@@ -895,7 +895,8 @@ ieee80211_crypto_aes_cmac_256_encrypt(st - - info = IEEE80211_SKB_CB(skb); - -- if (info->control.hw_key) -+ if (info->control.hw_key && -+ !(key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIE)) - return TX_CONTINUE; - - if (WARN_ON(skb_tailroom(skb) < sizeof(*mmie))) -@@ -911,6 +912,9 @@ ieee80211_crypto_aes_cmac_256_encrypt(st - - bip_ipn_set64(mmie->sequence_number, pn64); - -+ if (info->control.hw_key) -+ return TX_CONTINUE; -+ - bip_aad(skb, aad); - - /* MIC = AES-256-CMAC(IGTK, AAD || Management Frame Body || MMIE, 128) -@@ -1040,7 +1044,8 @@ ieee80211_crypto_aes_gmac_encrypt(struct - - info = IEEE80211_SKB_CB(skb); - -- if (info->control.hw_key) -+ if (info->control.hw_key && -+ !(key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIE)) - return TX_CONTINUE; - - if (WARN_ON(skb_tailroom(skb) < sizeof(*mmie))) -@@ -1056,6 +1061,9 @@ ieee80211_crypto_aes_gmac_encrypt(struct - - bip_ipn_set64(mmie->sequence_number, pn64); - -+ if (info->control.hw_key) -+ return TX_CONTINUE; -+ - bip_aad(skb, aad); - - hdr = (struct ieee80211_hdr *)skb->data; diff --git a/package/kernel/mac80211/patches/subsys/331-wifi-mac80211-flush-queues-on-STA-removal.patch b/package/kernel/mac80211/patches/subsys/331-wifi-mac80211-flush-queues-on-STA-removal.patch new file mode 100644 index 000000000..00232ec1b --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/331-wifi-mac80211-flush-queues-on-STA-removal.patch @@ -0,0 +1,36 @@ +From: Johannes Berg +Date: Mon, 13 Mar 2023 11:42:12 +0100 +Subject: [PATCH] wifi: mac80211: flush queues on STA removal + +When we remove a station, we first make it unreachable, +then we (must) remove its keys, and then remove the +station itself. Depending on the hardware design, if +we have hardware crypto at all, frames still sitting +on hardware queues may then be transmitted without a +valid key, possibly unencrypted or with a fixed key. + +Fix this by flushing the queues when removing stations +so this cannot happen. + +Cc: stable@vger.kernel.org +Signed-off-by: Johannes Berg +Reviewed-by: Greenman, Gregory +--- + +--- a/net/mac80211/sta_info.c ++++ b/net/mac80211/sta_info.c +@@ -1271,6 +1271,14 @@ static void __sta_info_destroy_part2(str + WARN_ON_ONCE(ret); + } + ++ /* Flush queues before removing keys, as that might remove them ++ * from hardware, and then depending on the offload method, any ++ * frames sitting on hardware queues might be sent out without ++ * any encryption at all. ++ */ ++ if (local->ops->set_key) ++ ieee80211_flush_queues(local, sta->sdata, false); ++ + /* now keys can no longer be reached */ + ieee80211_free_sta_keys(local, sta); + diff --git a/package/kernel/mac80211/patches/subsys/332-wifi-iwlwifi-mvm-support-flush-on-AP-interfaces.patch b/package/kernel/mac80211/patches/subsys/332-wifi-iwlwifi-mvm-support-flush-on-AP-interfaces.patch new file mode 100644 index 000000000..3c31dfedd --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/332-wifi-iwlwifi-mvm-support-flush-on-AP-interfaces.patch @@ -0,0 +1,34 @@ +From: Johannes Berg +Date: Mon, 13 Mar 2023 12:02:58 +0100 +Subject: [PATCH] wifi: iwlwifi: mvm: support flush on AP interfaces + +Support TX flush on AP interfaces so that we will do a +proper flush for frames on the queue before keys are +removed. + +Signed-off-by: Johannes Berg +Reviewed-by: Greenman, Gregory +--- + +--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +@@ -4854,9 +4854,6 @@ static void iwl_mvm_mac_flush(struct iee + return; + } + +- if (vif->type != NL80211_IFTYPE_STATION) +- return; +- + /* Make sure we're done with the deferred traffic before flushing */ + flush_work(&mvm->add_stream_wk); + +@@ -4874,9 +4871,6 @@ static void iwl_mvm_mac_flush(struct iee + if (mvmsta->vif != vif) + continue; + +- /* make sure only TDLS peers or the AP are flushed */ +- WARN_ON(i != mvmvif->ap_sta_id && !sta->tdls); +- + if (drop) { + if (iwl_mvm_flush_sta(mvm, mvmsta, false)) + IWL_ERR(mvm, "flush request fail\n"); diff --git a/package/kernel/mac80211/patches/subsys/333-wifi-mac80211-add-flush_sta-method.patch b/package/kernel/mac80211/patches/subsys/333-wifi-mac80211-add-flush_sta-method.patch new file mode 100644 index 000000000..3bba0b7e6 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/333-wifi-mac80211-add-flush_sta-method.patch @@ -0,0 +1,91 @@ +From: Johannes Berg +Date: Mon, 13 Mar 2023 11:53:51 +0100 +Subject: [PATCH] wifi: mac80211: add flush_sta method + +Some drivers like iwlwifi might have per-STA queues, so we +may want to flush/drop just those queues rather than all +when removing a station. Add a separate method for that. + +Signed-off-by: Johannes Berg +Reviewed-by: Greenman, Gregory +--- + +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -3918,6 +3918,10 @@ struct ieee80211_prep_tx_info { + * Note that vif can be NULL. + * The callback can sleep. + * ++ * @flush_sta: Flush or drop all pending frames from the hardware queue(s) for ++ * the given station, as it's about to be removed. ++ * The callback can sleep. ++ * + * @channel_switch: Drivers that need (or want) to offload the channel + * switch operation for CSAs received from the AP may implement this + * callback. They must then call ieee80211_chswitch_done() to indicate +@@ -4372,6 +4376,8 @@ struct ieee80211_ops { + #endif + void (*flush)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + u32 queues, bool drop); ++ void (*flush_sta)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, ++ struct ieee80211_sta *sta); + void (*channel_switch)(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_channel_switch *ch_switch); +--- a/net/mac80211/driver-ops.h ++++ b/net/mac80211/driver-ops.h +@@ -617,6 +617,21 @@ static inline void drv_flush(struct ieee + trace_drv_return_void(local); + } + ++static inline void drv_flush_sta(struct ieee80211_local *local, ++ struct ieee80211_sub_if_data *sdata, ++ struct sta_info *sta) ++{ ++ might_sleep(); ++ ++ if (sdata && !check_sdata_in_driver(sdata)) ++ return; ++ ++ trace_drv_flush_sta(local, sdata, &sta->sta); ++ if (local->ops->flush_sta) ++ local->ops->flush_sta(&local->hw, &sdata->vif, &sta->sta); ++ trace_drv_return_void(local); ++} ++ + static inline void drv_channel_switch(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata, + struct ieee80211_channel_switch *ch_switch) +--- a/net/mac80211/sta_info.c ++++ b/net/mac80211/sta_info.c +@@ -1276,8 +1276,12 @@ static void __sta_info_destroy_part2(str + * frames sitting on hardware queues might be sent out without + * any encryption at all. + */ +- if (local->ops->set_key) +- ieee80211_flush_queues(local, sta->sdata, false); ++ if (local->ops->set_key) { ++ if (local->ops->flush_sta) ++ drv_flush_sta(local, sta->sdata, sta); ++ else ++ ieee80211_flush_queues(local, sta->sdata, false); ++ } + + /* now keys can no longer be reached */ + ieee80211_free_sta_keys(local, sta); +--- a/net/mac80211/trace.h ++++ b/net/mac80211/trace.h +@@ -1177,6 +1177,13 @@ TRACE_EVENT(drv_flush, + ) + ); + ++DEFINE_EVENT(sta_event, drv_flush_sta, ++ TP_PROTO(struct ieee80211_local *local, ++ struct ieee80211_sub_if_data *sdata, ++ struct ieee80211_sta *sta), ++ TP_ARGS(local, sdata, sta) ++); ++ + TRACE_EVENT(drv_channel_switch, + TP_PROTO(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata, diff --git a/package/kernel/mac80211/patches/subsys/334-wifi-iwlwifi-mvm-support-new-flush_sta-method.patch b/package/kernel/mac80211/patches/subsys/334-wifi-iwlwifi-mvm-support-new-flush_sta-method.patch new file mode 100644 index 000000000..18f39d505 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/334-wifi-iwlwifi-mvm-support-new-flush_sta-method.patch @@ -0,0 +1,53 @@ +From: Johannes Berg +Date: Mon, 13 Mar 2023 12:05:35 +0100 +Subject: [PATCH] wifi: iwlwifi: mvm: support new flush_sta method + +For iwlwifi this is simple to implement, and on newer hardware +it's an improvement since we have per-station queues. + +Signed-off-by: Johannes Berg +Reviewed-by: Greenman, Gregory +--- + +--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +@@ -4890,6 +4890,31 @@ static void iwl_mvm_mac_flush(struct iee + iwl_trans_wait_tx_queues_empty(mvm->trans, msk); + } + ++static void iwl_mvm_mac_flush_sta(struct ieee80211_hw *hw, ++ struct ieee80211_vif *vif, ++ struct ieee80211_sta *sta) ++{ ++ struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); ++ int i; ++ ++ mutex_lock(&mvm->mutex); ++ for (i = 0; i < mvm->fw->ucode_capa.num_stations; i++) { ++ struct iwl_mvm_sta *mvmsta; ++ struct ieee80211_sta *tmp; ++ ++ tmp = rcu_dereference_protected(mvm->fw_id_to_mac_id[i], ++ lockdep_is_held(&mvm->mutex)); ++ if (tmp != sta) ++ continue; ++ ++ mvmsta = iwl_mvm_sta_from_mac80211(sta); ++ ++ if (iwl_mvm_flush_sta(mvm, mvmsta, false)) ++ IWL_ERR(mvm, "flush request fail\n"); ++ } ++ mutex_unlock(&mvm->mutex); ++} ++ + static int iwl_mvm_mac_get_survey(struct ieee80211_hw *hw, int idx, + struct survey_info *survey) + { +@@ -5417,6 +5442,7 @@ const struct ieee80211_ops iwl_mvm_hw_op + .mgd_complete_tx = iwl_mvm_mac_mgd_complete_tx, + .mgd_protect_tdls_discover = iwl_mvm_mac_mgd_protect_tdls_discover, + .flush = iwl_mvm_mac_flush, ++ .flush_sta = iwl_mvm_mac_flush_sta, + .sched_scan_start = iwl_mvm_mac_sched_scan_start, + .sched_scan_stop = iwl_mvm_mac_sched_scan_stop, + .set_key = iwl_mvm_mac_set_key, diff --git a/package/kernel/mac80211/patches/subsys/335-wifi-mac80211-add-LDPC-related-flags-in-ieee80211_bs.patch b/package/kernel/mac80211/patches/subsys/335-wifi-mac80211-add-LDPC-related-flags-in-ieee80211_bs.patch new file mode 100644 index 000000000..1b379b76a --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/335-wifi-mac80211-add-LDPC-related-flags-in-ieee80211_bs.patch @@ -0,0 +1,62 @@ +From: Ryder Lee +Date: Sat, 18 Feb 2023 01:49:25 +0800 +Subject: [PATCH] wifi: mac80211: add LDPC related flags in ieee80211_bss_conf + +This is utilized to pass LDPC configurations from user space +(i.e. hostapd) to driver. + +Signed-off-by: Ryder Lee +Link: https://lore.kernel.org/r/1de696aaa34efd77a926eb657b8c0fda05aaa177.1676628065.git.ryder.lee@mediatek.com +Signed-off-by: Johannes Berg +--- + +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -653,6 +653,9 @@ struct ieee80211_fils_discovery { + * write-protected by sdata_lock and local->mtx so holding either is fine + * for read access. + * @color_change_color: the bss color that will be used after the change. ++ * @ht_ldpc: in AP mode, indicates interface has HT LDPC capability. ++ * @vht_ldpc: in AP mode, indicates interface has VHT LDPC capability. ++ * @he_ldpc: in AP mode, indicates interface has HE LDPC capability. + * @vht_su_beamformer: in AP mode, does this BSS support operation as an VHT SU + * beamformer + * @vht_su_beamformee: in AP mode, does this BSS support operation as an VHT SU +@@ -744,6 +747,9 @@ struct ieee80211_bss_conf { + bool color_change_active; + u8 color_change_color; + ++ bool ht_ldpc; ++ bool vht_ldpc; ++ bool he_ldpc; + bool vht_su_beamformer; + bool vht_su_beamformee; + bool vht_mu_beamformer; +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -1252,7 +1252,15 @@ static int ieee80211_start_ap(struct wip + prev_beacon_int = link_conf->beacon_int; + link_conf->beacon_int = params->beacon_interval; + ++ if (params->ht_cap) ++ link_conf->ht_ldpc = ++ params->ht_cap->cap_info & ++ cpu_to_le16(IEEE80211_HT_CAP_LDPC_CODING); ++ + if (params->vht_cap) { ++ link_conf->vht_ldpc = ++ params->vht_cap->vht_cap_info & ++ cpu_to_le32(IEEE80211_VHT_CAP_RXLDPC); + link_conf->vht_su_beamformer = + params->vht_cap->vht_cap_info & + cpu_to_le32(IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE); +@@ -1282,6 +1290,9 @@ static int ieee80211_start_ap(struct wip + } + + if (params->he_cap) { ++ link_conf->he_ldpc = ++ params->he_cap->phy_cap_info[1] & ++ IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD; + link_conf->he_su_beamformer = + params->he_cap->phy_cap_info[3] & + IEEE80211_HE_PHY_CAP3_SU_BEAMFORMER; diff --git a/package/kernel/mac80211/patches/subsys/336-v6.4-wifi-mac80211-generate-EMA-beacons-in-AP-mode.patch b/package/kernel/mac80211/patches/subsys/336-v6.4-wifi-mac80211-generate-EMA-beacons-in-AP-mode.patch new file mode 100644 index 000000000..088f468e3 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/336-v6.4-wifi-mac80211-generate-EMA-beacons-in-AP-mode.patch @@ -0,0 +1,372 @@ +From bd54f3c29077f23dad92ef82a78061b40be30c65 Mon Sep 17 00:00:00 2001 +From: Aloka Dixit +Date: Mon, 5 Dec 2022 16:50:37 -0800 +Subject: [PATCH] wifi: mac80211: generate EMA beacons in AP mode + +Add APIs to generate an array of beacons for an EMA AP (enhanced +multiple BSSID advertisements), each including a single MBSSID element. +EMA profile periodicity equals the count of elements. + +- ieee80211_beacon_get_template_ema_list() - Generate and return all +EMA beacon templates. Drivers must call ieee80211_beacon_free_ema_list() +to free the memory. No change in the prototype for the existing API, +ieee80211_beacon_get_template(), which should be used for non-EMA AP. + +- ieee80211_beacon_get_template_ema_index() - Generate a beacon which +includes the multiple BSSID element at the given index. Drivers can use +this function in a loop until NULL is returned which indicates end of +available MBSSID elements. + +- ieee80211_beacon_free_ema_list() - free the memory allocated for the +list of EMA beacon templates. + +Modify existing functions ieee80211_beacon_get_ap(), +ieee80211_get_mbssid_beacon_len() and ieee80211_beacon_add_mbssid() +to accept a new parameter for EMA index. + +Signed-off-by: Aloka Dixit +Co-developed-by: John Crispin +Signed-off-by: John Crispin +Link: https://lore.kernel.org/r/20221206005040.3177-2-quic_alokad@quicinc.com +Signed-off-by: Johannes Berg +--- + include/net/mac80211.h | 68 +++++++++++++++++++ + net/mac80211/cfg.c | 11 +-- + net/mac80211/ieee80211_i.h | 10 ++- + net/mac80211/tx.c | 134 ++++++++++++++++++++++++++++++++++--- + 4 files changed, 205 insertions(+), 18 deletions(-) + +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -5252,6 +5252,74 @@ ieee80211_beacon_get_template(struct iee + unsigned int link_id); + + /** ++ * ieee80211_beacon_get_template_ema_index - EMA beacon template generation ++ * @hw: pointer obtained from ieee80211_alloc_hw(). ++ * @vif: &struct ieee80211_vif pointer from the add_interface callback. ++ * @offs: &struct ieee80211_mutable_offsets pointer to struct that will ++ * receive the offsets that may be updated by the driver. ++ * @link_id: the link id to which the beacon belongs (or 0 for a non-MLD AP). ++ * @ema_index: index of the beacon in the EMA set. ++ * ++ * This function follows the same rules as ieee80211_beacon_get_template() ++ * but returns a beacon template which includes multiple BSSID element at the ++ * requested index. ++ * ++ * Return: The beacon template. %NULL indicates the end of EMA templates. ++ */ ++struct sk_buff * ++ieee80211_beacon_get_template_ema_index(struct ieee80211_hw *hw, ++ struct ieee80211_vif *vif, ++ struct ieee80211_mutable_offsets *offs, ++ unsigned int link_id, u8 ema_index); ++ ++/** ++ * struct ieee80211_ema_beacons - List of EMA beacons ++ * @cnt: count of EMA beacons. ++ * ++ * @bcn: array of EMA beacons. ++ * @bcn.skb: the skb containing this specific beacon ++ * @bcn.offs: &struct ieee80211_mutable_offsets pointer to struct that will ++ * receive the offsets that may be updated by the driver. ++ */ ++struct ieee80211_ema_beacons { ++ u8 cnt; ++ struct { ++ struct sk_buff *skb; ++ struct ieee80211_mutable_offsets offs; ++ } bcn[]; ++}; ++ ++/** ++ * ieee80211_beacon_get_template_ema_list - EMA beacon template generation ++ * @hw: pointer obtained from ieee80211_alloc_hw(). ++ * @vif: &struct ieee80211_vif pointer from the add_interface callback. ++ * @link_id: the link id to which the beacon belongs (or 0 for a non-MLD AP) ++ * ++ * This function follows the same rules as ieee80211_beacon_get_template() ++ * but allocates and returns a pointer to list of all beacon templates required ++ * to cover all profiles in the multiple BSSID set. Each template includes only ++ * one multiple BSSID element. ++ * ++ * Driver must call ieee80211_beacon_free_ema_list() to free the memory. ++ * ++ * Return: EMA beacon templates of type struct ieee80211_ema_beacons *. ++ * %NULL on error. ++ */ ++struct ieee80211_ema_beacons * ++ieee80211_beacon_get_template_ema_list(struct ieee80211_hw *hw, ++ struct ieee80211_vif *vif, ++ unsigned int link_id); ++ ++/** ++ * ieee80211_beacon_free_ema_list - free an EMA beacon template list ++ * @ema_beacons: list of EMA beacons of type &struct ieee80211_ema_beacons pointers. ++ * ++ * This function will free a list previously acquired by calling ++ * ieee80211_beacon_get_template_ema_list() ++ */ ++void ieee80211_beacon_free_ema_list(struct ieee80211_ema_beacons *ema_beacons); ++ ++/** + * ieee80211_beacon_get_tim - beacon generation function + * @hw: pointer obtained from ieee80211_alloc_hw(). + * @vif: &struct ieee80211_vif pointer from the add_interface callback. +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -1122,11 +1122,11 @@ static int ieee80211_assign_beacon(struc + if (params->mbssid_ies) { + mbssid = params->mbssid_ies; + size += struct_size(new->mbssid_ies, elem, mbssid->cnt); +- size += ieee80211_get_mbssid_beacon_len(mbssid); ++ size += ieee80211_get_mbssid_beacon_len(mbssid, mbssid->cnt); + } else if (old && old->mbssid_ies) { + mbssid = old->mbssid_ies; + size += struct_size(new->mbssid_ies, elem, mbssid->cnt); +- size += ieee80211_get_mbssid_beacon_len(mbssid); ++ size += ieee80211_get_mbssid_beacon_len(mbssid, mbssid->cnt); + } + + new = kzalloc(size, GFP_KERNEL); +@@ -3384,8 +3384,11 @@ cfg80211_beacon_dup(struct cfg80211_beac + + len = beacon->head_len + beacon->tail_len + beacon->beacon_ies_len + + beacon->proberesp_ies_len + beacon->assocresp_ies_len + +- beacon->probe_resp_len + beacon->lci_len + beacon->civicloc_len + +- ieee80211_get_mbssid_beacon_len(beacon->mbssid_ies); ++ beacon->probe_resp_len + beacon->lci_len + beacon->civicloc_len; ++ ++ if (beacon->mbssid_ies) ++ len += ieee80211_get_mbssid_beacon_len(beacon->mbssid_ies, ++ beacon->mbssid_ies->cnt); + + new_beacon = kzalloc(sizeof(*new_beacon) + len, GFP_KERNEL); + if (!new_beacon) +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -1182,13 +1182,17 @@ ieee80211_vif_get_shift(struct ieee80211 + } + + static inline int +-ieee80211_get_mbssid_beacon_len(struct cfg80211_mbssid_elems *elems) ++ieee80211_get_mbssid_beacon_len(struct cfg80211_mbssid_elems *elems, u8 i) + { +- int i, len = 0; ++ int len = 0; + +- if (!elems) ++ if (!elems || !elems->cnt || i > elems->cnt) + return 0; + ++ if (i < elems->cnt) ++ return elems->elem[i].len; ++ ++ /* i == elems->cnt, calculate total length of all MBSSID elements */ + for (i = 0; i < elems->cnt; i++) + len += elems->elem[i].len; + +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -5205,13 +5205,20 @@ ieee80211_beacon_get_finish(struct ieee8 + } + + static void +-ieee80211_beacon_add_mbssid(struct sk_buff *skb, struct beacon_data *beacon) ++ieee80211_beacon_add_mbssid(struct sk_buff *skb, struct beacon_data *beacon, ++ u8 i) + { +- int i; ++ if (!beacon->mbssid_ies || !beacon->mbssid_ies->cnt || ++ i > beacon->mbssid_ies->cnt) ++ return; + +- if (!beacon->mbssid_ies) ++ if (i < beacon->mbssid_ies->cnt) { ++ skb_put_data(skb, beacon->mbssid_ies->elem[i].data, ++ beacon->mbssid_ies->elem[i].len); + return; ++ } + ++ /* i == beacon->mbssid_ies->cnt, include all MBSSID elements */ + for (i = 0; i < beacon->mbssid_ies->cnt; i++) + skb_put_data(skb, beacon->mbssid_ies->elem[i].data, + beacon->mbssid_ies->elem[i].len); +@@ -5224,7 +5231,8 @@ ieee80211_beacon_get_ap(struct ieee80211 + struct ieee80211_mutable_offsets *offs, + bool is_template, + struct beacon_data *beacon, +- struct ieee80211_chanctx_conf *chanctx_conf) ++ struct ieee80211_chanctx_conf *chanctx_conf, ++ u8 ema_index) + { + struct ieee80211_local *local = hw_to_local(hw); + struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); +@@ -5243,7 +5251,9 @@ ieee80211_beacon_get_ap(struct ieee80211 + /* headroom, head length, + * tail length, maximum TIM length and multiple BSSID length + */ +- mbssid_len = ieee80211_get_mbssid_beacon_len(beacon->mbssid_ies); ++ mbssid_len = ieee80211_get_mbssid_beacon_len(beacon->mbssid_ies, ++ ema_index); ++ + skb = dev_alloc_skb(local->tx_headroom + beacon->head_len + + beacon->tail_len + 256 + + local->hw.extra_beacon_tailroom + mbssid_len); +@@ -5261,7 +5271,7 @@ ieee80211_beacon_get_ap(struct ieee80211 + offs->cntdwn_counter_offs[0] = beacon->cntdwn_counter_offsets[0]; + + if (mbssid_len) { +- ieee80211_beacon_add_mbssid(skb, beacon); ++ ieee80211_beacon_add_mbssid(skb, beacon, ema_index); + offs->mbssid_off = skb->len - mbssid_len; + } + +@@ -5280,12 +5290,51 @@ ieee80211_beacon_get_ap(struct ieee80211 + return skb; + } + ++static struct ieee80211_ema_beacons * ++ieee80211_beacon_get_ap_ema_list(struct ieee80211_hw *hw, ++ struct ieee80211_vif *vif, ++ struct ieee80211_link_data *link, ++ struct ieee80211_mutable_offsets *offs, ++ bool is_template, struct beacon_data *beacon, ++ struct ieee80211_chanctx_conf *chanctx_conf) ++{ ++ struct ieee80211_ema_beacons *ema = NULL; ++ ++ if (!beacon->mbssid_ies || !beacon->mbssid_ies->cnt) ++ return NULL; ++ ++ ema = kzalloc(struct_size(ema, bcn, beacon->mbssid_ies->cnt), ++ GFP_ATOMIC); ++ if (!ema) ++ return NULL; ++ ++ for (ema->cnt = 0; ema->cnt < beacon->mbssid_ies->cnt; ema->cnt++) { ++ ema->bcn[ema->cnt].skb = ++ ieee80211_beacon_get_ap(hw, vif, link, ++ &ema->bcn[ema->cnt].offs, ++ is_template, beacon, ++ chanctx_conf, ema->cnt); ++ if (!ema->bcn[ema->cnt].skb) ++ break; ++ } ++ ++ if (ema->cnt == beacon->mbssid_ies->cnt) ++ return ema; ++ ++ ieee80211_beacon_free_ema_list(ema); ++ return NULL; ++} ++ ++#define IEEE80211_INCLUDE_ALL_MBSSID_ELEMS -1 ++ + static struct sk_buff * + __ieee80211_beacon_get(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_mutable_offsets *offs, + bool is_template, +- unsigned int link_id) ++ unsigned int link_id, ++ int ema_index, ++ struct ieee80211_ema_beacons **ema_beacons) + { + struct ieee80211_local *local = hw_to_local(hw); + struct beacon_data *beacon = NULL; +@@ -5314,8 +5363,29 @@ __ieee80211_beacon_get(struct ieee80211_ + if (!beacon) + goto out; + +- skb = ieee80211_beacon_get_ap(hw, vif, link, offs, is_template, +- beacon, chanctx_conf); ++ if (ema_beacons) { ++ *ema_beacons = ++ ieee80211_beacon_get_ap_ema_list(hw, vif, link, ++ offs, ++ is_template, ++ beacon, ++ chanctx_conf); ++ } else { ++ if (beacon->mbssid_ies && beacon->mbssid_ies->cnt) { ++ if (ema_index >= beacon->mbssid_ies->cnt) ++ goto out; /* End of MBSSID elements */ ++ ++ if (ema_index <= IEEE80211_INCLUDE_ALL_MBSSID_ELEMS) ++ ema_index = beacon->mbssid_ies->cnt; ++ } else { ++ ema_index = 0; ++ } ++ ++ skb = ieee80211_beacon_get_ap(hw, vif, link, offs, ++ is_template, beacon, ++ chanctx_conf, ++ ema_index); ++ } + } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { + struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; + struct ieee80211_hdr *hdr; +@@ -5403,10 +5473,50 @@ ieee80211_beacon_get_template(struct iee + struct ieee80211_mutable_offsets *offs, + unsigned int link_id) + { +- return __ieee80211_beacon_get(hw, vif, offs, true, link_id); ++ return __ieee80211_beacon_get(hw, vif, offs, true, link_id, ++ IEEE80211_INCLUDE_ALL_MBSSID_ELEMS, NULL); + } + EXPORT_SYMBOL(ieee80211_beacon_get_template); + ++struct sk_buff * ++ieee80211_beacon_get_template_ema_index(struct ieee80211_hw *hw, ++ struct ieee80211_vif *vif, ++ struct ieee80211_mutable_offsets *offs, ++ unsigned int link_id, u8 ema_index) ++{ ++ return __ieee80211_beacon_get(hw, vif, offs, true, link_id, ema_index, ++ NULL); ++} ++EXPORT_SYMBOL(ieee80211_beacon_get_template_ema_index); ++ ++void ieee80211_beacon_free_ema_list(struct ieee80211_ema_beacons *ema_beacons) ++{ ++ u8 i; ++ ++ if (!ema_beacons) ++ return; ++ ++ for (i = 0; i < ema_beacons->cnt; i++) ++ kfree_skb(ema_beacons->bcn[i].skb); ++ ++ kfree(ema_beacons); ++} ++EXPORT_SYMBOL(ieee80211_beacon_free_ema_list); ++ ++struct ieee80211_ema_beacons * ++ieee80211_beacon_get_template_ema_list(struct ieee80211_hw *hw, ++ struct ieee80211_vif *vif, ++ unsigned int link_id) ++{ ++ struct ieee80211_ema_beacons *ema_beacons = NULL; ++ ++ WARN_ON(__ieee80211_beacon_get(hw, vif, NULL, false, link_id, 0, ++ &ema_beacons)); ++ ++ return ema_beacons; ++} ++EXPORT_SYMBOL(ieee80211_beacon_get_template_ema_list); ++ + struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + u16 *tim_offset, u16 *tim_length, +@@ -5414,7 +5524,9 @@ struct sk_buff *ieee80211_beacon_get_tim + { + struct ieee80211_mutable_offsets offs = {}; + struct sk_buff *bcn = __ieee80211_beacon_get(hw, vif, &offs, false, +- link_id); ++ link_id, ++ IEEE80211_INCLUDE_ALL_MBSSID_ELEMS, ++ NULL); + struct sk_buff *copy; + int shift; + diff --git a/package/kernel/mac80211/patches/subsys/337-mac80211-fix-sband-iftype-data-lookup-for-AP_VLAN.patch b/package/kernel/mac80211/patches/subsys/337-mac80211-fix-sband-iftype-data-lookup-for-AP_VLAN.patch new file mode 100644 index 000000000..67b428494 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/337-mac80211-fix-sband-iftype-data-lookup-for-AP_VLAN.patch @@ -0,0 +1,23 @@ +From: Felix Fietkau +Date: Thu, 22 Jun 2023 18:02:25 +0200 +Subject: [PATCH] mac80211: fix sband iftype data lookup for AP_VLAN + +AP_VLAN interfaces are virtual, so doesn't really exist as a type for +capabilities. When passed in as a type, AP is the one that's really intended. + +Fixes: c4cbaf7973a7 ("cfg80211: Add support for HE") +Signed-off-by: Felix Fietkau +--- + +--- a/include/net/cfg80211.h ++++ b/include/net/cfg80211.h +@@ -567,6 +567,9 @@ ieee80211_get_sband_iftype_data(const st + if (WARN_ON(iftype >= NL80211_IFTYPE_MAX)) + return NULL; + ++ if (iftype == NL80211_IFTYPE_AP_VLAN) ++ iftype = NL80211_IFTYPE_AP; ++ + for (i = 0; i < sband->n_iftype_data; i++) { + const struct ieee80211_sband_iftype_data *data = + &sband->iftype_data[i]; diff --git a/package/kernel/mac80211/patches/subsys/338-mac80211-split-mesh-fast-tx-cache-into-local-proxied.patch b/package/kernel/mac80211/patches/subsys/338-mac80211-split-mesh-fast-tx-cache-into-local-proxied.patch new file mode 100644 index 000000000..f7391a580 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/338-mac80211-split-mesh-fast-tx-cache-into-local-proxied.patch @@ -0,0 +1,219 @@ +From: Felix Fietkau +Date: Fri, 30 Jun 2023 13:11:51 +0200 +Subject: [PATCH] mac80211: split mesh fast tx cache into + local/proxied/forwarded + +Depending on the origin of the packets (and their SA), 802.11 + mesh headers +could be filled in differently. In order to properly deal with that, add a +new field to the lookup key, indicating the type (local, proxied or +forwarded). This can fix spurious packet drop issues that depend on the order +in which nodes/hosts communicate with each other. + +Signed-off-by: Felix Fietkau +--- + +--- a/net/mac80211/mesh.c ++++ b/net/mac80211/mesh.c +@@ -703,6 +703,9 @@ bool ieee80211_mesh_xmit_fast(struct iee + struct sk_buff *skb, u32 ctrl_flags) + { + struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; ++ struct ieee80211_mesh_fast_tx_key key = { ++ .type = MESH_FAST_TX_TYPE_LOCAL ++ }; + struct ieee80211_mesh_fast_tx *entry; + struct ieee80211s_hdr *meshhdr; + u8 sa[ETH_ALEN] __aligned(2); +@@ -738,7 +741,10 @@ bool ieee80211_mesh_xmit_fast(struct iee + return false; + } + +- entry = mesh_fast_tx_get(sdata, skb->data); ++ ether_addr_copy(key.addr, skb->data); ++ if (!ether_addr_equal(skb->data + ETH_ALEN, sdata->vif.addr)) ++ key.type = MESH_FAST_TX_TYPE_PROXIED; ++ entry = mesh_fast_tx_get(sdata, &key); + if (!entry) + return false; + +--- a/net/mac80211/mesh.h ++++ b/net/mac80211/mesh.h +@@ -133,9 +133,33 @@ struct mesh_path { + #define MESH_FAST_TX_CACHE_TIMEOUT 8000 /* msecs */ + + /** ++ * enum ieee80211_mesh_fast_tx_type - cached mesh fast tx entry type ++ * ++ * @MESH_FAST_TX_TYPE_LOCAL: tx from the local vif address as SA ++ * @MESH_FAST_TX_TYPE_PROXIED: local tx with a different SA (e.g. bridged) ++ * @MESH_FAST_TX_TYPE_FORWARDED: forwarded from a different mesh point ++ */ ++enum ieee80211_mesh_fast_tx_type { ++ MESH_FAST_TX_TYPE_LOCAL, ++ MESH_FAST_TX_TYPE_PROXIED, ++ MESH_FAST_TX_TYPE_FORWARDED, ++}; ++ ++/** ++ * struct ieee80211_mesh_fast_tx_key - cached mesh fast tx entry key ++ * ++ * @addr: The Ethernet DA for this entry ++ * @type: cache entry type ++ */ ++struct ieee80211_mesh_fast_tx_key { ++ u8 addr[ETH_ALEN] __aligned(2); ++ enum ieee80211_mesh_fast_tx_type type; ++}; ++ ++/** + * struct ieee80211_mesh_fast_tx - cached mesh fast tx entry + * @rhash: rhashtable pointer +- * @addr_key: The Ethernet DA which is the key for this entry ++ * @key: the lookup key for this cache entry + * @fast_tx: base fast_tx data + * @hdr: cached mesh and rfc1042 headers + * @hdrlen: length of mesh + rfc1042 +@@ -146,7 +170,7 @@ struct mesh_path { + */ + struct ieee80211_mesh_fast_tx { + struct rhash_head rhash; +- u8 addr_key[ETH_ALEN] __aligned(2); ++ struct ieee80211_mesh_fast_tx_key key; + + struct ieee80211_fast_tx fast_tx; + u8 hdr[sizeof(struct ieee80211s_hdr) + sizeof(rfc1042_header)]; +@@ -329,7 +353,8 @@ void mesh_path_tx_root_frame(struct ieee + + bool mesh_action_is_path_sel(struct ieee80211_mgmt *mgmt); + struct ieee80211_mesh_fast_tx * +-mesh_fast_tx_get(struct ieee80211_sub_if_data *sdata, const u8 *addr); ++mesh_fast_tx_get(struct ieee80211_sub_if_data *sdata, ++ struct ieee80211_mesh_fast_tx_key *key); + bool ieee80211_mesh_xmit_fast(struct ieee80211_sub_if_data *sdata, + struct sk_buff *skb, u32 ctrl_flags); + void mesh_fast_tx_cache(struct ieee80211_sub_if_data *sdata, +--- a/net/mac80211/mesh_pathtbl.c ++++ b/net/mac80211/mesh_pathtbl.c +@@ -36,8 +36,8 @@ static const struct rhashtable_params me + static const struct rhashtable_params fast_tx_rht_params = { + .nelem_hint = 10, + .automatic_shrinking = true, +- .key_len = ETH_ALEN, +- .key_offset = offsetof(struct ieee80211_mesh_fast_tx, addr_key), ++ .key_len = sizeof(struct ieee80211_mesh_fast_tx_key), ++ .key_offset = offsetof(struct ieee80211_mesh_fast_tx, key), + .head_offset = offsetof(struct ieee80211_mesh_fast_tx, rhash), + .hashfn = mesh_table_hash, + }; +@@ -426,20 +426,21 @@ static void mesh_fast_tx_entry_free(stru + } + + struct ieee80211_mesh_fast_tx * +-mesh_fast_tx_get(struct ieee80211_sub_if_data *sdata, const u8 *addr) ++mesh_fast_tx_get(struct ieee80211_sub_if_data *sdata, ++ struct ieee80211_mesh_fast_tx_key *key) + { + struct ieee80211_mesh_fast_tx *entry; + struct mesh_tx_cache *cache; + + cache = &sdata->u.mesh.tx_cache; +- entry = rhashtable_lookup(&cache->rht, addr, fast_tx_rht_params); ++ entry = rhashtable_lookup(&cache->rht, key, fast_tx_rht_params); + if (!entry) + return NULL; + + if (!(entry->mpath->flags & MESH_PATH_ACTIVE) || + mpath_expired(entry->mpath)) { + spin_lock_bh(&cache->walk_lock); +- entry = rhashtable_lookup(&cache->rht, addr, fast_tx_rht_params); ++ entry = rhashtable_lookup(&cache->rht, key, fast_tx_rht_params); + if (entry) + mesh_fast_tx_entry_free(cache, entry); + spin_unlock_bh(&cache->walk_lock); +@@ -484,18 +485,24 @@ void mesh_fast_tx_cache(struct ieee80211 + if (!sta) + return; + ++ build.key.type = MESH_FAST_TX_TYPE_LOCAL; + if ((meshhdr->flags & MESH_FLAGS_AE) == MESH_FLAGS_AE_A5_A6) { + /* This is required to keep the mppath alive */ + mppath = mpp_path_lookup(sdata, meshhdr->eaddr1); + if (!mppath) + return; + build.mppath = mppath; ++ if (!ether_addr_equal(meshhdr->eaddr2, sdata->vif.addr)) ++ build.key.type = MESH_FAST_TX_TYPE_PROXIED; + } else if (ieee80211_has_a4(hdr->frame_control)) { + mppath = mpath; + } else { + return; + } + ++ if (!ether_addr_equal(hdr->addr4, sdata->vif.addr)) ++ build.key.type = MESH_FAST_TX_TYPE_FORWARDED; ++ + /* rate limit, in case fast xmit can't be enabled */ + if (mppath->fast_tx_check == jiffies) + return; +@@ -542,7 +549,7 @@ void mesh_fast_tx_cache(struct ieee80211 + } + } + +- memcpy(build.addr_key, mppath->dst, ETH_ALEN); ++ memcpy(build.key.addr, mppath->dst, ETH_ALEN); + build.timestamp = jiffies; + build.fast_tx.band = info->band; + build.fast_tx.da_offs = offsetof(struct ieee80211_hdr, addr3); +@@ -644,13 +651,19 @@ void mesh_fast_tx_flush_addr(struct ieee + const u8 *addr) + { + struct mesh_tx_cache *cache = &sdata->u.mesh.tx_cache; ++ struct ieee80211_mesh_fast_tx_key key = {}; + struct ieee80211_mesh_fast_tx *entry; ++ int i; + ++ ether_addr_copy(key.addr, addr); + cache = &sdata->u.mesh.tx_cache; + spin_lock_bh(&cache->walk_lock); +- entry = rhashtable_lookup(&cache->rht, addr, fast_tx_rht_params); +- if (entry) +- mesh_fast_tx_entry_free(cache, entry); ++ for (i = MESH_FAST_TX_TYPE_LOCAL; i < MESH_FAST_TX_TYPE_FORWARDED; i++) { ++ key.type = i; ++ entry = rhashtable_lookup(&cache->rht, &key, fast_tx_rht_params); ++ if (entry) ++ mesh_fast_tx_entry_free(cache, entry); ++ } + spin_unlock_bh(&cache->walk_lock); + } + +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -2726,7 +2726,10 @@ ieee80211_rx_mesh_fast_forward(struct ie + struct sk_buff *skb, int hdrlen) + { + struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; +- struct ieee80211_mesh_fast_tx *entry = NULL; ++ struct ieee80211_mesh_fast_tx_key key = { ++ .type = MESH_FAST_TX_TYPE_FORWARDED ++ }; ++ struct ieee80211_mesh_fast_tx *entry; + struct ieee80211s_hdr *mesh_hdr; + struct tid_ampdu_tx *tid_tx; + struct sta_info *sta; +@@ -2735,9 +2738,13 @@ ieee80211_rx_mesh_fast_forward(struct ie + + mesh_hdr = (struct ieee80211s_hdr *)(skb->data + sizeof(eth)); + if ((mesh_hdr->flags & MESH_FLAGS_AE) == MESH_FLAGS_AE_A5_A6) +- entry = mesh_fast_tx_get(sdata, mesh_hdr->eaddr1); ++ ether_addr_copy(key.addr, mesh_hdr->eaddr1); + else if (!(mesh_hdr->flags & MESH_FLAGS_AE)) +- entry = mesh_fast_tx_get(sdata, skb->data); ++ ether_addr_copy(key.addr, skb->data); ++ else ++ return false; ++ ++ entry = mesh_fast_tx_get(sdata, &key); + if (!entry) + return false; + diff --git a/package/kernel/mac80211/patches/subsys/340-wifi-nl80211-split-helper-function-from-nl80211_put_.patch b/package/kernel/mac80211/patches/subsys/340-wifi-nl80211-split-helper-function-from-nl80211_put_.patch deleted file mode 100644 index 40757e377..000000000 --- a/package/kernel/mac80211/patches/subsys/340-wifi-nl80211-split-helper-function-from-nl80211_put_.patch +++ /dev/null @@ -1,145 +0,0 @@ -From: Felix Fietkau -Date: Tue, 4 Jun 2024 14:31:09 +0200 -Subject: [PATCH] wifi: nl80211: split helper function from - nl80211_put_iface_combinations - -Create a helper function that puts the data from struct -ieee80211_iface_combination to a nl80211 message. -This will be used for adding per-radio interface combination data. - -Signed-off-by: Felix Fietkau ---- - ---- a/net/wireless/nl80211.c -+++ b/net/wireless/nl80211.c -@@ -1620,71 +1620,78 @@ nla_put_failure: - return -ENOBUFS; - } - --static int nl80211_put_iface_combinations(struct wiphy *wiphy, -- struct sk_buff *msg, -- bool large) -+static int nl80211_put_ifcomb_data(struct sk_buff *msg, bool large, int idx, -+ const struct ieee80211_iface_combination *c) - { -- struct nlattr *nl_combis; -- int i, j; -+ struct nlattr *nl_combi, *nl_limits; -+ int i; - -- nl_combis = nla_nest_start_noflag(msg, -- NL80211_ATTR_INTERFACE_COMBINATIONS); -- if (!nl_combis) -+ nl_combi = nla_nest_start_noflag(msg, idx); -+ if (!nl_combi) - goto nla_put_failure; - -- for (i = 0; i < wiphy->n_iface_combinations; i++) { -- const struct ieee80211_iface_combination *c; -- struct nlattr *nl_combi, *nl_limits; -+ nl_limits = nla_nest_start_noflag(msg, NL80211_IFACE_COMB_LIMITS); -+ if (!nl_limits) -+ goto nla_put_failure; - -- c = &wiphy->iface_combinations[i]; -+ for (i = 0; i < c->n_limits; i++) { -+ struct nlattr *nl_limit; - -- nl_combi = nla_nest_start_noflag(msg, i + 1); -- if (!nl_combi) -+ nl_limit = nla_nest_start_noflag(msg, i + 1); -+ if (!nl_limit) - goto nla_put_failure; -- -- nl_limits = nla_nest_start_noflag(msg, -- NL80211_IFACE_COMB_LIMITS); -- if (!nl_limits) -+ if (nla_put_u32(msg, NL80211_IFACE_LIMIT_MAX, c->limits[i].max)) - goto nla_put_failure; -+ if (nl80211_put_iftypes(msg, NL80211_IFACE_LIMIT_TYPES, -+ c->limits[i].types)) -+ goto nla_put_failure; -+ nla_nest_end(msg, nl_limit); -+ } - -- for (j = 0; j < c->n_limits; j++) { -- struct nlattr *nl_limit; -+ nla_nest_end(msg, nl_limits); - -- nl_limit = nla_nest_start_noflag(msg, j + 1); -- if (!nl_limit) -- goto nla_put_failure; -- if (nla_put_u32(msg, NL80211_IFACE_LIMIT_MAX, -- c->limits[j].max)) -- goto nla_put_failure; -- if (nl80211_put_iftypes(msg, NL80211_IFACE_LIMIT_TYPES, -- c->limits[j].types)) -- goto nla_put_failure; -- nla_nest_end(msg, nl_limit); -- } -+ if (c->beacon_int_infra_match && -+ nla_put_flag(msg, NL80211_IFACE_COMB_STA_AP_BI_MATCH)) -+ goto nla_put_failure; -+ if (nla_put_u32(msg, NL80211_IFACE_COMB_NUM_CHANNELS, -+ c->num_different_channels) || -+ nla_put_u32(msg, NL80211_IFACE_COMB_MAXNUM, -+ c->max_interfaces)) -+ goto nla_put_failure; -+ if (large && -+ (nla_put_u32(msg, NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS, -+ c->radar_detect_widths) || -+ nla_put_u32(msg, NL80211_IFACE_COMB_RADAR_DETECT_REGIONS, -+ c->radar_detect_regions))) -+ goto nla_put_failure; -+ if (c->beacon_int_min_gcd && -+ nla_put_u32(msg, NL80211_IFACE_COMB_BI_MIN_GCD, -+ c->beacon_int_min_gcd)) -+ goto nla_put_failure; - -- nla_nest_end(msg, nl_limits); -+ nla_nest_end(msg, nl_combi); - -- if (c->beacon_int_infra_match && -- nla_put_flag(msg, NL80211_IFACE_COMB_STA_AP_BI_MATCH)) -- goto nla_put_failure; -- if (nla_put_u32(msg, NL80211_IFACE_COMB_NUM_CHANNELS, -- c->num_different_channels) || -- nla_put_u32(msg, NL80211_IFACE_COMB_MAXNUM, -- c->max_interfaces)) -- goto nla_put_failure; -- if (large && -- (nla_put_u32(msg, NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS, -- c->radar_detect_widths) || -- nla_put_u32(msg, NL80211_IFACE_COMB_RADAR_DETECT_REGIONS, -- c->radar_detect_regions))) -- goto nla_put_failure; -- if (c->beacon_int_min_gcd && -- nla_put_u32(msg, NL80211_IFACE_COMB_BI_MIN_GCD, -- c->beacon_int_min_gcd)) -- goto nla_put_failure; -+ return 0; -+nla_put_failure: -+ return -ENOBUFS; -+} - -- nla_nest_end(msg, nl_combi); -- } -+static int nl80211_put_iface_combinations(struct wiphy *wiphy, -+ struct sk_buff *msg, -+ bool large) -+{ -+ struct nlattr *nl_combis; -+ int i; -+ -+ nl_combis = nla_nest_start_noflag(msg, -+ NL80211_ATTR_INTERFACE_COMBINATIONS); -+ if (!nl_combis) -+ goto nla_put_failure; -+ -+ for (i = 0; i < wiphy->n_iface_combinations; i++) -+ if (nl80211_put_ifcomb_data(msg, large, i + 1, -+ &wiphy->iface_combinations[i])) -+ goto nla_put_failure; - - nla_nest_end(msg, nl_combis); - diff --git a/package/kernel/mac80211/patches/subsys/341-wifi-cfg80211-add-support-for-advertising-multiple-r.patch b/package/kernel/mac80211/patches/subsys/341-wifi-cfg80211-add-support-for-advertising-multiple-r.patch deleted file mode 100644 index 45349891b..000000000 --- a/package/kernel/mac80211/patches/subsys/341-wifi-cfg80211-add-support-for-advertising-multiple-r.patch +++ /dev/null @@ -1,348 +0,0 @@ -From: Felix Fietkau -Date: Wed, 22 May 2024 11:42:57 +0200 -Subject: [PATCH] wifi: cfg80211: add support for advertising multiple - radios belonging to a wiphy - -The prerequisite for MLO support in cfg80211/mac80211 is that all the links -participating in MLO must be from the same wiphy/ieee80211_hw. To meet this -expectation, some drivers may need to group multiple discrete hardware each -acting as a link in MLO under single wiphy. - -With this change, supported frequencies and interface combinations of each -individual radio are reported to user space. This allows user space to figure -out the limitations of what combination of channels can be used concurrently. - -Even for non-MLO devices, this improves support for devices capable of -running on multiple channels at the same time. - -Signed-off-by: Felix Fietkau ---- - ---- a/include/net/cfg80211.h -+++ b/include/net/cfg80211.h -@@ -5045,7 +5045,9 @@ struct ieee80211_iface_limit { - * struct ieee80211_iface_combination - possible interface combination - * - * With this structure the driver can describe which interface -- * combinations it supports concurrently. -+ * combinations it supports concurrently. When set in a struct wiphy_radio, -+ * the combinations refer to combinations of interfaces currently active on -+ * that radio. - * - * Examples: - * -@@ -5403,6 +5405,38 @@ struct wiphy_iftype_akm_suites { - int n_akm_suites; - }; - -+/** -+ * struct wiphy_radio_freq_range - wiphy frequency range -+ * @start_freq: start range edge frequency (kHz) -+ * @end_freq: end range edge frequency (kHz) -+ */ -+struct wiphy_radio_freq_range { -+ u32 start_freq; -+ u32 end_freq; -+}; -+ -+ -+/** -+ * struct wiphy_radio - physical radio of a wiphy -+ * This structure describes a physical radio belonging to a wiphy. -+ * It is used to describe concurrent-channel capabilities. Only one channel -+ * can be active on the radio described by struct wiphy_radio. -+ * -+ * @freq_range: frequency range that the radio can operate on. -+ * @n_freq_range: number of elements in @freq_range -+ * -+ * @iface_combinations: Valid interface combinations array, should not -+ * list single interface types. -+ * @n_iface_combinations: number of entries in @iface_combinations array. -+ */ -+struct wiphy_radio { -+ const struct wiphy_radio_freq_range *freq_range; -+ int n_freq_range; -+ -+ const struct ieee80211_iface_combination *iface_combinations; -+ int n_iface_combinations; -+}; -+ - #define CFG80211_HW_TIMESTAMP_ALL_PEERS 0xffff - - /** -@@ -5621,6 +5655,9 @@ struct wiphy_iftype_akm_suites { - * A value of %CFG80211_HW_TIMESTAMP_ALL_PEERS indicates the driver - * supports enabling HW timestamping for all peers (i.e. no need to - * specify a mac address). -+ * -+ * @radio: radios belonging to this wiphy -+ * @n_radio: number of radios - */ - struct wiphy { - struct mutex mtx; -@@ -5771,6 +5808,9 @@ struct wiphy { - - u16 hw_timestamp_max_peers; - -+ int n_radio; -+ const struct wiphy_radio *radio; -+ - char priv[] __aligned(NETDEV_ALIGN); - }; - ---- a/include/uapi/linux/nl80211.h -+++ b/include/uapi/linux/nl80211.h -@@ -2061,6 +2061,10 @@ enum nl80211_commands { - * @NL80211_ATTR_INTERFACE_COMBINATIONS: Nested attribute listing the supported - * interface combinations. In each nested item, it contains attributes - * defined in &enum nl80211_if_combination_attrs. -+ * If the wiphy uses multiple radios (@NL80211_ATTR_WIPHY_RADIOS is set), -+ * this attribute contains the interface combinations of the first radio. -+ * See @NL80211_ATTR_WIPHY_INTERFACE_COMBINATIONS for the global wiphy -+ * combinations for the sum of all radios. - * @NL80211_ATTR_SOFTWARE_IFTYPES: Nested attribute (just like - * %NL80211_ATTR_SUPPORTED_IFTYPES) containing the interface types that - * are managed in software: interfaces of these types aren't subject to -@@ -2856,6 +2860,14 @@ enum nl80211_commands { - * %NL80211_CMD_ASSOCIATE indicating the SPP A-MSDUs - * are used on this connection - * -+ * @NL80211_ATTR_WIPHY_RADIOS: Nested attribute describing physical radios -+ * belonging to this wiphy. See &enum nl80211_wiphy_radio_attrs. -+ * -+ * @NL80211_ATTR_WIPHY_INTERFACE_COMBINATIONS: Nested attribute listing the -+ * supported interface combinations for all radios combined. In each -+ * nested item, it contains attributes defined in -+ * &enum nl80211_if_combination_attrs. -+ * - * @NUM_NL80211_ATTR: total number of nl80211_attrs available - * @NL80211_ATTR_MAX: highest attribute number currently defined - * @__NL80211_ATTR_AFTER_LAST: internal use -@@ -3401,6 +3413,9 @@ enum nl80211_attrs { - - NL80211_ATTR_ASSOC_SPP_AMSDU, - -+ NL80211_ATTR_WIPHY_RADIOS, -+ NL80211_ATTR_WIPHY_INTERFACE_COMBINATIONS, -+ - /* add attributes here, update the policy in nl80211.c */ - - __NL80211_ATTR_AFTER_LAST, -@@ -7987,4 +8002,54 @@ enum nl80211_ap_settings_flags { - NL80211_AP_SETTINGS_SA_QUERY_OFFLOAD_SUPPORT = 1 << 1, - }; - -+/** -+ * enum nl80211_wiphy_radio_attrs - wiphy radio attributes -+ * -+ * @__NL80211_WIPHY_RADIO_ATTR_INVALID: Invalid -+ * -+ * @NL80211_WIPHY_RADIO_ATTR_INDEX: Index of this radio (u32) -+ * @NL80211_WIPHY_RADIO_ATTR_FREQ_RANGE: Frequency range supported by this -+ * radio. Attribute may be present multiple times. -+ * @NL80211_WIPHY_RADIO_ATTR_INTERFACE_COMBINATION: Supported interface -+ * combination for this radio. Attribute may be present multiple times -+ * and contains attributes defined in &enum nl80211_if_combination_attrs. -+ * -+ * @__NL80211_WIPHY_RADIO_ATTR_LAST: Internal -+ * @NL80211_WIPHY_RADIO_ATTR_MAX: Highest attribute -+ */ -+enum nl80211_wiphy_radio_attrs { -+ __NL80211_WIPHY_RADIO_ATTR_INVALID, -+ -+ NL80211_WIPHY_RADIO_ATTR_INDEX, -+ NL80211_WIPHY_RADIO_ATTR_FREQ_RANGE, -+ NL80211_WIPHY_RADIO_ATTR_INTERFACE_COMBINATION, -+ -+ /* keep last */ -+ __NL80211_WIPHY_RADIO_ATTR_LAST, -+ NL80211_WIPHY_RADIO_ATTR_MAX = __NL80211_WIPHY_RADIO_ATTR_LAST - 1, -+}; -+ -+/** -+ * enum nl80211_wiphy_radio_freq_range - wiphy radio frequency range -+ * -+ * @__NL80211_WIPHY_RADIO_FREQ_ATTR_INVALID: Invalid -+ * -+ * @NL80211_WIPHY_RADIO_FREQ_ATTR_START: Frequency range start (u32). -+ * The unit is kHz. -+ * @NL80211_WIPHY_RADIO_FREQ_ATTR_END: Frequency range end (u32). -+ * The unit is kHz. -+ * -+ * @__NL80211_WIPHY_RADIO_FREQ_ATTR_LAST: Internal -+ * @NL80211_WIPHY_RADIO_FREQ_ATTR_MAX: Highest attribute -+ */ -+enum nl80211_wiphy_radio_freq_range { -+ __NL80211_WIPHY_RADIO_FREQ_ATTR_INVALID, -+ -+ NL80211_WIPHY_RADIO_FREQ_ATTR_START, -+ NL80211_WIPHY_RADIO_FREQ_ATTR_END, -+ -+ __NL80211_WIPHY_RADIO_FREQ_ATTR_LAST, -+ NL80211_WIPHY_RADIO_FREQ_ATTR_MAX = __NL80211_WIPHY_RADIO_FREQ_ATTR_LAST - 1, -+}; -+ - #endif /* __LINUX_NL80211_H */ ---- a/net/wireless/nl80211.c -+++ b/net/wireless/nl80211.c -@@ -1621,16 +1621,18 @@ nla_put_failure: - } - - static int nl80211_put_ifcomb_data(struct sk_buff *msg, bool large, int idx, -- const struct ieee80211_iface_combination *c) -+ const struct ieee80211_iface_combination *c, -+ u16 nested) - { - struct nlattr *nl_combi, *nl_limits; - int i; - -- nl_combi = nla_nest_start_noflag(msg, idx); -+ nl_combi = nla_nest_start_noflag(msg, idx | nested); - if (!nl_combi) - goto nla_put_failure; - -- nl_limits = nla_nest_start_noflag(msg, NL80211_IFACE_COMB_LIMITS); -+ nl_limits = nla_nest_start_noflag(msg, NL80211_IFACE_COMB_LIMITS | -+ nested); - if (!nl_limits) - goto nla_put_failure; - -@@ -1678,19 +1680,26 @@ nla_put_failure: - - static int nl80211_put_iface_combinations(struct wiphy *wiphy, - struct sk_buff *msg, -- bool large) -+ int attr, int radio, -+ bool large, u16 nested) - { -+ const struct ieee80211_iface_combination *c; - struct nlattr *nl_combis; -- int i; -+ int i, n; - -- nl_combis = nla_nest_start_noflag(msg, -- NL80211_ATTR_INTERFACE_COMBINATIONS); -+ nl_combis = nla_nest_start_noflag(msg, attr | nested); - if (!nl_combis) - goto nla_put_failure; - -- for (i = 0; i < wiphy->n_iface_combinations; i++) -- if (nl80211_put_ifcomb_data(msg, large, i + 1, -- &wiphy->iface_combinations[i])) -+ if (radio >= 0) { -+ c = wiphy->radio[0].iface_combinations; -+ n = wiphy->radio[0].n_iface_combinations; -+ } else { -+ c = wiphy->iface_combinations; -+ n = wiphy->n_iface_combinations; -+ } -+ for (i = 0; i < n; i++) -+ if (nl80211_put_ifcomb_data(msg, large, i + 1, &c[i], nested)) - goto nla_put_failure; - - nla_nest_end(msg, nl_combis); -@@ -2397,6 +2406,80 @@ fail: - return -ENOBUFS; - } - -+static int nl80211_put_radio(struct wiphy *wiphy, struct sk_buff *msg, int idx) -+{ -+ const struct wiphy_radio *r = &wiphy->radio[idx]; -+ struct nlattr *radio, *freq; -+ int i; -+ -+ radio = nla_nest_start(msg, idx); -+ if (!radio) -+ return -ENOBUFS; -+ -+ if (nla_put_u32(msg, NL80211_WIPHY_RADIO_ATTR_INDEX, idx)) -+ goto nla_put_failure; -+ -+ for (i = 0; i < r->n_freq_range; i++) { -+ const struct wiphy_radio_freq_range *range = &r->freq_range[i]; -+ -+ freq = nla_nest_start(msg, NL80211_WIPHY_RADIO_ATTR_FREQ_RANGE); -+ if (!freq) -+ goto nla_put_failure; -+ -+ if (nla_put_u32(msg, NL80211_WIPHY_RADIO_FREQ_ATTR_START, -+ range->start_freq) || -+ nla_put_u32(msg, NL80211_WIPHY_RADIO_FREQ_ATTR_END, -+ range->end_freq)) -+ goto nla_put_failure; -+ -+ nla_nest_end(msg, freq); -+ } -+ -+ for (i = 0; i < r->n_iface_combinations; i++) -+ if (nl80211_put_ifcomb_data(msg, true, -+ NL80211_WIPHY_RADIO_ATTR_INTERFACE_COMBINATION, -+ &r->iface_combinations[i], -+ NLA_F_NESTED)) -+ goto nla_put_failure; -+ -+ nla_nest_end(msg, radio); -+ -+ return 0; -+ -+nla_put_failure: -+ return -ENOBUFS; -+} -+ -+static int nl80211_put_radios(struct wiphy *wiphy, struct sk_buff *msg) -+{ -+ struct nlattr *radios; -+ int i; -+ -+ if (!wiphy->n_radio) -+ return 0; -+ -+ radios = nla_nest_start(msg, NL80211_ATTR_WIPHY_RADIOS); -+ if (!radios) -+ return -ENOBUFS; -+ -+ for (i = 0; i < wiphy->n_radio; i++) -+ if (nl80211_put_radio(wiphy, msg, i)) -+ goto fail; -+ -+ nla_nest_end(msg, radios); -+ -+ if (nl80211_put_iface_combinations(wiphy, msg, -+ NL80211_ATTR_WIPHY_INTERFACE_COMBINATIONS, -+ -1, true, NLA_F_NESTED)) -+ return -ENOBUFS; -+ -+ return 0; -+ -+fail: -+ nla_nest_cancel(msg, radios); -+ return -ENOBUFS; -+} -+ - struct nl80211_dump_wiphy_state { - s64 filter_wiphy; - long start; -@@ -2692,7 +2775,9 @@ static int nl80211_send_wiphy(struct cfg - goto nla_put_failure; - - if (nl80211_put_iface_combinations(&rdev->wiphy, msg, -- state->split)) -+ NL80211_ATTR_INTERFACE_COMBINATIONS, -+ rdev->wiphy.n_radio ? 0 : -1, -+ state->split, 0)) - goto nla_put_failure; - - state->split_start++; -@@ -3006,6 +3091,12 @@ static int nl80211_send_wiphy(struct cfg - rdev->wiphy.hw_timestamp_max_peers)) - goto nla_put_failure; - -+ state->split_start++; -+ break; -+ case 17: -+ if (nl80211_put_radios(&rdev->wiphy, msg)) -+ goto nla_put_failure; -+ - /* done */ - state->split_start = 0; - break; diff --git a/package/kernel/mac80211/patches/subsys/342-wifi-cfg80211-extend-interface-combination-check-for.patch b/package/kernel/mac80211/patches/subsys/342-wifi-cfg80211-extend-interface-combination-check-for.patch deleted file mode 100644 index 0ba97a2c0..000000000 --- a/package/kernel/mac80211/patches/subsys/342-wifi-cfg80211-extend-interface-combination-check-for.patch +++ /dev/null @@ -1,172 +0,0 @@ -From: Felix Fietkau -Date: Tue, 4 Jun 2024 21:01:50 +0200 -Subject: [PATCH] wifi: cfg80211: extend interface combination check for - multi-radio - -Add a field in struct iface_combination_params to check per-radio -interface combinations instead of per-wiphy ones. - -Signed-off-by: Felix Fietkau ---- - ---- a/include/net/cfg80211.h -+++ b/include/net/cfg80211.h -@@ -1598,6 +1598,7 @@ struct cfg80211_color_change_settings { - * - * Used to pass interface combination parameters - * -+ * @radio_idx: wiphy radio index or -1 for global - * @num_different_channels: the number of different channels we want - * to use for verification - * @radar_detect: a bitmap where each bit corresponds to a channel -@@ -1611,6 +1612,7 @@ struct cfg80211_color_change_settings { - * the verification - */ - struct iface_combination_params { -+ int radio_idx; - int num_different_channels; - u8 radar_detect; - int iftype_num[NUM_NL80211_IFTYPES]; -@@ -4579,6 +4581,8 @@ struct mgmt_frame_regs { - * - * @set_hw_timestamp: Enable/disable HW timestamping of TM/FTM frames. - * @set_ttlm: set the TID to link mapping. -+ * @get_radio_mask: get bitmask of radios in use. -+ * (invoked with the wiphy mutex held) - */ - struct cfg80211_ops { - int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow); -@@ -4940,6 +4944,7 @@ struct cfg80211_ops { - struct cfg80211_set_hw_timestamp *hwts); - int (*set_ttlm)(struct wiphy *wiphy, struct net_device *dev, - struct cfg80211_ttlm_params *params); -+ u32 (*get_radio_mask)(struct wiphy *wiphy, struct net_device *dev); - }; - - /* ---- a/net/mac80211/util.c -+++ b/net/mac80211/util.c -@@ -3930,6 +3930,7 @@ int ieee80211_check_combinations(struct - int total = 1; - struct iface_combination_params params = { - .radar_detect = radar_detect, -+ .radio_idx = -1, - }; - - lockdep_assert_wiphy(local->hw.wiphy); -@@ -4020,7 +4021,9 @@ int ieee80211_max_num_channels(struct ie - struct ieee80211_chanctx *ctx; - u32 max_num_different_channels = 1; - int err; -- struct iface_combination_params params = {0}; -+ struct iface_combination_params params = { -+ .radio_idx = -1, -+ }; - - lockdep_assert_wiphy(local->hw.wiphy); - ---- a/net/wireless/rdev-ops.h -+++ b/net/wireless/rdev-ops.h -@@ -1542,4 +1542,16 @@ rdev_set_ttlm(struct cfg80211_registered - - return ret; - } -+ -+static inline u32 -+rdev_get_radio_mask(struct cfg80211_registered_device *rdev, -+ struct net_device *dev) -+{ -+ struct wiphy *wiphy = &rdev->wiphy; -+ -+ if (!rdev->ops->get_radio_mask) -+ return 0; -+ -+ return rdev->ops->get_radio_mask(wiphy, dev); -+} - #endif /* __CFG80211_RDEV_OPS */ ---- a/net/wireless/util.c -+++ b/net/wireless/util.c -@@ -2305,13 +2305,16 @@ static int cfg80211_wdev_bi(struct wirel - - static void cfg80211_calculate_bi_data(struct wiphy *wiphy, u32 new_beacon_int, - u32 *beacon_int_gcd, -- bool *beacon_int_different) -+ bool *beacon_int_different, -+ int radio_idx) - { -+ struct cfg80211_registered_device *rdev; - struct wireless_dev *wdev; - - *beacon_int_gcd = 0; - *beacon_int_different = false; - -+ rdev = wiphy_to_rdev(wiphy); - list_for_each_entry(wdev, &wiphy->wdev_list, list) { - int wdev_bi; - -@@ -2319,6 +2322,11 @@ static void cfg80211_calculate_bi_data(s - if (wdev->valid_links) - continue; - -+ /* skip wdevs not active on the given wiphy radio */ -+ if (radio_idx >= 0 && -+ !(rdev_get_radio_mask(rdev, wdev->netdev) & BIT(radio_idx))) -+ continue; -+ - wdev_bi = cfg80211_wdev_bi(wdev); - - if (!wdev_bi) -@@ -2366,14 +2374,19 @@ int cfg80211_iter_combinations(struct wi - void *data), - void *data) - { -+ const struct wiphy_radio *radio = NULL; -+ const struct ieee80211_iface_combination *c, *cs; - const struct ieee80211_regdomain *regdom; - enum nl80211_dfs_regions region = 0; -- int i, j, iftype; -+ int i, j, n, iftype; - int num_interfaces = 0; - u32 used_iftypes = 0; - u32 beacon_int_gcd; - bool beacon_int_different; - -+ if (params->radio_idx >= 0) -+ radio = &wiphy->radio[params->radio_idx]; -+ - /* - * This is a bit strange, since the iteration used to rely only on - * the data given by the driver, but here it now relies on context, -@@ -2385,7 +2398,8 @@ int cfg80211_iter_combinations(struct wi - * interfaces (while being brought up) and channel/radar data. - */ - cfg80211_calculate_bi_data(wiphy, params->new_beacon_int, -- &beacon_int_gcd, &beacon_int_different); -+ &beacon_int_gcd, &beacon_int_different, -+ params->radio_idx); - - if (params->radar_detect) { - rcu_read_lock(); -@@ -2402,13 +2416,18 @@ int cfg80211_iter_combinations(struct wi - used_iftypes |= BIT(iftype); - } - -- for (i = 0; i < wiphy->n_iface_combinations; i++) { -- const struct ieee80211_iface_combination *c; -+ if (radio) { -+ cs = radio->iface_combinations; -+ n = radio->n_iface_combinations; -+ } else { -+ cs = wiphy->iface_combinations; -+ n = wiphy->n_iface_combinations; -+ } -+ for (i = 0; i < n; i++) { - struct ieee80211_iface_limit *limits; - u32 all_iftypes = 0; - -- c = &wiphy->iface_combinations[i]; -- -+ c = &cs[i]; - if (num_interfaces > c->max_interfaces) - continue; - if (params->num_different_channels > c->num_different_channels) diff --git a/package/kernel/mac80211/patches/subsys/343-wifi-cfg80211-add-helper-for-checking-if-a-chandef-i.patch b/package/kernel/mac80211/patches/subsys/343-wifi-cfg80211-add-helper-for-checking-if-a-chandef-i.patch deleted file mode 100644 index d115dd2e5..000000000 --- a/package/kernel/mac80211/patches/subsys/343-wifi-cfg80211-add-helper-for-checking-if-a-chandef-i.patch +++ /dev/null @@ -1,69 +0,0 @@ -From: Felix Fietkau -Date: Fri, 7 Jun 2024 17:58:54 +0200 -Subject: [PATCH] wifi: cfg80211: add helper for checking if a chandef is - valid on a radio - -Check if the full channel width is in the radio's frequency range. - -Signed-off-by: Felix Fietkau ---- - ---- a/include/net/cfg80211.h -+++ b/include/net/cfg80211.h -@@ -6485,6 +6485,15 @@ static inline bool cfg80211_channel_is_p - } - - /** -+ * cfg80211_radio_chandef_valid - Check if the radio supports the chandef -+ * -+ * @radio: wiphy radio -+ * @chandef: chandef for current channel -+ */ -+bool cfg80211_radio_chandef_valid(const struct wiphy_radio *radio, -+ const struct cfg80211_chan_def *chandef); -+ -+/** - * ieee80211_get_response_rate - get basic rate for a given rate - * - * @sband: the band to look for rates in ---- a/net/wireless/util.c -+++ b/net/wireless/util.c -@@ -2884,3 +2884,38 @@ cfg80211_get_iftype_ext_capa(struct wiph - return NULL; - } - EXPORT_SYMBOL(cfg80211_get_iftype_ext_capa); -+ -+static bool -+ieee80211_radio_freq_range_valid(const struct wiphy_radio *radio, -+ u32 freq, u32 width) -+{ -+ const struct wiphy_radio_freq_range *r; -+ int i; -+ -+ for (i = 0; i < radio->n_freq_range; i++) { -+ r = &radio->freq_range[i]; -+ if (freq - width / 2 >= r->start_freq && -+ freq + width / 2 <= r->end_freq) -+ return true; -+ } -+ -+ return false; -+} -+ -+bool cfg80211_radio_chandef_valid(const struct wiphy_radio *radio, -+ const struct cfg80211_chan_def *chandef) -+{ -+ u32 freq, width; -+ -+ freq = ieee80211_chandef_to_khz(chandef); -+ width = nl80211_chan_width_to_mhz(chandef->width); -+ if (!ieee80211_radio_freq_range_valid(radio, freq, width)) -+ return false; -+ -+ freq = MHZ_TO_KHZ(chandef->center_freq2); -+ if (freq && !ieee80211_radio_freq_range_valid(radio, freq, width)) -+ return false; -+ -+ return true; -+} -+EXPORT_SYMBOL(cfg80211_radio_chandef_valid); diff --git a/package/kernel/mac80211/patches/subsys/344-wifi-mac80211-add-support-for-DFS-with-multiple-radi.patch b/package/kernel/mac80211/patches/subsys/344-wifi-mac80211-add-support-for-DFS-with-multiple-radi.patch deleted file mode 100644 index 18634fe14..000000000 --- a/package/kernel/mac80211/patches/subsys/344-wifi-mac80211-add-support-for-DFS-with-multiple-radi.patch +++ /dev/null @@ -1,88 +0,0 @@ -From: Felix Fietkau -Date: Thu, 6 Jun 2024 12:19:08 +0200 -Subject: [PATCH] wifi: mac80211: add support for DFS with multiple - radios - -DFS can be supported with multi-channel combinations, as long as each DFS -capable radio only supports one channel. - -Signed-off-by: Felix Fietkau ---- - ---- a/net/mac80211/main.c -+++ b/net/mac80211/main.c -@@ -1084,6 +1084,27 @@ static int ieee80211_init_cipher_suites( - return 0; - } - -+static bool -+ieee80211_ifcomb_check(const struct ieee80211_iface_combination *c, int n_comb) -+{ -+ int i, j; -+ -+ for (i = 0; i < n_comb; i++, c++) { -+ /* DFS is not supported with multi-channel combinations yet */ -+ if (c->radar_detect_widths && -+ c->num_different_channels > 1) -+ return false; -+ -+ /* mac80211 doesn't support more than one IBSS interface */ -+ for (j = 0; j < c->n_limits; j++) -+ if ((c->limits[j].types & BIT(NL80211_IFTYPE_ADHOC)) && -+ c->limits[j].max > 1) -+ return false; -+ } -+ -+ return true; -+} -+ - int ieee80211_register_hw(struct ieee80211_hw *hw) - { - struct ieee80211_local *local = hw_to_local(hw); -@@ -1173,17 +1194,20 @@ int ieee80211_register_hw(struct ieee802 - if (comb->num_different_channels > 1) - return -EINVAL; - } -- } else { -- /* DFS is not supported with multi-channel combinations yet */ -- for (i = 0; i < local->hw.wiphy->n_iface_combinations; i++) { -- const struct ieee80211_iface_combination *comb; -+ } - -- comb = &local->hw.wiphy->iface_combinations[i]; -+ if (hw->wiphy->n_radio) { -+ for (i = 0; i < hw->wiphy->n_radio; i++) { -+ const struct wiphy_radio *radio = &hw->wiphy->radio[i]; - -- if (comb->radar_detect_widths && -- comb->num_different_channels > 1) -+ if (!ieee80211_ifcomb_check(radio->iface_combinations, -+ radio->n_iface_combinations)) - return -EINVAL; - } -+ } else { -+ if (!ieee80211_ifcomb_check(hw->wiphy->iface_combinations, -+ hw->wiphy->n_iface_combinations)) -+ return -EINVAL; - } - - /* Only HW csum features are currently compatible with mac80211 */ -@@ -1313,18 +1337,6 @@ int ieee80211_register_hw(struct ieee802 - hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR); - hw->wiphy->software_iftypes |= BIT(NL80211_IFTYPE_MONITOR); - -- /* mac80211 doesn't support more than one IBSS interface right now */ -- for (i = 0; i < hw->wiphy->n_iface_combinations; i++) { -- const struct ieee80211_iface_combination *c; -- int j; -- -- c = &hw->wiphy->iface_combinations[i]; -- -- for (j = 0; j < c->n_limits; j++) -- if ((c->limits[j].types & BIT(NL80211_IFTYPE_ADHOC)) && -- c->limits[j].max > 1) -- return -EINVAL; -- } - - local->int_scan_req = kzalloc(sizeof(*local->int_scan_req) + - sizeof(void *) * channels, GFP_KERNEL); diff --git a/package/kernel/mac80211/patches/subsys/345-wifi-mac80211-add-radio-index-to-ieee80211_chanctx_c.patch b/package/kernel/mac80211/patches/subsys/345-wifi-mac80211-add-radio-index-to-ieee80211_chanctx_c.patch deleted file mode 100644 index b832a2a12..000000000 --- a/package/kernel/mac80211/patches/subsys/345-wifi-mac80211-add-radio-index-to-ieee80211_chanctx_c.patch +++ /dev/null @@ -1,66 +0,0 @@ -From: Felix Fietkau -Date: Wed, 5 Jun 2024 10:41:34 +0200 -Subject: [PATCH] wifi: mac80211: add radio index to - ieee80211_chanctx_conf - -Will be used to explicitly assign a channel context to a wiphy radio. - -Signed-off-by: Felix Fietkau ---- - ---- a/include/net/mac80211.h -+++ b/include/net/mac80211.h -@@ -250,6 +250,7 @@ struct ieee80211_chan_req { - * @min_def: the minimum channel definition currently required. - * @ap: the channel definition the AP actually is operating as, - * for use with (wider bandwidth) OFDMA -+ * @radio_idx: index of the wiphy radio used used for this channel - * @rx_chains_static: The number of RX chains that must always be - * active on the channel to receive MIMO transmissions - * @rx_chains_dynamic: The number of RX chains that must be enabled -@@ -264,6 +265,7 @@ struct ieee80211_chanctx_conf { - struct cfg80211_chan_def min_def; - struct cfg80211_chan_def ap; - -+ int radio_idx; - u8 rx_chains_static, rx_chains_dynamic; - - bool radar_enabled; ---- a/net/mac80211/chan.c -+++ b/net/mac80211/chan.c -@@ -623,7 +623,8 @@ ieee80211_chanctx_radar_required(struct - static struct ieee80211_chanctx * - ieee80211_alloc_chanctx(struct ieee80211_local *local, - const struct ieee80211_chan_req *chanreq, -- enum ieee80211_chanctx_mode mode) -+ enum ieee80211_chanctx_mode mode, -+ int radio_idx) - { - struct ieee80211_chanctx *ctx; - -@@ -641,6 +642,7 @@ ieee80211_alloc_chanctx(struct ieee80211 - ctx->conf.rx_chains_dynamic = 1; - ctx->mode = mode; - ctx->conf.radar_enabled = false; -+ ctx->conf.radio_idx = radio_idx; - _ieee80211_recalc_chanctx_min_def(local, ctx, NULL); - - return ctx; -@@ -680,7 +682,7 @@ ieee80211_new_chanctx(struct ieee80211_l - - lockdep_assert_wiphy(local->hw.wiphy); - -- ctx = ieee80211_alloc_chanctx(local, chanreq, mode); -+ ctx = ieee80211_alloc_chanctx(local, chanreq, mode, -1); - if (!ctx) - return ERR_PTR(-ENOMEM); - -@@ -1098,7 +1100,7 @@ int ieee80211_link_reserve_chanctx(struc - !list_empty(&curr_ctx->reserved_links)) - return -EBUSY; - -- new_ctx = ieee80211_alloc_chanctx(local, chanreq, mode); -+ new_ctx = ieee80211_alloc_chanctx(local, chanreq, mode, -1); - if (!new_ctx) - return -ENOMEM; - diff --git a/package/kernel/mac80211/patches/subsys/346-wifi-mac80211-extend-ifcomb-check-functions-for-mult.patch b/package/kernel/mac80211/patches/subsys/346-wifi-mac80211-extend-ifcomb-check-functions-for-mult.patch deleted file mode 100644 index 168cf6fad..000000000 --- a/package/kernel/mac80211/patches/subsys/346-wifi-mac80211-extend-ifcomb-check-functions-for-mult.patch +++ /dev/null @@ -1,322 +0,0 @@ -From: Felix Fietkau -Date: Tue, 4 Jun 2024 21:48:48 +0200 -Subject: [PATCH] wifi: mac80211: extend ifcomb check functions for - multi-radio - -Add support for counting global and per-radio max/current number of -channels, as well as checking radio-specific interface combinations. - -Signed-off-by: Felix Fietkau ---- - ---- a/net/mac80211/cfg.c -+++ b/net/mac80211/cfg.c -@@ -263,7 +263,7 @@ static int ieee80211_start_p2p_device(st - - lockdep_assert_wiphy(sdata->local->hw.wiphy); - -- ret = ieee80211_check_combinations(sdata, NULL, 0, 0); -+ ret = ieee80211_check_combinations(sdata, NULL, 0, 0, -1); - if (ret < 0) - return ret; - -@@ -285,7 +285,7 @@ static int ieee80211_start_nan(struct wi - - lockdep_assert_wiphy(sdata->local->hw.wiphy); - -- ret = ieee80211_check_combinations(sdata, NULL, 0, 0); -+ ret = ieee80211_check_combinations(sdata, NULL, 0, 0, -1); - if (ret < 0) - return ret; - -@@ -3992,7 +3992,7 @@ __ieee80211_channel_switch(struct wiphy - goto out; - - /* if reservation is invalid then this will fail */ -- err = ieee80211_check_combinations(sdata, NULL, chanctx->mode, 0); -+ err = ieee80211_check_combinations(sdata, NULL, chanctx->mode, 0, -1); - if (err) { - ieee80211_link_unreserve_chanctx(link_data); - goto out; -@@ -5161,4 +5161,5 @@ const struct cfg80211_ops mac80211_confi - .del_link_station = ieee80211_del_link_station, - .set_hw_timestamp = ieee80211_set_hw_timestamp, - .set_ttlm = ieee80211_set_ttlm, -+ .get_radio_mask = ieee80211_get_radio_mask, - }; ---- a/net/mac80211/chan.c -+++ b/net/mac80211/chan.c -@@ -47,24 +47,29 @@ int ieee80211_chanctx_refcount(struct ie - ieee80211_chanctx_num_reserved(local, ctx); - } - --static int ieee80211_num_chanctx(struct ieee80211_local *local) -+static int ieee80211_num_chanctx(struct ieee80211_local *local, int radio_idx) - { - struct ieee80211_chanctx *ctx; - int num = 0; - - lockdep_assert_wiphy(local->hw.wiphy); - -- list_for_each_entry(ctx, &local->chanctx_list, list) -+ list_for_each_entry(ctx, &local->chanctx_list, list) { -+ if (radio_idx >= 0 && ctx->conf.radio_idx != radio_idx) -+ continue; - num++; -+ } - - return num; - } - --static bool ieee80211_can_create_new_chanctx(struct ieee80211_local *local) -+static bool ieee80211_can_create_new_chanctx(struct ieee80211_local *local, -+ int radio_idx) - { - lockdep_assert_wiphy(local->hw.wiphy); - -- return ieee80211_num_chanctx(local) < ieee80211_max_num_channels(local); -+ return ieee80211_num_chanctx(local, radio_idx) < -+ ieee80211_max_num_channels(local, radio_idx); - } - - static struct ieee80211_chanctx * -@@ -1045,7 +1050,7 @@ int ieee80211_link_reserve_chanctx(struc - - new_ctx = ieee80211_find_reservation_chanctx(local, chanreq, mode); - if (!new_ctx) { -- if (ieee80211_can_create_new_chanctx(local)) { -+ if (ieee80211_can_create_new_chanctx(local, -1)) { - new_ctx = ieee80211_new_chanctx(local, chanreq, mode); - if (IS_ERR(new_ctx)) - return PTR_ERR(new_ctx); -@@ -1736,7 +1741,7 @@ int ieee80211_link_use_channel(struct ie - link->radar_required = ret; - - ret = ieee80211_check_combinations(sdata, &chanreq->oper, mode, -- radar_detect_width); -+ radar_detect_width, -1); - if (ret < 0) - goto out; - ---- a/net/mac80211/ibss.c -+++ b/net/mac80211/ibss.c -@@ -1745,7 +1745,7 @@ int ieee80211_ibss_join(struct ieee80211 - IEEE80211_CHANCTX_SHARED : IEEE80211_CHANCTX_EXCLUSIVE; - - ret = ieee80211_check_combinations(sdata, ¶ms->chandef, chanmode, -- radar_detect_width); -+ radar_detect_width, -1); - if (ret < 0) - return ret; - ---- a/net/mac80211/ieee80211_i.h -+++ b/net/mac80211/ieee80211_i.h -@@ -2596,8 +2596,9 @@ void ieee80211_recalc_dtim(struct ieee80 - int ieee80211_check_combinations(struct ieee80211_sub_if_data *sdata, - const struct cfg80211_chan_def *chandef, - enum ieee80211_chanctx_mode chanmode, -- u8 radar_detect); --int ieee80211_max_num_channels(struct ieee80211_local *local); -+ u8 radar_detect, int radio_idx); -+int ieee80211_max_num_channels(struct ieee80211_local *local, int radio_idx); -+u32 ieee80211_get_radio_mask(struct wiphy *wiphy, struct net_device *dev); - void ieee80211_recalc_chanctx_chantype(struct ieee80211_local *local, - struct ieee80211_chanctx *ctx); - ---- a/net/mac80211/iface.c -+++ b/net/mac80211/iface.c -@@ -397,7 +397,7 @@ static int ieee80211_check_concurrent_if - } - } - -- return ieee80211_check_combinations(sdata, NULL, 0, 0); -+ return ieee80211_check_combinations(sdata, NULL, 0, 0, -1); - } - - static int ieee80211_check_queues(struct ieee80211_sub_if_data *sdata, ---- a/net/mac80211/util.c -+++ b/net/mac80211/util.c -@@ -3918,20 +3918,103 @@ static u8 ieee80211_chanctx_radar_detect - return radar_detect; - } - -+static u32 -+__ieee80211_get_radio_mask(struct ieee80211_sub_if_data *sdata) -+{ -+ struct ieee80211_bss_conf *link_conf; -+ struct ieee80211_chanctx_conf *conf; -+ unsigned int link_id; -+ u32 mask = 0; -+ -+ for_each_vif_active_link(&sdata->vif, link_conf, link_id) { -+ conf = sdata_dereference(link_conf->chanctx_conf, sdata); -+ if (!conf || conf->radio_idx < 0) -+ continue; -+ -+ mask |= BIT(conf->radio_idx); -+ } -+ -+ return mask; -+} -+ -+u32 ieee80211_get_radio_mask(struct wiphy *wiphy, struct net_device *dev) -+{ -+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); -+ -+ return __ieee80211_get_radio_mask(sdata); -+} -+ -+static bool -+ieee80211_sdata_uses_radio(struct ieee80211_sub_if_data *sdata, int radio_idx) -+{ -+ if (radio_idx < 0) -+ return true; -+ -+ return __ieee80211_get_radio_mask(sdata) & BIT(radio_idx); -+} -+ -+static int -+ieee80211_fill_ifcomb_params(struct ieee80211_local *local, -+ struct iface_combination_params *params, -+ const struct cfg80211_chan_def *chandef, -+ struct ieee80211_sub_if_data *sdata) -+{ -+ struct ieee80211_sub_if_data *sdata_iter; -+ struct ieee80211_chanctx *ctx; -+ int total = !!sdata; -+ -+ list_for_each_entry(ctx, &local->chanctx_list, list) { -+ if (ctx->replace_state == IEEE80211_CHANCTX_WILL_BE_REPLACED) -+ continue; -+ -+ if (params->radio_idx >= 0 && -+ ctx->conf.radio_idx != params->radio_idx) -+ continue; -+ -+ params->radar_detect |= -+ ieee80211_chanctx_radar_detect(local, ctx); -+ -+ if (chandef && ctx->mode != IEEE80211_CHANCTX_EXCLUSIVE && -+ cfg80211_chandef_compatible(chandef, &ctx->conf.def)) -+ continue; -+ -+ params->num_different_channels++; -+ } -+ -+ list_for_each_entry(sdata_iter, &local->interfaces, list) { -+ struct wireless_dev *wdev_iter; -+ -+ wdev_iter = &sdata_iter->wdev; -+ -+ if (sdata_iter == sdata || -+ !ieee80211_sdata_running(sdata_iter) || -+ cfg80211_iftype_allowed(local->hw.wiphy, -+ wdev_iter->iftype, 0, 1)) -+ continue; -+ -+ if (!ieee80211_sdata_uses_radio(sdata_iter, params->radio_idx)) -+ continue; -+ -+ params->iftype_num[wdev_iter->iftype]++; -+ total++; -+ } -+ -+ return total; -+} -+ - int ieee80211_check_combinations(struct ieee80211_sub_if_data *sdata, - const struct cfg80211_chan_def *chandef, - enum ieee80211_chanctx_mode chanmode, -- u8 radar_detect) -+ u8 radar_detect, int radio_idx) - { -+ bool shared = chanmode == IEEE80211_CHANCTX_SHARED; - struct ieee80211_local *local = sdata->local; -- struct ieee80211_sub_if_data *sdata_iter; - enum nl80211_iftype iftype = sdata->wdev.iftype; -- struct ieee80211_chanctx *ctx; -- int total = 1; - struct iface_combination_params params = { - .radar_detect = radar_detect, -- .radio_idx = -1, -+ .radio_idx = radio_idx, - }; -+ int total; - - lockdep_assert_wiphy(local->hw.wiphy); - -@@ -3968,37 +4051,9 @@ int ieee80211_check_combinations(struct - if (iftype != NL80211_IFTYPE_UNSPECIFIED) - params.iftype_num[iftype] = 1; - -- list_for_each_entry(ctx, &local->chanctx_list, list) { -- if (ctx->replace_state == IEEE80211_CHANCTX_WILL_BE_REPLACED) -- continue; -- params.radar_detect |= -- ieee80211_chanctx_radar_detect(local, ctx); -- if (ctx->mode == IEEE80211_CHANCTX_EXCLUSIVE) { -- params.num_different_channels++; -- continue; -- } -- if (chandef && chanmode == IEEE80211_CHANCTX_SHARED && -- cfg80211_chandef_compatible(chandef, -- &ctx->conf.def)) -- continue; -- params.num_different_channels++; -- } -- -- list_for_each_entry_rcu(sdata_iter, &local->interfaces, list) { -- struct wireless_dev *wdev_iter; -- -- wdev_iter = &sdata_iter->wdev; -- -- if (sdata_iter == sdata || -- !ieee80211_sdata_running(sdata_iter) || -- cfg80211_iftype_allowed(local->hw.wiphy, -- wdev_iter->iftype, 0, 1)) -- continue; -- -- params.iftype_num[wdev_iter->iftype]++; -- total++; -- } -- -+ total = ieee80211_fill_ifcomb_params(local, ¶ms, -+ shared ? chandef : NULL, -+ sdata); - if (total == 1 && !params.radar_detect) - return 0; - -@@ -4015,30 +4070,17 @@ ieee80211_iter_max_chans(const struct ie - c->num_different_channels); - } - --int ieee80211_max_num_channels(struct ieee80211_local *local) -+int ieee80211_max_num_channels(struct ieee80211_local *local, int radio_idx) - { -- struct ieee80211_sub_if_data *sdata; -- struct ieee80211_chanctx *ctx; - u32 max_num_different_channels = 1; - int err; - struct iface_combination_params params = { -- .radio_idx = -1, -+ .radio_idx = radio_idx, - }; - - lockdep_assert_wiphy(local->hw.wiphy); - -- list_for_each_entry(ctx, &local->chanctx_list, list) { -- if (ctx->replace_state == IEEE80211_CHANCTX_WILL_BE_REPLACED) -- continue; -- -- params.num_different_channels++; -- -- params.radar_detect |= -- ieee80211_chanctx_radar_detect(local, ctx); -- } -- -- list_for_each_entry_rcu(sdata, &local->interfaces, list) -- params.iftype_num[sdata->wdev.iftype]++; -+ ieee80211_fill_ifcomb_params(local, ¶ms, NULL, NULL); - - err = cfg80211_iter_combinations(local->hw.wiphy, ¶ms, - ieee80211_iter_max_chans, diff --git a/package/kernel/mac80211/patches/subsys/347-wifi-mac80211-move-code-in-ieee80211_link_reserve_ch.patch b/package/kernel/mac80211/patches/subsys/347-wifi-mac80211-move-code-in-ieee80211_link_reserve_ch.patch deleted file mode 100644 index 9a8506760..000000000 --- a/package/kernel/mac80211/patches/subsys/347-wifi-mac80211-move-code-in-ieee80211_link_reserve_ch.patch +++ /dev/null @@ -1,175 +0,0 @@ -From: Felix Fietkau -Date: Wed, 5 Jun 2024 10:49:22 +0200 -Subject: [PATCH] wifi: mac80211: move code in - ieee80211_link_reserve_chanctx to a helper - -Reduces indentation in preparation for further changes - -Signed-off-by: Felix Fietkau ---- - ---- a/net/mac80211/chan.c -+++ b/net/mac80211/chan.c -@@ -1033,6 +1033,71 @@ int ieee80211_link_unreserve_chanctx(str - return 0; - } - -+static struct ieee80211_chanctx * -+ieee80211_replace_chanctx(struct ieee80211_local *local, -+ const struct ieee80211_chan_req *chanreq, -+ enum ieee80211_chanctx_mode mode, -+ struct ieee80211_chanctx *curr_ctx) -+{ -+ struct ieee80211_chanctx *new_ctx, *ctx; -+ -+ if (!curr_ctx || (curr_ctx->replace_state == -+ IEEE80211_CHANCTX_WILL_BE_REPLACED) || -+ !list_empty(&curr_ctx->reserved_links)) { -+ /* -+ * Another link already requested this context for a -+ * reservation. Find another one hoping all links assigned -+ * to it will also switch soon enough. -+ * -+ * TODO: This needs a little more work as some cases -+ * (more than 2 chanctx capable devices) may fail which could -+ * otherwise succeed provided some channel context juggling was -+ * performed. -+ * -+ * Consider ctx1..3, link1..6, each ctx has 2 links. link1 and -+ * link2 from ctx1 request new different chandefs starting 2 -+ * in-place reserations with ctx4 and ctx5 replacing ctx1 and -+ * ctx2 respectively. Next link5 and link6 from ctx3 reserve -+ * ctx4. If link3 and link4 remain on ctx2 as they are then this -+ * fails unless `replace_ctx` from ctx5 is replaced with ctx3. -+ */ -+ list_for_each_entry(ctx, &local->chanctx_list, list) { -+ if (ctx->replace_state != -+ IEEE80211_CHANCTX_REPLACE_NONE) -+ continue; -+ -+ if (!list_empty(&ctx->reserved_links)) -+ continue; -+ -+ curr_ctx = ctx; -+ break; -+ } -+ } -+ -+ /* -+ * If that's true then all available contexts already have reservations -+ * and cannot be used. -+ */ -+ if (!curr_ctx || (curr_ctx->replace_state == -+ IEEE80211_CHANCTX_WILL_BE_REPLACED) || -+ !list_empty(&curr_ctx->reserved_links)) -+ return ERR_PTR(-EBUSY); -+ -+ new_ctx = ieee80211_alloc_chanctx(local, chanreq, mode, -1); -+ if (!new_ctx) -+ return ERR_PTR(-ENOMEM); -+ -+ new_ctx->replace_ctx = curr_ctx; -+ new_ctx->replace_state = IEEE80211_CHANCTX_REPLACES_OTHER; -+ -+ curr_ctx->replace_ctx = new_ctx; -+ curr_ctx->replace_state = IEEE80211_CHANCTX_WILL_BE_REPLACED; -+ -+ list_add_rcu(&new_ctx->list, &local->chanctx_list); -+ -+ return new_ctx; -+} -+ - int ieee80211_link_reserve_chanctx(struct ieee80211_link_data *link, - const struct ieee80211_chan_req *chanreq, - enum ieee80211_chanctx_mode mode, -@@ -1040,7 +1105,7 @@ int ieee80211_link_reserve_chanctx(struc - { - struct ieee80211_sub_if_data *sdata = link->sdata; - struct ieee80211_local *local = sdata->local; -- struct ieee80211_chanctx *new_ctx, *curr_ctx, *ctx; -+ struct ieee80211_chanctx *new_ctx, *curr_ctx; - - lockdep_assert_wiphy(local->hw.wiphy); - -@@ -1050,75 +1115,13 @@ int ieee80211_link_reserve_chanctx(struc - - new_ctx = ieee80211_find_reservation_chanctx(local, chanreq, mode); - if (!new_ctx) { -- if (ieee80211_can_create_new_chanctx(local, -1)) { -+ if (ieee80211_can_create_new_chanctx(local, -1)) - new_ctx = ieee80211_new_chanctx(local, chanreq, mode); -- if (IS_ERR(new_ctx)) -- return PTR_ERR(new_ctx); -- } else { -- if (!curr_ctx || -- (curr_ctx->replace_state == -- IEEE80211_CHANCTX_WILL_BE_REPLACED) || -- !list_empty(&curr_ctx->reserved_links)) { -- /* -- * Another link already requested this context -- * for a reservation. Find another one hoping -- * all links assigned to it will also switch -- * soon enough. -- * -- * TODO: This needs a little more work as some -- * cases (more than 2 chanctx capable devices) -- * may fail which could otherwise succeed -- * provided some channel context juggling was -- * performed. -- * -- * Consider ctx1..3, link1..6, each ctx has 2 -- * links. link1 and link2 from ctx1 request new -- * different chandefs starting 2 in-place -- * reserations with ctx4 and ctx5 replacing -- * ctx1 and ctx2 respectively. Next link5 and -- * link6 from ctx3 reserve ctx4. If link3 and -- * link4 remain on ctx2 as they are then this -- * fails unless `replace_ctx` from ctx5 is -- * replaced with ctx3. -- */ -- list_for_each_entry(ctx, &local->chanctx_list, -- list) { -- if (ctx->replace_state != -- IEEE80211_CHANCTX_REPLACE_NONE) -- continue; -- -- if (!list_empty(&ctx->reserved_links)) -- continue; -- -- curr_ctx = ctx; -- break; -- } -- } -- -- /* -- * If that's true then all available contexts already -- * have reservations and cannot be used. -- */ -- if (!curr_ctx || -- (curr_ctx->replace_state == -- IEEE80211_CHANCTX_WILL_BE_REPLACED) || -- !list_empty(&curr_ctx->reserved_links)) -- return -EBUSY; -- -- new_ctx = ieee80211_alloc_chanctx(local, chanreq, mode, -1); -- if (!new_ctx) -- return -ENOMEM; -- -- new_ctx->replace_ctx = curr_ctx; -- new_ctx->replace_state = -- IEEE80211_CHANCTX_REPLACES_OTHER; -- -- curr_ctx->replace_ctx = new_ctx; -- curr_ctx->replace_state = -- IEEE80211_CHANCTX_WILL_BE_REPLACED; -- -- list_add_rcu(&new_ctx->list, &local->chanctx_list); -- } -+ else -+ new_ctx = ieee80211_replace_chanctx(local, chanreq, -+ mode, curr_ctx); -+ if (IS_ERR(new_ctx)) -+ return PTR_ERR(new_ctx); - } - - list_add(&link->reserved_chanctx_list, &new_ctx->reserved_links); diff --git a/package/kernel/mac80211/patches/subsys/348-wifi-mac80211-add-wiphy-radio-assignment-and-validat.patch b/package/kernel/mac80211/patches/subsys/348-wifi-mac80211-add-wiphy-radio-assignment-and-validat.patch deleted file mode 100644 index c559f070e..000000000 --- a/package/kernel/mac80211/patches/subsys/348-wifi-mac80211-add-wiphy-radio-assignment-and-validat.patch +++ /dev/null @@ -1,132 +0,0 @@ -From: Felix Fietkau -Date: Wed, 5 Jun 2024 18:39:55 +0200 -Subject: [PATCH] wifi: mac80211: add wiphy radio assignment and - validation - -Validate number of channels and interface combinations per radio. -Assign each channel context to a radio. - -Signed-off-by: Felix Fietkau ---- - ---- a/net/mac80211/chan.c -+++ b/net/mac80211/chan.c -@@ -680,14 +680,15 @@ static int ieee80211_add_chanctx(struct - static struct ieee80211_chanctx * - ieee80211_new_chanctx(struct ieee80211_local *local, - const struct ieee80211_chan_req *chanreq, -- enum ieee80211_chanctx_mode mode) -+ enum ieee80211_chanctx_mode mode, -+ int radio_idx) - { - struct ieee80211_chanctx *ctx; - int err; - - lockdep_assert_wiphy(local->hw.wiphy); - -- ctx = ieee80211_alloc_chanctx(local, chanreq, mode, -1); -+ ctx = ieee80211_alloc_chanctx(local, chanreq, mode, radio_idx); - if (!ctx) - return ERR_PTR(-ENOMEM); - -@@ -1040,6 +1041,8 @@ ieee80211_replace_chanctx(struct ieee802 - struct ieee80211_chanctx *curr_ctx) - { - struct ieee80211_chanctx *new_ctx, *ctx; -+ struct wiphy *wiphy = local->hw.wiphy; -+ const struct wiphy_radio *radio; - - if (!curr_ctx || (curr_ctx->replace_state == - IEEE80211_CHANCTX_WILL_BE_REPLACED) || -@@ -1069,6 +1072,12 @@ ieee80211_replace_chanctx(struct ieee802 - if (!list_empty(&ctx->reserved_links)) - continue; - -+ if (ctx->conf.radio_idx >= 0) { -+ radio = &wiphy->radio[ctx->conf.radio_idx]; -+ if (!cfg80211_radio_chandef_valid(radio, &chanreq->oper)) -+ continue; -+ } -+ - curr_ctx = ctx; - break; - } -@@ -1098,6 +1107,34 @@ ieee80211_replace_chanctx(struct ieee802 - return new_ctx; - } - -+static bool -+ieee80211_find_available_radio(struct ieee80211_local *local, -+ const struct ieee80211_chan_req *chanreq, -+ int *radio_idx) -+{ -+ struct wiphy *wiphy = local->hw.wiphy; -+ const struct wiphy_radio *radio; -+ int i; -+ -+ *radio_idx = -1; -+ if (!wiphy->n_radio) -+ return true; -+ -+ for (i = 0; i < wiphy->n_radio; i++) { -+ radio = &wiphy->radio[i]; -+ if (!cfg80211_radio_chandef_valid(radio, &chanreq->oper)) -+ continue; -+ -+ if (!ieee80211_can_create_new_chanctx(local, i)) -+ continue; -+ -+ *radio_idx = i; -+ return true; -+ } -+ -+ return false; -+} -+ - int ieee80211_link_reserve_chanctx(struct ieee80211_link_data *link, - const struct ieee80211_chan_req *chanreq, - enum ieee80211_chanctx_mode mode, -@@ -1106,6 +1143,7 @@ int ieee80211_link_reserve_chanctx(struc - struct ieee80211_sub_if_data *sdata = link->sdata; - struct ieee80211_local *local = sdata->local; - struct ieee80211_chanctx *new_ctx, *curr_ctx; -+ int radio_idx; - - lockdep_assert_wiphy(local->hw.wiphy); - -@@ -1115,8 +1153,10 @@ int ieee80211_link_reserve_chanctx(struc - - new_ctx = ieee80211_find_reservation_chanctx(local, chanreq, mode); - if (!new_ctx) { -- if (ieee80211_can_create_new_chanctx(local, -1)) -- new_ctx = ieee80211_new_chanctx(local, chanreq, mode); -+ if (ieee80211_can_create_new_chanctx(local, -1) && -+ ieee80211_find_available_radio(local, chanreq, &radio_idx)) -+ new_ctx = ieee80211_new_chanctx(local, chanreq, mode, -+ radio_idx); - else - new_ctx = ieee80211_replace_chanctx(local, chanreq, - mode, curr_ctx); -@@ -1724,6 +1764,7 @@ int ieee80211_link_use_channel(struct ie - struct ieee80211_local *local = sdata->local; - struct ieee80211_chanctx *ctx; - u8 radar_detect_width = 0; -+ int radio_idx; - int ret; - - lockdep_assert_wiphy(local->hw.wiphy); -@@ -1751,8 +1792,12 @@ int ieee80211_link_use_channel(struct ie - __ieee80211_link_release_channel(link); - - ctx = ieee80211_find_chanctx(local, chanreq, mode); -- if (!ctx) -- ctx = ieee80211_new_chanctx(local, chanreq, mode); -+ if (!ctx) { -+ if (!ieee80211_find_available_radio(local, chanreq, &radio_idx)) -+ ctx = ERR_PTR(-EBUSY); -+ else -+ ctx = ieee80211_new_chanctx(local, chanreq, mode, radio_idx); -+ } - if (IS_ERR(ctx)) { - ret = PTR_ERR(ctx); - goto out; diff --git a/package/kernel/mac80211/patches/subsys/349-wifi-mac80211_hwsim-add-support-for-multi-radio-wiph.patch b/package/kernel/mac80211/patches/subsys/349-wifi-mac80211_hwsim-add-support-for-multi-radio-wiph.patch deleted file mode 100644 index 91fe6d83d..000000000 --- a/package/kernel/mac80211/patches/subsys/349-wifi-mac80211_hwsim-add-support-for-multi-radio-wiph.patch +++ /dev/null @@ -1,199 +0,0 @@ -From: Felix Fietkau -Date: Tue, 11 Jun 2024 09:02:55 +0200 -Subject: [PATCH] wifi: mac80211_hwsim: add support for multi-radio wiphy - -This registers one wiphy radio per supported band. Number of different -channels is set per radio. - -Signed-off-by: Felix Fietkau ---- - ---- a/drivers/net/wireless/virtual/mac80211_hwsim.c -+++ b/drivers/net/wireless/virtual/mac80211_hwsim.c -@@ -69,6 +69,10 @@ static bool mlo; - module_param(mlo, bool, 0444); - MODULE_PARM_DESC(mlo, "Support MLO"); - -+static bool multi_radio; -+module_param(multi_radio, bool, 0444); -+MODULE_PARM_DESC(mlo, "Support Multiple Radios per wiphy"); -+ - /** - * enum hwsim_regtest - the type of regulatory tests we offer - * -@@ -669,6 +673,10 @@ struct mac80211_hwsim_data { - struct ieee80211_iface_limit if_limits[3]; - int n_if_limits; - -+ struct ieee80211_iface_combination if_combination_radio; -+ struct wiphy_radio_freq_range radio_range[NUM_NL80211_BANDS]; -+ struct wiphy_radio radio[NUM_NL80211_BANDS]; -+ - u32 ciphers[ARRAY_SIZE(hwsim_ciphers)]; - - struct mac_address addresses[2]; -@@ -917,6 +925,7 @@ static const struct nla_policy hwsim_gen - [HWSIM_ATTR_MLO_SUPPORT] = { .type = NLA_FLAG }, - [HWSIM_ATTR_PMSR_SUPPORT] = NLA_POLICY_NESTED(hwsim_pmsr_capa_policy), - [HWSIM_ATTR_PMSR_RESULT] = NLA_POLICY_NESTED(hwsim_pmsr_peers_result_policy), -+ [HWSIM_ATTR_MULTI_RADIO] = { .type = NLA_FLAG }, - }; - - #if IS_REACHABLE(CONFIG_VIRTIO) -@@ -4007,6 +4016,7 @@ struct hwsim_new_radio_params { - bool reg_strict; - bool p2p_device; - bool use_chanctx; -+ bool multi_radio; - bool destroy_on_close; - const char *hwname; - bool no_vif; -@@ -4083,6 +4093,12 @@ static int append_radio_msg(struct sk_bu - return ret; - } - -+ if (param->multi_radio) { -+ ret = nla_put_flag(skb, HWSIM_ATTR_MULTI_RADIO); -+ if (ret < 0) -+ return ret; -+ } -+ - if (param->hwname) { - ret = nla_put(skb, HWSIM_ATTR_RADIO_NAME, - strlen(param->hwname), param->hwname); -@@ -5099,6 +5115,7 @@ static int mac80211_hwsim_new_radio(stru - struct net *net; - int idx, i; - int n_limits = 0; -+ int n_bands = 0; - - if (WARN_ON(param->channels > 1 && !param->use_chanctx)) - return -EINVAL; -@@ -5202,22 +5219,22 @@ static int mac80211_hwsim_new_radio(stru - n_limits++; - } - -+ data->if_combination.radar_detect_widths = -+ BIT(NL80211_CHAN_WIDTH_5) | -+ BIT(NL80211_CHAN_WIDTH_10) | -+ BIT(NL80211_CHAN_WIDTH_20_NOHT) | -+ BIT(NL80211_CHAN_WIDTH_20) | -+ BIT(NL80211_CHAN_WIDTH_40) | -+ BIT(NL80211_CHAN_WIDTH_80) | -+ BIT(NL80211_CHAN_WIDTH_160); -+ - if (data->use_chanctx) { - hw->wiphy->max_scan_ssids = 255; - hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN; - hw->wiphy->max_remain_on_channel_duration = 1000; -- data->if_combination.radar_detect_widths = 0; - data->if_combination.num_different_channels = data->channels; - } else { - data->if_combination.num_different_channels = 1; -- data->if_combination.radar_detect_widths = -- BIT(NL80211_CHAN_WIDTH_5) | -- BIT(NL80211_CHAN_WIDTH_10) | -- BIT(NL80211_CHAN_WIDTH_20_NOHT) | -- BIT(NL80211_CHAN_WIDTH_20) | -- BIT(NL80211_CHAN_WIDTH_40) | -- BIT(NL80211_CHAN_WIDTH_80) | -- BIT(NL80211_CHAN_WIDTH_160); - } - - if (!n_limits) { -@@ -5333,6 +5350,9 @@ static int mac80211_hwsim_new_radio(stru - - for (band = NL80211_BAND_2GHZ; band < NUM_NL80211_BANDS; band++) { - struct ieee80211_supported_band *sband = &data->bands[band]; -+ struct wiphy_radio_freq_range *radio_range; -+ const struct ieee80211_channel *c; -+ struct wiphy_radio *radio; - - sband->band = band; - -@@ -5406,8 +5426,36 @@ static int mac80211_hwsim_new_radio(stru - mac80211_hwsim_sband_capab(sband); - - hw->wiphy->bands[band] = sband; -+ -+ if (!param->multi_radio) -+ continue; -+ -+ c = sband->channels; -+ radio_range = &data->radio_range[n_bands]; -+ radio_range->start_freq = ieee80211_channel_to_khz(c) - 10000; -+ -+ c += sband->n_channels - 1; -+ radio_range->end_freq = ieee80211_channel_to_khz(c) + 10000; -+ -+ radio = &data->radio[n_bands++]; -+ radio->freq_range = radio_range; -+ radio->n_freq_range = 1; -+ radio->iface_combinations = &data->if_combination_radio; -+ radio->n_iface_combinations = 1; - } - -+ if (param->multi_radio) { -+ hw->wiphy->radio = data->radio; -+ hw->wiphy->n_radio = n_bands; -+ -+ memcpy(&data->if_combination_radio, &data->if_combination, -+ sizeof(data->if_combination)); -+ data->if_combination.num_different_channels *= n_bands; -+ } -+ -+ if (data->use_chanctx) -+ data->if_combination.radar_detect_widths = 0; -+ - /* By default all radios belong to the first group */ - data->group = 1; - mutex_init(&data->mutex); -@@ -6025,6 +6073,9 @@ static int hwsim_new_radio_nl(struct sk_ - else - param.use_chanctx = (param.channels > 1); - -+ if (info->attrs[HWSIM_ATTR_MULTI_RADIO]) -+ param.multi_radio = true; -+ - if (info->attrs[HWSIM_ATTR_REG_HINT_ALPHA2]) - param.reg_alpha2 = - nla_data(info->attrs[HWSIM_ATTR_REG_HINT_ALPHA2]); -@@ -6105,7 +6156,7 @@ static int hwsim_new_radio_nl(struct sk_ - - param.mlo = info->attrs[HWSIM_ATTR_MLO_SUPPORT]; - -- if (param.mlo) -+ if (param.mlo || param.multi_radio) - param.use_chanctx = true; - - if (info->attrs[HWSIM_ATTR_RADIO_NAME]) { -@@ -6802,7 +6853,8 @@ static int __init init_mac80211_hwsim(vo - - param.p2p_device = support_p2p_device; - param.mlo = mlo; -- param.use_chanctx = channels > 1 || mlo; -+ param.multi_radio = multi_radio; -+ param.use_chanctx = channels > 1 || mlo || multi_radio; - param.iftypes = HWSIM_IFTYPE_SUPPORT_MASK; - if (param.p2p_device) - param.iftypes |= BIT(NL80211_IFTYPE_P2P_DEVICE); ---- a/drivers/net/wireless/virtual/mac80211_hwsim.h -+++ b/drivers/net/wireless/virtual/mac80211_hwsim.h -@@ -157,6 +157,9 @@ enum hwsim_commands { - * to provide details about peer measurement request (nl80211_peer_measurement_attrs) - * @HWSIM_ATTR_PMSR_RESULT: nested attributed used with %HWSIM_CMD_REPORT_PMSR - * to provide peer measurement result (nl80211_peer_measurement_attrs) -+ * @HWSIM_ATTR_MULTI_RADIO: Register multiple wiphy radios (flag). -+ * Adds one radio for each band. Number of supported channels will be set for -+ * each radio instead of for the wiphy. - * @__HWSIM_ATTR_MAX: enum limit - */ - enum hwsim_attrs { -@@ -189,6 +192,7 @@ enum hwsim_attrs { - HWSIM_ATTR_PMSR_SUPPORT, - HWSIM_ATTR_PMSR_REQUEST, - HWSIM_ATTR_PMSR_RESULT, -+ HWSIM_ATTR_MULTI_RADIO, - __HWSIM_ATTR_MAX, - }; - #define HWSIM_ATTR_MAX (__HWSIM_ATTR_MAX - 1) diff --git a/package/kernel/mac80211/patches/subsys/400-allow-ibss-mixed.patch b/package/kernel/mac80211/patches/subsys/400-allow-ibss-mixed.patch index 7a96f9f2b..c38fa13f0 100644 --- a/package/kernel/mac80211/patches/subsys/400-allow-ibss-mixed.patch +++ b/package/kernel/mac80211/patches/subsys/400-allow-ibss-mixed.patch @@ -16,7 +16,7 @@ and we should ignore this. --- a/net/wireless/core.c +++ b/net/wireless/core.c -@@ -651,21 +651,6 @@ static int wiphy_verify_combinations(str +@@ -614,21 +614,6 @@ static int wiphy_verify_combinations(str c->limits[j].max > 1)) return -EINVAL; diff --git a/package/kernel/mac80211/patches/subsys/401-mac80211-allow-vht-on-2g.patch b/package/kernel/mac80211/patches/subsys/401-mac80211-allow-vht-on-2g.patch new file mode 100644 index 000000000..5d8742ba9 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/401-mac80211-allow-vht-on-2g.patch @@ -0,0 +1,36 @@ +--- a/net/mac80211/vht.c ++++ b/net/mac80211/vht.c +@@ -135,7 +135,8 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(stru + have_80mhz = false; + for (i = 0; i < sband->n_channels; i++) { + if (sband->channels[i].flags & (IEEE80211_CHAN_DISABLED | +- IEEE80211_CHAN_NO_80MHZ)) ++ IEEE80211_CHAN_NO_80MHZ) & ++ (sband->band != NL80211_BAND_2GHZ)) + continue; + + have_80mhz = true; +--- a/net/mac80211/util.c ++++ b/net/mac80211/util.c +@@ -1955,7 +1955,8 @@ static int ieee80211_build_preq_ies_band + /* Check if any channel in this sband supports at least 80 MHz */ + for (i = 0; i < sband->n_channels; i++) { + if (sband->channels[i].flags & (IEEE80211_CHAN_DISABLED | +- IEEE80211_CHAN_NO_80MHZ)) ++ IEEE80211_CHAN_NO_80MHZ) & ++ (sband->band != NL80211_BAND_2GHZ)) + continue; + + have_80mhz = true; +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -4744,7 +4744,8 @@ static int ieee80211_prep_channel(struct + have_80mhz = false; + for (i = 0; i < sband->n_channels; i++) { + if (sband->channels[i].flags & (IEEE80211_CHAN_DISABLED | +- IEEE80211_CHAN_NO_80MHZ)) ++ IEEE80211_CHAN_NO_80MHZ) & ++ (sband->band != NL80211_BAND_2GHZ)) + continue; + + have_80mhz = true; diff --git a/package/kernel/mac80211/patches/subsys/500-mac80211_configure_antenna_gain.patch b/package/kernel/mac80211/patches/subsys/500-mac80211_configure_antenna_gain.patch new file mode 100644 index 000000000..bc5e7e76c --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/500-mac80211_configure_antenna_gain.patch @@ -0,0 +1,162 @@ +--- a/include/net/cfg80211.h ++++ b/include/net/cfg80211.h +@@ -4084,6 +4084,7 @@ struct mgmt_frame_regs { + * (as advertised by the nl80211 feature flag.) + * @get_tx_power: store the current TX power into the dbm variable; + * return 0 if successful ++ * @set_antenna_gain: set antenna gain to reduce maximum tx power if necessary + * + * @rfkill_poll: polls the hw rfkill line, use cfg80211 reporting + * functions to adjust rfkill hw state +@@ -4434,6 +4435,7 @@ struct cfg80211_ops { + enum nl80211_tx_power_setting type, int mbm); + int (*get_tx_power)(struct wiphy *wiphy, struct wireless_dev *wdev, + int *dbm); ++ int (*set_antenna_gain)(struct wiphy *wiphy, int dbi); + + void (*rfkill_poll)(struct wiphy *wiphy); + +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -1677,6 +1677,7 @@ enum ieee80211_smps_mode { + * + * @power_level: requested transmit power (in dBm), backward compatibility + * value only that is set to the minimum of all interfaces ++ * @max_antenna_gain: maximum antenna gain adjusted by user config (in dBi) + * + * @chandef: the channel definition to tune to + * @radar_enabled: whether radar detection is enabled +@@ -1697,6 +1698,7 @@ enum ieee80211_smps_mode { + struct ieee80211_conf { + u32 flags; + int power_level, dynamic_ps_timeout; ++ int max_antenna_gain; + + u16 listen_interval; + u8 ps_dtim_period; +--- a/include/uapi/linux/nl80211.h ++++ b/include/uapi/linux/nl80211.h +@@ -2749,6 +2749,9 @@ enum nl80211_commands { + * When used with %NL80211_CMD_FRAME_TX_STATUS, indicates the ack RX + * timestamp. When used with %NL80211_CMD_FRAME RX notification, indicates + * the incoming frame RX timestamp. ++ * @NL80211_ATTR_WIPHY_ANTENNA_GAIN: Configured antenna gain. Used to reduce ++ * transmit power to stay within regulatory limits. u32, dBi. ++ * + * @NUM_NL80211_ATTR: total number of nl80211_attrs available + * @NL80211_ATTR_MAX: highest attribute number currently defined + * @__NL80211_ATTR_AFTER_LAST: internal use +@@ -3277,6 +3280,8 @@ enum nl80211_attrs { + NL80211_ATTR_TX_HW_TIMESTAMP, + NL80211_ATTR_RX_HW_TIMESTAMP, + ++ NL80211_ATTR_WIPHY_ANTENNA_GAIN, ++ + /* add attributes here, update the policy in nl80211.c */ + + __NL80211_ATTR_AFTER_LAST, +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -3046,6 +3046,19 @@ static int ieee80211_get_tx_power(struct + return 0; + } + ++static int ieee80211_set_antenna_gain(struct wiphy *wiphy, int dbi) ++{ ++ struct ieee80211_local *local = wiphy_priv(wiphy); ++ ++ if (dbi < 0) ++ return -EINVAL; ++ ++ local->user_antenna_gain = dbi; ++ ieee80211_hw_config(local, 0); ++ ++ return 0; ++} ++ + static void ieee80211_rfkill_poll(struct wiphy *wiphy) + { + struct ieee80211_local *local = wiphy_priv(wiphy); +@@ -4956,6 +4969,7 @@ const struct cfg80211_ops mac80211_confi + .set_wiphy_params = ieee80211_set_wiphy_params, + .set_tx_power = ieee80211_set_tx_power, + .get_tx_power = ieee80211_get_tx_power, ++ .set_antenna_gain = ieee80211_set_antenna_gain, + .rfkill_poll = ieee80211_rfkill_poll, + CFG80211_TESTMODE_CMD(ieee80211_testmode_cmd) + CFG80211_TESTMODE_DUMP(ieee80211_testmode_dump) +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -1542,6 +1542,7 @@ struct ieee80211_local { + int dynamic_ps_forced_timeout; + + int user_power_level; /* in dBm, for all interfaces */ ++ int user_antenna_gain; /* in dBi */ + + enum ieee80211_smps_mode smps_mode; + +--- a/net/mac80211/main.c ++++ b/net/mac80211/main.c +@@ -96,7 +96,7 @@ static u32 ieee80211_hw_conf_chan(struct + struct ieee80211_sub_if_data *sdata; + struct cfg80211_chan_def chandef = {}; + u32 changed = 0; +- int power; ++ int power, max_power; + u32 offchannel_flag; + + offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL; +@@ -157,6 +157,12 @@ static u32 ieee80211_hw_conf_chan(struct + } + rcu_read_unlock(); + ++ max_power = chandef.chan->max_reg_power; ++ if (local->user_antenna_gain > 0) { ++ max_power -= local->user_antenna_gain; ++ power = min(power, max_power); ++ } ++ + if (local->hw.conf.power_level != power) { + changed |= IEEE80211_CONF_CHANGE_POWER; + local->hw.conf.power_level = power; +@@ -762,6 +768,7 @@ struct ieee80211_hw *ieee80211_alloc_hw_ + IEEE80211_RADIOTAP_MCS_HAVE_BW; + local->hw.radiotap_vht_details = IEEE80211_RADIOTAP_VHT_KNOWN_GI | + IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH; ++ local->user_antenna_gain = 0; + local->hw.uapsd_queues = IEEE80211_DEFAULT_UAPSD_QUEUES; + local->hw.uapsd_max_sp_len = IEEE80211_DEFAULT_MAX_SP_LEN; + local->hw.max_mtu = IEEE80211_MAX_DATA_LEN; +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -823,6 +823,7 @@ static const struct nla_policy nl80211_p + [NL80211_ATTR_MLD_ADDR] = NLA_POLICY_EXACT_LEN(ETH_ALEN), + [NL80211_ATTR_MLO_SUPPORT] = { .type = NLA_FLAG }, + [NL80211_ATTR_MAX_NUM_AKM_SUITES] = { .type = NLA_REJECT }, ++ [NL80211_ATTR_WIPHY_ANTENNA_GAIN] = { .type = NLA_U32 }, + }; + + /* policy for the key attributes */ +@@ -3535,6 +3536,22 @@ static int nl80211_set_wiphy(struct sk_b + if (result) + goto out; + } ++ ++ if (info->attrs[NL80211_ATTR_WIPHY_ANTENNA_GAIN]) { ++ int idx, dbi = 0; ++ ++ if (!rdev->ops->set_antenna_gain) { ++ result = -EOPNOTSUPP; ++ goto out; ++ } ++ ++ idx = NL80211_ATTR_WIPHY_ANTENNA_GAIN; ++ dbi = nla_get_u32(info->attrs[idx]); ++ ++ result = rdev->ops->set_antenna_gain(&rdev->wiphy, dbi); ++ if (result) ++ goto out; ++ } + + if (info->attrs[NL80211_ATTR_WIPHY_TX_POWER_SETTING]) { + struct wireless_dev *txp_wdev = wdev; diff --git a/package/kernel/mac80211/patches/subsys/780-avoid-crashing-missing-band.patch b/package/kernel/mac80211/patches/subsys/780-avoid-crashing-missing-band.patch index e64ca1753..2bc11efd0 100644 --- a/package/kernel/mac80211/patches/subsys/780-avoid-crashing-missing-band.patch +++ b/package/kernel/mac80211/patches/subsys/780-avoid-crashing-missing-band.patch @@ -18,7 +18,7 @@ Signed-off-by: David Bauer --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c -@@ -2459,6 +2459,13 @@ static void sta_stats_decode_rate(struct +@@ -2422,6 +2422,13 @@ static void sta_stats_decode_rate(struct sband = local->hw.wiphy->bands[band]; diff --git a/package/kernel/mac80211/patches/subsys/800-rework-eth_hw_addr_set.patch b/package/kernel/mac80211/patches/subsys/800-rework-eth_hw_addr_set.patch new file mode 100644 index 000000000..20f857f2d --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/800-rework-eth_hw_addr_set.patch @@ -0,0 +1,11 @@ +--- a/backport-include/linux/etherdevice.h ++++ b/backport-include/linux/etherdevice.h +@@ -39,7 +39,7 @@ static inline void u64_to_ether_addr(u64 + } + #endif /* LINUX_VERSION_IS_LESS(4,11,0) */ + +-#if LINUX_VERSION_IS_LESS(5,15,0) ++#if LINUX_VERSION_IS_LESS(5,4,0) + /** + * eth_hw_addr_set - Assign Ethernet address to a net_device + * @dev: pointer to net_device structure diff --git a/package/kernel/mac80211/patches/subsys/900-add-eth-ieee80211_bss_conf.patch b/package/kernel/mac80211/patches/subsys/900-add-eth-ieee80211_bss_conf.patch new file mode 100644 index 000000000..55e2e1b73 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/900-add-eth-ieee80211_bss_conf.patch @@ -0,0 +1,55 @@ +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -673,6 +673,12 @@ + * @he_full_ul_mumimo: does this BSS support the reception (AP) or transmission + * (non-AP STA) of an HE TB PPDU on an RU that spans the entire PPDU + * bandwidth ++ * @eht_su_beamformer: in AP-mode, does this BSS enable operation as an EHT SU ++ * beamformer ++ * @eht_su_beamformee: in AP-mode, does this BSS enable operation as an EHT SU ++ * beamformee ++ * @eht_mu_beamformer: in AP-mode, does this BSS enable operation as an EHT MU ++ * beamformer + */ + struct ieee80211_bss_conf { + const u8 *bssid; +@@ -758,6 +764,9 @@ + bool he_su_beamformee; + bool he_mu_beamformer; + bool he_full_ul_mumimo; ++ bool eht_su_beamformer; ++ bool eht_su_beamformee; ++ bool eht_mu_beamformer; + }; + + /** +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -1307,6 +1307,27 @@ + IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO; + } + ++ if (params->eht_cap) { ++ if (!link_conf->he_support) ++ return -EOPNOTSUPP; ++ link_conf->eht_support = true; ++ link_conf->eht_su_beamformer = ++ params->eht_cap->fixed.phy_cap_info[0] & ++ IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMER; ++ link_conf->eht_su_beamformee = ++ params->eht_cap->fixed.phy_cap_info[0] & ++ IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMEE; ++ link_conf->eht_mu_beamformer = ++ params->eht_cap->fixed.phy_cap_info[7] & ++ (IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_80MHZ | ++ IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_160MHZ | ++ IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_320MHZ); ++ } else { ++ link_conf->eht_su_beamformer = false; ++ link_conf->eht_su_beamformee = false; ++ link_conf->eht_mu_beamformer = false; ++ } ++ + if (sdata->vif.type == NL80211_IFTYPE_AP && + params->mbssid_config.tx_wdev) { + err = ieee80211_set_ap_mbssid_options(sdata, diff --git a/package/kernel/mac80211/patches/subsys/910-fix-build-for-kernel-5.10.patch b/package/kernel/mac80211/patches/subsys/910-fix-build-for-kernel-5.10.patch deleted file mode 100644 index 78c77ff81..000000000 --- a/package/kernel/mac80211/patches/subsys/910-fix-build-for-kernel-5.10.patch +++ /dev/null @@ -1,20 +0,0 @@ ---- a/backport-include/net/dropreason-core.h -+++ b/backport-include/net/dropreason-core.h -@@ -21,6 +21,17 @@ - #define SKB_CONSUMED SKB_DROP_REASON_NOT_SPECIFIED - #endif - -+#if LINUX_VERSION_IS_LESS(5,15,0) -+#define SKB_DROP_REASON_NOT_SPECIFIED 0 -+#define SKB_DROP_REASON_MAX 12 -+static inline void kfree_skb_reason(struct sk_buff *skb, int reason) -+{ -+ if (!skb_unref(skb)) -+ return; -+ __kfree_skb(skb); -+} -+#endif -+ - #if LINUX_VERSION_IS_LESS(6,4,0) - #define SKB_DROP_REASON_SUBSYS_MASK 0xffff0000 - #define SKB_DROP_REASON_SUBSYS_SHIFT 16 diff --git a/package/kernel/mac80211/patches/subsys/920-mac80211-mtk-ACS-channel-time-is-reset-by-ch_restore.patch b/package/kernel/mac80211/patches/subsys/920-mac80211-mtk-ACS-channel-time-is-reset-by-ch_restore.patch deleted file mode 100644 index 71095caf0..000000000 --- a/package/kernel/mac80211/patches/subsys/920-mac80211-mtk-ACS-channel-time-is-reset-by-ch_restore.patch +++ /dev/null @@ -1,58 +0,0 @@ -From e86b89d026fa963ff6c789747b9b373884956157 Mon Sep 17 00:00:00 2001 -From: Evelyn Tsai -Date: Fri, 1 Dec 2023 08:48:35 +0800 -Subject: [PATCH] mac80211: mtk: ACS channel time is reset by ch_restore - -Issue: -There's a chance that the channel time for duty channel is zero in ACS -scan. - -Root cause: -The chan_stat may be reset when restore to duty channel. -Mac80211 will notify to hostapd when scan done and then restore to duty -channel. -And mt76 will clear scan flag after restore done. -If hostapd get the chan_stat before channel_restore, will get the -correct channel time; -If hostapd get the chan_stat after channel_restore, will get zero -channel time; - -Solution: -When channel switch, will check the mac80211 scan state but not the mt76 scan flag. -Mac80211 scan state will be set in scanning, and will be reset after -scan done and before restore to duty channel. - -Signed-off-by: fancy.liu ---- - include/net/mac80211.h | 6 ++++++ - net/mac80211/util.c | 8 ++++++++ - 2 files changed, 14 insertions(+) - ---- a/include/net/mac80211.h -+++ b/include/net/mac80211.h -@@ -7444,4 +7444,10 @@ int ieee80211_set_active_links(struct ie - void ieee80211_set_active_links_async(struct ieee80211_vif *vif, - u16 active_links); - -+/** -+ * ieee80211_get_scanning - get scanning bitmask -+ * -+ * @hw: pointer as obtained from ieee80211_alloc_hw() -+ */ -+unsigned long ieee80211_get_scanning(struct ieee80211_hw *hw); - #endif /* MAC80211_H */ ---- a/net/mac80211/util.c -+++ b/net/mac80211/util.c -@@ -5147,3 +5147,11 @@ void ieee80211_fragment_element(struct s - - *len_pos = elem_len; - } -+ -+unsigned long ieee80211_get_scanning(struct ieee80211_hw *hw) -+{ -+ struct ieee80211_local *local = hw_to_local(hw); -+ -+ return local->scanning; -+} -+EXPORT_SYMBOL(ieee80211_get_scanning); -\ No newline at end of file diff --git a/package/kernel/mac80211/realtek.mk b/package/kernel/mac80211/realtek.mk index 28ea6a657..2f1fa8376 100644 --- a/package/kernel/mac80211/realtek.mk +++ b/package/kernel/mac80211/realtek.mk @@ -1,9 +1,7 @@ PKG_DRIVERS += \ rtlwifi rtlwifi-pci rtlwifi-btcoexist rtlwifi-usb rtl8192c-common \ - rtl8192ce rtl8192se rtl8192de rtl8192cu rtl8723-common rtl8723be rtl8723bs rtl8821ae \ - rtl8xxxu rtw88 rtw88-pci rtw88-usb rtw88-8821c rtw88-8822b rtw88-8822c \ - rtw88-8723d rtw88-8821ce rtw88-8821cu rtw88-8822be rtw88-8822bu \ - rtw88-8822ce rtw88-8822cu rtw88-8723de + rtl8192ce rtl8192se rtl8192de rtl8192cu rtl8723bs rtl8821ae \ + rtl8xxxu rtw88 config-$(call config_package,rtlwifi) += RTL_CARDS RTLWIFI config-$(call config_package,rtlwifi-pci) += RTLWIFI_PCI @@ -20,26 +18,11 @@ config-$(CONFIG_PACKAGE_RTLWIFI_DEBUG) += RTLWIFI_DEBUG config-$(call config_package,rtl8xxxu) += RTL8XXXU config-y += RTL8XXXU_UNTESTED -config-$(call config_package,rtl8723-common) += RTL8723_COMMON -config-$(call config_package,rtl8723be) += RTL8723BE - config-$(call config_package,rtl8723bs) += RTL8723BS config-y += STAGING -config-$(call config_package,rtw88) += RTW88 RTW88_CORE -config-$(call config_package,rtw88-pci) += RTW88_PCI -config-$(call config_package,rtw88-usb) += RTW88_USB -config-$(call config_package,rtw88-8821c) += RTW88_8821C -config-$(call config_package,rtw88-8821ce) += RTW88_8821CE -config-$(call config_package,rtw88-8821cu) += RTW88_8821CU -config-$(call config_package,rtw88-8822b) += RTW88_8822B -config-$(call config_package,rtw88-8822be) += RTW88_8822BE -config-$(call config_package,rtw88-8822bu) += RTW88_8822BU -config-$(call config_package,rtw88-8822c) += RTW88_8822C -config-$(call config_package,rtw88-8822ce) += RTW88_8822CE -config-$(call config_package,rtw88-8822cu) += RTW88_8822CU -config-$(call config_package,rtw88-8723d) += RTW88_8723D -config-$(call config_package,rtw88-8723de) += RTW88_8723DE +config-$(call config_package,rtw88) += RTW88 RTW88_CORE RTW88_PCI +config-y += RTW88_8821CE RTW88_8822BE RTW88_8822CE RTW88_8723DE config-$(CONFIG_PACKAGE_RTW88_DEBUG) += RTW88_DEBUG config-$(CONFIG_PACKAGE_RTW88_DEBUGFS) += RTW88_DEBUGFS @@ -55,7 +38,7 @@ endef define KernelPackage/rtlwifi $(call KernelPackage/mac80211/Default) TITLE:=Realtek common driver part - DEPENDS+= @(PCI_SUPPORT||USB_SUPPORT) +kmod-mac80211 + DEPENDS+= @(PCI_SUPPORT||USB_SUPPORT) +kmod-mac80211 +@DRIVER_11N_SUPPORT FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtlwifi/rtlwifi.ko HIDDEN:=1 endef @@ -185,137 +168,20 @@ endef define KernelPackage/rtw88 $(call KernelPackage/mac80211/Default) - TITLE:=Realtek RTW88 common part - DEPENDS+= @(PCI_SUPPORT||USB_SUPPORT) +kmod-mac80211 - FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw88/rtw88_core.ko - AUTOLOAD:=$(call AutoProbe,rtw88_core) - HIDDEN:=1 -endef - -define KernelPackage/rtw88-pci - $(call KernelPackage/mac80211/Default) - TITLE:=Realtek RTW88 PCI chips support - DEPENDS+= @PCI_SUPPORT +kmod-rtw88 - FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw88/rtw88_pci.ko - AUTOLOAD:=$(call AutoProbe,rtw88_pci) - HIDDEN:=1 -endef - -define KernelPackage/rtw88-usb - $(call KernelPackage/mac80211/Default) - TITLE:=Realtek RTW88 USB chips support - DEPENDS+= @USB_SUPPORT +kmod-rtw88 +kmod-usb-core - FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw88/rtw88_usb.ko - AUTOLOAD:=$(call AutoProbe,rtw88_usb) - HIDDEN:=1 -endef - -define KernelPackage/rtw88-8821c - $(call KernelPackage/mac80211/Default) - TITLE:=Realtek RTL8821C family support - DEPENDS+= +kmod-rtw88 +rtl8821ce-firmware +@DRIVER_11AC_SUPPORT - FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw88/rtw88_8821c.ko - AUTOLOAD:=$(call AutoProbe,rtw88_8821c) - HIDDEN:=1 -endef - -define KernelPackage/rtw88-8822b - $(call KernelPackage/mac80211/Default) - TITLE:=Realtek RTL8822B family support - DEPENDS+= +kmod-rtw88 +rtl8822be-firmware +@DRIVER_11AC_SUPPORT - FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw88/rtw88_8822b.ko - AUTOLOAD:=$(call AutoProbe,rtw88_8822b) - HIDDEN:=1 -endef - -define KernelPackage/rtw88-8822c - $(call KernelPackage/mac80211/Default) - TITLE:=Realtek RTL8822C family support - DEPENDS+= +kmod-rtw88 +rtl8822ce-firmware +@DRIVER_11AC_SUPPORT - FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw88/rtw88_8822c.ko - AUTOLOAD:=$(call AutoProbe,rtw88_8822c) - HIDDEN:=1 -endef - -define KernelPackage/rtw88-8723d - $(call KernelPackage/mac80211/Default) - TITLE:=Realtek RTL8723D family support - DEPENDS+= +kmod-rtw88 +rtl8723de-firmware - FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw88/rtw88_8723d.ko - AUTOLOAD:=$(call AutoProbe,rtw88_8723d) - HIDDEN:=1 -endef - -define KernelPackage/rtw88-8821ce - $(call KernelPackage/mac80211/Default) - TITLE:=Realtek RTL8821CE support - DEPENDS+= +kmod-rtw88-pci +kmod-rtw88-8821c - FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw88/rtw88_8821ce.ko - AUTOLOAD:=$(call AutoProbe,rtw88_8821ce) -endef - -define KernelPackage/rtw88-8821cu - $(call KernelPackage/mac80211/Default) - TITLE:=Realtek RTL8821CU support - DEPENDS+= +kmod-rtw88-usb +kmod-rtw88-8821c - FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw88/rtw88_8821cu.ko - AUTOLOAD:=$(call AutoProbe,rtw88_8821cu) -endef - -define KernelPackage/rtw88-8822be - $(call KernelPackage/mac80211/Default) - TITLE:=Realtek RTL8822BE support - DEPENDS+= +kmod-rtw88-pci +kmod-rtw88-8822b - FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw88/rtw88_8822be.ko - AUTOLOAD:=$(call AutoProbe,rtw88_8822be) -endef - -define KernelPackage/rtw88-8822bu - $(call KernelPackage/mac80211/Default) - TITLE:=Realtek RTL8822BU support - DEPENDS+= +kmod-rtw88-usb +kmod-rtw88-8822b - FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw88/rtw88_8822bu.ko - AUTOLOAD:=$(call AutoProbe,rtw88_8822bu) -endef - -define KernelPackage/rtw88-8822ce - $(call KernelPackage/mac80211/Default) - TITLE:=Realtek RTL8822CE support - DEPENDS+= +kmod-rtw88-pci +kmod-rtw88-8822c - FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw88/rtw88_8822ce.ko - AUTOLOAD:=$(call AutoProbe,rtw88_8822ce) -endef - -define KernelPackage/rtw88-8822cu - $(call KernelPackage/mac80211/Default) - TITLE:=Realtek RTL8822CU support - DEPENDS+= +kmod-rtw88-usb +kmod-rtw88-8822c - FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw88/rtw88_8822cu.ko - AUTOLOAD:=$(call AutoProbe,rtw88_8822cu) -endef - -define KernelPackage/rtw88-8723de - $(call KernelPackage/mac80211/Default) - TITLE:=Realtek RTL8723DE support - DEPENDS+= +kmod-rtw88-pci +kmod-rtw88-8723d - FILES:= $(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw88/rtw88_8723de.ko - AUTOLOAD:=$(call AutoProbe,rtw88_8723) -endef - -define KernelPackage/rtl8723-common - $(call KernelPackage/mac80211/Default) - TITLE:=Realtek RTL8723AE/RTL8723BE common support module - DEPENDS+= +kmod-rtlwifi - FILES:= $(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtlwifi/rtl8723com/rtl8723-common.ko - HIDDEN:=1 -endef - -define KernelPackage/rtl8723be - $(call KernelPackage/mac80211/Default) - TITLE:=Realtek RTL8723AE/RTL8723BE support - DEPENDS+= +kmod-rtlwifi-btcoexist +kmod-rtlwifi-pci +kmod-rtl8723-common +rtl8723be-firmware - FILES:= $(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtlwifi/rtl8723be/rtl8723be.ko - AUTOLOAD:=$(call AutoProbe,rtl8723be) + TITLE:=Realtek RTL8821CE/RTL8822BE/RTL8822CE/RTL8723DE + DEPENDS+= @(PCI_SUPPORT) +kmod-mac80211 +@DRIVER_11AC_SUPPORT +@DRIVER_11N_SUPPORT + FILES:=\ + $(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw88/rtw88_8821ce.ko \ + $(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw88/rtw88_8821c.ko \ + $(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw88/rtw88_8822be.ko \ + $(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw88/rtw88_8822b.ko \ + $(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw88/rtw88_8822ce.ko \ + $(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw88/rtw88_8822c.ko \ + $(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw88/rtw88_8723de.ko \ + $(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw88/rtw88_8723d.ko \ + $(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw88/rtw88_core.ko \ + $(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw88/rtw88_pci.ko + AUTOLOAD:=$(call AutoProbe,rtw88_8821ce rtw88_8822be rtw88_8822ce rtw88_8723de) endef define KernelPackage/rtl8723bs diff --git a/package/kernel/mt76/Makefile b/package/kernel/mt76/Makefile index ffa01afec..a28afcb92 100644 --- a/package/kernel/mt76/Makefile +++ b/package/kernel/mt76/Makefile @@ -6,11 +6,24 @@ PKG_RELEASE=1 PKG_LICENSE:=GPLv2 PKG_LICENSE_FILES:= -PKG_SOURCE_VERSION:=20240714 -PKG_SOURCE_URL:=https://codeload.github.com/ptpt52/mt76/tar.gz/$(PKG_SOURCE_VERSION)? -PKG_HASH:=aa2e2c91d3f0d4b5151ac8ab3d1ea4dd2289ea825cdab80c7a9af166459be0df -PKG_SOURCE:=$(PKG_NAME)-$(PKG_SOURCE_VERSION).tar.gz -PKG_VERSION := $(PKG_SOURCE_VERSION) +PKG_SOURCE_URL:=https://github.com/openwrt/mt76 +PKG_SOURCE_PROTO:=git + +ifdef CONFIG_LINUX_5_4 +PKG_SOURCE_DATE:=2022-12-22 +PKG_SOURCE_VERSION:=5b509e80384ab019ac11aa90c81ec0dbb5b0d7f2 +PKG_MIRROR_HASH:=6fc25df4d28becd010ff4971b23731c08b53e69381a9e4c868091899712f78a9 +PATCH_DIR:=./patches-5.4 +else ifndef ($(filter on,$(CONFIG_LINUX_6_1) $(CONFIG_LINUX_6_6)),) +PKG_SOURCE_DATE:=2024-04-04 +PKG_SOURCE_VERSION:=8f301a5c5fe3d998b50666bde1d35d412833be89 +PKG_MIRROR_HASH:=49291145ccceeac2964c9a43a46bed88298e5c1da63c6f3c2c1f6b3c1902a61e +PATCH_DIR:=./patches-6.x +else +PKG_SOURCE_DATE:=2023-08-14 +PKG_SOURCE_VERSION:=b14c2351ddb8601c322576d84029e463d456caef +PKG_MIRROR_HASH:=62b5e157ad525424b6857e77ed373e8d39d03af71b057f8b309d8b293d6eac5f +endif PKG_MAINTAINER:=Felix Fietkau PKG_USE_NINJA:=0 @@ -632,11 +645,6 @@ define Package/mt76-test/install $(INSTALL_BIN) $(PKG_BUILD_DIR)/tools/mt76-test $(1)/usr/sbin endef -define Build/InstallDev - mkdir -p $(STAGING_DIR_IMAGE) - $(CP) $(PKG_BUILD_DIR)/firmware/mt7981_eeprom_mt7976_dbdc.bin $(STAGING_DIR_IMAGE)/ -endef - $(eval $(call KernelPackage,mt76-core)) $(eval $(call KernelPackage,mt76-usb)) $(eval $(call KernelPackage,mt76x02-usb)) diff --git a/package/kernel/mt76/patches-5.4/001-allow-vht-on-2g.patch b/package/kernel/mt76/patches-5.4/001-allow-vht-on-2g.patch new file mode 100644 index 000000000..12ce67daf --- /dev/null +++ b/package/kernel/mt76/patches-5.4/001-allow-vht-on-2g.patch @@ -0,0 +1,59 @@ +From ed0b9c38becdbf9379787ca0b4db557f03a31dd7 Mon Sep 17 00:00:00 2001 +From: DENG Qingfang +Date: Mon, 23 Nov 2020 10:46:37 +0800 +Subject: [PATCH] mt76: allow VHT rate on 2.4GHz + +Allow chips that support 11ac to use 256QAM on 2.4GHz + +Signed-off-by: DENG Qingfang +--- + mac80211.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/mac80211.c b/mac80211.c +index 766681a4..06aa4228 100644 +--- a/mac80211.c ++++ b/mac80211.c +@@ -281,7 +281,7 @@ static void mt76_init_stream_cap(struct mt76_phy *phy, + void mt76_set_stream_caps(struct mt76_phy *phy, bool vht) + { + if (phy->cap.has_2ghz) +- mt76_init_stream_cap(phy, &phy->sband_2g.sband, false); ++ mt76_init_stream_cap(phy, &phy->sband_2g.sband, vht); + if (phy->cap.has_5ghz) + mt76_init_stream_cap(phy, &phy->sband_5g.sband, vht); + if (phy->cap.has_6ghz) +@@ -348,13 +348,13 @@ mt76_init_sband(struct mt76_phy *phy, struct mt76_sband *msband, + + static int + mt76_init_sband_2g(struct mt76_phy *phy, struct ieee80211_rate *rates, +- int n_rates) ++ int n_rates, bool vht) + { + phy->hw->wiphy->bands[NL80211_BAND_2GHZ] = &phy->sband_2g.sband; + + return mt76_init_sband(phy, &phy->sband_2g, mt76_channels_2ghz, + ARRAY_SIZE(mt76_channels_2ghz), rates, +- n_rates, true, false); ++ n_rates, true, vht); + } + + static int +@@ -506,7 +506,7 @@ int mt76_register_phy(struct mt76_phy *phy, bool vht, + return ret; + + if (phy->cap.has_2ghz) { +- ret = mt76_init_sband_2g(phy, rates, n_rates); ++ ret = mt76_init_sband_2g(phy, rates, n_rates, vht); + if (ret) + return ret; + } +@@ -644,7 +644,7 @@ int mt76_register_device(struct mt76_dev *dev, bool vht, + return ret; + + if (phy->cap.has_2ghz) { +- ret = mt76_init_sband_2g(phy, rates, n_rates); ++ ret = mt76_init_sband_2g(phy, rates, n_rates, vht); + if (ret) + return ret; + } diff --git a/package/kernel/mt76/patches-5.4/002-fix-build-error.patch b/package/kernel/mt76/patches-5.4/002-fix-build-error.patch new file mode 100644 index 000000000..0480a4eb3 --- /dev/null +++ b/package/kernel/mt76/patches-5.4/002-fix-build-error.patch @@ -0,0 +1,57 @@ +--- a/debugfs.c ++++ b/debugfs.c +@@ -25,6 +25,7 @@ mt76_reg_get(void *data, u64 *val) + DEFINE_DEBUGFS_ATTRIBUTE(fops_regval, mt76_reg_get, mt76_reg_set, + "0x%08llx\n"); + ++#if 0 + static int + mt76_napi_threaded_set(void *data, u64 val) + { +@@ -50,6 +51,7 @@ mt76_napi_threaded_get(void *data, u64 *val) + + DEFINE_DEBUGFS_ATTRIBUTE(fops_napi_threaded, mt76_napi_threaded_get, + mt76_napi_threaded_set, "%llu\n"); ++#endif + + int mt76_queues_read(struct seq_file *s, void *data) + { +@@ -116,8 +118,6 @@ mt76_register_debugfs_fops(struct mt76_phy *phy, + debugfs_create_bool("led_active_low", 0600, dir, &phy->leds.al); + debugfs_create_u32("regidx", 0600, dir, &dev->debugfs_reg); + debugfs_create_file_unsafe("regval", 0600, dir, dev, fops); +- debugfs_create_file_unsafe("napi_threaded", 0600, dir, dev, +- &fops_napi_threaded); + debugfs_create_blob("eeprom", 0400, dir, &dev->eeprom); + if (dev->otp.data) + debugfs_create_blob("otp", 0400, dir, &dev->otp); +--- a/mt7615/mcu.c ++++ b/mt7615/mcu.c +@@ -6,6 +6,7 @@ + */ + + #include ++#include + #include "mt7615.h" + #include "mcu.h" + #include "mac.h" +--- a/mt7915/mt7915.h ++++ b/mt7915/mt7915.h +@@ -6,6 +6,7 @@ + + #include + #include ++#include + #include "../mt76_connac.h" + #include "regs.h" + +--- a/mt76_connac_mcu.c ++++ b/mt76_connac_mcu.c +@@ -2,6 +2,7 @@ + /* Copyright (C) 2020 MediaTek Inc. */ + + #include ++#include + #include "mt76_connac2_mac.h" + #include "mt76_connac_mcu.h" + diff --git a/package/kernel/mt76/patches-5.4/100-api_update.patch b/package/kernel/mt76/patches-5.4/100-api_update.patch new file mode 100644 index 000000000..3a76f1175 --- /dev/null +++ b/package/kernel/mt76/patches-5.4/100-api_update.patch @@ -0,0 +1,11 @@ +--- a/tx.c ++++ b/tx.c +@@ -330,7 +330,7 @@ mt76_tx(struct mt76_phy *phy, struct iee + if ((dev->drv->drv_flags & MT_DRV_HW_MGMT_TXQ) && + !(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) && + !ieee80211_is_data(hdr->frame_control) && +- !ieee80211_is_bufferable_mmpdu(hdr->frame_control)) { ++ !ieee80211_is_bufferable_mmpdu(skb)) { + qid = MT_TXQ_PSD; + } + diff --git a/package/kernel/mt76/patches-5.4/110-wifi-mt76-ignore-key-disable-commands.patch b/package/kernel/mt76/patches-5.4/110-wifi-mt76-ignore-key-disable-commands.patch new file mode 100644 index 000000000..3c132420e --- /dev/null +++ b/package/kernel/mt76/patches-5.4/110-wifi-mt76-ignore-key-disable-commands.patch @@ -0,0 +1,301 @@ +From: Felix Fietkau +Date: Wed, 22 Mar 2023 10:17:49 +0100 +Subject: [PATCH] wifi: mt76: ignore key disable commands + +This helps avoid cleartext leakage of already queued or powersave buffered +packets, when a reassoc triggers the key deletion. + +Cc: stable@vger.kernel.org +Signed-off-by: Felix Fietkau +--- + +--- a/mt7603/main.c ++++ b/mt7603/main.c +@@ -512,15 +512,15 @@ mt7603_set_key(struct ieee80211_hw *hw, + !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) + return -EOPNOTSUPP; + +- if (cmd == SET_KEY) { +- key->hw_key_idx = wcid->idx; +- wcid->hw_key_idx = idx; +- } else { ++ if (cmd != SET_KEY) { + if (idx == wcid->hw_key_idx) + wcid->hw_key_idx = -1; + +- key = NULL; ++ return 0; + } ++ ++ key->hw_key_idx = wcid->idx; ++ wcid->hw_key_idx = idx; + mt76_wcid_key_setup(&dev->mt76, wcid, key); + + return mt7603_wtbl_set_key(dev, wcid->idx, key); +--- a/mt7615/mac.c ++++ b/mt7615/mac.c +@@ -1193,8 +1193,7 @@ EXPORT_SYMBOL_GPL(mt7615_mac_enable_rtsc + static int + mt7615_mac_wtbl_update_key(struct mt7615_dev *dev, struct mt76_wcid *wcid, + struct ieee80211_key_conf *key, +- enum mt76_cipher_type cipher, u16 cipher_mask, +- enum set_key_cmd cmd) ++ enum mt76_cipher_type cipher, u16 cipher_mask) + { + u32 addr = mt7615_mac_wtbl_addr(dev, wcid->idx) + 30 * 4; + u8 data[32] = {}; +@@ -1203,27 +1202,18 @@ mt7615_mac_wtbl_update_key(struct mt7615 + return -EINVAL; + + mt76_rr_copy(dev, addr, data, sizeof(data)); +- if (cmd == SET_KEY) { +- if (cipher == MT_CIPHER_TKIP) { +- /* Rx/Tx MIC keys are swapped */ +- memcpy(data, key->key, 16); +- memcpy(data + 16, key->key + 24, 8); +- memcpy(data + 24, key->key + 16, 8); +- } else { +- if (cipher_mask == BIT(cipher)) +- memcpy(data, key->key, key->keylen); +- else if (cipher != MT_CIPHER_BIP_CMAC_128) +- memcpy(data, key->key, 16); +- if (cipher == MT_CIPHER_BIP_CMAC_128) +- memcpy(data + 16, key->key, 16); +- } ++ if (cipher == MT_CIPHER_TKIP) { ++ /* Rx/Tx MIC keys are swapped */ ++ memcpy(data, key->key, 16); ++ memcpy(data + 16, key->key + 24, 8); ++ memcpy(data + 24, key->key + 16, 8); + } else { ++ if (cipher_mask == BIT(cipher)) ++ memcpy(data, key->key, key->keylen); ++ else if (cipher != MT_CIPHER_BIP_CMAC_128) ++ memcpy(data, key->key, 16); + if (cipher == MT_CIPHER_BIP_CMAC_128) +- memset(data + 16, 0, 16); +- else if (cipher_mask) +- memset(data, 0, 16); +- if (!cipher_mask) +- memset(data, 0, sizeof(data)); ++ memcpy(data + 16, key->key, 16); + } + + mt76_wr_copy(dev, addr, data, sizeof(data)); +@@ -1234,7 +1224,7 @@ mt7615_mac_wtbl_update_key(struct mt7615 + static int + mt7615_mac_wtbl_update_pk(struct mt7615_dev *dev, struct mt76_wcid *wcid, + enum mt76_cipher_type cipher, u16 cipher_mask, +- int keyidx, enum set_key_cmd cmd) ++ int keyidx) + { + u32 addr = mt7615_mac_wtbl_addr(dev, wcid->idx), w0, w1; + +@@ -1253,9 +1243,7 @@ mt7615_mac_wtbl_update_pk(struct mt7615_ + else + w0 &= ~MT_WTBL_W0_RX_IK_VALID; + +- if (cmd == SET_KEY && +- (cipher != MT_CIPHER_BIP_CMAC_128 || +- cipher_mask == BIT(cipher))) { ++ if (cipher != MT_CIPHER_BIP_CMAC_128 || cipher_mask == BIT(cipher)) { + w0 &= ~MT_WTBL_W0_KEY_IDX; + w0 |= FIELD_PREP(MT_WTBL_W0_KEY_IDX, keyidx); + } +@@ -1272,19 +1260,10 @@ mt7615_mac_wtbl_update_pk(struct mt7615_ + + static void + mt7615_mac_wtbl_update_cipher(struct mt7615_dev *dev, struct mt76_wcid *wcid, +- enum mt76_cipher_type cipher, u16 cipher_mask, +- enum set_key_cmd cmd) ++ enum mt76_cipher_type cipher, u16 cipher_mask) + { + u32 addr = mt7615_mac_wtbl_addr(dev, wcid->idx); + +- if (!cipher_mask) { +- mt76_clear(dev, addr + 2 * 4, MT_WTBL_W2_KEY_TYPE); +- return; +- } +- +- if (cmd != SET_KEY) +- return; +- + if (cipher == MT_CIPHER_BIP_CMAC_128 && + cipher_mask & ~BIT(MT_CIPHER_BIP_CMAC_128)) + return; +@@ -1295,8 +1274,7 @@ mt7615_mac_wtbl_update_cipher(struct mt7 + + int __mt7615_mac_wtbl_set_key(struct mt7615_dev *dev, + struct mt76_wcid *wcid, +- struct ieee80211_key_conf *key, +- enum set_key_cmd cmd) ++ struct ieee80211_key_conf *key) + { + enum mt76_cipher_type cipher; + u16 cipher_mask = wcid->cipher; +@@ -1306,19 +1284,14 @@ int __mt7615_mac_wtbl_set_key(struct mt7 + if (cipher == MT_CIPHER_NONE) + return -EOPNOTSUPP; + +- if (cmd == SET_KEY) +- cipher_mask |= BIT(cipher); +- else +- cipher_mask &= ~BIT(cipher); +- +- mt7615_mac_wtbl_update_cipher(dev, wcid, cipher, cipher_mask, cmd); +- err = mt7615_mac_wtbl_update_key(dev, wcid, key, cipher, cipher_mask, +- cmd); ++ cipher_mask |= BIT(cipher); ++ mt7615_mac_wtbl_update_cipher(dev, wcid, cipher, cipher_mask); ++ err = mt7615_mac_wtbl_update_key(dev, wcid, key, cipher, cipher_mask); + if (err < 0) + return err; + + err = mt7615_mac_wtbl_update_pk(dev, wcid, cipher, cipher_mask, +- key->keyidx, cmd); ++ key->keyidx); + if (err < 0) + return err; + +@@ -1329,13 +1302,12 @@ int __mt7615_mac_wtbl_set_key(struct mt7 + + int mt7615_mac_wtbl_set_key(struct mt7615_dev *dev, + struct mt76_wcid *wcid, +- struct ieee80211_key_conf *key, +- enum set_key_cmd cmd) ++ struct ieee80211_key_conf *key) + { + int err; + + spin_lock_bh(&dev->mt76.lock); +- err = __mt7615_mac_wtbl_set_key(dev, wcid, key, cmd); ++ err = __mt7615_mac_wtbl_set_key(dev, wcid, key); + spin_unlock_bh(&dev->mt76.lock); + + return err; +--- a/mt7615/main.c ++++ b/mt7615/main.c +@@ -391,18 +391,17 @@ static int mt7615_set_key(struct ieee802 + + if (cmd == SET_KEY) + *wcid_keyidx = idx; +- else if (idx == *wcid_keyidx) +- *wcid_keyidx = -1; +- else ++ else { ++ if (idx == *wcid_keyidx) ++ *wcid_keyidx = -1; + goto out; ++ } + +- mt76_wcid_key_setup(&dev->mt76, wcid, +- cmd == SET_KEY ? key : NULL); +- ++ mt76_wcid_key_setup(&dev->mt76, wcid, key); + if (mt76_is_mmio(&dev->mt76)) +- err = mt7615_mac_wtbl_set_key(dev, wcid, key, cmd); ++ err = mt7615_mac_wtbl_set_key(dev, wcid, key); + else +- err = __mt7615_mac_wtbl_set_key(dev, wcid, key, cmd); ++ err = __mt7615_mac_wtbl_set_key(dev, wcid, key); + + out: + mt7615_mutex_release(dev); +--- a/mt7615/mt7615.h ++++ b/mt7615/mt7615.h +@@ -491,11 +491,9 @@ int mt7615_mac_write_txwi(struct mt7615_ + void mt7615_mac_set_timing(struct mt7615_phy *phy); + int __mt7615_mac_wtbl_set_key(struct mt7615_dev *dev, + struct mt76_wcid *wcid, +- struct ieee80211_key_conf *key, +- enum set_key_cmd cmd); ++ struct ieee80211_key_conf *key); + int mt7615_mac_wtbl_set_key(struct mt7615_dev *dev, struct mt76_wcid *wcid, +- struct ieee80211_key_conf *key, +- enum set_key_cmd cmd); ++ struct ieee80211_key_conf *key); + void mt7615_mac_reset_work(struct work_struct *work); + u32 mt7615_mac_get_sta_tid_sn(struct mt7615_dev *dev, int wcid, u8 tid); + +--- a/mt76x02_util.c ++++ b/mt76x02_util.c +@@ -454,20 +454,20 @@ int mt76x02_set_key(struct ieee80211_hw + msta = sta ? (struct mt76x02_sta *)sta->drv_priv : NULL; + wcid = msta ? &msta->wcid : &mvif->group_wcid; + +- if (cmd == SET_KEY) { +- key->hw_key_idx = wcid->idx; +- wcid->hw_key_idx = idx; +- if (key->flags & IEEE80211_KEY_FLAG_RX_MGMT) { +- key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX; +- wcid->sw_iv = true; +- } +- } else { ++ if (cmd != SET_KEY) { + if (idx == wcid->hw_key_idx) { + wcid->hw_key_idx = -1; + wcid->sw_iv = false; + } + +- key = NULL; ++ return 0; ++ } ++ ++ key->hw_key_idx = wcid->idx; ++ wcid->hw_key_idx = idx; ++ if (key->flags & IEEE80211_KEY_FLAG_RX_MGMT) { ++ key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX; ++ wcid->sw_iv = true; + } + mt76_wcid_key_setup(&dev->mt76, wcid, key); + +--- a/mt7915/main.c ++++ b/mt7915/main.c +@@ -399,16 +399,15 @@ static int mt7915_set_key(struct ieee802 + mt7915_mcu_add_bss_info(phy, vif, true); + } + +- if (cmd == SET_KEY) ++ if (cmd == SET_KEY) { + *wcid_keyidx = idx; +- else if (idx == *wcid_keyidx) +- *wcid_keyidx = -1; +- else ++ } else { ++ if (idx == *wcid_keyidx) ++ *wcid_keyidx = -1; + goto out; ++ } + +- mt76_wcid_key_setup(&dev->mt76, wcid, +- cmd == SET_KEY ? key : NULL); +- ++ mt76_wcid_key_setup(&dev->mt76, wcid, key); + err = mt76_connac_mcu_add_key(&dev->mt76, vif, &msta->bip, + key, MCU_EXT_CMD(STA_REC_UPDATE), + &msta->wcid, cmd); +--- a/mt7921/main.c ++++ b/mt7921/main.c +@@ -569,16 +569,15 @@ static int mt7921_set_key(struct ieee802 + + mt7921_mutex_acquire(dev); + +- if (cmd == SET_KEY) ++ if (cmd == SET_KEY) { + *wcid_keyidx = idx; +- else if (idx == *wcid_keyidx) +- *wcid_keyidx = -1; +- else ++ } else { ++ if (idx == *wcid_keyidx) ++ *wcid_keyidx = -1; + goto out; ++ } + +- mt76_wcid_key_setup(&dev->mt76, wcid, +- cmd == SET_KEY ? key : NULL); +- ++ mt76_wcid_key_setup(&dev->mt76, wcid, key); + err = mt76_connac_mcu_add_key(&dev->mt76, vif, &msta->bip, + key, MCU_UNI_CMD(STA_REC_UPDATE), + &msta->wcid, cmd); diff --git a/package/kernel/mt76/patches-6.x/001-allow-vht-on-2g.patch b/package/kernel/mt76/patches-6.x/001-allow-vht-on-2g.patch new file mode 100644 index 000000000..aaa8dd5fa --- /dev/null +++ b/package/kernel/mt76/patches-6.x/001-allow-vht-on-2g.patch @@ -0,0 +1,59 @@ +From ed0b9c38becdbf9379787ca0b4db557f03a31dd7 Mon Sep 17 00:00:00 2001 +From: DENG Qingfang +Date: Mon, 23 Nov 2020 10:46:37 +0800 +Subject: [PATCH] mt76: allow VHT rate on 2.4GHz + +Allow chips that support 11ac to use 256QAM on 2.4GHz + +Signed-off-by: DENG Qingfang +--- + mac80211.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/mac80211.c b/mac80211.c +index 766681a4..06aa4228 100644 +--- a/mac80211.c ++++ b/mac80211.c +@@ -282,7 +282,7 @@ static void mt76_init_stream_cap(struct mt76_phy *phy, + void mt76_set_stream_caps(struct mt76_phy *phy, bool vht) + { + if (phy->cap.has_2ghz) +- mt76_init_stream_cap(phy, &phy->sband_2g.sband, false); ++ mt76_init_stream_cap(phy, &phy->sband_2g.sband, vht); + if (phy->cap.has_5ghz) + mt76_init_stream_cap(phy, &phy->sband_5g.sband, vht); + if (phy->cap.has_6ghz) +@@ -349,13 +349,13 @@ mt76_init_sband(struct mt76_phy *phy, struct mt76_sband *msband, + + static int + mt76_init_sband_2g(struct mt76_phy *phy, struct ieee80211_rate *rates, +- int n_rates) ++ int n_rates, bool vht) + { + phy->hw->wiphy->bands[NL80211_BAND_2GHZ] = &phy->sband_2g.sband; + + return mt76_init_sband(phy, &phy->sband_2g, mt76_channels_2ghz, + ARRAY_SIZE(mt76_channels_2ghz), rates, +- n_rates, true, false); ++ n_rates, true, vht); + } + + static int +@@ -508,7 +508,7 @@ int mt76_register_phy(struct mt76_phy *phy, bool vht, + return ret; + + if (phy->cap.has_2ghz) { +- ret = mt76_init_sband_2g(phy, rates, n_rates); ++ ret = mt76_init_sband_2g(phy, rates, n_rates, vht); + if (ret) + return ret; + } +@@ -691,7 +691,7 @@ int mt76_register_device(struct mt76_dev *dev, bool vht, + return ret; + + if (phy->cap.has_2ghz) { +- ret = mt76_init_sband_2g(phy, rates, n_rates); ++ ret = mt76_init_sband_2g(phy, rates, n_rates, vht); + if (ret) + return ret; + } diff --git a/package/kernel/mt76/patches-6.x/002-wifi-mt76-mt7915-fix-oops.patch b/package/kernel/mt76/patches-6.x/002-wifi-mt76-mt7915-fix-oops.patch new file mode 100644 index 000000000..d472dac92 --- /dev/null +++ b/package/kernel/mt76/patches-6.x/002-wifi-mt76-mt7915-fix-oops.patch @@ -0,0 +1,100 @@ +From 3b47d9df427c4833605a172f2a8f0e0012b04c80 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= +Date: Sat, 13 Jul 2024 15:00:10 +0200 +Subject: [PATCH] wifi: mt76: mt7915: fix oops on non-dbdc mt7986 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +mt7915_band_config() sets band_idx = 1 on the main phy for mt7986 +with MT7975_ONE_ADIE or MT7976_ONE_ADIE. + +Commit 0335c034e726 ("wifi: mt76: fix race condition related to +checking tx queue fill status") introduced a dereference of the +phys array indirectly indexed by band_idx via wcid->phy_idx in +mt76_wcid_cleanup(). This caused the following Oops on affected +mt7986 devices: + + Unable to handle kernel read from unreadable memory at virtual address 0000000000000024 + Mem abort info: + ESR = 0x0000000096000005 + EC = 0x25: DABT (current EL), IL = 32 bits + SET = 0, FnV = 0 + EA = 0, S1PTW = 0 + FSC = 0x05: level 1 translation fault + Data abort info: + ISV = 0, ISS = 0x00000005 + CM = 0, WnR = 0 + user pgtable: 4k pages, 39-bit VAs, pgdp=0000000042545000 + [0000000000000024] pgd=0000000000000000, p4d=0000000000000000, pud=0000000000000000 + Internal error: Oops: 0000000096000005 [#1] SMP + Modules linked in: ... mt7915e mt76_connac_lib mt76 mac80211 cfg80211 ... + CPU: 2 PID: 1631 Comm: hostapd Not tainted 5.15.150 #0 + Hardware name: ZyXEL EX5700 (Telenor) (DT) + pstate: 80400005 (Nzcv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) + pc : mt76_wcid_cleanup+0x84/0x22c [mt76] + lr : mt76_wcid_cleanup+0x64/0x22c [mt76] + sp : ffffffc00a803700 + x29: ffffffc00a803700 x28: ffffff80008f7300 x27: ffffff80003f3c00 + x26: ffffff80000a7880 x25: ffffffc008c26e00 x24: 0000000000000001 + x23: ffffffc000a68114 x22: 0000000000000000 x21: ffffff8004172cc8 + x20: ffffffc00a803748 x19: ffffff8004152020 x18: 0000000000000000 + x17: 00000000000017c0 x16: ffffffc008ef5000 x15: 0000000000000be0 + x14: ffffff8004172e28 x13: ffffff8004172e28 x12: 0000000000000000 + x11: 0000000000000000 x10: ffffff8004172e30 x9 : ffffff8004172e28 + x8 : 0000000000000000 x7 : ffffff8004156020 x6 : 0000000000000000 + x5 : 0000000000000031 x4 : 0000000000000000 x3 : 0000000000000001 + x2 : 0000000000000000 x1 : ffffff80008f7300 x0 : 0000000000000024 + Call trace: + mt76_wcid_cleanup+0x84/0x22c [mt76] + __mt76_sta_remove+0x70/0xbc [mt76] + mt76_sta_state+0x8c/0x1a4 [mt76] + mt7915_eeprom_get_power_delta+0x11e4/0x23a0 [mt7915e] + drv_sta_state+0x144/0x274 [mac80211] + sta_info_move_state+0x1cc/0x2a4 [mac80211] + sta_set_sinfo+0xaf8/0xc24 [mac80211] + sta_info_destroy_addr_bss+0x4c/0x6c [mac80211] + + ieee80211_color_change_finish+0x1c08/0x1e70 [mac80211] + cfg80211_check_station_change+0x1360/0x4710 [cfg80211] + genl_family_rcv_msg_doit+0xb4/0x110 + genl_rcv_msg+0xd0/0x1bc + netlink_rcv_skb+0x58/0x120 + genl_rcv+0x34/0x50 + netlink_unicast+0x1f0/0x2ec + netlink_sendmsg+0x198/0x3d0 + ____sys_sendmsg+0x1b0/0x210 + ___sys_sendmsg+0x80/0xf0 + __sys_sendmsg+0x44/0xa0 + __arm64_sys_sendmsg+0x20/0x30 + invoke_syscall.constprop.0+0x4c/0xe0 + do_el0_svc+0x40/0xd0 + el0_svc+0x14/0x4c + el0t_64_sync_handler+0x100/0x110 + el0t_64_sync+0x15c/0x160 + Code: d2800002 910092c0 52800023 f9800011 (885f7c01) + ---[ end trace 7e42dd9a39ed2281 ]--- + +Fix by using mt76_dev_phy() which will map band_idx to the correct phy +for all hardware combinations. + +Fixes: 0335c034e726 ("wifi: mt76: fix race condition related to checking tx queue fill status") +Link: https://github.com/openwrt/openwrt/issues/14548 +Signed-off-by: Bjørn Mork +Link: https://patch.msgid.link/20240713130010.516037-1-bjorn@mork.no +Signed-off-by: Felix Fietkau +--- + mac80211.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/mac80211.c ++++ b/mac80211.c +@@ -1515,7 +1515,7 @@ EXPORT_SYMBOL_GPL(mt76_wcid_init); + + void mt76_wcid_cleanup(struct mt76_dev *dev, struct mt76_wcid *wcid) + { +- struct mt76_phy *phy = dev->phys[wcid->phy_idx]; ++ struct mt76_phy *phy = mt76_dev_phy(dev, wcid->phy_idx); + struct ieee80211_hw *hw; + struct sk_buff_head list; + struct sk_buff *skb; diff --git a/package/kernel/mt76/patches-6.x/101-fixes-mt7925-build-error.patch b/package/kernel/mt76/patches-6.x/101-fixes-mt7925-build-error.patch new file mode 100644 index 000000000..915f1c495 --- /dev/null +++ b/package/kernel/mt76/patches-6.x/101-fixes-mt7925-build-error.patch @@ -0,0 +1,23 @@ +--- a/mt7925/main.c ++++ b/mt7925/main.c +@@ -260,7 +260,8 @@ __mt7925_set_stream_he_eht_caps(struct m + n++; + } + +- _ieee80211_set_sband_iftype_data(sband, data, n); ++ sband->iftype_data = data; ++ sband->n_iftype_data = n; + } + + void mt7925_set_stream_he_eht_caps(struct mt792x_phy *phy) +--- a/mt7925/mcu.c ++++ b/mt7925/mcu.c +@@ -2209,7 +2209,7 @@ mt7925_mcu_bss_mld_tlv(struct sk_buff *s + struct ieee80211_sta *sta) + { + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; +- bool is_mld = ieee80211_vif_is_mld(vif); ++ bool is_mld = (vif->valid_links != 0); + struct bss_mld_tlv *mld; + struct tlv *tlv; + diff --git a/package/kernel/mt76/patches/001-allow-vht-on-2g.patch b/package/kernel/mt76/patches/001-allow-vht-on-2g.patch new file mode 100644 index 000000000..aaa8dd5fa --- /dev/null +++ b/package/kernel/mt76/patches/001-allow-vht-on-2g.patch @@ -0,0 +1,59 @@ +From ed0b9c38becdbf9379787ca0b4db557f03a31dd7 Mon Sep 17 00:00:00 2001 +From: DENG Qingfang +Date: Mon, 23 Nov 2020 10:46:37 +0800 +Subject: [PATCH] mt76: allow VHT rate on 2.4GHz + +Allow chips that support 11ac to use 256QAM on 2.4GHz + +Signed-off-by: DENG Qingfang +--- + mac80211.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/mac80211.c b/mac80211.c +index 766681a4..06aa4228 100644 +--- a/mac80211.c ++++ b/mac80211.c +@@ -282,7 +282,7 @@ static void mt76_init_stream_cap(struct mt76_phy *phy, + void mt76_set_stream_caps(struct mt76_phy *phy, bool vht) + { + if (phy->cap.has_2ghz) +- mt76_init_stream_cap(phy, &phy->sband_2g.sband, false); ++ mt76_init_stream_cap(phy, &phy->sband_2g.sband, vht); + if (phy->cap.has_5ghz) + mt76_init_stream_cap(phy, &phy->sband_5g.sband, vht); + if (phy->cap.has_6ghz) +@@ -349,13 +349,13 @@ mt76_init_sband(struct mt76_phy *phy, struct mt76_sband *msband, + + static int + mt76_init_sband_2g(struct mt76_phy *phy, struct ieee80211_rate *rates, +- int n_rates) ++ int n_rates, bool vht) + { + phy->hw->wiphy->bands[NL80211_BAND_2GHZ] = &phy->sband_2g.sband; + + return mt76_init_sband(phy, &phy->sband_2g, mt76_channels_2ghz, + ARRAY_SIZE(mt76_channels_2ghz), rates, +- n_rates, true, false); ++ n_rates, true, vht); + } + + static int +@@ -508,7 +508,7 @@ int mt76_register_phy(struct mt76_phy *phy, bool vht, + return ret; + + if (phy->cap.has_2ghz) { +- ret = mt76_init_sband_2g(phy, rates, n_rates); ++ ret = mt76_init_sband_2g(phy, rates, n_rates, vht); + if (ret) + return ret; + } +@@ -691,7 +691,7 @@ int mt76_register_device(struct mt76_dev *dev, bool vht, + return ret; + + if (phy->cap.has_2ghz) { +- ret = mt76_init_sband_2g(phy, rates, n_rates); ++ ret = mt76_init_sband_2g(phy, rates, n_rates, vht); + if (ret) + return ret; + } diff --git a/package/kernel/mt76/patches/002-fix-page-pool.patch b/package/kernel/mt76/patches/002-fix-page-pool.patch new file mode 100644 index 000000000..b8d552ffd --- /dev/null +++ b/package/kernel/mt76/patches/002-fix-page-pool.patch @@ -0,0 +1,24 @@ +--- a/mac80211.c ++++ b/mac80211.c +@@ -4,7 +4,9 @@ + */ + #include + #include ++#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 4, 0) + #include ++#endif + #include "mt76.h" + + #define CHAN2G(_idx, _freq) { \ +--- a/mt76.h ++++ b/mt76.h +@@ -15,6 +15,9 @@ + #include + #include + #include ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,4,0) ++#include ++#endif + #include "util.h" + #include "testmode.h" + diff --git a/package/kernel/rtw88-usb/Makefile b/package/kernel/rtw88-usb/Makefile new file mode 100644 index 000000000..7afa41c7f --- /dev/null +++ b/package/kernel/rtw88-usb/Makefile @@ -0,0 +1,105 @@ +# +# Copyright (C) 2017 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=rtw88-usb +PKG_RELEASE:=1 + +PKG_SOURCE_PROTO:=git +PKG_SOURCE_DATE:=2024-04-10 +PKG_SOURCE_URL:=https://github.com/lwfinger/rtw88.git +PKG_SOURCE_VERSION:=2e9f468009df592a51990d024928034e0af1c2b4 +PKG_MIRROR_HASH:=684b30e58d8b990bbe141baae00c48439f45c9f39faa6f552ffb18afb6594c74 + +PKG_BUILD_PARALLEL:=1 + +STAMP_CONFIGURED_DEPENDS := $(STAGING_DIR)/usr/include/mac80211-backport/backport/autoconf.h + +include $(INCLUDE_DIR)/kernel.mk +include $(INCLUDE_DIR)/package.mk + +define KernelPackage/rtw88-default + SUBMENU:=Wireless Drivers + TITLE:=Realtek rtw88 family usb driver + DEPENDS:=+kmod-mac80211 +kmod-usb-core \ + +@DRIVER_11N_SUPPORT +@DRIVER_11AC_SUPPORT +endef + +define KernelPackage/rtw88-usb + $(KernelPackage/rtw88-default) + HIDDEN:=1 + FILES:= \ + $(PKG_BUILD_DIR)/rtw_core.ko \ + $(PKG_BUILD_DIR)/rtw_usb.ko +endef + +define KernelPackage/rtl8723du + $(KernelPackage/rtw88-default) + TITLE:=Realtek RTL8723DU support + DEPENDS+=+kmod-rtw88-usb +rtl8723du-firmware + FILES:= \ + $(PKG_BUILD_DIR)/rtw_8723d.ko \ + $(PKG_BUILD_DIR)/rtw_8723du.ko + AUTOLOAD:=$(call AutoProbe,rtw_8723du) +endef + +define KernelPackage/rtl8821cu + $(KernelPackage/rtw88-default) + TITLE:=Realtek RTL8821CU support + DEPENDS+=+kmod-rtw88-usb +rtl8821ce-firmware + FILES:= \ + $(PKG_BUILD_DIR)/rtw_8821c.ko \ + $(PKG_BUILD_DIR)/rtw_8821cu.ko + AUTOLOAD:=$(call AutoProbe,rtw_8821cu) +endef + +define KernelPackage/rtl8822bu + $(KernelPackage/rtw88-default) + TITLE:=Realtek RTL8822BU support + DEPENDS+=+kmod-rtw88-usb +rtl8822be-firmware + FILES:= \ + $(PKG_BUILD_DIR)/rtw_8822b.ko \ + $(PKG_BUILD_DIR)/rtw_8822bu.ko + AUTOLOAD:=$(call AutoProbe,rtw_8822bu) +endef + +define KernelPackage/rtl8822cu + $(KernelPackage/rtw88-default) + TITLE:=Realtek RTL8822CU support + DEPENDS+=+kmod-rtw88-usb +rtl8822ce-firmware + FILES:= \ + $(PKG_BUILD_DIR)/rtw_8822c.ko \ + $(PKG_BUILD_DIR)/rtw_8822cu.ko + AUTOLOAD:=$(call AutoProbe,rtw_8822cu) +endef + +NOSTDINC_FLAGS := \ + $(KERNEL_NOSTDINC_FLAGS) \ + -I$(PKG_BUILD_DIR) \ + -I$(STAGING_DIR)/usr/include/mac80211-backport/uapi \ + -I$(STAGING_DIR)/usr/include/mac80211-backport \ + -I$(STAGING_DIR)/usr/include/mac80211/uapi \ + -I$(STAGING_DIR)/usr/include/mac80211 \ + -include backport/autoconf.h \ + -include backport/backport.h + +NOSTDINC_FLAGS+=-DBUILD_OPENWRT + +define Build/Compile + +$(MAKE) $(PKG_JOBS) -C "$(LINUX_DIR)" \ + $(KERNEL_MAKE_FLAGS) \ + M="$(PKG_BUILD_DIR)" \ + NOSTDINC_FLAGS="$(NOSTDINC_FLAGS)" \ + modules +endef + +$(eval $(call KernelPackage,rtw88-usb)) +$(eval $(call KernelPackage,rtl8723du)) +$(eval $(call KernelPackage,rtl8821cu)) +$(eval $(call KernelPackage,rtl8822bu)) +$(eval $(call KernelPackage,rtl8822cu)) diff --git a/package/kernel/rtw88-usb/patches/001-fix-merge-error.patch b/package/kernel/rtw88-usb/patches/001-fix-merge-error.patch new file mode 100644 index 000000000..4439c4f18 --- /dev/null +++ b/package/kernel/rtw88-usb/patches/001-fix-merge-error.patch @@ -0,0 +1,96 @@ +--- a/fw.c ++++ b/fw.c +@@ -1009,7 +1009,7 @@ static u8 rtw_get_rsvd_page_probe_req_location(struct rtw_dev *rtwdev, + if (rsvd_pkt->type != RSVD_PROBE_REQ) + continue; + if ((!ssid && !rsvd_pkt->ssid) || +- cfg80211_ssid_eq(rsvd_pkt->ssid, ssid)) ++ cfg80211_ssid_eq(rsvd_pkt->ssid, ssid)) + location = rsvd_pkt->page; + } + +--- a/mac.c ++++ b/mac.c +@@ -316,13 +316,6 @@ static int rtw_mac_power_switch(struct rtw_dev *rtwdev, bool pwr_on) + rtw_write8_clr(rtwdev, REG_SYS_STATUS1 + 1, BIT(0)); + } + +- if (pwr_on && rtw_hci_type(rtwdev) == RTW_HCI_TYPE_USB) { +- if (chip->id == RTW_CHIP_TYPE_8822C || +- chip->id == RTW_CHIP_TYPE_8822B || +- chip->id == RTW_CHIP_TYPE_8821C) +- rtw_write8_clr(rtwdev, REG_SYS_STATUS1 + 1, BIT(0)); +- } +- + if (rtw_hci_type(rtwdev) == RTW_HCI_TYPE_SDIO) + rtw_write32(rtwdev, REG_SDIO_HIMR, imr); + +@@ -956,18 +949,6 @@ static int __rtw_download_firmware_legacy(struct rtw_dev *rtwdev, + rtw_write8(rtwdev, REG_MCUFW_CTRL, 0x00); + } + +- /* reset firmware if still present */ +- if (rtwdev->chip->id == RTW_CHIP_TYPE_8703B && +- rtw_read8_mask(rtwdev, REG_MCUFW_CTRL, BIT_RAM_DL_SEL)) { +- rtw_write8(rtwdev, REG_MCUFW_CTRL, 0x00); +- } +- +- /* reset firmware if still present */ +- if (rtwdev->chip->id == RTW_CHIP_TYPE_8703B && +- rtw_read8_mask(rtwdev, REG_MCUFW_CTRL, BIT_RAM_DL_SEL)) { +- rtw_write8(rtwdev, REG_MCUFW_CTRL, 0x00); +- } +- + en_download_firmware_legacy(rtwdev, true); + ret = download_firmware_legacy(rtwdev, fw->firmware->data, fw->firmware->size); + en_download_firmware_legacy(rtwdev, false); +--- a/main.c ++++ b/main.c +@@ -110,9 +110,7 @@ static const struct ieee80211_iface_limit rtw_iface_limits[] = { + }, + { + .max = 1, +- .types = BIT(NL80211_IFTYPE_AP) | +- BIT(NL80211_IFTYPE_P2P_CLIENT) | +- BIT(NL80211_IFTYPE_P2P_GO) ++ .types = BIT(NL80211_IFTYPE_AP), + } + }; + +@@ -2124,11 +2122,6 @@ static int rtw_chip_efuse_info_setup(struct rtw_dev *rtwdev) + dev_warn(rtwdev->dev, "efuse MAC invalid, using random\n"); + } + +- if (!is_valid_ether_addr(efuse->addr)) { +- eth_random_addr(efuse->addr); +- dev_warn(rtwdev->dev, "efuse MAC invalid, using random\n"); +- } +- + out_disable: + rtw_chip_efuse_disable(rtwdev); + +@@ -2361,9 +2354,7 @@ int rtw_register_hw(struct rtw_dev *rtwdev, struct ieee80211_hw *hw) + hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_AP) | + BIT(NL80211_IFTYPE_ADHOC) | +- BIT(NL80211_IFTYPE_MESH_POINT) | +- BIT(NL80211_IFTYPE_P2P_CLIENT) | +- BIT(NL80211_IFTYPE_P2P_GO); ++ BIT(NL80211_IFTYPE_MESH_POINT); + hw->wiphy->available_antennas_tx = hal->antenna_tx; + hw->wiphy->available_antennas_rx = hal->antenna_rx; + +--- a/usb.c ++++ b/usb.c +@@ -93,11 +93,6 @@ static u32 rtw_usb_read(struct rtw_dev *rtwdev, u32 addr, u16 len) + rtwdev->chip->id == RTW_CHIP_TYPE_8821C) + rtw_usb_reg_sec(rtwdev, addr, data); + +- if (rtwdev->chip->id == RTW_CHIP_TYPE_8822C || +- rtwdev->chip->id == RTW_CHIP_TYPE_8822B || +- rtwdev->chip->id == RTW_CHIP_TYPE_8821C) +- rtw_usb_reg_sec(rtwdev, addr, data); +- + return le32_to_cpu(*data); + } + diff --git a/package/kernel/rtw88-usb/patches/101-wireless-6.1.patch b/package/kernel/rtw88-usb/patches/101-wireless-6.1.patch new file mode 100644 index 000000000..37a9bca9f --- /dev/null +++ b/package/kernel/rtw88-usb/patches/101-wireless-6.1.patch @@ -0,0 +1,432 @@ +--- a/bf.c ++++ b/bf.c +@@ -57,7 +57,7 @@ void rtw_bf_assoc(struct rtw_dev *rtwdev, struct ieee80211_vif *vif, + } + + ic_vht_cap = &hw->wiphy->bands[NL80211_BAND_5GHZ]->vht_cap; +-#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 19, 0) ++#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 19, 0) && !defined(BUILD_OPENWRT) + vht_cap = &sta->vht_cap; + #else + vht_cap = &sta->deflink.vht_cap; +@@ -75,7 +75,7 @@ void rtw_bf_assoc(struct rtw_dev *rtwdev, struct ieee80211_vif *vif, + ether_addr_copy(bfee->mac_addr, bssid); + bfee->role = RTW_BFEE_MU; + bfee->p_aid = (bssid[5] << 1) | (bssid[4] >> 7); +-#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0) || defined(BUILD_OPENWRT) + bfee->aid = vif->cfg.aid; + #else + bfee->aid = bss_conf->aid; +--- a/fw.c ++++ b/fw.c +@@ -191,7 +191,7 @@ legacy: + si->ra_report.desc_rate = rate; + si->ra_report.bit_rate = bit_rate; + +-#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) || defined(BUILD_OPENWRT) + sta->deflink.agg.max_rc_amsdu_len = get_max_amsdu_len(bit_rate); + #else + sta->max_rc_amsdu_len = get_max_amsdu_len(bit_rate); +@@ -726,7 +726,7 @@ void rtw_fw_send_rssi_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si) + rtw_fw_send_h2c_command(rtwdev, h2c_pkt); + } + +-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 18, 0) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 18, 0) || defined(BUILD_OPENWRT) + void rtw_fw_send_ra_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si, + bool reset_ra_mask) + #else +@@ -735,7 +735,7 @@ void rtw_fw_send_ra_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si) + { + u8 h2c_pkt[H2C_PKT_SIZE] = {0}; + bool disable_pt = true; +-#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 18, 0) ++#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 18, 0) && !defined(BUILD_OPENWRT) + bool reset_ra_mask = true; + #endif + +@@ -1228,7 +1228,7 @@ static struct sk_buff *rtw_get_rsvd_page_skb(struct ieee80211_hw *hw, + + switch (rsvd_pkt->type) { + case RSVD_BEACON: +-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)) ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)) || defined(BUILD_OPENWRT) + skb_new = ieee80211_beacon_get_tim(hw, vif, &tim_offset, NULL, 0); + #else + skb_new = ieee80211_beacon_get_tim(hw, vif, &tim_offset, NULL); +@@ -1243,7 +1243,7 @@ static struct sk_buff *rtw_get_rsvd_page_skb(struct ieee80211_hw *hw, + break; + case RSVD_NULL: + #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 17) +-#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) || defined(BUILD_OPENWRT) + skb_new = ieee80211_nullfunc_get(hw, vif, -1, false); + #else + skb_new = ieee80211_nullfunc_get(hw, vif, false); +@@ -1254,7 +1254,7 @@ static struct sk_buff *rtw_get_rsvd_page_skb(struct ieee80211_hw *hw, + break; + case RSVD_QOS_NULL: + #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 17) +-#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) || defined(BUILD_OPENWRT) + skb_new = ieee80211_nullfunc_get(hw, vif, -1, true); + #else + skb_new = ieee80211_nullfunc_get(hw, vif, true); +--- a/fw.h ++++ b/fw.h +@@ -834,7 +834,7 @@ void rtw_fw_coex_query_hid_info(struct rtw_dev *rtwdev, u8 sub_id, u8 data); + + void rtw_fw_bt_wifi_control(struct rtw_dev *rtwdev, u8 op_code, u8 *data); + void rtw_fw_send_rssi_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si); +-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 18, 0) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 18, 0) || defined(BUILD_OPENWRT) + void rtw_fw_send_ra_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si, + bool reset_ra_mask); + #else +--- a/mac80211.c ++++ b/mac80211.c +@@ -365,7 +365,7 @@ static void rtw_conf_tx(struct rtw_dev *rtwdev, + static void rtw_ops_bss_info_changed(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *conf, +-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)) ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)) || defined(BUILD_OPENWRT) + u64 changed) + #else + u32 changed) +@@ -383,7 +383,7 @@ static void rtw_ops_bss_info_changed(struct ieee80211_hw *hw, + + if (changed & BSS_CHANGED_ASSOC) { + rtw_vif_assoc_changed(rtwvif, conf); +-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)) ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)) || defined(BUILD_OPENWRT) + if (vif->cfg.assoc) { + #else + if (conf->assoc) { +@@ -393,7 +393,7 @@ static void rtw_ops_bss_info_changed(struct ieee80211_hw *hw, + rtw_fw_download_rsvd_page(rtwdev); + rtw_send_rsvd_page_h2c(rtwdev); + rtw_fw_default_port(rtwdev, rtwvif); +-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)) ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)) || defined(BUILD_OPENWRT) + rtw_coex_media_status_notify(rtwdev, vif->cfg.assoc); + #else + rtw_coex_media_status_notify(rtwdev, conf->assoc); +@@ -460,7 +460,7 @@ static void rtw_ops_bss_info_changed(struct ieee80211_hw *hw, + mutex_unlock(&rtwdev->mutex); + } + +-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)) ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)) || defined(BUILD_OPENWRT) + static int rtw_ops_start_ap(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *link_conf) +@@ -481,7 +481,7 @@ static int rtw_ops_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif) + return 0; + } + +-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)) ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)) || defined(BUILD_OPENWRT) + static void rtw_ops_stop_ap(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *link_conf) +@@ -502,7 +502,7 @@ static void rtw_ops_stop_ap(struct ieee80211_hw *hw, + + static int rtw_ops_conf_tx(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, +-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)) ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)) || defined(BUILD_OPENWRT) + unsigned int link_id, u16 ac, + #else + u16 ac, +@@ -731,7 +731,7 @@ static void rtw_ops_sw_scan_complete(struct ieee80211_hw *hw, + #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 18, 0) + static void rtw_ops_mgd_prepare_tx(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, +- #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5,14,0)) ++ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5,14,0)) || defined(BUILD_OPENWRT) + struct ieee80211_prep_tx_info *info) + #else + u16 duration) +--- a/main.c ++++ b/main.c +@@ -191,7 +191,7 @@ static void rtw_vif_watch_dog_iter(void *data, struct ieee80211_vif *vif) + struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv; + + if (vif->type == NL80211_IFTYPE_STATION) +-#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0) || defined(BUILD_OPENWRT) + if (vif->cfg.assoc) + #else + if (vif->bss_conf.assoc) +@@ -343,7 +343,7 @@ int rtw_sta_add(struct rtw_dev *rtwdev, struct ieee80211_sta *sta, + if (si->mac_id >= RTW_MAX_MAC_ID_NUM) + return -ENOSPC; + +-#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0) || defined(BUILD_OPENWRT) + if (vif->type == NL80211_IFTYPE_STATION && vif->cfg.assoc == 0) + #else + if (vif->type == NL80211_IFTYPE_STATION && vif->bss_conf.assoc == 0) +@@ -572,7 +572,7 @@ EXPORT_SYMBOL(rtw_dump_reg); + void rtw_vif_assoc_changed(struct rtw_vif *rtwvif, + struct ieee80211_bss_conf *conf) + { +-#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0) || defined(BUILD_OPENWRT) + struct ieee80211_vif *vif = NULL; + + if (conf) +@@ -1000,7 +1000,7 @@ static void rtw_hw_config_rf_ant_num(struct rtw_dev *rtwdev, u8 hw_ant_num) + static u64 get_vht_ra_mask(struct ieee80211_sta *sta) + { + u64 ra_mask = 0; +-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0) || defined(BUILD_OPENWRT) + u16 mcs_map = le16_to_cpu(sta->deflink.vht_cap.vht_mcs.rx_mcs_map); + #else + u16 mcs_map = le16_to_cpu(sta->vht_cap.vht_mcs.rx_mcs_map); +@@ -1224,26 +1224,26 @@ void rtw_update_sta_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si, + bool is_vht_enable = false; + bool is_support_sgi = false; + +-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0) || defined(BUILD_OPENWRT) + if (sta->deflink.vht_cap.vht_supported) { + #else + if (sta->vht_cap.vht_supported) { + #endif + is_vht_enable = true; + ra_mask |= get_vht_ra_mask(sta); +-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0) || defined(BUILD_OPENWRT) + if (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_RXSTBC_MASK) + #else + if (sta->vht_cap.cap & IEEE80211_VHT_CAP_RXSTBC_MASK) + #endif + stbc_en = VHT_STBC_EN; +-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0) || defined(BUILD_OPENWRT) + if (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC) + #else + if (sta->vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC) + #endif + ldpc_en = VHT_LDPC_EN; +-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0) || defined(BUILD_OPENWRT) + } else if (sta->deflink.ht_cap.ht_supported) { + ra_mask |= (sta->deflink.ht_cap.mcs.rx_mask[1] << 20) | + (sta->deflink.ht_cap.mcs.rx_mask[0] << 12); +@@ -1266,20 +1266,20 @@ void rtw_update_sta_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si, + ra_mask &= RA_MASK_VHT_RATES_1SS | RA_MASK_HT_RATES_1SS; + + if (hal->current_band_type == RTW_BAND_5G) { +-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0) || defined(BUILD_OPENWRT) + ra_mask |= (u64)sta->deflink.supp_rates[NL80211_BAND_5GHZ] << 4; + #else + ra_mask |= (u64)sta->supp_rates[NL80211_BAND_5GHZ] << 4; + #endif + ra_mask_bak = ra_mask; +-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0) || defined(BUILD_OPENWRT) + if (sta->deflink.vht_cap.vht_supported) { + #else + if (sta->vht_cap.vht_supported) { + #endif + ra_mask &= RA_MASK_VHT_RATES | RA_MASK_OFDM_IN_VHT; + wireless_set = WIRELESS_OFDM | WIRELESS_VHT; +-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0) || defined(BUILD_OPENWRT) + } else if (sta->deflink.ht_cap.ht_supported) { + #else + } else if (sta->ht_cap.ht_supported) { +@@ -1291,13 +1291,13 @@ void rtw_update_sta_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si, + } + dm_info->rrsr_val_init = RRSR_INIT_5G; + } else if (hal->current_band_type == RTW_BAND_2G) { +-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0) || defined(BUILD_OPENWRT) + ra_mask |= sta->deflink.supp_rates[NL80211_BAND_2GHZ]; + #else + ra_mask |= sta->supp_rates[NL80211_BAND_2GHZ]; + #endif + ra_mask_bak = ra_mask; +-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0) || defined(BUILD_OPENWRT) + if (sta->deflink.vht_cap.vht_supported) { + #else + if (sta->vht_cap.vht_supported) { +@@ -1306,7 +1306,7 @@ void rtw_update_sta_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si, + RA_MASK_OFDM_IN_VHT; + wireless_set = WIRELESS_CCK | WIRELESS_OFDM | + WIRELESS_HT | WIRELESS_VHT; +-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0) || defined(BUILD_OPENWRT) + } else if (sta->deflink.ht_cap.ht_supported) { + #else + } else if (sta->ht_cap.ht_supported) { +@@ -1315,7 +1315,7 @@ void rtw_update_sta_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si, + RA_MASK_OFDM_IN_HT_2G; + wireless_set = WIRELESS_CCK | WIRELESS_OFDM | + WIRELESS_HT; +-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0) || defined(BUILD_OPENWRT) + } else if (sta->deflink.supp_rates[0] <= 0xf) { + #else + } else if (sta->supp_rates[0] <= 0xf) { +@@ -1332,14 +1332,14 @@ void rtw_update_sta_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si, + wireless_set = 0; + } + +-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0) || defined(BUILD_OPENWRT) + switch (sta->deflink.bandwidth) { + #else + switch (sta->bandwidth) { + #endif + case IEEE80211_STA_RX_BW_80: + bw_mode = RTW_CHANNEL_WIDTH_80; +-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0) || defined(BUILD_OPENWRT) + is_support_sgi = sta->deflink.vht_cap.vht_supported && + (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_80); + #else +@@ -1349,7 +1349,7 @@ void rtw_update_sta_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si, + break; + case IEEE80211_STA_RX_BW_40: + bw_mode = RTW_CHANNEL_WIDTH_40; +-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0) || defined(BUILD_OPENWRT) + is_support_sgi = sta->deflink.ht_cap.ht_supported && + (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_SGI_40); + #else +@@ -1359,7 +1359,7 @@ void rtw_update_sta_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si, + break; + default: + bw_mode = RTW_CHANNEL_WIDTH_20; +-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0) || defined(BUILD_OPENWRT) + is_support_sgi = sta->deflink.ht_cap.ht_supported && + (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_SGI_20); + #else +@@ -1369,14 +1369,14 @@ void rtw_update_sta_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si, + break; + } + +-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0) || defined(BUILD_OPENWRT) + if (sta->deflink.vht_cap.vht_supported && ra_mask & 0xffc00000) { + #else + if (sta->vht_cap.vht_supported && ra_mask & 0xffc00000) { + #endif + tx_num = 2; + rf_type = RF_2T2R; +-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0) || defined(BUILD_OPENWRT) + } else if (sta->deflink.ht_cap.ht_supported && ra_mask & 0xfff00000) { + #else + } else if (sta->ht_cap.ht_supported && ra_mask & 0xfff00000) { +@@ -1400,7 +1400,7 @@ void rtw_update_sta_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si, + si->ra_mask = ra_mask; + si->rate_id = rate_id; + +-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 18, 0) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 18, 0) || defined(BUILD_OPENWRT) + rtw_fw_send_ra_info(rtwdev, si, reset_ra_mask); + #else + rtw_fw_send_ra_info(rtwdev, si); +@@ -1780,7 +1780,7 @@ static void rtw_vif_smps_iter(void *data, u8 *mac, + { + struct rtw_dev *rtwdev = (struct rtw_dev *)data; + +-#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0) || defined(BUILD_OPENWRT) + if (vif->type != NL80211_IFTYPE_STATION || !vif->cfg.assoc) + #else + if (vif->type != NL80211_IFTYPE_STATION || !vif->bss_conf.assoc) +@@ -1788,13 +1788,13 @@ static void rtw_vif_smps_iter(void *data, u8 *mac, + return; + + if (rtwdev->hal.txrx_1ss) +-#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0) || defined(BUILD_OPENWRT) + ieee80211_request_smps(vif, 0, IEEE80211_SMPS_STATIC); + #else + ieee80211_request_smps(vif, IEEE80211_SMPS_STATIC); + #endif + else +-#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0) || defined(BUILD_OPENWRT) + ieee80211_request_smps(vif, 0, IEEE80211_SMPS_OFF); + #else + ieee80211_request_smps(vif, IEEE80211_SMPS_OFF); +@@ -2516,7 +2516,7 @@ static void rtw_check_sta_active_iter(void *data, struct ieee80211_vif *vif) + if (vif->type != NL80211_IFTYPE_STATION) + return; + +-#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0) || defined(BUILD_OPENWRT) + if (vif->cfg.assoc || !is_zero_ether_addr(rtwvif->bssid)) + #else + if (vif->bss_conf.assoc || !is_zero_ether_addr(rtwvif->bssid)) +--- a/ps.c ++++ b/ps.c +@@ -334,7 +334,7 @@ void rtw_recalc_lps(struct rtw_dev *rtwdev, struct ieee80211_vif *new_vif) + __rtw_vif_recalc_lps(&data, new_vif); + rtw_iterate_vifs(rtwdev, rtw_vif_recalc_lps_iter, &data); + +-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)) ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)) || defined(BUILD_OPENWRT) + if (data.count == 1 && data.found_vif->cfg.ps) { + rtwdev->ps_enabled = true; + } else { +--- a/tx.c ++++ b/tx.c +@@ -90,7 +90,7 @@ EXPORT_SYMBOL(rtw_tx_fill_tx_desc); + + static u8 get_tx_ampdu_factor(struct ieee80211_sta *sta) + { +-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0) || defined(BUILD_OPENWRT) + u8 exp = sta->deflink.ht_cap.ampdu_factor; + #else + u8 exp = sta->ht_cap.ampdu_factor; +@@ -105,7 +105,7 @@ static u8 get_tx_ampdu_factor(struct ieee80211_sta *sta) + + static u8 get_tx_ampdu_density(struct ieee80211_sta *sta) + { +-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0) || defined(BUILD_OPENWRT) + return sta->deflink.ht_cap.ampdu_density; + #else + return sta->ht_cap.ampdu_density; +@@ -117,7 +117,7 @@ static u8 get_highest_ht_tx_rate(struct rtw_dev *rtwdev, + { + u8 rate; + +-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0) || defined(BUILD_OPENWRT) + if (rtwdev->hal.rf_type == RF_2T2R && sta->deflink.ht_cap.mcs.rx_mask[1] != 0) + #else + if (rtwdev->hal.rf_type == RF_2T2R && sta->ht_cap.mcs.rx_mask[1] != 0) +@@ -136,7 +136,7 @@ static u8 get_highest_vht_tx_rate(struct rtw_dev *rtwdev, + u8 rate; + u16 tx_mcs_map; + +-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0) || defined(BUILD_OPENWRT) + tx_mcs_map = le16_to_cpu(sta->deflink.vht_cap.vht_mcs.tx_mcs_map); + #else + tx_mcs_map = le16_to_cpu(sta->vht_cap.vht_mcs.tx_mcs_map); +@@ -382,7 +382,7 @@ static void rtw_tx_data_pkt_info_update(struct rtw_dev *rtwdev, + if (info->control.use_rts || skb->len > hw->wiphy->rts_threshold) + pkt_info->rts = true; + +-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0) || defined(BUILD_OPENWRT) + if (sta->deflink.vht_cap.vht_supported) + rate = get_highest_vht_tx_rate(rtwdev, sta); + else if (sta->deflink.ht_cap.ht_supported) diff --git a/package/kernel/rtw88-usb/patches/102-disable-pcie.patch b/package/kernel/rtw88-usb/patches/102-disable-pcie.patch new file mode 100644 index 000000000..f57ad4c88 --- /dev/null +++ b/package/kernel/rtw88-usb/patches/102-disable-pcie.patch @@ -0,0 +1,69 @@ +--- a/Makefile ++++ b/Makefile +@@ -30,10 +30,6 @@ NO_SKIP_SIGN := y + endif + + EXTRA_CFLAGS += -O2 +-EXTRA_CFLAGS += -DCONFIG_RTW88_8822BE=1 +-EXTRA_CFLAGS += -DCONFIG_RTW88_8821CE=1 +-EXTRA_CFLAGS += -DCONFIG_RTW88_8822CE=1 +-EXTRA_CFLAGS += -DCONFIG_RTW88_8723DE=1 + EXTRA_CFLAGS += -DCONFIG_RTW88_DEBUG=1 + EXTRA_CFLAGS += -DCONFIG_RTW88_DEBUGFS=1 + #EXTRA_CFLAGS += -DCONFIG_RTW88_REGD_USER_REG_HINTS +@@ -60,9 +56,6 @@ rtw_core-objs += main.o \ + obj-m += rtw_8822b.o + rtw_8822b-objs := rtw8822b.o rtw8822b_table.o + +-obj-m += rtw_8822be.o +-rtw_8822be-objs := rtw8822be.o +- + obj-m += rtw_8822bu.o + rtw_8822bu-objs := rtw8822bu.o + +@@ -72,9 +65,6 @@ rtw_8822bs-objs := rtw8822bs.o + obj-m += rtw_8822c.o + rtw_8822c-objs := rtw8822c.o rtw8822c_table.o + +-obj-m += rtw_8822ce.o +-rtw_8822ce-objs := rtw8822ce.o +- + obj-m += rtw_8822cu.o + rtw_8822cu-objs := rtw8822cu.o + +@@ -102,9 +92,6 @@ rtw_8723cs-objs := rtw8723cs.o + obj-m += rtw_8723d.o + rtw_8723d-objs := rtw8723d.o rtw8723d_table.o + +-obj-m += rtw_8723de.o +-rtw_8723de-objs := rtw8723de.o +- + obj-m += rtw_8723du.o + rtw_8723du-objs := rtw8723du.o + +@@ -114,15 +101,9 @@ rtw_8723ds-objs := rtw8723ds.o + obj-m += rtw_8821c.o + rtw_8821c-objs := rtw8821c.o rtw8821c_table.o + +-obj-m += rtw_8821ce.o +-rtw_8821ce-objs := rtw8821ce.o +- + obj-m += rtw_8821a.o + rtw_8821a-objs := rtw8821a.o rtw8821a_table.o + +-obj-m += rtw_8821ae.o +-rtw_8821ae-objs := rtw8821ae.o +- + obj-m += rtw_8821au.o + rtw_8821au-objs := rtw8821au.o + +@@ -132,9 +113,6 @@ rtw_8821cs-objs := rtw8821cs.o + obj-m += rtw_8821cu.o + rtw_8821cu-objs := rtw8821cu.o + +-obj-m += rtw_pci.o +-rtw_pci-objs := pci.o +- + obj-m += rtw_sdio.o + rtw_sdio-objs := sdio.o + diff --git a/package/lean/autocore/files/x86/autocore b/package/lean/autocore/files/x86/autocore index ecae6d7d2..f5d8a0106 100755 --- a/package/lean/autocore/files/x86/autocore +++ b/package/lean/autocore/files/x86/autocore @@ -66,9 +66,7 @@ start() ethtool -K $c tx-checksum-ipv4 on >/dev/null 2>&1 ethtool -K $c tx-checksum-ipv6 on >/dev/null 2>&1) ethtool -K $c tx-scatter-gather on >/dev/null 2>&1 - ethtool -K $c gso on >/dev/null 2>&1 ethtool -K $c tso on >/dev/null 2>&1 - ethtool -K $c ufo on >/dev/null 2>&1 done [ -f /etc/index.htm ] && mv /etc/index.htm /usr/lib/lua/luci/view/admin_status/index.htm diff --git a/package/lean/default-settings/files/zzz-default-settings b/package/lean/default-settings/files/zzz-default-settings index fa949ecf0..804667ed5 100755 --- a/package/lean/default-settings/files/zzz-default-settings +++ b/package/lean/default-settings/files/zzz-default-settings @@ -3,8 +3,16 @@ uci set luci.main.lang=zh_cn uci commit luci -uci set system.@system[0].timezone=CST-8 -uci set system.@system[0].zonename=Asia/Shanghai +uci -q batch <<-EOF + set system.@system[0].timezone='CST-8' + set system.@system[0].zonename='Asia/Shanghai' + + delete system.ntp.server + add_list system.ntp.server='ntp1.aliyun.com' + add_list system.ntp.server='ntp.tencent.com' + add_list system.ntp.server='ntp.ntsc.ac.cn' + add_list system.ntp.server='time.ustc.edu.cn' +EOF uci commit system uci set fstab.@global[0].anon_mount=1 @@ -28,28 +36,30 @@ sed -i 's/\"services\"/\"nas\"/g' /usr/lib/lua/luci/controller/usb_printer.lua sed -i 's/\"services\"/\"nas\"/g' /usr/lib/lua/luci/controller/xunlei.lua sed -i 's/services/nas/g' /usr/lib/lua/luci/view/minidlna_status.htm -ln -sf /sbin/ip /usr/bin/ip - -sed -i 's#downloads.openwrt.org#mirrors.cloud.tencent.com/lede#g' /etc/opkg/distfeeds.conf +sed -i 's#downloads.openwrt.org#mirrors.tencent.com/lede#g' /etc/opkg/distfeeds.conf sed -i 's/root::0:0:99999:7:::/root:$1$V4UetPzk$CYXluq4wUazHjmCDBCqXF.:0:0:99999:7:::/g' /etc/shadow sed -i 's/root:::0:99999:7:::/root:$1$V4UetPzk$CYXluq4wUazHjmCDBCqXF.:0:0:99999:7:::/g' /etc/shadow sed -i "s/# //g" /etc/opkg/distfeeds.conf sed -i '/openwrt_luci/ { s/snapshots/releases\/18.06.9/g; }' /etc/opkg/distfeeds.conf +sed -i '/check_signature/d' /etc/opkg.conf + sed -i '/REDIRECT --to-ports 53/d' /etc/firewall.user -# echo 'iptables -A OUTPUT -m string --string "api.installer.xiaomi.cn" --algo bm --to 65535 -j DROP' >> /etc/firewall.user sed -i '/option disabled/d' /etc/config/wireless +sed -i '/set wireless.radio${devidx}.disabled/d' /lib/wifi/mac80211.sh sed -i '/DISTRIB_REVISION/d' /etc/openwrt_release -echo "DISTRIB_REVISION='R24.06.29-D'" >> /etc/openwrt_release +echo "DISTRIB_REVISION='R24.07.19-D'" >> /etc/openwrt_release sed -i '/DISTRIB_DESCRIPTION/d' /etc/openwrt_release echo "DISTRIB_DESCRIPTION='OpenWrt '" >> /etc/openwrt_release sed -i '/log-facility/d' /etc/dnsmasq.conf echo "log-facility=/dev/null" >> /etc/dnsmasq.conf +#ln -sf /sbin/ip /usr/bin/ip + rm -rf /tmp/luci-modulecache/ rm -f /tmp/luci-indexcache diff --git a/package/lean/r8101/Makefile b/package/lean/r8101/Makefile new file mode 100644 index 000000000..232ad16f0 --- /dev/null +++ b/package/lean/r8101/Makefile @@ -0,0 +1,39 @@ +# +# Download realtek r8101 linux driver from official site: +# [https://www.realtek.com/component/zoo/category/network-interface-controllers-10-100-1000m-gigabit-ethernet-pci-express-software] +# + +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/kernel.mk + +PKG_NAME:=r8101 +PKG_VERSION:=1.038.02 +PKG_RELEASE:=1 + +PKG_SOURCE_PROTO:=git +PKG_SOURCE_URL:=https://github.com/sbwml/package_kernel_r8101 +PKG_SOURCE_VERSION:=5dea36329c0524490c093991801973fc48d92a8b +PKG_MIRROR_HASH:=f4182719b25cd177023dddd6f0f555597c8e340fa38127566681d10be885dd9a + +PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION) + +include $(INCLUDE_DIR)/package.mk + +define KernelPackage/r8101 + TITLE:=Driver for Realtek r8101 chipsets + SUBMENU:=Network Devices + VERSION:=$(LINUX_VERSION)+$(PKG_VERSION)-$(BOARD)-$(PKG_RELEASE) + DEPENDS:=@PCI_SUPPORT + FILES:= $(PKG_BUILD_DIR)/src/r8101.ko + AUTOLOAD:=$(call AutoProbe,r8101) +endef + +define Package/r8101/description + This package contains a driver for Realtek r8101 chipsets. +endef + +define Build/Compile + +$(KERNEL_MAKE) M=$(PKG_BUILD_DIR)/src modules +endef + +$(eval $(call KernelPackage,r8101)) diff --git a/package/lean/r8101/patches/010-6.1-support.patch b/package/lean/r8101/patches/010-6.1-support.patch new file mode 100644 index 000000000..489d2ebed --- /dev/null +++ b/package/lean/r8101/patches/010-6.1-support.patch @@ -0,0 +1,14 @@ +--- a/src/r8101.h +--- b/src/r8101.h +@@ -492,7 +492,11 @@ + typedef struct napi_struct *napi_ptr; + typedef int napi_budget; + ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) ++#define RTL_NAPI_CONFIG(ndev, priv, function, weight) netif_napi_add_weight(ndev, &priv->napi, function, weight) ++#else + #define RTL_NAPI_CONFIG(ndev, priv, function, weight) netif_napi_add(ndev, &priv->napi, function, weight) ++#endif + #define RTL_NAPI_QUOTA(budget, ndev) min(budget, budget) + #define RTL_GET_PRIV(stuct_ptr, priv_struct) container_of(stuct_ptr, priv_struct, stuct_ptr) + #define RTL_GET_NETDEV(priv_ptr) struct net_device *dev = priv_ptr->dev; diff --git a/package/utils/f2fs-tools/Makefile b/package/utils/f2fs-tools/Makefile index d5dc1a6d7..d11e89d8e 100644 --- a/package/utils/f2fs-tools/Makefile +++ b/package/utils/f2fs-tools/Makefile @@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=f2fs-tools PKG_VERSION:=1.16.0 -PKG_RELEASE:=2 +PKG_RELEASE:=3 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs-tools.git/snapshot/ @@ -137,6 +137,7 @@ define Package/f2fsck/install $(LN) ../sbin/fsck.f2fs $(1)/usr/sbin/dump.f2fs $(LN) ../sbin/fsck.f2fs $(1)/usr/sbin/sload.f2fs $(LN) ../sbin/fsck.f2fs $(1)/usr/sbin/resize.f2fs + $(LN) ../sbin/fsck.f2fs $(1)/usr/sbin/f2fslabel endef Package/f2fsck-selinux/install = $(Package/f2fsck/install) diff --git a/package/utils/lua/Makefile b/package/utils/lua/Makefile index e4d2fd1c5..247a2a7ca 100644 --- a/package/utils/lua/Makefile +++ b/package/utils/lua/Makefile @@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=lua PKG_VERSION:=5.1.5 -PKG_RELEASE:=10 +PKG_RELEASE:=11 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://www.lua.org/ftp/ \ diff --git a/package/utils/lua/patches-host/001-include-version-number.patch b/package/utils/lua/patches-host/001-include-version-number.patch index f769e6073..806d37003 100644 --- a/package/utils/lua/patches-host/001-include-version-number.patch +++ b/package/utils/lua/patches-host/001-include-version-number.patch @@ -8,7 +8,6 @@ Including it allows multiple lua versions to coexist. Signed-off-by: Rafał Miłecki --- -diff --git a/Makefile b/Makefile --- a/Makefile +++ b/Makefile @@ -41,10 +41,10 @@ RANLIB= ranlib @@ -42,7 +41,7 @@ rename to doc/luac5.1.1 diff --git a/src/Makefile b/src/Makefile --- a/src/Makefile +++ b/src/Makefile -@@ -29,10 +29,10 @@ CORE_O= lapi.o lcode.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o lmem.o \ +@@ -29,10 +29,10 @@ CORE_O= lapi.o lcode.o ldebug.o ldo.o ld LIB_O= lauxlib.o lbaselib.o ldblib.o liolib.o lmathlib.o loslib.o ltablib.o \ lstrlib.o loadlib.o linit.o diff --git a/package/utils/lua/patches-host/013-lnum-strtoul-parsing-fixes.patch b/package/utils/lua/patches-host/013-lnum-strtoul-parsing-fixes.patch index 7f00c8c3a..888722958 100644 --- a/package/utils/lua/patches-host/013-lnum-strtoul-parsing-fixes.patch +++ b/package/utils/lua/patches-host/013-lnum-strtoul-parsing-fixes.patch @@ -1,8 +1,6 @@ -diff --git a/src/lnum.c b/src/lnum.c -index 1456b6a2ed23..b0632b04c2b7 100644 --- a/src/lnum.c +++ b/src/lnum.c -@@ -127,6 +127,8 @@ static int luaO_str2i (const char *s, lua_Integer *res, char **endptr_ref) { +@@ -127,6 +127,8 @@ static int luaO_str2i (const char *s, lu #else return 0; /* Reject the number */ #endif @@ -11,7 +9,7 @@ index 1456b6a2ed23..b0632b04c2b7 100644 } } else if ((v > LUA_INTEGER_MAX) || (*endptr && (!isspace(*endptr)))) { return TK_NUMBER; /* not in signed range, or has '.', 'e' etc. trailing */ -@@ -310,3 +312,13 @@ int try_unmint( lua_Integer *r, lua_Integer ib ) { +@@ -310,3 +312,13 @@ int try_unmint( lua_Integer *r, lua_Inte return 0; } @@ -25,8 +23,6 @@ index 1456b6a2ed23..b0632b04c2b7 100644 + return (unsigned LUA_INTEGER)v; +} +#endif -diff --git a/src/lnum_config.h b/src/lnum_config.h -index 19d7a4231a49..1092eead6629 100644 --- a/src/lnum_config.h +++ b/src/lnum_config.h @@ -141,7 +141,12 @@ @@ -43,6 +39,3 @@ index 19d7a4231a49..1092eead6629 100644 #endif #ifndef LUA_INTEGER_MIN # define LUA_INTEGER_MIN (-LUA_INTEGER_MAX -1) /* -2^16|32 */ --- -1.9.1 - diff --git a/package/utils/lua/patches-host/100-no_readline.patch b/package/utils/lua/patches-host/100-no_readline.patch index 209c302bb..700114e43 100644 --- a/package/utils/lua/patches-host/100-no_readline.patch +++ b/package/utils/lua/patches-host/100-no_readline.patch @@ -10,7 +10,7 @@ #if defined(LUA_USE_MACOSX) --- a/src/Makefile +++ b/src/Makefile -@@ -17,6 +17,7 @@ +@@ -17,6 +17,7 @@ LIBS= -lm $(MYLIBS) MYCFLAGS= MYLDFLAGS= MYLIBS= @@ -18,7 +18,7 @@ # == END OF USER SETTINGS. NO NEED TO CHANGE ANYTHING BELOW THIS LINE ========= -@@ -75,7 +76,7 @@ +@@ -75,7 +76,7 @@ echo: @echo "MYLIBS = $(MYLIBS)" # convenience targets for popular platforms @@ -27,7 +27,7 @@ none: @echo "Please choose a platform:" @echo " $(PLATS)" -@@ -90,16 +91,16 @@ +@@ -90,16 +91,16 @@ bsd: $(MAKE) all MYCFLAGS="-DLUA_USE_POSIX -DLUA_USE_DLOPEN" MYLIBS="-Wl,-E" freebsd: diff --git a/package/utils/lua/patches-host/400-CVE-2014-5461.patch b/package/utils/lua/patches-host/400-CVE-2014-5461.patch new file mode 100644 index 000000000..cce73ff96 --- /dev/null +++ b/package/utils/lua/patches-host/400-CVE-2014-5461.patch @@ -0,0 +1,19 @@ +From: Enrico Tassi +Date: Tue, 26 Aug 2014 16:20:55 +0200 +Subject: Fix stack overflow in vararg functions + +--- + src/ldo.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/src/ldo.c ++++ b/src/ldo.c +@@ -274,7 +274,7 @@ int luaD_precall (lua_State *L, StkId fu + CallInfo *ci; + StkId st, base; + Proto *p = cl->p; +- luaD_checkstack(L, p->maxstacksize); ++ luaD_checkstack(L, p->maxstacksize + p->numparams); + func = restorestack(L, funcr); + if (!p->is_vararg) { /* no varargs? */ + base = func + 1; diff --git a/package/utils/lua/patches/001-include-version-number.patch b/package/utils/lua/patches/001-include-version-number.patch index f769e6073..806d37003 100644 --- a/package/utils/lua/patches/001-include-version-number.patch +++ b/package/utils/lua/patches/001-include-version-number.patch @@ -8,7 +8,6 @@ Including it allows multiple lua versions to coexist. Signed-off-by: Rafał Miłecki --- -diff --git a/Makefile b/Makefile --- a/Makefile +++ b/Makefile @@ -41,10 +41,10 @@ RANLIB= ranlib @@ -42,7 +41,7 @@ rename to doc/luac5.1.1 diff --git a/src/Makefile b/src/Makefile --- a/src/Makefile +++ b/src/Makefile -@@ -29,10 +29,10 @@ CORE_O= lapi.o lcode.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o lmem.o \ +@@ -29,10 +29,10 @@ CORE_O= lapi.o lcode.o ldebug.o ldo.o ld LIB_O= lauxlib.o lbaselib.o ldblib.o liolib.o lmathlib.o loslib.o ltablib.o \ lstrlib.o loadlib.o linit.o diff --git a/package/utils/lua/patches/013-lnum-strtoul-parsing-fixes.patch b/package/utils/lua/patches/013-lnum-strtoul-parsing-fixes.patch index 7f00c8c3a..888722958 100644 --- a/package/utils/lua/patches/013-lnum-strtoul-parsing-fixes.patch +++ b/package/utils/lua/patches/013-lnum-strtoul-parsing-fixes.patch @@ -1,8 +1,6 @@ -diff --git a/src/lnum.c b/src/lnum.c -index 1456b6a2ed23..b0632b04c2b7 100644 --- a/src/lnum.c +++ b/src/lnum.c -@@ -127,6 +127,8 @@ static int luaO_str2i (const char *s, lua_Integer *res, char **endptr_ref) { +@@ -127,6 +127,8 @@ static int luaO_str2i (const char *s, lu #else return 0; /* Reject the number */ #endif @@ -11,7 +9,7 @@ index 1456b6a2ed23..b0632b04c2b7 100644 } } else if ((v > LUA_INTEGER_MAX) || (*endptr && (!isspace(*endptr)))) { return TK_NUMBER; /* not in signed range, or has '.', 'e' etc. trailing */ -@@ -310,3 +312,13 @@ int try_unmint( lua_Integer *r, lua_Integer ib ) { +@@ -310,3 +312,13 @@ int try_unmint( lua_Integer *r, lua_Inte return 0; } @@ -25,8 +23,6 @@ index 1456b6a2ed23..b0632b04c2b7 100644 + return (unsigned LUA_INTEGER)v; +} +#endif -diff --git a/src/lnum_config.h b/src/lnum_config.h -index 19d7a4231a49..1092eead6629 100644 --- a/src/lnum_config.h +++ b/src/lnum_config.h @@ -141,7 +141,12 @@ @@ -43,6 +39,3 @@ index 19d7a4231a49..1092eead6629 100644 #endif #ifndef LUA_INTEGER_MIN # define LUA_INTEGER_MIN (-LUA_INTEGER_MAX -1) /* -2^16|32 */ --- -1.9.1 - diff --git a/package/utils/lua/patches/400-CVE-2014-5461.patch b/package/utils/lua/patches/400-CVE-2014-5461.patch new file mode 100644 index 000000000..cce73ff96 --- /dev/null +++ b/package/utils/lua/patches/400-CVE-2014-5461.patch @@ -0,0 +1,19 @@ +From: Enrico Tassi +Date: Tue, 26 Aug 2014 16:20:55 +0200 +Subject: Fix stack overflow in vararg functions + +--- + src/ldo.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/src/ldo.c ++++ b/src/ldo.c +@@ -274,7 +274,7 @@ int luaD_precall (lua_State *L, StkId fu + CallInfo *ci; + StkId st, base; + Proto *p = cl->p; +- luaD_checkstack(L, p->maxstacksize); ++ luaD_checkstack(L, p->maxstacksize + p->numparams); + func = restorestack(L, funcr); + if (!p->is_vararg) { /* no varargs? */ + base = func + 1; diff --git a/package/wwan/luci-app-modem/Makefile b/package/wwan/luci-app-modem/Makefile index 16a8cc292..ba7cbe485 100644 --- a/package/wwan/luci-app-modem/Makefile +++ b/package/wwan/luci-app-modem/Makefile @@ -24,7 +24,6 @@ LUCI_DEPENDS:=+luci-compat \ +kmod-pcie_mhi \ +pciutils \ +quectel-CM-5G \ - +sms-tool \ +jq define Package/luci-app-modem/conffiles diff --git a/package/wwan/luci-app-sms-tool/LICENSE b/package/wwan/luci-app-sms-tool/LICENSE deleted file mode 100644 index f288702d2..000000000 --- a/package/wwan/luci-app-sms-tool/LICENSE +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. diff --git a/package/wwan/luci-app-sms-tool/Makefile b/package/wwan/luci-app-sms-tool/Makefile deleted file mode 100644 index db9d2a20c..000000000 --- a/package/wwan/luci-app-sms-tool/Makefile +++ /dev/null @@ -1,32 +0,0 @@ -# Copyright (C) 2023 Siriling -# This is free software, licensed under the GNU General Public License v3. - -include $(TOPDIR)/rules.mk - -PKG_NAME:=luci-app-sms-tool -LUCI_TITLE:=LuCI Support for sms_tool -LUCI_PKGARCH:=all -PKG_VERSION:=1.0.0 -PKG_LICENSE:=GPLv3 -PKG_LINCESE_FILES:=LICENSE -PKF_MAINTAINER:=siriling -LUCI_DEPENDS:=+sms-tool +luci-compat +kmod-usb-serial +kmod-usb-serial-option - -define Package/luci-app-sms-tool/postinst -#!/bin/sh -rm -rf /tmp/luci-indexcache -rm -rf /tmp/luci-modulecache/ -/sbin/set_sms_ports.sh -exit 0 -endef - -define Package/$(PKG_NAME)/config -# shown in make menuconfig -help - $(LUCI_TITLE) - Version: $(PKG_VERSION) -endef - -include $(TOPDIR)/feeds/luci/luci.mk - -# call BuildPackage - OpenWrt buildroot signature diff --git a/package/wwan/luci-app-sms-tool/htdocs/luci-static/resources/icons/delsms.png b/package/wwan/luci-app-sms-tool/htdocs/luci-static/resources/icons/delsms.png deleted file mode 100644 index b036e813f546c56ad0e934e1c7ec9ee359f469b4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9221 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 be4qXWXHQajJ#~#t00000NkvXXu0mjfyr5CZ diff --git a/package/wwan/luci-app-sms-tool/htdocs/luci-static/resources/icons/delsms2.png b/package/wwan/luci-app-sms-tool/htdocs/luci-static/resources/icons/delsms2.png deleted file mode 100644 index eeb13c5e674a1a826e0f8f0fdb809834922e1d3c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1365 zcmV-b1*-aqP)EX>4Tx04R}tkv&MmKpe$iQ>7}k4(*`gkfAzR5EXHhDi*;)X)CnqU~=gfG-*gu zTpR`0f`cE6RRbkxtGNhls^O2g@DIiiS!&O&nHKjq-(z z!wTmu&T6^JTKD8H^yjpd6xV5vAciHxk$?ypRg_SMg$S)0DJGJ%A9e8$H~k56$>b`5 zkz)ZBsF0d|@IUz7t(l*ibdvm0p!>zPKSlxHF3_mi_V=-EH%AO zt%Z+(foN9LZ_VkgwU5&WAWdB@-v9@P zz*vE@*InM-)7jg_CX>@2HM@dakSAh-}0009lNkl3);i_xxh&zU`YW(NM_B_D3B3d(07uYwH%kIooE2pE9_0t8?{g8ocMJ&Yn~AB7-I z+Ae?e?(#S9$Oqf27a_h401ANtPS6r`J@AA;fvyK^5CX^ux!(_vDUoDAxb^4wd^V49 z&B%x_f{x&bU?1lm^c1sEW?}_>3}FG0Awot71m)4iqjB~q{f~ynA;AP^8^;O2qXNgQ zt}{`^QFc&vka!A}5rQKmif3{uPKfou2ROI!sA^kJ;By33^-7QeR3Ql@Hc-wZj1Xxs zGjit!w1gaDej5WWf&nGq zZ`N!m zkc$g}VtuA1;LF`L?*G&h7#1x~!NZPano6TIWNB!lWixgdD@bp#5TUq}&8xyw=XlgB zKYi|bR0NA!&E9*-fkaIzp(M#ne4n3p!Mw^>3FC9L4#RB-uU5}7bCix&OXKt222d@v~Uodcxa!gfjslTV}&Oh7^HfxJdQG= zl;LtF5)ep?Pzu2=1A(Ps@1Ci2bFD(BM7^UjpaH@nFal}FSt1LXAb~U}=O932w^k`9 z!Q(^^`j;e0A6Y8c{jZI{c~S{y%ZFJ zZteQY=9RNdw0vsBiB64t4fN_+N2Z=4sEU3nqE|j&`6JFskRLFn*FkQqzwle|{{sF2 XGLww0Jg8t@00000NkvXXu0mjfu%1_o diff --git a/package/wwan/luci-app-sms-tool/luasrc/controller/modem/sms.lua b/package/wwan/luci-app-sms-tool/luasrc/controller/modem/sms.lua deleted file mode 100644 index f807e9e72..000000000 --- a/package/wwan/luci-app-sms-tool/luasrc/controller/modem/sms.lua +++ /dev/null @@ -1,242 +0,0 @@ - local util = require "luci.util" - local fs = require "nixio.fs" - local sys = require "luci.sys" - local http = require "luci.http" - local dispatcher = require "luci.dispatcher" - local http = require "luci.http" - local sys = require "luci.sys" - local uci = require "luci.model.uci".cursor() - -module("luci.controller.modem.sms", package.seeall) - -function index() - entry({"admin", "modem"}, firstchild(), "Modem", 30).dependent=false - entry({"admin", "modem", "sms"}, alias("admin", "modem", "sms", "readsms"), translate("短信"), 20) - entry({"admin", "modem", "sms", "readsms"},template("modem/readsms"),translate("收到的信息"), 10) - entry({"admin", "modem", "sms", "sendsms"},template("modem/sendsms"),translate("发送消息"), 20) - entry({"admin", "modem", "sms", "ussd"},template("modem/ussd"),translate("USSD 代码"), 30) - entry({"admin", "modem", "sms", "atcommands"},template("modem/atcommands"),translate("AT 命令"), 40) - entry({"admin", "modem", "sms", "smsconfig"},cbi("modem/smsconfig"),translate("配置"), 50) - entry({"admin", "modem", "sms", "delete_one"}, call("delete_sms", smsindex), nil).leaf = true - entry({"admin", "modem", "sms", "delete_all"}, call("delete_all_sms"), nil).leaf = true - entry({"admin", "modem", "sms", "run_ussd"}, call("ussd"), nil).leaf = true - entry({"admin", "modem", "sms", "run_at"}, call("at"), nil).leaf = true - entry({"admin", "modem", "sms", "run_sms"}, call("sms"), nil).leaf = true - entry({"admin", "modem", "sms", "readsim"}, call("slots"), nil).leaf = true - entry({"admin", "modem", "sms", "countsms"}, call("count_sms"), nil).leaf = true - entry({"admin", "modem", "sms", "user_ussd"}, call("userussd"), nil).leaf = true - entry({"admin", "modem", "sms", "user_atc"}, call("useratc"), nil).leaf = true - entry({"admin", "modem", "sms", "user_phonebook"}, call("userphb"), nil).leaf = true -end - - -function delete_sms(smsindex) -local devv = tostring(uci:get("sms_tool", "general", "readport")) -local s = smsindex -for d in s:gmatch("%d+") do - os.execute("sms_tool -d " .. devv .. " delete " .. d .. "") -end -end - -function delete_all_sms() - local devv = tostring(uci:get("sms_tool", "general", "readport")) - os.execute("sms_tool -d " .. devv .. " delete all") -end - -function get_ussd() - local cursor = luci.model.uci.cursor() - if cursor:get("sms_tool", "general", "ussd") == "1" then - return " -R" - else - return "" - end -end - - -function get_pdu() - local cursor = luci.model.uci.cursor() - if cursor:get("sms_tool", "general", "pdu") == "1" then - return " -r" - else - return "" - end -end - - -function ussd() - local devv = tostring(uci:get("sms_tool", "general", "ussdport")) - - local ussd = get_ussd() - local pdu = get_pdu() - - local ussd_code = http.formvalue("code") - if ussd_code then - local odpall = io.popen("sms_tool -d " .. devv .. ussd .. pdu .. " ussd " .. ussd_code .." 2>&1") - local odp = odpall:read("*a") - odpall:close() - http.write(tostring(odp)) - else - http.write_json(http.formvalue()) - end -end - - -function at() - local devv = tostring(uci:get("sms_tool", "general", "atport")) - - local at_code = http.formvalue("code") - if at_code then - local odpall = io.popen("sms_tool -d " .. devv .. " at " ..at_code:gsub("[$]", "\\\$"):gsub("\"", "\\\"").." 2>&1") - local odp = odpall:read("*a") - odpall:close() - http.write(tostring(odp)) - else - http.write_json(http.formvalue()) - end -end - - -function sms() - local devv = tostring(uci:get("sms_tool", "general", "sendport")) - local sms_code = http.formvalue("scode") - - nr = (string.sub(sms_code, 1, 20)) - msgall = string.sub(sms_code, 21) - msg = string.gsub(msgall, "\n", " ") - - if sms_code then - local odpall = io.popen("sms_tool -d " .. devv .. " send " .. nr .." '".. msg .."'") - local odp = odpall:read("*a") - odpall:close() - http.write(tostring(odp)) - else - http.write_json(http.formvalue()) - end - -end - -function slots() - local sim = { } - local devv = tostring(uci:get("sms_tool", "general", "readport")) - local led = tostring(uci:get("sms_tool", "general", "smsled")) - local dsled = tostring(uci:get("sms_tool", "general", "ledtype")) - local ln = tostring(uci:get("sms_tool", "general", "lednotify")) - - local smsmem = tostring(uci:get("sms_tool", "general", "storage")) - - local statusb = luci.util.exec("sms_tool -s" .. smsmem .. " -d ".. devv .. " status") - local usex = string.sub (statusb, 23, 27) - local max = statusb:match('[^: ]+$') - sim["use"] = string.match(usex, '%d+') - local smscount = string.match(usex, '%d+') - if ln == "1" then - luci.sys.call("echo " .. smscount .. " > /etc/config/sms_count") - if dsled == "S" then - luci.util.exec("/etc/init.d/led restart") - end - if dsled == "D" then - luci.sys.call("echo 0 > '/sys/class/leds/" .. led .. "/brightness'") - end - end - sim["all"] = string.match(max, '%d+') - luci.http.prepare_content("application/json") - luci.http.write_json(sim) -end - - -function count_sms() - os.execute("sleep 3") - local cursor = luci.model.uci.cursor() - if cursor:get("sms_tool", "general", "lednotify") == "1" then - local devv = tostring(uci:get("sms_tool", "general", "readport")) - - local smsmem = tostring(uci:get("sms_tool", "general", "storage")) - - local statusb = luci.util.exec("sms_tool -s" .. smsmem .. " -d ".. devv .. " status") - local smsnum = string.sub (statusb, 23, 27) - local smscount = string.match(smsnum, '%d+') - os.execute("echo " .. smscount .. " > /etc/config/sms_count") - end -end - - -function uussd(rv) - local c = nixio.fs.access("/etc/config/ussd.user") and - io.popen("cat /etc/config/ussd.user") - - if c then - for l in c:lines() do - local i = l - if i then - rv[#rv + 1] = { - usd = i - } - end - end - c:close() - end -end - - - -function userussd() - local usd = { } - uussd(usd) - luci.http.prepare_content("application/json") - luci.http.write_json(usd) -end - - -function uat(rv) - local c = nixio.fs.access("/etc/config/atcmds.user") and - io.popen("cat /etc/config/atcmds.user") - - if c then - for l in c:lines() do - local i = l - if i then - rv[#rv + 1] = { - atu = i - } - end - end - c:close() - end -end - - - -function useratc() - local atu = { } - uat(atu) - luci.http.prepare_content("application/json") - luci.http.write_json(atu) -end - - - -function uphb(rv) - local c = nixio.fs.access("/etc/config/phonebook.user") and - io.popen("cat /etc/config/phonebook.user") - - if c then - for l in c:lines() do - local i = l - if i then - rv[#rv + 1] = { - phb = i - } - end - end - c:close() - end -end - - - -function userphb() - local phb = { } - uphb(phb) - luci.http.prepare_content("application/json") - luci.http.write_json(phb) -end diff --git a/package/wwan/luci-app-sms-tool/luasrc/model/cbi/modem/smsconfig.lua b/package/wwan/luci-app-sms-tool/luasrc/model/cbi/modem/smsconfig.lua deleted file mode 100644 index dc756e5c4..000000000 --- a/package/wwan/luci-app-sms-tool/luasrc/model/cbi/modem/smsconfig.lua +++ /dev/null @@ -1,226 +0,0 @@ -local util = require "luci.util" -local fs = require "nixio.fs" -local sys = require "luci.sys" -local http = require "luci.http" -local dispatcher = require "luci.dispatcher" -local http = require "luci.http" -local sys = require "luci.sys" -local uci = require "luci.model.uci".cursor() - -local USSD_FILE_PATH = "/etc/config/ussd.user" -local PHB_FILE_PATH = "/etc/config/phonebook.user" -local SMSC_FILE_PATH = "/etc/config/smscommands.user" -local AT_FILE_PATH = "/etc/config/atcmds.user" - -local led = tostring(uci:get("sms_tool", "general", "smsled")) -local dsled = tostring(uci:get("sms_tool", "general", "ledtype")) -local ledtime = tostring(uci:get("sms_tool", "general", "checktime")) - -local m -local s -local dev1, dev2, dev3, dev4, leds -local try_devices1 = nixio.fs.glob("/dev/tty[A-Z][A-Z]*") -local try_devices2 = nixio.fs.glob("/dev/tty[A-Z][A-Z]*") -local try_devices3 = nixio.fs.glob("/dev/tty[A-Z][A-Z]*") -local try_devices4 = nixio.fs.glob("/dev/tty[A-Z][A-Z]*") -local try_leds = nixio.fs.glob("/sys/class/leds/*") - - -local devv = tostring(uci:get("sms_tool", "general", "readport")) - -local smsmem = tostring(uci:get("sms_tool", "general", "storage")) - -local statusb = luci.util.exec("sms_tool -s".. smsmem .. " -d ".. devv .. " status") - -local smsnum = string.sub (statusb, 23, 27) - -local smscount = string.match(smsnum, '%d+') - -m = Map("sms_tool", translate("配置短信工具"), - translate("sms_tool和gui应用程序的配置面板。")) - -s = m:section(NamedSection, 'general' , "sms_tool" , "" .. translate("")) -s.anonymous = true -s:tab("sms", translate("SMS 设置")) -s:tab("ussd", translate("USSD 代码设置")) -s:tab("at", translate("AT 命令设置")) -s:tab("info", translate("通知设置")) - -this_tab = "sms" - -dev1 = s:taboption(this_tab, Value, "readport", translate("短信读取端口")) -if try_devices1 then -local node -for node in try_devices1 do -dev1:value(node, node) -end -end - -mem = s:taboption(this_tab, ListValue, "storage", translate("信息存储区"), translate("信息存储在一个特定的位置(例如,在SIM卡或调制解调器内存),但根据设备的类型,其他区域也可能是可用的。")) -mem.default = "SM" -mem:value("SM", translate("SIM 卡")) -mem:value("ME", translate("调制解调器内存")) -mem.rmempty = true - -local msm = s:taboption(this_tab, Flag, "mergesms", translate("合并分割的信息"), translate("勾选这个选项会使阅读信息更容易,但会导致显示和接收的信息数量不一致。")) -msm.rmempty = false - -dev2 = s:taboption(this_tab, Value, "sendport", translate("短信发送端口")) -if try_devices2 then -local node -for node in try_devices2 do -dev2:value(node, node) -end -end - -local t = s:taboption(this_tab, Value, "pnumber", translate("前缀号码"), translate("电话号码的前面应该有国家的前缀(波兰是48,没有'+')。如果号码是5个、4个或3个字符,它将被视为 '短',不应该在前面加上国家前缀。")) -t.rmempty = true -t.default = 48 - -local f = s:taboption(this_tab, Flag, "prefix", translate("为电话号码添加前缀"), translate("自动添加电话号码字段的前缀。")) -f.rmempty = false - - -local i = s:taboption(this_tab, Flag, "information", translate("号码和前缀的解释"), translate("在发送短信的标签中,显示前缀的解释和正确的电话号码。")) -i.rmempty = false - -local ta = s:taboption(this_tab, TextValue, "user_phonebook", translate("用户电话簿"), translate("每一行必须有以下格式。'联系人姓名;电话号码'。保存到文件'/etc/config/phonebook.user'。")) -ta.rows = 7 -ta.rmempty = false - -function ta.cfgvalue(self, section) - return fs.readfile(PHB_FILE_PATH) -end - -function ta.write(self, section, value) - value = value:gsub("\r\n", "\n") - fs.writefile(PHB_FILE_PATH, value) -end - -this_taba = "ussd" - -dev3 = s:taboption(this_taba, Value, "ussdport", translate("USSD发送端口")) -if try_devices3 then -local node -for node in try_devices3 do -dev3:value(node, node) -end -end - -local u = s:taboption(this_taba, Flag, "ussd", translate("以纯文本发送USSD代码"), translate("以纯文本发送USSD代码。命令没有被编码到PDU中。")) -u.rmempty = false - -local p = s:taboption(this_taba, Flag, "pdu", translate("接收没有PDU解码的信息"), translate("接收并显示消息,而不将其解码为PDU。")) -p.rmempty = false - -local tb = s:taboption(this_taba, TextValue, "user_ussd", translate("用户USSD代码"), translate("每一行必须有以下格式。'代码名称;代码'。保存到文件'/etc/config/ussd.user'。")) -tb.rows = 7 -tb.rmempty = true - -function tb.cfgvalue(self, section) - return fs.readfile(USSD_FILE_PATH) -end - -function tb.write(self, section, value) - value = value:gsub("\r\n", "\n") - fs.writefile(USSD_FILE_PATH, value) -end - -this_tabc = "at" - -dev4 = s:taboption(this_tabc, Value, "atport", translate("AT命令的发送端口")) -if try_devices4 then -local node -for node in try_devices4 do -dev4:value(node, node) -end -end - -local tat = s:taboption(this_tabc, TextValue, "user_at", translate("用户AT命令"), translate("每一行必须有以下格式。'AT命令名称;AT命令'。保存到文件'/etc/config/atcmds.user'。")) -tat.rows = 20 -tat.rmempty = true - -function tat.cfgvalue(self, section) - return fs.readfile(AT_FILE_PATH) -end - -function tat.write(self, section, value) - value = value:gsub("\r\n", "\n") - fs.writefile(AT_FILE_PATH, value) -end - -this_tabb = "info" - -local uw = s:taboption(this_tabb, Flag, "lednotify", translate("通知新消息"), translate("LED通知有新的信息。在激活这个功能之前,请配置并保存短信阅读端口,检查短信收件箱的时间,并选择通知LED。")) -uw.rmempty = false - -function uw.write(self, section, value) -if devv ~= nil or devv ~= '' then -if ( smscount ~= nil and led ~= nil ) then - if value == '1' then - - luci.sys.call("echo " .. smscount .. " > /etc/config/sms_count") - luci.sys.call("uci set sms_tool.general.lednotify=" .. 1 .. ";/etc/init.d/smsled enable;/etc/init.d/smsled start") - luci.sys.call("/sbin/cronsync.sh") - - elseif value == '0' then - luci.sys.call("uci set sms_tool.general.lednotify=" .. 0 .. ";/etc/init.d/smsled stop;/etc/init.d/smsled disable") - if dsled == 'D' then - luci.sys.call("echo 0 > '/sys/class/leds/" .. led .. "/brightness'") - end - luci.sys.call("/sbin/cronsync.sh") - - end -return Flag.write(self, section ,value) - end -end -end - -local time = s:taboption(this_tabb, Value, "checktime", translate("每(几)分钟检查一次收件箱"), translate("指定你想在多少分钟内检查你的收件箱。")) -time.rmempty = false -time.maxlength = 2 -time.default = 5 - -function time.validate(self, value) - if ( tonumber(value) < 60 and tonumber(value) > 0 ) then - return value - end -end - -sync = s:taboption(this_tabb, ListValue, "prestart", translate("每隔一段时间重新启动收件箱检查程序"), translate("该过程将在选定的时间间隔内重新启动。这将消除检查收件箱的延迟。")) -sync.default = "6" -sync:value("4", translate("4h")) -sync:value("6", translate("6h")) -sync:value("8", translate("8h")) -sync:value("12", translate("12h")) -sync.rmempty = true - - -leds = s:taboption(this_tabb, Value, "smsled", translate("通知LED"), translate("选择通知LED。")) -if try_leds then -local node -local status -for node in try_leds do -local status = node -local all = string.sub (status, 17) -leds:value(all, all) -end -end - -oled = s:taboption(this_tabb, ListValue, "ledtype", translate("该二极管只专门用于这些通知"), translate("如果路由器只有一个LED,或者LED是多任务的,就选'No'。")) -oled.default = "D" -oled:value("S", translate("No")) -oled:value("D", translate("Yes")) -oled.rmempty = true - -local timeon = s:taboption(this_tabb, Value, "ledtimeon", translate("每(几)秒打开LED灯"), translate("指定LED应该亮多长时间。")) -timeon.rmempty = false -timeon.maxlength = 3 -timeon.default = 1 - -local timeoff = s:taboption(this_tabb, Value, "ledtimeoff", translate("每(几)秒关闭LED灯"), translate("指定LED应该关闭多长时间。")) -timeoff.rmempty = false -timeoff.maxlength = 3 -timeoff.default = 5 - -return m diff --git a/package/wwan/luci-app-sms-tool/luasrc/view/modem/atcommands.htm b/package/wwan/luci-app-sms-tool/luasrc/view/modem/atcommands.htm deleted file mode 100644 index 3510d8b87..000000000 --- a/package/wwan/luci-app-sms-tool/luasrc/view/modem/atcommands.htm +++ /dev/null @@ -1,136 +0,0 @@ -<%+header%> - - - -

    <%:AT 命令%>

    -
    -

    -

    <%:向调制解调器发送命令%>

    -
    - -
    -
    <%:用户AT命令%>:
    - -
    - -
    -
    -
    - -
    -
    <%:要发送的命令%>:
    -
    -
    - -
    - -
    -
    <%:回复%>: -

    -

    - -
    -
    -
    - -
    - - - -<%+footer%> - diff --git a/package/wwan/luci-app-sms-tool/luasrc/view/modem/readsms.htm b/package/wwan/luci-app-sms-tool/luasrc/view/modem/readsms.htm deleted file mode 100644 index dc8245e2d..000000000 --- a/package/wwan/luci-app-sms-tool/luasrc/view/modem/readsms.htm +++ /dev/null @@ -1,285 +0,0 @@ -<% - local util = require "luci.util" - local fs = require "nixio.fs" - local sys = require "luci.sys" - local http = require "luci.http" - local dispatcher = require "luci.dispatcher" - local uci = require "luci.model.uci".cursor() - - local devv = tostring(uci:get("sms_tool", "general", "readport")) - local smsmem = tostring(uci:get("sms_tool", "general", "storage")) - local sms = tostring(luci.sys.exec("sms_tool -s" .. smsmem .. " -d " .. devv .. " -f '%Y-%m-%d %H:%M' -j recv 2>/dev/null")) - local smsmer = tostring(uci:get("sms_tool", "general", "mergesms")) - local smscuta = string.sub (sms, 8) - local smscut = smscuta:sub(1, #smscuta - 2) - local statusb = luci.util.exec("sms_tool -s" .. smsmem .. " -d ".. devv .. " status") - local all = statusb:match('[^: ]+$') - local location = "" - local l = string.sub (statusb, 15, 16) - if l == "SM" then - location = translate("SIM card") - end - if l == "ME" then - location = translate("Modem memory") - end --%> - -<%+header%> - - - - - - - -

    <%:短信%>

    -
    <%:通过sms_tool接收信息的Web用户界面。关于短信工具的更多信息,请见%> <%:eko.one.pl 论坛%>
    -

    -

    <%:接收的信息%>

    -
    -
    <%:信息存储在%>:
    <%=location%>
    -
    <%:信息 (收件箱 / 最大值)%>:
    -
    - - - - - - - - - - -
    <%:来自%><%:收到%><%:信息%>
    - -
    -
    - -
    -
    -     - -
    -
    - -<%+footer%> diff --git a/package/wwan/luci-app-sms-tool/luasrc/view/modem/sendsms.htm b/package/wwan/luci-app-sms-tool/luasrc/view/modem/sendsms.htm deleted file mode 100644 index f9747c6a5..000000000 --- a/package/wwan/luci-app-sms-tool/luasrc/view/modem/sendsms.htm +++ /dev/null @@ -1,237 +0,0 @@ -<% - local util = require "luci.util" - local sys = require "luci.sys" - local uci = require "luci.model.uci".cursor() - - local pon = tostring(uci:get("sms_tool", "general", "prefix")) - local pnumber = tostring(uci:get("sms_tool", "general", "pnumber")) - local info = tostring(uci:get("sms_tool", "general", "information")) - --%> - -<%+header%> - - - - - - - - -

    <%:短信%>

    -
    <%:通过sms_tool发送信息的Web用户界面。关于短信工具的更多信息,请见%> <%:eko.one.pl 论坛%>.
    -

    - -

    <%:发送短信%>

    - -
    - -
    -
    <%:用户电话簿%>:
    -
    - - -
    -
    -
    - -
    -
    <%:发送至%>:
    -
    -
    -
    -
    -
    <%:消息正文%>:
    -
    160
    -
    -
    - -
    -
    <%:状态%>:
    - -
    - -
    -
    - -
    -
    -
    - -
    - - - -<%+footer%> diff --git a/package/wwan/luci-app-sms-tool/luasrc/view/modem/ussd.htm b/package/wwan/luci-app-sms-tool/luasrc/view/modem/ussd.htm deleted file mode 100644 index 38be1c3c4..000000000 --- a/package/wwan/luci-app-sms-tool/luasrc/view/modem/ussd.htm +++ /dev/null @@ -1,265 +0,0 @@ -<% - local util = require "luci.util" - local fs = require "nixio.fs" - local sys = require "luci.sys" - local http = require "luci.http" - local dispatcher = require "luci.dispatcher" - local uci = require "luci.model.uci".cursor() - --%> - - -<%+header%> - - - -

    <%:USSD 代码%>

    -
    <%:通过sms_tool处理USSD代码的Web用户界面。关于短信工具的更多信息,请见%> <%:eko.one.pl forum%>.
    -

    -

    <%:发送 USSD 代码%>

    -
    - -
    -
    <%:用户 USSD 代码%>:
    - -
    - -
    -
    -
    - -
    -
    <%:要发送的代码%>:
    -
    - -
    -
    -
    <%:回复%>:
    - -
    -
    - -
    -
    -
    -
    - -
    - - - -<%+footer%> diff --git a/package/wwan/luci-app-sms-tool/po/pl/sms-tool.po b/package/wwan/luci-app-sms-tool/po/pl/sms-tool.po deleted file mode 100644 index 2ef0778b5..000000000 --- a/package/wwan/luci-app-sms-tool/po/pl/sms-tool.po +++ /dev/null @@ -1,288 +0,0 @@ -msgid "" -msgstr "Content-Type: text/plain; charset=UTF-8" - -"Language: pl\n" -"Last-Translator: Rafał Wabik (IceG) - From eko.one.pl forum\n" - -msgid "SMS Messages" -msgstr "Wiadomości SMS" - -msgid "Received Messages" -msgstr "Odebrane wiadomości" - -msgid "Send Messages" -msgstr "Wysyłanie wiadomości" - -msgid "USSD" -msgstr "USSD" - -msgid "From" -msgstr "Nadawca" - -msgid "Received" -msgstr "Odebrano" - -msgid "Message" -msgstr "Wiadomość" - -msgid "Configuration" -msgstr "Ustawienia" - -msgid "Sample codes" -msgstr "Przykładowe kody" - -msgid "Sending USSD codes" -msgstr "Wysyłanie kodów USSD" - -msgid "Please enter phone number" -msgstr "Proszę podać numer telefonu" - -msgid "Please correct phone number" -msgstr "Proszę poprawić numer telefonu" - -msgid "Please enter a message text" -msgstr "Proszę podać treść wiadomości" - -msgid "Please select the message(s) to be deleted" -msgstr "Proszę wybrać wiadomość(-ci) do usunięcia" - -msgid "Reply" -msgstr "Odpowiedź" - -msgid "SMS sent sucessfully" -msgstr "SMS został wysłany" - -msgid "Please enter a USSD code" -msgstr "Proszę podać kod do wysłania" - -msgid "Delete selected message(s)?" -msgstr "Usunąć wybraną(-e) wiadomość(-ci)?" - -msgid "Delete all the messages?" -msgstr "Usunąć wszystkie wiadomości?" - -msgid "Configuration sms-tool" -msgstr "Konfiguracja sms-tool" - -msgid "Configuration panel for sms_tool and gui application." -msgstr "Panel ustawień dla aplikacji sms_tool oraz dla interfejsu użytkownika." - -msgid "Device" -msgstr "Urządzenie" - -msgid "Web UI for handling messages via sms_tool." -msgstr "Interfejs użytkownika dla sms_tool do obsługi wiadomości SMS." - -msgid "Web UI for handling USSD codes via sms_tool." -msgstr "Interfejs użytkownika dla sms_tool do obsługi kodów USSD." - -msgid "SIM card" -msgstr "Karta SIM" - -msgid "Modem memory" -msgstr "Pamięć modemu" - -msgid "Messages store in" -msgstr "Miejsce przechowywania wiadomości" - -msgid "Messages (Inbox / Maximum)" -msgstr "Wiadomości (Odebrane / Maksymalnie)" - -msgid "Delete Selected" -msgstr "Usuń wybraną" - -msgid "Delete message(s)" -msgstr "Usuń wiadomość(-ci)" - -msgid "Delete All" -msgstr "Usuń wszystkie" - -msgid "USSD Codes" -msgstr "Kody USSD" - -msgid "Send to" -msgstr "Wyślij do" - -msgid "Message text" -msgstr "Treść wiadomości" - -msgid "Send Message" -msgstr "Wyślij SMS" - -msgid "Code to send" -msgstr "Kod do wysłania" - -msgid "Send Code" -msgstr "Wyślij kod" - -msgid "SMS Settings" -msgstr "Ustawienia dla wiadomości SMS" - -msgid "USSD Codes Settings" -msgstr "Ustawienia dla kodów USSD" - -msgid "SMS Reading Port" -msgstr "Port do odczytu SMS" - -msgid "SMS Sending Port" -msgstr "Port do wysyłania SMS" - -msgid "USSD Sending Port" -msgstr "Port do wysyłania kodów USSD" - -msgid "Add Prefix to Phone Number" -msgstr "Dodaj prefiks do numeru telefonu" - -msgid "Automatically add prefix to the phone number field." -msgstr "Automatycznie uzupełnij pole numeru telefonu o prefiks." - -msgid "Prefix Number" -msgstr "Numer prefiks" - -msgid "PHONE_NUMBER" -msgstr "48NumerTelefonu" - -msgid "Refresh SMS" -msgstr "Odśwież" - -msgid "Sending USSD Code in plain text" -msgstr "Wysyłaj kod USSD jawnym tekstem" - -msgid "Receive message without PDU decoding" -msgstr "Odbierz wiadomość bez dekodowania jej jako PDU" - -msgid "Send the USSD code in plain text. Command is not being coded to the PDU." -msgstr "Wysyła kod USSD jawnym tekstem. Polecenie nie jest dekodowane na PDU." - -msgid "Receive and display the message without decoding it as a PDU." -msgstr "Odebrana wiadomość wyświetlana jest bez dekodowania jej jako PDU." - -msgid "Explanation of number and prefix" -msgstr "Wyjaśnienie dot. numeru i prefiksu" - -msgid "In the tab for sending SMSes, show an explanation of the prefix and the correct phone number." -msgstr "W zakładce umożliwiającej wysyłanie SMS-ów pokaż wyjaśnienie dotyczące prefiksu i poprawnego numeru telefonu." - -msgid "The phone number should be preceded by the country prefix (for Poland it is 48, without '+'). If the number is 5, 4 or 3 characters, it is treated as 'short' and should not be preceded by a country prefix." -msgstr "Numer telefonu należy poprzedzić prefiksem kraju (dla Polski jest to 48, bez znaku '+'). Jeżeli numer jest 5, 4 lub 3 znakowy to jest on traktowany jako 'krótki' i nie należy go poprzedzać prefiksem kraju." - -msgid "The phone number should be preceded by the country prefix (for Poland it is 48, without +). If the number is 5, 4 or 3 characters, it is treated as.. short and should not be preceded by a country prefix." -msgstr "Numer telefonu należy poprzedzić prefiksem kraju (dla Polski jest to 48, bez znaku +). Jeżeli numer jest 5, 4 lub 3 znakowy to jest on traktowany jako krótki i nie należy go poprzedzać prefiksem kraju." - -msgid "Each line must have the following format: 'Contact name;Phone number'. Save to file '/etc/config/phonebook.user'." -msgstr "Każda linijka powinna mieć następujący format: 'Nazwa kontaktu;Numer telefonu'. Dla wygody kontakty użytkownika zapisywane są w pliku '/etc/config/phonebook.user'." - -msgid "User Phonebook" -msgstr "Kontakty użytkownika" - -msgid "User USSD Codes" -msgstr "Kody USSD użytkownika" - -msgid "Each line must have the following format: 'Code name;Code'. Save to file '/etc/config/ussd.user'." -msgstr "Każda linijka powinna mieć następujący format: 'Etykieta kodu;Kod'. Dla wygody kody użytkownika zapisywane są w pliku '/etc/config/ussd.user'." - -msgid "Notification Settings" -msgstr "Ustawienia powiadomień" - -msgid "The LED informs about a new message. Before activating this function, please config and save the SMS reading port, time to check SMS inbox and select the notification LED." -msgstr "Powiadomienie diodą o nowej wiadomości. Przed uruchomieniem tej funkcji proszę ustawić port odczytu wiadomości, czas sprawdzania skrzynki odbiorczej oraz wybrać diodę powiadomień." - -msgid "Check inbox every minute(s)" -msgstr "Sprawdzaj skrzynkę odbiorczą co minut(-y)" - -msgid "Specify how many minutes you want your inbox to be checked." -msgstr "Podaj co ile minut ma być sprawdzana skrzynka odbiorcza w poszukiwaniu nowych wiadomości." - -msgid "Notification LED" -msgstr "Dioda powiadomień" - -msgid "Select the notification LED." -msgstr "Wybierz diodę powiadomień." - -msgid "Notify new messages" -msgstr "Powiadomienie o nowych wiadomościach" - -msgid "Turn on the LED for seconds(s)" -msgstr "Włącz diodę na sekund(-y)" - -msgid "Turn off the LED for seconds(s)" -msgstr "Wyłącz diodę na sekund(-y)" - -msgid "Specify for how long the LED should be on." -msgstr "Podaj przez jaki czas dioda ma być włączona." - -msgid "Specify for how long the LED should be off." -msgstr "Podaj przez jaki czas dioda ma być wyłączona." - -msgid "Merge split messages" -msgstr "Połącz podzielone wiadomości" - -msgid "Checking this option will make it easier to read the messages, but it will cause a discrepancy in the number of messages shown and received." -msgstr "Podzielone wiadomości zostaną złączone. Zaznaczenie tej opcji ułatwi czytanie SMS-ów, ale spowoduje niezgodność w ilości pokazanych, odebranych wiadomości." - -msgid "Message storage area" -msgstr "Miejsce przechowywania wiadomości" - -msgid "Messages are stored in a specific location (for example, on the SIM card or modem memory), but other areas may also be available depending on the type of device." -msgstr "Wiadomości przechowywane są w określonym miejscu (np. na karcie SIM lub pamięci modemu), ale w zależności od typu urządzenia mogą być dostępne także inne obszary." - -msgid "AT Commands" -msgstr "Polecenia AT" - -msgid "Web UI for handling AT commands via sms_tool." -msgstr "Interfejs użytkownika dla sms_tool do obsługi poleceń AT." - -msgid "Sending commands to modem" -msgstr "Wysyłanie poleceń do modemu" - -msgid "User AT Commands" -msgstr "Polecenia AT użytkownika" - -msgid "Command to send" -msgstr "Polecenie do wysłania" - -msgid "Please enter a AT Command" -msgstr "Proszę podać polecenie AT do wysłania" - -msgid "AT Commands Sending Port" -msgstr "Port do wysyłania poleceń AT" - -msgid "Send Command" -msgstr "Wyślij polecenie" - -msgid "AT Commands Settings" -msgstr "Ustawienia dla poleceń AT" - -msgid "Each line must have the following format: 'AT Command name;AT Command'. Save to file '/etc/config/atcmds.user'." -msgstr "Każda linijka powinna mieć następujący format: 'Etykieta polecenia;polecenie AT'. Dla wygody polecenia użytkownika zapisywane są w pliku '/etc/config/atcmds.user'." - -msgid "Restart the inbox checking process every" -msgstr "Uruchom proces ponownie po" - -msgid "The process will restart at the selected time interval. This will eliminate the delay in checking your inbox." -msgstr "Proces zostanie uruchomiony ponownie po wybranym przez użytkownika czasie. Pozwoli to wyeliminować opóźnienie w sprawdzaniu skrzynki odbiorczej." - -msgid "4h" -msgstr "4 godz." - -msgid "6h" -msgstr "6 godz." - -msgid "8h" -msgstr "8 godz." - -msgid "12h" -msgstr "12 godz." - -msgid "The diode is dedicated only to these notifications" -msgstr "Dioda jest dedykowana tylko tym powiadomieniom" - -msgid "Select 'No' in case the router has only one LED or if the LED is multi-tasking." -msgstr "Wybierz 'Nie' w przypadku, kiedy router ma tylko jedną diodę lub gdy dioda obsługuje wiele zadań." - -msgid "No" -msgstr "Nie" - -msgid "Yes" -msgstr "Tak" - diff --git a/package/wwan/luci-app-sms-tool/po/zh-cn/sms-tool.po b/package/wwan/luci-app-sms-tool/po/zh-cn/sms-tool.po deleted file mode 100644 index 4417c9cbe..000000000 --- a/package/wwan/luci-app-sms-tool/po/zh-cn/sms-tool.po +++ /dev/null @@ -1,246 +0,0 @@ -msgid "Modem" -msgstr "调制解调器" - -msgid "SMS Messages" -msgstr "SMS 信息" - -msgid "Received Messages" -msgstr "接收信息" - -msgid "Send Messages" -msgstr "发送信息" - -msgid "From" -msgstr "发件人" - -msgid "Received" -msgstr "接收时间" - -msgid "Message" -msgstr "信息" - -msgid "Configuration" -msgstr "参数配置" - -msgid "Sample codes" -msgstr "代码样本" - -msgid "Please enter phone number" -msgstr "请输入手机号" - -msgid "Please correct phone number" -msgstr "请更正手机号" - -msgid "Please enter a message text" -msgstr "请输入信息内容" - -msgid "Please select the message(s) to be deleted" -msgstr "请选择要删除的信息" - -msgid "Reply" -msgstr "回复" - -msgid "SMS sent sucessfully" -msgstr "信息发送成功" - -msgid "Delete selected message(s)?" -msgstr "删除选择的信息?" - -msgid "Delete all the messages?" -msgstr "删除所有信息?" - -msgid "Configuration sms-tool" -msgstr "配置 sms-tool" - -msgid "Configuration panel for sms_tool and gui application." -msgstr "sms_tool 和 gui 应用程序的配置面板." - -msgid "Device" -msgstr "设备" - -msgid "Web UI for handling messages via sms_tool." -msgstr "用于通过 sms_tool 处理信息的 Web UI." - -msgid "Web UI for sending messages via sms_tool." -msgstr "用于通过 sms_tool 发送信息的 Web UI." - -msgid "Web UI for receiveling messages via sms_tool." -msgstr "用于通过 sms_tool 接收信息的 Web UI." - -msgid "SIM card" -msgstr "SIM卡" - -msgid "Modem memory" -msgstr "Modem内存" - -msgid "Messages store in" -msgstr "信息存储在" - -msgid "Messages (Inbox / Maximum)" -msgstr "信息(收件箱/最大)" - -msgid "Delete Selected" -msgstr "删除所选" - -msgid "Delete message(s)" -msgstr "删除信息" - -msgid "Delete All" -msgstr "删除所有" - -msgid "Send to" -msgstr "发送到" - -msgid "Message text" -msgstr "信息文本" - -msgid "Send Message" -msgstr "发送信息" - -msgid "Code to send" -msgstr "代码发送" - -msgid "Send Code" -msgstr "发送代码" - -msgid "SMS Settings" -msgstr "SMS 设置" - -msgid "SMS Reading Port" -msgstr "SMS 读取端口" - -msgid "SMS Sending Port" -msgstr "SMS 发送端口" - -msgid "Add Prefix to Phone Number" -msgstr "为手机号码添加前缀" - -msgid "Automatically add prefix to the phone number field." -msgstr "自动为手机号码字段添加前缀." - -msgid "Prefix Number" -msgstr "前缀编号" - -msgid "PHONE_NUMBER" -msgstr "手机号码" - -msgid "Refresh SMS" -msgstr "刷新信息" - -msgid "Explanation of number and prefix" -msgstr "数字和前缀的解释" - -msgid "In the tab for sending SMSes, show an explanation of the prefix and the correct phone number." -msgstr "在发送短信的选项卡中,显示前缀说明和正确的电话号码." - -msgid "The phone number should be preceded by the country prefix (for Poland it is 48, without '+'). If the number is 5, 4 or 3 characters, it is treated as 'short' and should not be preceded by a country prefix." -msgstr "电话号码前面应有国家/地区前缀(中国为 86,不带“+”), 号码是 5、4 或 3 个字符的短号除外." - -msgid "The phone number should be preceded by the country prefix (for Poland it is 48, without +). If the number is 5, 4 or 3 characters, it is treated as.. short and should not be preceded by a country prefix." -msgstr "电话号码前面应有国家/地区前缀(中国为 86,不带“+”), 号码是 5、4 或 3 个字符的短号除外." - -msgid "Each line must have the following format: 'Contact name;Phone number'. Save to file '/etc/config/phonebook.user'." -msgstr "每行必须具有以下格式:“联系人姓名;电话号码”。 保存到文件“/etc/config/phonebook.user”." - -msgid "User Phonebook" -msgstr "电话簿" - -msgid "Notification Settings" -msgstr "通知设置" - -msgid "The LED informs about a new message. Before activating this function, please config and save the SMS reading port, time to check SMS inbox and select the notification LED." -msgstr "LED 新消息通知。 激活此功能前,请配置并保存短信阅读端口,及时查看短信收件箱并选择通知LED." - -msgid "Check inbox every minute(s)" -msgstr "每分钟检查收件箱" - -msgid "Specify how many minutes you want your inbox to be checked." -msgstr "指定要检查收件箱的分钟数." - -msgid "Notification LED" -msgstr "通知LED" - -msgid "Select the notification LED." -msgstr "选择通知LED." - -msgid "Notify new messages" -msgstr "通知新消息" - -msgid "Turn on the LED for seconds(s)" -msgstr "打开LED秒数" - -msgid "Turn off the LED for seconds(s)" -msgstr "关闭LED秒数" - -msgid "Specify for how long the LED should be on." -msgstr "指定 LED 应亮多长时间." - -msgid "Specify for how long the LED should be off." -msgstr "指定 LED 应关闭多长时间." - -msgid "Merge split messages" -msgstr "合并分割的消息" - -msgid "Checking this option will make it easier to read the messages, but it will cause a discrepancy in the number of messages shown and received." -msgstr "选中此选项将使阅读消息更容易,但会导致显示和接收的消息数量出现差异." - -msgid "Message storage area" -msgstr "消息存储区" - -msgid "Messages are stored in a specific location (for example, on the SIM card or modem memory), but other areas may also be available depending on the type of device." -msgstr "消息存储在特定位置(例如,SIM 卡或调制解调器内存中),但其他区域也可能可用,具体取决于设备类型." - -msgid "AT Commands" -msgstr "AT 命令" - -msgid "Web UI for handling AT commands via sms_tool." -msgstr "用于通过 sms_tool 处理 AT 命令的 Web UI." - -msgid "Sending commands to modem" -msgstr "向调制解调器发送命令" - -msgid "User AT Commands" -msgstr "用户 AT 命令" - -msgid "Command to send" -msgstr "命令发送" - -msgid "Please enter a AT Command" -msgstr "请输入 AT 命令" - -msgid "AT Commands Sending Port" -msgstr "AT命令发送端口" - -msgid "Send Command" -msgstr "发送命令" - -msgid "AT Commands Settings" -msgstr "AT命令设置" - -msgid "Each line must have the following format: 'AT Command name;AT Command'. Save to file '/etc/config/atcmds.user'." -msgstr "每行必须具有以下格式:'AT Command name;AT Command'。 保存到文件“/etc/config/atcmds.user”." - -msgid "Restart the inbox checking process every" -msgstr "每次重新启动收件箱检查过程" - -msgid "The process will restart at the selected time interval. This will eliminate the delay in checking your inbox." -msgstr "该过程将在选定的时间间隔重新开始。 这将消除检查收件箱的延迟." - -msgid "4h" -msgstr "4小时." - -msgid "6h" -msgstr "6小时." - -msgid "8h" -msgstr "8小时." - -msgid "12h" -msgstr "12小时." - -msgid "The diode is dedicated only to these notifications" -msgstr "二极管仅用于这些通知" - -msgid "Select 'No' in case the router has only one LED or if the LED is multi-tasking." -msgstr "如果路由器只有一个 LED 或者 LED 是多任务处理,请选择“否”." - diff --git a/package/wwan/luci-app-sms-tool/root/etc/config/atcmds.user b/package/wwan/luci-app-sms-tool/root/etc/config/atcmds.user deleted file mode 100644 index 44bafb90e..000000000 --- a/package/wwan/luci-app-sms-tool/root/etc/config/atcmds.user +++ /dev/null @@ -1,28 +0,0 @@ -------查询------;AT -查看IMEI;AT+CGSN -固件版本信息;AT+GMR -信号强度;AT+CSQ -正在使用的网络信息;AT+QNWINFO -查询限速;AT+C5GQOSRDP=1 -模块温度;AT+QTEMP -查询运营商名称;AT+QSPN -查询小区信息;AT+QENG="servingcell" ------3/4/5G网络配置-----;AT -查询当前网络搜索模式;AT+QNWPREFCFG="mode_pref" -!切换仅3G;AT+QNWPREFCFG="mode_pref",WCDMA -切换仅4G;AT+QNWPREFCFG="mode_pref",LTE -切换仅5G;AT+QNWPREFCFG="mode_pref",NR5G -切换5,4G;AT+QNWPREFCFG="mode_pref",NR5G:LTE -切换AUTO;AT+QNWPREFCFG="mode_pref",AUTO ------锁频段-----;AT -查询支持的所有频段;AT+QNWPREFCFG=? -查询当前配置的5G频段;AT+QNWPREFCFG="nr5g_band" -查询当前配置的4G频段;AT+QNWPREFCFG="lte_band" -!5G锁频段(78);AT+QNWPREFCFG="nr5g_band",78 -5G默认频段;AT+QNWPREFCFG="nr5g_band",1:28:41:77:78:79 -!4G锁频段(1);AT+QNWPREFCFG="lte_band",1 -4G默认频段;AT+QNWPREFCFG="lte_band",1:2:3:5:7:8:20:28:34:38:39:40:41 ------MORE-----;AT -查看产品型号;ATI -挂断现有语音;ATH -!更改IMEI,需重启;AT+EGMR=1,7,"868227050701486" \ No newline at end of file diff --git a/package/wwan/luci-app-sms-tool/root/etc/config/phonebook.user b/package/wwan/luci-app-sms-tool/root/etc/config/phonebook.user deleted file mode 100644 index 74c98ab4d..000000000 --- a/package/wwan/luci-app-sms-tool/root/etc/config/phonebook.user +++ /dev/null @@ -1 +0,0 @@ -other user;8613188888888 diff --git a/package/wwan/luci-app-sms-tool/root/etc/config/sms_tool b/package/wwan/luci-app-sms-tool/root/etc/config/sms_tool deleted file mode 100644 index 7bff8f6d2..000000000 --- a/package/wwan/luci-app-sms-tool/root/etc/config/sms_tool +++ /dev/null @@ -1,14 +0,0 @@ - -config sms_tool 'general' - option pnumber '86' - option prefix '1' - option ledtimeon '1' - option ledtimeoff '5' - option lednotify '0' - option checktime '10' - option mergesms '0' - option information '0' - option pdu '0' - option storage 'SM' - option prestart '6' - option ledtype 'D' diff --git a/package/wwan/luci-app-sms-tool/root/etc/init.d/smsled b/package/wwan/luci-app-sms-tool/root/etc/init.d/smsled deleted file mode 100755 index 2442b145e..000000000 --- a/package/wwan/luci-app-sms-tool/root/etc/init.d/smsled +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/sh /etc/rc.common -# Copyright 2020 Rafał Wabik (IceG) - From eko.one.pl forum -# Licensed to the GNU General Public License v3.0. - -USE_PROCD=1 -START=99 -STOP=01 - -start_service() { - procd_open_instance - procd_set_param command /bin/sh "/sbin/smsled-init.sh" - procd_close_instance -} - -stop_service() { - for KILLPID in `ps | grep 'smsled' | awk ' { print $1;}'`; do - (kill -9 $KILLPID >/dev/null 2>&1 )& - done - sleep 1 - return 0 -} - -restart_service() { - stop_service - start_service -} diff --git a/package/wwan/luci-app-sms-tool/root/etc/uci-defaults/set_sms_ports.sh b/package/wwan/luci-app-sms-tool/root/etc/uci-defaults/set_sms_ports.sh deleted file mode 100755 index fbc77d705..000000000 --- a/package/wwan/luci-app-sms-tool/root/etc/uci-defaults/set_sms_ports.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/sh -# Copyright 2020-2021 Rafał Wabik (IceG) - From eko.one.pl forum -# Licensed to the GNU General Public License v3.0. - -work=false -for port in /dev/ttyUSB* -do - [[ -e $port ]] || continue - gcom -d $port info &> /tmp/testusb - testUSB=`cat /tmp/testusb | grep "Error\|Can't"` - if [ -z "$testUSB" ]; then - work=$port - break - fi -done -rm -rf /tmp/testusb - -if [ $work != false ]; then -uci set sms_tool.@sms_tool[0].readport=$work -uci set sms_tool.@sms_tool[0].sendport=$work -uci set sms_tool.@sms_tool[0].atport=$work -uci commit sms_tool -fi diff --git a/package/wwan/luci-app-sms-tool/root/etc/uci-defaults/start-smsled b/package/wwan/luci-app-sms-tool/root/etc/uci-defaults/start-smsled deleted file mode 100755 index 95ca388b7..000000000 --- a/package/wwan/luci-app-sms-tool/root/etc/uci-defaults/start-smsled +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/sh -# Copyright 2020 Rafał Wabik (IceG) - From eko.one.pl forum -# Licensed to the GNU General Public License v3.0. - -/etc/init.d/smsled disable - -exit 0 diff --git a/package/wwan/luci-app-sms-tool/root/sbin/cronsync.sh b/package/wwan/luci-app-sms-tool/root/sbin/cronsync.sh deleted file mode 100755 index 39f7899c3..000000000 --- a/package/wwan/luci-app-sms-tool/root/sbin/cronsync.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/sh - -[ -e /etc/crontabs/root ] || touch /etc/crontabs/root - -SLED=$(uci -q get sms_tool.general.lednotify) -if [ "x$SLED" != "x1" ]; then - if grep -q "smsled" /etc/crontabs/root; then - grep -v "/init.d/smsled" /etc/crontabs/root > /tmp/new_cron - mv /tmp/new_cron /etc/crontabs/root - /etc/init.d/cron restart - fi - exit 0 -fi - -if ! grep -q "smsled" /etc/crontabs/root; then -PTR=$(uci -q get sms_tool.general.prestart) - echo "1 */$PTR * * * /etc/init.d/smsled enable" >> /etc/crontabs/root - /etc/init.d/cron restart -fi - -exit 0 diff --git a/package/wwan/luci-app-sms-tool/root/sbin/set_sms_ports.sh b/package/wwan/luci-app-sms-tool/root/sbin/set_sms_ports.sh deleted file mode 100755 index e89eb1737..000000000 --- a/package/wwan/luci-app-sms-tool/root/sbin/set_sms_ports.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/sh -# Copyright 2020-2021 Rafał Wabik (IceG) - From eko.one.pl forum -# Licensed to the GNU General Public License v3.0. - -work=false -for port in /dev/ttyUSB* -do - [[ -e $port ]] || continue - gcom -d $port info &> /tmp/testusb - testUSB=`cat /tmp/testusb | grep "Error\|Can't"` - if [ -z "$testUSB" ]; then - work=$port - break - fi -done -rm -rf /tmp/testusb - -if [ $work != false ]; then -uci set sms_tool.@sms_tool[0].readport=$work -uci set sms_tool.@sms_tool[0].sendport=$work -uci set sms_tool.@sms_tool[0].ussdport=$work -uci set sms_tool.@sms_tool[0].atport=$work -uci commit sms_tool -fi diff --git a/package/wwan/luci-app-sms-tool/root/sbin/smsled-init.sh b/package/wwan/luci-app-sms-tool/root/sbin/smsled-init.sh deleted file mode 100755 index fa7d86304..000000000 --- a/package/wwan/luci-app-sms-tool/root/sbin/smsled-init.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/sh -# Copyright 2020 Rafał Wabik (IceG) - From eko.one.pl forum -# Licensed to the GNU General Public License v3.0. - -sleep 10 -CT=$(uci -q get sms_tool.general.checktime) -TX=$(echo $CT | tr -dc '0-9') -TM=$(($TX * 60)) - -while [ 1 ]; do - LED=$(uci -q get sms_tool.general.lednotify) - if [ $LED == "1" ]; then - sleep $TM - (/sbin/smsled.sh >/dev/null 2>&1 )& - continue - fi - sleep 1 -done - -exit 0 - diff --git a/package/wwan/luci-app-sms-tool/root/sbin/smsled.sh b/package/wwan/luci-app-sms-tool/root/sbin/smsled.sh deleted file mode 100755 index fffd8566c..000000000 --- a/package/wwan/luci-app-sms-tool/root/sbin/smsled.sh +++ /dev/null @@ -1,39 +0,0 @@ -#!/bin/sh -# Copyright 2020-2021 Rafał Wabik (IceG) - From eko.one.pl forum -# Licensed to the GNU General Public License v3.0. - - DEV=$(uci -q get sms_tool.general.readport) - LEDX=$(uci -q get sms_tool.general.smsled) - MEM=$(uci -q get sms_tool.general.storage) - STX=$(sms_tool -s $MEM -d $DEV status | cut -c23-27) - SMS=$(echo $STX | tr -dc '0-9') - SMSC=$(cat /etc/config/sms_count) - LEDT="/sys/class/leds/$LEDX/trigger" - LEDON="/sys/class/leds/$LEDX/delay_on" - LEDOFF="/sys/class/leds/$LEDX/delay_off" - LED="/sys/class/leds/$LEDX/brightness" - - LON=$(uci -q get sms_tool.general.ledtimeon) - TXON=$(echo $LON | tr -dc '0-9') - TMON=$(($TXON * 1000)) - - LOFF=$(uci -q get sms_tool.general.ledtimeoff) - TXOFF=$(echo $LOFF | tr -dc '0-9') - TMOFF=$(($TXOFF * 1000)) - -if [ $SMS == $SMSC ]; then - - exit 0 -fi - -if [ $SMS > $SMSC ]; then - -echo timer > $LEDT -echo $TMOFF > $LEDOFF -echo $TMON > $LEDON -exit 0 - -fi - - -exit 0 diff --git a/package/wwan/luci-app-sms-tool/root/usr/share/rpcd/acl.d/luci-app-sms-tool.json b/package/wwan/luci-app-sms-tool/root/usr/share/rpcd/acl.d/luci-app-sms-tool.json deleted file mode 100644 index 3f4e02f78..000000000 --- a/package/wwan/luci-app-sms-tool/root/usr/share/rpcd/acl.d/luci-app-sms-tool.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "luci-app-sms-tool": { - "description": "Grant UCI and file access for luci-app-sms-tool", - "read": { - "file": { - "/usr/bin/sms_tool *": [ "exec" ], - }, - "uci": [ "sms_tool" ] - }, - "write": { - "file": { - "/usr/bin/sms_tool *": [ "exec" ], - - }, - "uci": [ "sms_tool" ] - } - } -} - - - - - - diff --git a/target/linux/mediatek/Makefile b/target/linux/mediatek/Makefile index b60b94de6..f66708125 100644 --- a/target/linux/mediatek/Makefile +++ b/target/linux/mediatek/Makefile @@ -9,11 +9,9 @@ SUBTARGETS:=mt7622 mt7623 mt7629 filogic FEATURES:=dt-overlay emmc fpu gpio nand pci pcie rootfs-part separate_ramdisk squashfs usb KERNEL_PATCHVER:=6.6 -KERNEL_TESTING_PATCHVER:=6.1 include $(INCLUDE_DIR)/target.mk DEFAULT_PACKAGES += \ - kmod-leds-gpio kmod-gpio-button-hotplug \ - autocore-arm htop wpad-openssl uboot-envtools + kmod-leds-gpio kmod-gpio-button-hotplug $(eval $(call BuildTarget)) diff --git a/target/linux/mediatek/base-files/lib/preinit/05_set_preinit_iface b/target/linux/mediatek/base-files/lib/preinit/05_set_preinit_iface index 3ac856d1c..6dfa52c29 100644 --- a/target/linux/mediatek/base-files/lib/preinit/05_set_preinit_iface +++ b/target/linux/mediatek/base-files/lib/preinit/05_set_preinit_iface @@ -1,11 +1,33 @@ set_preinit_iface() { - ip link set eth0 up - case $(board_name) in - ubnt,unifi-6-lr) + cudy,m3000-v1|\ + cudy,tr3000-v1|\ + glinet,gl-mt3000) + ip link set eth1 up + ifname=eth1 + ;; + cudy,re3000-v1|\ + ubnt,unifi-6-lr|\ + zyxel,nwa50ax-pro) + ip link set eth0 up ifname=eth0 ;; + smartrg,sdg-8622|\ + smartrg,sdg-8632) + ip link set lan up + ifname=lan + ;; + xiaomi,mi-router-ax3000t|\ + xiaomi,mi-router-ax3000t-ubootmod|\ + xiaomi,mi-router-wr30u-stock|\ + xiaomi,mi-router-wr30u-ubootmod|\ + xiaomi,redmi-router-ax6000-stock|\ + xiaomi,redmi-router-ax6000-ubootmod) + ip link set eth0 up + ifname=lan4 + ;; *) + ip link set eth0 up ifname=lan1 ;; esac diff --git a/target/linux/mediatek/dts/mt7622-buffalo-wsr-2533dhp2.dts b/target/linux/mediatek/dts/mt7622-buffalo-wsr-2533dhp2.dts index 6d77be532..b8fac373a 100644 --- a/target/linux/mediatek/dts/mt7622-buffalo-wsr-2533dhp2.dts +++ b/target/linux/mediatek/dts/mt7622-buffalo-wsr-2533dhp2.dts @@ -1,108 +1,20 @@ // SPDX-License-Identifier: GPL-2.0-or-later OR MIT /dts-v1/; -#include -#include -#include "mt7622.dtsi" -#include "mt6380.dtsi" +#include "mt7622-buffalo-wsr.dtsi" / { model = "Buffalo WSR-2533DHP2"; compatible = "buffalo,wsr-2533dhp2", "mediatek,mt7622"; aliases { - serial0 = &uart0; - led-boot = &power_green; - led-failsafe = &power_amber; - led-running = &power_green; - led-upgrade = &power_green; - }; - - chosen { - bootargs = "earlycon=uart8250,mmio32,0x11002000 console=ttyS0,115200n8 swiotlb=512"; + label-mac-device = &gmac0; }; memory { reg = <0 0x40000000 0 0x0F000000>; }; - leds { - compatible = "gpio-leds"; - - wireless_amber { - label = "amber:wireless"; - gpios = <&pio 2 GPIO_ACTIVE_HIGH>; - }; - - power_amber: power_amber { - label = "amber:power"; - gpios = <&pio 3 GPIO_ACTIVE_LOW>; - }; - - power_green: power_green { - label = "green:power"; - gpios = <&pio 4 GPIO_ACTIVE_LOW>; - default-state = "on"; - }; - - wireless_green { - label = "green:wireless"; - gpios = <&pio 15 GPIO_ACTIVE_HIGH>; - }; - - internet { - label = "green:internet"; - gpios = <&pio 19 GPIO_ACTIVE_HIGH>; - }; - - router { - label = "green:router"; - gpios = <&pio 20 GPIO_ACTIVE_HIGH>; - }; - }; - - keys { - compatible = "gpio-keys"; - poll-interval = <100>; - - reset { - label = "reset"; - gpios = <&pio 0 GPIO_ACTIVE_LOW>; - linux,code = ; - }; - - /* GPIO 1 and 16 are a tri-state switch button with - * ROUTER / AP / WB. - */ - router { - label = "router"; - gpios = <&pio 1 GPIO_ACTIVE_LOW>; - linux,code = ; - linux,input-type = ; - }; - - bridge { - label = "wb"; - gpios = <&pio 16 GPIO_ACTIVE_LOW>; - linux,code = ; - linux,input-type = ; - }; - - /* GPIO 18 is a switch button with AUTO / MANUAL. */ - manual { - label = "manual"; - gpios = <&pio 18 GPIO_ACTIVE_LOW>; - linux,code = ; - linux,input-type = ; - }; - - wps { - label = "wps"; - gpios = <&pio 102 GPIO_ACTIVE_LOW>; - linux,code = ; - }; - }; - rtkgsw: rtkgsw@0 { compatible = "mediatek,rtk-gsw"; mediatek,ethsys = <ðsys>; @@ -111,41 +23,7 @@ }; }; -&cpu0 { - proc-supply = <&mt6380_vcpu_reg>; - sram-supply = <&mt6380_vm_reg>; -}; - -&cpu1 { - proc-supply = <&mt6380_vcpu_reg>; - sram-supply = <&mt6380_vm_reg>; -}; - -&pcie0 { - pinctrl-names = "default"; - pinctrl-0 = <&pcie0_pins>; - status = "okay"; -}; - -&slot0 { - status = "okay"; - - wifi@0,0 { - compatible = "mediatek,mt76"; - reg = <0x0000 0 0 0 0>; - mediatek,mtd-eeprom = <&factory 0x5000>; - ieee80211-freq-limit = <5000000 6000000>; - }; -}; - &pio { - eth_pins: eth-pins { - mux { - function = "eth"; - groups = "mdc_mdio", "rgmii_via_gmac2"; - }; - }; - /* Parallel nand is shared pin with eMMC */ parallel_nand_pins: parallel-nand-pins { mux { @@ -164,75 +42,11 @@ bias-pull-up; }; }; - - pcie0_pins: pcie0-pins { - mux { - function = "pcie"; - groups = "pcie0_pad_perst", - "pcie0_1_waken", - "pcie0_1_clkreq"; - }; - }; - - pmic_bus_pins: pmic-bus-pins { - mux { - function = "pmic"; - groups = "pmic_bus"; - }; - }; - - pwm7_pins: pwm1-2-pins { - mux { - function = "pwm"; - groups = "pwm_ch7_2"; - }; - }; - - uart0_pins: uart0-pins { - mux { - function = "uart"; - groups = "uart0_0_tx_rx" ; - }; - }; - - watchdog_pins: watchdog-pins { - mux { - function = "watchdog"; - groups = "watchdog"; - }; - }; }; -&bch { - status = "okay"; -}; - -ð { - pinctrl-names = "default"; - pinctrl-0 = <ð_pins>; - status = "okay"; - - gmac0: mac@0 { - compatible = "mediatek,eth-mac"; - reg = <0>; - - phy-connection-type = "2500base-x"; - - nvmem-cells = <&macaddr_factory_4>; - nvmem-cell-names = "mac-address"; - mac-address-increment = <(-1)>; - - fixed-link { - speed = <2500>; - full-duplex; - pause; - }; - }; - - mdio: mdio-bus { - #address-cells = <1>; - #size-cells = <0>; - }; +&gmac0 { + nvmem-cells = <&macaddr_factory_4 (-1)>; + nvmem-cell-names = "mac-address"; }; &nandc { @@ -276,6 +90,18 @@ label = "factory"; reg = <0x1c0000 0x40000>; read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + macaddr_factory_4: macaddr@4 { + compatible = "mac-base"; + reg = <0x4 0x6>; + #nvmem-cell-cells = <1>; + }; + }; }; partition@200000 { @@ -304,47 +130,3 @@ }; }; }; - -&pwm { - pinctrl-names = "default"; - pinctrl-0 = <&pwm7_pins>; - status = "okay"; -}; - -&pwrap { - pinctrl-names = "default"; - pinctrl-0 = <&pmic_bus_pins>; - status = "okay"; -}; - -&uart0 { - pinctrl-names = "default"; - pinctrl-0 = <&uart0_pins>; - status = "okay"; -}; - -&watchdog { - pinctrl-names = "default"; - pinctrl-0 = <&watchdog_pins>; - status = "okay"; -}; - -&wmac { - status = "okay"; - - mediatek,mtd-eeprom = <&factory 0x0>; -}; - -&rtc { - status = "disabled"; -}; - -&factory { - compatible = "nvmem-cells"; - #address-cells = <1>; - #size-cells = <1>; - - macaddr_factory_4: macaddr@4 { - reg = <0x4 0x6>; - }; -}; diff --git a/target/linux/mediatek/dts/mt7622-buffalo-wsr-3200ax4s.dts b/target/linux/mediatek/dts/mt7622-buffalo-wsr-3200ax4s.dts new file mode 100644 index 000000000..82cc970fd --- /dev/null +++ b/target/linux/mediatek/dts/mt7622-buffalo-wsr-3200ax4s.dts @@ -0,0 +1,175 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT +/dts-v1/; + +#include "mt7622-buffalo-wsr.dtsi" + +/ { + model = "Buffalo WSR-3200AX4S"; + compatible = "buffalo,wsr-3200ax4s", "mediatek,mt7622"; + + memory { + reg = <0 0x40000000 0 0x1f000000>; + }; +}; + +&pio { + /* Serial NAND is shared pin with SPI-NOR */ + serial_nand_pins: serial-nand-pins { + mux { + function = "flash"; + groups = "snfi"; + }; + + conf-cmd-dat { + pins = "SPI_WP", "SPI_HOLD", "SPI_MOSI", + "SPI_MISO", "SPI_CS"; + input-enable; + drive-strength = <16>; + bias-pull-up; + }; + + conf-clk { + pins = "SPI_CLK"; + drive-strength = <16>; + bias-pull-down; + }; + }; +}; + +&mdio { + switch@1f { + compatible = "mediatek,mt7531"; + reg = <31>; + reset-gpios = <&pio 54 GPIO_ACTIVE_HIGH>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + label = "lan4"; + }; + + port@1 { + reg = <1>; + label = "lan3"; + }; + + port@2 { + reg = <2>; + label = "lan2"; + }; + + port@3 { + reg = <3>; + label = "lan1"; + }; + + port@4 { + reg = <4>; + label = "wan"; + }; + + port@6 { + reg = <6>; + label = "cpu"; + ethernet = <&gmac0>; + phy-connection-type = "2500base-x"; + + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; + }; + }; + }; +}; + +&snfi { + pinctrl-names = "default"; + pinctrl-0 = <&serial_nand_pins>; + status = "okay"; + + flash@0 { + compatible = "spi-nand"; + reg = <0>; + spi-max-frequency = <104000000>; + nand-ecc-engine = <&snfi>; + mediatek,bmt-v2; + mediatek,bmt-table-size = <0x1000>; + /* + * - Preloader - (kernel (6MiB, in firmware)) + * - Kernel2 - WTB + */ + mediatek,bmt-remap-range = <0x0 0x8c0000>, + <0x1ac0000 0x5200000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "Preloader"; + reg = <0x0 0x80000>; + read-only; + }; + + partition@80000 { + label = "ATF"; + reg = <0x80000 0x40000>; + read-only; + }; + + partition@c0000 { + label = "u-boot"; + reg = <0xc0000 0x80000>; + read-only; + }; + + partition@140000 { + label = "u-boot-env"; + reg = <0x140000 0x80000>; + read-only; + }; + + factory: partition@1c0000 { + label = "factory"; + reg = <0x1c0000 0x100000>; + read-only; + }; + + partition@2c0000 { + compatible = "brcm,trx"; + brcm,trx-magic = <0x33504844>; + label = "firmware"; + reg = <0x2c0000 0x1800000>; + }; + + partition@1ac0000 { + label = "Kernel2"; + reg = <0x1ac0000 0x1800000>; + }; + + partition@32c0000 { + label = "glbcfg"; + reg = <0x32c0000 0x200000>; + read-only; + }; + + partition@34c0000 { + label = "board_data"; + reg = <0x34c0000 0x200000>; + read-only; + }; + + partition@36c0000 { + label = "WTB"; + reg = <0x36c0000 0x3600000>; + read-only; + }; + }; + }; +}; diff --git a/target/linux/mediatek/dts/mt7622-buffalo-wsr.dtsi b/target/linux/mediatek/dts/mt7622-buffalo-wsr.dtsi new file mode 100644 index 000000000..2f0540f41 --- /dev/null +++ b/target/linux/mediatek/dts/mt7622-buffalo-wsr.dtsi @@ -0,0 +1,230 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT +/dts-v1/; + +#include +#include +#include + +#include "mt7622.dtsi" +#include "mt6380.dtsi" + +/ { + aliases { + serial0 = &uart0; + led-boot = &power_green; + led-failsafe = &power_amber; + led-running = &power_green; + led-upgrade = &power_green; + }; + + chosen { + bootargs = "earlycon=uart8250,mmio32,0x11002000 console=ttyS0,115200n8 swiotlb=512"; + }; + + leds { + compatible = "gpio-leds"; + + led-0 { + gpios = <&pio 2 GPIO_ACTIVE_HIGH>; + color = ; + function = LED_FUNCTION_WLAN; + }; + + power_amber: led-1 { + gpios = <&pio 3 GPIO_ACTIVE_LOW>; + color = ; + function = LED_FUNCTION_POWER; + }; + + power_green: led-2 { + gpios = <&pio 4 GPIO_ACTIVE_LOW>; + color = ; + function = LED_FUNCTION_POWER; + }; + + led-3 { + gpios = <&pio 15 GPIO_ACTIVE_HIGH>; + color = ; + function = LED_FUNCTION_WLAN; + }; + + led-4 { + gpios = <&pio 19 GPIO_ACTIVE_HIGH>; + color = ; + function = LED_FUNCTION_WAN; + }; + + led-5 { + gpios = <&pio 20 GPIO_ACTIVE_HIGH>; + color = ; + function = LED_FUNCTION_INDICATOR; + }; + }; + + keys { + compatible = "gpio-keys"; + + key-reset { + label = "reset"; + gpios = <&pio 0 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + + /* GPIO 1 and 16 are a tri-state switch button with + * ROUTER / AP / WB. + */ + key-router { + label = "router"; + gpios = <&pio 1 GPIO_ACTIVE_LOW>; + linux,code = ; + linux,input-type = ; + }; + + key-bridge { + label = "wb"; + gpios = <&pio 16 GPIO_ACTIVE_LOW>; + linux,code = ; + linux,input-type = ; + }; + + /* GPIO 18 is a switch button with AUTO / MANUAL. */ + key-manual { + label = "manual"; + gpios = <&pio 18 GPIO_ACTIVE_LOW>; + linux,code = ; + linux,input-type = ; + }; + + key-wps { + label = "wps"; + gpios = <&pio 102 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; +}; + +&cpu0 { + proc-supply = <&mt6380_vcpu_reg>; + sram-supply = <&mt6380_vm_reg>; +}; + +&cpu1 { + proc-supply = <&mt6380_vcpu_reg>; + sram-supply = <&mt6380_vm_reg>; +}; + +&pcie0 { + pinctrl-names = "default"; + pinctrl-0 = <&pcie0_pins>; + status = "okay"; +}; + +&slot0 { + status = "okay"; + + wifi@0,0 { + compatible = "mediatek,mt76"; + reg = <0x0000 0 0 0 0>; + mediatek,mtd-eeprom = <&factory 0x5000>; + ieee80211-freq-limit = <5000000 6000000>; + }; +}; + +&pio { + eth_pins: eth-pins { + mux { + function = "eth"; + groups = "mdc_mdio", "rgmii_via_gmac2"; + }; + }; + + pcie0_pins: pcie0-pins { + mux { + function = "pcie"; + groups = "pcie0_pad_perst", + "pcie0_1_waken", + "pcie0_1_clkreq"; + }; + }; + + pmic_bus_pins: pmic-bus-pins { + mux { + function = "pmic"; + groups = "pmic_bus"; + }; + }; + + uart0_pins: uart0-pins { + mux { + function = "uart"; + groups = "uart0_0_tx_rx" ; + }; + }; + + watchdog_pins: watchdog-pins { + mux { + function = "watchdog"; + groups = "watchdog"; + }; + }; +}; + +ð { + pinctrl-names = "default"; + pinctrl-0 = <ð_pins>; + status = "okay"; + + gmac0: mac@0 { + compatible = "mediatek,eth-mac"; + reg = <0>; + + phy-connection-type = "2500base-x"; + + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; + }; + + mdio: mdio-bus { + #address-cells = <1>; + #size-cells = <0>; + }; +}; + +&bch { + status = "okay"; +}; + +&pwm { + status = "okay"; +}; + +&pwrap { + pinctrl-names = "default"; + pinctrl-0 = <&pmic_bus_pins>; + status = "okay"; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins>; + status = "okay"; +}; + +&watchdog { + pinctrl-names = "default"; + pinctrl-0 = <&watchdog_pins>; + status = "okay"; +}; + +&wmac { + status = "okay"; + + mediatek,mtd-eeprom = <&factory 0x0>; +}; + +&rtc { + status = "disabled"; +}; diff --git a/target/linux/mediatek/dts/mt7622-dlink-eagle-pro-ai-ax3200-a1.dtsi b/target/linux/mediatek/dts/mt7622-dlink-eagle-pro-ai-ax3200-a1.dtsi new file mode 100644 index 000000000..0560bbd33 --- /dev/null +++ b/target/linux/mediatek/dts/mt7622-dlink-eagle-pro-ai-ax3200-a1.dtsi @@ -0,0 +1,365 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +/dts-v1/; +#include "mt7622.dtsi" +#include "mt6380.dtsi" +#include +#include + +/ { + aliases { + serial0 = &uart0; + label-mac-device = &gmac0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + bootargs = "earlycon=uart8250,mmio32,0x11002000 console=ttyS0,115200n8 swiotlb=512"; + }; + + cpus { + cpu@0 { + proc-supply = <&mt6380_vcpu_reg>; + sram-supply = <&mt6380_vm_reg>; + }; + + cpu@1 { + proc-supply = <&mt6380_vcpu_reg>; + sram-supply = <&mt6380_vm_reg>; + }; + }; + + gpio-keys { + compatible = "gpio-keys"; + + button-reset { + gpios = <&pio 0 GPIO_ACTIVE_LOW>; + label = "reset"; + linux,code = ; + }; + + button-wps { + gpios = <&pio 102 GPIO_ACTIVE_LOW>; + label = "wps"; + linux,code = ; + }; + }; + + memory { + reg = <0 0x40000000 0 0x40000000>; + }; +}; + +&bch { + status = "okay"; +}; + +ð { + pinctrl-names = "default"; + pinctrl-0 = <ð_pins>; + status = "okay"; + + gmac0: mac@0 { + compatible = "mediatek,eth-mac"; + phy-mode = "2500base-x"; + reg = <0>; + nvmem-cells = <&macaddr_odm 1>; + nvmem-cell-names = "mac-address"; + fixed-link { + full-duplex; + pause; + speed = <2500>; + }; + }; + + mdio-bus { + #address-cells = <1>; + #size-cells = <0>; + + switch: switch@1f { + compatible = "mediatek,mt7531"; + reg = <31>; + interrupt-controller; + #interrupt-cells = <1>; + interrupt-parent = <&pio>; + interrupts = <53 IRQ_TYPE_LEVEL_HIGH>; + reset-gpios = <&pio 54 0>; + + ports { + wan: port@4 { + reg = <4>; + label = "wan"; + nvmem-cells = <&macaddr_odm 0>; + nvmem-cell-names = "mac-address"; + }; + + port@6 { + reg = <6>; + ethernet = <&gmac0>; + phy-mode = "2500base-x"; + + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; + }; + }; + }; + }; +}; + +&pcie0 { + pinctrl-names = "default"; + pinctrl-0 = <&pcie0_pins>; + status = "okay"; +}; + +&pcie1 { + pinctrl-names = "default"; + pinctrl-0 = <&pcie1_pins>; + status = "okay"; +}; + +&pio { + epa_elna_pins: epa-elna-pins { + mux { + function = "antsel"; + groups = "antsel0", "antsel1", "antsel2", "antsel3", + "antsel4", "antsel5", "antsel6", "antsel7", + "antsel8", "antsel9", "antsel12", "antsel13", + "antsel14", "antsel15", "antsel16", "antsel17"; + }; + }; + + eth_pins: eth-pins { + mux { + function = "eth"; + groups = "mdc_mdio", "rgmii_via_gmac2"; + }; + }; + + pcie0_pins: pcie0-pins { + mux { + function = "pcie"; + groups = "pcie0_pad_perst", + "pcie0_1_waken", + "pcie0_1_clkreq"; + }; + }; + + pcie1_pins: pcie1-pins { + mux { + function = "pcie"; + groups = "pcie1_pad_perst", + "pcie1_0_waken", + "pcie1_0_clkreq"; + }; + }; + + pmic_bus_pins: pmic-bus-pins { + mux { + function = "pmic"; + groups = "pmic_bus"; + }; + }; + + /* Serial NAND is shared pin with SPI-NOR */ + serial_nand_pins: serial-nand-pins { + mux { + function = "flash"; + groups = "snfi"; + }; + }; + + uart0_pins: uart0-pins { + mux { + function = "uart"; + groups = "uart0_0_tx_rx"; + }; + }; + + watchdog_pins: watchdog-pins { + mux { + function = "watchdog"; + groups = "watchdog"; + }; + }; +}; + +&pwrap { + pinctrl-names = "default"; + pinctrl-0 = <&pmic_bus_pins>; + status = "okay"; +}; + +&rtc { + status = "disabled"; +}; + +&sata { + status = "disabled"; +}; + +&sata_phy { + status = "disabled"; +}; + +&slot0 { + wmac1: mt7915@0,0 { + reg = <0x0000 0 0 0 0>; + ieee80211-freq-limit = <5000000 6000000>; + mediatek,mtd-eeprom = <&factory 0x05000>; + nvmem-cells = <&macaddr_odm 3>; + nvmem-cell-names = "mac-address"; + }; +}; + +&snfi { + pinctrl-names = "default"; + pinctrl-0 = <&serial_nand_pins>; + status = "okay"; + + snand: flash@0 { + compatible = "spi-nand"; + mediatek,bmt-table-size = <0x1000>; + mediatek,bmt-v2; + nand-ecc-engine = <&snfi>; + reg = <0>; + spi-rx-bus-width = <4>; + spi-tx-bus-width = <4>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "Preloader"; + reg = <0x00000000 0x00080000>; + read-only; + }; + + partition@80000 { + label = "ATF"; + reg = <0x00080000 0x00040000>; + read-only; + }; + + partition@C0000 { + label = "Bootloader"; + reg = <0x000C0000 0x00080000>; + read-only; + }; + + partition@140000 { + label = "BootConfig"; + reg = <0x00140000 0x00040000>; + }; + + partition@180000 { + label = "Odm"; + reg = <0x00180000 0x00040000>; + read-only; + odm_partition: nvmem-layout { + compatible = "fixed-layout"; + }; + }; + + config1: partition@1C0000 { + compatible = "nvmem-cells"; + label = "Config1"; + reg = <0x001C0000 0x00080000>; + read-only; + }; + + partition@240000 { + label = "Config2"; + reg = <0x00240000 0x00080000>; + read-only; + }; + + partition@2C0000 { + label = "Kernel1"; + reg = <0x002C0000 0x02D00000>; + + compatible = "denx,fit"; + openwrt,cmdline-match = "boot_part=Kernel1"; + partition@0 { + label = "kernel"; + reg = <0x00000000 0x00800000>; + }; + + partition@800000 { + label = "ubi"; + reg = <0x00800000 0x02500000>; + }; + }; + + partition@2FC0000 { + label = "Kernel2"; + reg = <0x02FC0000 0x02D00000>; + + compatible = "denx,fit"; + openwrt,cmdline-match = "boot_part=Kernel2"; + partition@0 { + label = "kernel"; + reg = <0x00000000 0x00800000>; + }; + + partition@800000 { + label = "ubi"; + reg = <0x00800000 0x02500000>; + }; + }; + + factory: partition@5CC0000 { + label = "Factory"; + reg = <0x05CC0000 0x00100000>; + read-only; + }; + + partition@5DC0000 { + label = "Mydlink"; + reg = <0x05DC0000 0x00200000>; + read-only; + }; + + partition@5FC0000 { + label = "Storage"; + reg = <0x05FC0000 0x00300000>; + read-only; + }; + }; + }; +}; + +&ssusb { + status = "disabled"; +}; + +&u3phy { + status = "disabled"; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins>; + status = "okay"; +}; + +&watchdog { + pinctrl-names = "default"; + pinctrl-0 = <&watchdog_pins>; + status = "okay"; +}; + +&wmac { + pinctrl-names = "default"; + pinctrl-0 = <&epa_elna_pins>; + mediatek,mtd-eeprom = <&factory 0x0000>; + nvmem-cells = <&macaddr_odm 2>; + nvmem-cell-names = "mac-address"; + status = "okay"; +}; + diff --git a/target/linux/mediatek/dts/mt7622-dlink-eagle-pro-ai-m32-a1.dts b/target/linux/mediatek/dts/mt7622-dlink-eagle-pro-ai-m32-a1.dts new file mode 100644 index 000000000..2b40c5e7d --- /dev/null +++ b/target/linux/mediatek/dts/mt7622-dlink-eagle-pro-ai-m32-a1.dts @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +/dts-v1/; +#include "mt7622-dlink-eagle-pro-ai-ax3200-a1.dtsi" +#include + +/ { + model = "D-Link EAGLE PRO AI M32 A1"; + compatible = "dlink,eagle-pro-ai-m32-a1", "mediatek,mt7622"; + + aliases { + led-boot = &led_status_orange; + led-failsafe = &led_status_red; + led-running = &led_status_white; + led-upgrade = &led_status_red; + }; + + leds { + compatible = "gpio-leds"; + + led_status_white: led-status-white { + color = ; + function = LED_FUNCTION_STATUS; + gpios = <&pio 85 GPIO_ACTIVE_LOW>; + }; + + led_status_orange: led-status-orange { + color = ; + function = LED_FUNCTION_STATUS; + gpios = <&pio 20 GPIO_ACTIVE_LOW>; + default-state = "on"; + }; + + led_status_red: led-status-red { + color = ; + function = LED_FUNCTION_STATUS; + gpios = <&pio 17 GPIO_ACTIVE_LOW>; + }; + }; +}; + +&switch { + ports { + port@2 { + reg = <2>; + label = "lan2"; + }; + + port@3 { + reg = <3>; + label = "lan1"; + }; + }; +}; + +&odm_partition { + macaddr_odm: macaddr@83 { + compatible = "mac-base"; + reg = <0x83 0x6>; + #nvmem-cell-cells = <1>; + }; +}; + diff --git a/target/linux/mediatek/dts/mt7622-dlink-eagle-pro-ai-r32-a1.dts b/target/linux/mediatek/dts/mt7622-dlink-eagle-pro-ai-r32-a1.dts new file mode 100644 index 000000000..b21ba36cf --- /dev/null +++ b/target/linux/mediatek/dts/mt7622-dlink-eagle-pro-ai-r32-a1.dts @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +/dts-v1/; +#include "mt7622-dlink-eagle-pro-ai-ax3200-a1.dtsi" +#include + +/ { + model = "D-Link EAGLE PRO AI R32 A1"; + compatible = "dlink,eagle-pro-ai-r32-a1", "mediatek,mt7622"; + + aliases { + led-boot = &led_power_orange; + led-failsafe = &led_power_orange; + led-running = &led_power_white; + led-upgrade = &led_power_orange; + }; + + leds { + compatible = "gpio-leds"; + + led_power_orange: led-power-orange { + color = ; + function = LED_FUNCTION_STATUS; + gpios = <&pio 20 GPIO_ACTIVE_HIGH>; + }; + + led_power_white: led-power-white { + color = ; + function = LED_FUNCTION_STATUS; + gpios = <&pio 85 GPIO_ACTIVE_LOW>; + }; + + led_internet_orange: led-internet-orange { + color = ; + function = "internet"; // LED_FUNCTION_INTERNET; + gpios = <&pio 5 GPIO_ACTIVE_HIGH>; + }; + + led_internet_white: led-internet-white { + color = ; + function = "internet"; // LED_FUNCTION_INTERNET; + gpios = <&pio 17 GPIO_ACTIVE_LOW>; + }; + }; +}; + +&switch { + ports { + port@0 { + reg = <0>; + label = "lan4"; + }; + + port@1 { + reg = <1>; + label = "lan3"; + }; + + port@2 { + reg = <2>; + label = "lan2"; + }; + + port@3 { + reg = <3>; + label = "lan1"; + }; + }; +}; + +&odm_partition { + macaddr_odm: macaddr@81 { + compatible = "mac-base"; + reg = <0x81 0x6>; + #nvmem-cell-cells = <1>; + }; +}; + diff --git a/target/linux/mediatek/dts/mt7622-elecom-wrc-2533gent.dts b/target/linux/mediatek/dts/mt7622-elecom-wrc-2533gent.dts index 3e061ef94..7fe5d02e1 100644 --- a/target/linux/mediatek/dts/mt7622-elecom-wrc-2533gent.dts +++ b/target/linux/mediatek/dts/mt7622-elecom-wrc-2533gent.dts @@ -130,7 +130,7 @@ regulator-name = "usb_vbus"; regulator-min-microvolt = <5000000>; regulator-max-microvolt = <5000000>; - gpio = <&pio 22 GPIO_ACTIVE_LOW>; + gpios = <&pio 22 GPIO_ACTIVE_LOW>; enable-active-high; }; diff --git a/target/linux/mediatek/dts/mt7622-elecom-wrc-x3200gst3.dts b/target/linux/mediatek/dts/mt7622-elecom-wrc-x3200gst3.dts index fdbcbc18b..2bf4a33a5 100644 --- a/target/linux/mediatek/dts/mt7622-elecom-wrc-x3200gst3.dts +++ b/target/linux/mediatek/dts/mt7622-elecom-wrc-x3200gst3.dts @@ -33,14 +33,12 @@ compatible = "gpio-leds"; led-0 { - label = "red:wps"; gpios = <&pio 47 GPIO_ACTIVE_HIGH>; color = ; function = LED_FUNCTION_WPS; }; led_power_red: led-1 { - label = "red:power"; gpios = <&pio 48 GPIO_ACTIVE_HIGH>; color = ; function = LED_FUNCTION_POWER; @@ -48,7 +46,6 @@ }; led_power_green: led-2 { - label = "green:power"; gpios = <&pio 49 GPIO_ACTIVE_HIGH>; color = ; function = LED_FUNCTION_POWER; @@ -56,7 +53,6 @@ }; led-3 { - label = "blue:power"; gpios = <&pio 50 GPIO_ACTIVE_HIGH>; color = ; function = LED_FUNCTION_POWER; @@ -64,7 +60,6 @@ }; led-4 { - label = "white:wlan2g"; gpios = <&pio 85 GPIO_ACTIVE_HIGH>; color = ; function = LED_FUNCTION_WLAN; @@ -73,7 +68,6 @@ }; led-5 { - label = "white:wlan5g"; gpios = <&pio 89 GPIO_ACTIVE_HIGH>; color = ; function = LED_FUNCTION_WLAN; @@ -215,9 +209,9 @@ #address-cells = <1>; #size-cells = <0>; - switch@0 { + switch@1f { compatible = "mediatek,mt7531"; - reg = <0>; + reg = <31>; interrupt-controller; #interrupt-cells = <1>; interrupt-parent = <&pio>; @@ -258,7 +252,6 @@ port@6 { reg = <6>; - label = "cpu"; ethernet = <&gmac0>; phy-mode = "2500base-x"; @@ -327,20 +320,24 @@ reg = <0x1c0000 0x100000>; read-only; - compatible = "nvmem-cells"; - #address-cells = <1>; - #size-cells = <1>; + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; - macaddr_factory_4: macaddr@4 { - reg = <0x4 0x6>; - }; + macaddr_factory_4: macaddr@4 { + compatible = "mac-base"; + reg = <0x4 0x6>; + #nvmem-cell-cells = <1>; + }; - macaddr_factory_7fff4: macaddr@7fff4 { - reg = <0x7fff4 0x6>; - }; + macaddr_factory_7fff4: macaddr@7fff4 { + reg = <0x7fff4 0x6>; + }; - macaddr_factory_7fffa: macaddr@7fffa { - reg = <0x7fffa 0x6>; + macaddr_factory_7fffa: macaddr@7fffa { + reg = <0x7fffa 0x6>; + }; }; }; @@ -395,9 +392,8 @@ reg = <0x0000 0 0 0 0>; mediatek,mtd-eeprom = <&factory 0x5000>; ieee80211-freq-limit = <5000000 6000000>; - nvmem-cells = <&macaddr_factory_4>; + nvmem-cells = <&macaddr_factory_4 1>; nvmem-cell-names = "mac-address"; - mac-address-increment = <1>; }; }; diff --git a/target/linux/mediatek/dts/mt7622-linksys-e8450-ubi.dts b/target/linux/mediatek/dts/mt7622-linksys-e8450-ubi.dts index 9df736eb0..88538c8b0 100644 --- a/target/linux/mediatek/dts/mt7622-linksys-e8450-ubi.dts +++ b/target/linux/mediatek/dts/mt7622-linksys-e8450-ubi.dts @@ -10,6 +10,11 @@ aliases { label-mac-device = &wan; }; + + chosen { + rootdisk = <&ubi_rootfs>; + bootargs = "earlycon=uart8250,mmio32,0x11002000 console=ttyS0,115200n1 swiotlb=512 ubi.block=0,fit root=/dev/fit0 rootwait"; + }; }; &snand { @@ -25,31 +30,70 @@ }; partition@80000 { - label = "fip"; - reg = <0x80000 0x140000>; - read-only; - }; - - factory: partition@1c0000 { - label = "factory"; - reg = <0x1c0000 0x100000>; - read-only; - }; - - partition@300000 { label = "ubi"; - reg = <0x300000 0x7d00000>; + reg = <0x80000 0x7f80000>; + compatible = "linux,ubi"; + + volumes { + ubi-volume-ubootenv { + volname = "ubootenv"; + nvmem-layout { + compatible = "u-boot,env-redundant-bool-layout"; + }; + }; + + ubi-volume-ubootenv2 { + volname = "ubootenv2"; + nvmem-layout { + compatible = "u-boot,env-redundant-bool-layout"; + }; + }; + + ubi_rootfs: ubi-volume-fit { + volname = "fit"; + }; + + ubi_factory: ubi-volume-factory { + volname = "factory"; + }; + }; + }; + }; +}; + +&ubi_factory { + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + eeprom_factory_0: eeprom@0 { + reg = <0x0 0x4da8>; /* actual length 0x400 */ + }; + + eeprom_factory_5000: eeprom@5000 { + reg = <0x5000 0xe00>; + }; + + macaddr_factory_7fff4: macaddr@7fff4 { + reg = <0x7fff4 0x6>; + }; + + macaddr_factory_7fffa: macaddr@7fffa { + reg = <0x7fffa 0x6>; }; }; }; &wmac { - mediatek,mtd-eeprom = <&factory 0x0>; + nvmem-cells = <&eeprom_factory_0>; + nvmem-cell-names = "eeprom"; status = "okay"; }; &wmac1 { - mediatek,mtd-eeprom = <&factory 0x5000>; + nvmem-cells = <&eeprom_factory_5000>; + nvmem-cell-names = "eeprom"; }; &gmac0 { @@ -61,17 +105,3 @@ nvmem-cells = <&macaddr_factory_7fffa>; nvmem-cell-names = "mac-address"; }; - -&factory { - compatible = "nvmem-cells"; - #address-cells = <1>; - #size-cells = <1>; - - macaddr_factory_7fff4: macaddr@7fff4 { - reg = <0x7fff4 0x6>; - }; - - macaddr_factory_7fffa: macaddr@7fffa { - reg = <0x7fffa 0x6>; - }; -}; diff --git a/target/linux/mediatek/dts/mt7622-linksys-e8450.dts b/target/linux/mediatek/dts/mt7622-linksys-e8450.dts index 8552dbf1a..dedcc057f 100644 --- a/target/linux/mediatek/dts/mt7622-linksys-e8450.dts +++ b/target/linux/mediatek/dts/mt7622-linksys-e8450.dts @@ -45,6 +45,20 @@ factory: partition@1c0000 { label = "factory"; reg = <0x1c0000 0x0100000>; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + macaddr_factory_7fff4: macaddr@7fff4 { + reg = <0x7fff4 0x6>; + }; + + macaddr_factory_7fffa: macaddr@7fffa { + reg = <0x7fffa 0x6>; + }; + }; }; partition@300000 { @@ -106,17 +120,3 @@ nvmem-cells = <&macaddr_factory_7fffa>; nvmem-cell-names = "mac-address"; }; - -&factory { - compatible = "nvmem-cells"; - #address-cells = <1>; - #size-cells = <1>; - - macaddr_factory_7fff4: macaddr@7fff4 { - reg = <0x7fff4 0x6>; - }; - - macaddr_factory_7fffa: macaddr@7fffa { - reg = <0x7fffa 0x6>; - }; -}; diff --git a/target/linux/mediatek/dts/mt7622-linksys-e8450.dtsi b/target/linux/mediatek/dts/mt7622-linksys-e8450.dtsi index 1fe839575..48b25f7a4 100644 --- a/target/linux/mediatek/dts/mt7622-linksys-e8450.dtsi +++ b/target/linux/mediatek/dts/mt7622-linksys-e8450.dtsi @@ -1,8 +1,9 @@ // SPDX-License-Identifier: (GPL-2.0-only OR MIT) /dts-v1/; -#include #include +#include +#include #include "mt7622.dtsi" #include "mt6380.dtsi" @@ -110,10 +111,6 @@ }; }; -&btif { - status = "okay"; -}; - &cir { pinctrl-names = "default"; pinctrl-0 = <&irrx_pins>; @@ -141,9 +138,9 @@ #address-cells = <1>; #size-cells = <0>; - switch@0 { + switch@1f { compatible = "mediatek,mt7531"; - reg = <0>; + reg = <31>; interrupt-controller; #interrupt-cells = <1>; interrupt-parent = <&pio>; @@ -181,7 +178,6 @@ port@6 { reg = <6>; - label = "cpu"; ethernet = <&gmac0>; phy-mode = "2500base-x"; @@ -276,6 +272,11 @@ function = "flash"; groups = "snfi"; }; + + conf { + groups = "snfi"; + drive-strength = ; + }; }; spic0_pins: spic0-pins { diff --git a/target/linux/mediatek/dts/mt7622-netgear-wax206.dts b/target/linux/mediatek/dts/mt7622-netgear-wax206.dts index 5dd386bcd..524a49874 100644 --- a/target/linux/mediatek/dts/mt7622-netgear-wax206.dts +++ b/target/linux/mediatek/dts/mt7622-netgear-wax206.dts @@ -114,10 +114,6 @@ status = "okay"; }; -&btif { - status = "okay"; -}; - &cir { pinctrl-names = "default"; pinctrl-0 = <&irrx_pins>; @@ -147,13 +143,13 @@ #address-cells = <1>; #size-cells = <0>; - switch@0 { + switch@1f { compatible = "mediatek,mt7531"; + reg = <31>; #interrupt-cells = <1>; interrupt-controller; interrupt-parent = <&pio>; interrupts = <53 IRQ_TYPE_LEVEL_HIGH>; - reg = <0>; reset-gpios = <&pio 54 GPIO_ACTIVE_HIGH>; ports { @@ -191,7 +187,6 @@ port@6 { ethernet = <&gmac0>; - label = "cpu"; phy-mode = "2500base-x"; reg = <6>; @@ -406,19 +401,22 @@ }; factory: partition@1c0000 { - compatible = "nvmem-cells"; label = "Factory"; reg = <0x1c0000 0x0100000>; - #address-cells = <1>; - #size-cells = <1>; read-only; - macaddr_factory_7fff4: macaddr@7fff4 { - reg = <0x7fff4 0x6>; - }; + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; - macaddr_factory_7fffa: macaddr@7fffa { - reg = <0x7fffa 0x6>; + macaddr_factory_7fff4: macaddr@7fff4 { + reg = <0x7fff4 0x6>; + }; + + macaddr_factory_7fffa: macaddr@7fffa { + reg = <0x7fffa 0x6>; + }; }; }; diff --git a/target/linux/mediatek/dts/mt7622-reyee-ax3200-e5.dts b/target/linux/mediatek/dts/mt7622-reyee-ax3200-e5.dts new file mode 100644 index 000000000..d86ea52fc --- /dev/null +++ b/target/linux/mediatek/dts/mt7622-reyee-ax3200-e5.dts @@ -0,0 +1,96 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +/dts-v1/; +#include +#include + +#include "mt7622-ruijie-rg-ew3200.dtsi" + +/ { + model = "reyee AX3200 E5"; + compatible = "reyee,ax3200-e5", "mediatek,mt7622"; +}; + +&nor_flash { + status = "okay"; + + pinctrl-names = "default"; + pinctrl-0 = <&spi_nor_pins>; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <50000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "Preloader"; + reg = <0x0 0x20000>; + read-only; + }; + + partition@20000 { + label = "ATF"; + reg = <0x20000 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot"; + reg = <0x30000 0x80000>; + read-only; + }; + + partition@80000 { + label = "u-boot-env"; + reg = <0x80000 0x90000>; + }; + + factory: partition@90000 { + label = "Factory"; + reg = <0x90000 0xd0000>; + read-only; + }; + + partition@d0000 { + label = "product_info"; + reg = <0xd0000 0xe0000>; + read-only; + }; + + partition@e0000 { + label = "kdump"; + reg = <0xe0000 0xf0000>; + read-only; + }; + + partition@f0000 { + compatible = "denx,fit"; + label = "firmware"; + reg = <0xf0000 0x1000000>; + }; + }; + }; +}; + +&wmac { + status = "okay"; + + pinctrl-names = "default"; + pinctrl-0 = <&epa_elna_pins>; + mediatek,mtd-eeprom = <&factory 0x0>; +}; + +&slot0 { + wifi@0,0 { + compatible = "mediatek,mt76"; + reg = <0x0000 0 0 0 0>; + mediatek,mtd-eeprom = <&factory 0x5000>; + ieee80211-freq-limit = <5000000 6000000>; + mediatek,disable-radar-background; + }; +}; diff --git a/target/linux/mediatek/dts/mt7622-rfb1-ubi.dts b/target/linux/mediatek/dts/mt7622-rfb1-ubi.dts index 0f6d9bbc5..721695227 100644 --- a/target/linux/mediatek/dts/mt7622-rfb1-ubi.dts +++ b/target/linux/mediatek/dts/mt7622-rfb1-ubi.dts @@ -44,12 +44,12 @@ partition@200000 { label = "kernel"; - reg = <0x2c0000 0x400000>; + reg = <0x2c0000 0x600000>; }; partition@6c0000 { label = "ubi"; - reg = <0x6c0000 0x6f00000>; + reg = <0x8c0000 0x6f00000>; }; /delete-node/ partition@2200000; diff --git a/target/linux/mediatek/dts/mt7622-ruijie-rg-ew3200.dtsi b/target/linux/mediatek/dts/mt7622-ruijie-rg-ew3200.dtsi new file mode 100644 index 000000000..24ed92788 --- /dev/null +++ b/target/linux/mediatek/dts/mt7622-ruijie-rg-ew3200.dtsi @@ -0,0 +1,240 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +/dts-v1/; +#include +#include + +#include "mt7622.dtsi" +#include "mt6380.dtsi" + +/ { + aliases { + ethernet0 = &gmac0; + label-mac-device = &gmac0; + led-boot = &led_system; + led-failsafe = &led_system; + led-running = &led_system; + led-upgrade = &led_system; + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n1"; + bootargs = "console=ttyS0,115200n1 swiotlb=512"; + }; + + cpus { + cpu@0 { + proc-supply = <&mt6380_vcpu_reg>; + sram-supply = <&mt6380_vm_reg>; + }; + + cpu@1 { + proc-supply = <&mt6380_vcpu_reg>; + sram-supply = <&mt6380_vm_reg>; + }; + }; + + gpio-keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + linux,code = ; + gpios = <&pio 0 GPIO_ACTIVE_LOW>; + }; + + wps { + label = "wps"; + linux,code = ; + gpios = <&pio 102 GPIO_ACTIVE_LOW>; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + mesh_green { + label = "green:mesh"; + gpios = <&pio 79 GPIO_ACTIVE_LOW>; + }; + + mesh_red { + label = "red:mesh"; + gpios = <&pio 82 GPIO_ACTIVE_LOW>; + }; + + led_system: system_blue { + label = "blue:system"; + gpios = <&pio 81 GPIO_ACTIVE_LOW>; + default-state = "on"; + }; + }; + + memory { + reg = <0 0x40000000 0 0x40000000>; + }; +}; + +ð { + status = "okay"; + + pinctrl-names = "default"; + pinctrl-0 = <ð_pins>; + + gmac0: mac@0 { + compatible = "mediatek,eth-mac"; + reg = <0>; + phy-connection-type = "2500base-x"; + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; + }; + + mdio: mdio-bus { + #address-cells = <1>; + #size-cells = <0>; + + switch@1f { + compatible = "mediatek,mt7531"; + reg = <31>; + reset-gpios = <&pio 54 GPIO_ACTIVE_HIGH>; + interrupt-controller; + #interrupt-cells = <2>; + interrupt-parent = <&pio>; + interrupts = <53 IRQ_TYPE_LEVEL_HIGH>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + label = "lan1"; + }; + + port@1 { + reg = <1>; + label = "lan2"; + }; + + port@2 { + reg = <2>; + label = "lan3"; + }; + + port@3 { + reg = <3>; + label = "lan4"; + }; + + wan: port@4 { + reg = <4>; + label = "wan"; + }; + + port@6 { + reg = <6>; + ethernet = <&gmac0>; + phy-mode = "2500base-x"; + + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; + }; + }; + }; + }; +}; + +&pcie0 { + status = "okay"; + + pinctrl-names = "default"; + pinctrl-0 = <&pcie0_pins>; +}; + +&pio { + epa_elna_pins: epa-elna-pins { + mux { + function = "antsel"; + groups = "antsel0", "antsel1", "antsel2", "antsel3", + "antsel4", "antsel5", "antsel6", "antsel7", + "antsel8", "antsel9", "antsel12", "antsel13", + "antsel14", "antsel15", "antsel16", "antsel17"; + }; + }; + + eth_pins: eth-pins { + mux { + function = "eth"; + groups = "mdc_mdio", "rgmii_via_gmac2"; + }; + }; + + pcie0_pins: pcie0-pins { + mux { + function = "pcie"; + groups = "pcie0_pad_perst", + "pcie0_0_waken", + "pcie0_0_clkreq"; + }; + }; + + pmic_bus_pins: pmic-bus-pins { + mux { + function = "pmic"; + groups = "pmic_bus"; + }; + }; + + spi_nor_pins: spi-nor-pins { + mux { + function = "flash"; + groups = "spi_nor"; + }; + }; + + uart0_pins: uart0-pins { + mux { + function = "uart"; + groups = "uart0_0_tx_rx"; + }; + }; + + watchdog_pins: watchdog-pins { + mux { + function = "watchdog"; + groups = "watchdog"; + }; + }; +}; + +&pwrap { + status = "okay"; + + pinctrl-names = "default"; + pinctrl-0 = <&pmic_bus_pins>; +}; + +&rtc { + status = "disabled"; +}; + +&uart0 { + status = "okay"; + + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins>; +}; + +&watchdog { + status = "okay"; + + pinctrl-names = "default"; + pinctrl-0 = <&watchdog_pins>; +}; diff --git a/target/linux/mediatek/dts/mt7622-ruijie-rg-ew3200gx-pro.dts b/target/linux/mediatek/dts/mt7622-ruijie-rg-ew3200gx-pro.dts index fba9a1b8f..857f94ae9 100644 --- a/target/linux/mediatek/dts/mt7622-ruijie-rg-ew3200gx-pro.dts +++ b/target/linux/mediatek/dts/mt7622-ruijie-rg-ew3200gx-pro.dts @@ -1,239 +1,11 @@ // SPDX-License-Identifier: GPL-2.0-or-later OR MIT /dts-v1/; -#include -#include - -#include "mt7622.dtsi" -#include "mt6380.dtsi" +#include "mt7622-ruijie-rg-ew3200.dtsi" / { model = "Ruijie RG-EW3200GX PRO"; compatible = "ruijie,rg-ew3200gx-pro", "mediatek,mt7622"; - - aliases { - ethernet0 = &gmac0; - label-mac-device = &gmac0; - led-boot = &led_system; - led-failsafe = &led_system; - led-running = &led_system; - led-upgrade = &led_system; - serial0 = &uart0; - }; - - chosen { - stdout-path = "serial0:115200n1"; - bootargs = "console=ttyS0,115200n1 swiotlb=512"; - }; - - cpus { - cpu@0 { - proc-supply = <&mt6380_vcpu_reg>; - sram-supply = <&mt6380_vm_reg>; - }; - - cpu@1 { - proc-supply = <&mt6380_vcpu_reg>; - sram-supply = <&mt6380_vm_reg>; - }; - }; - - gpio-keys { - compatible = "gpio-keys"; - - reset { - label = "reset"; - linux,code = ; - gpios = <&pio 0 GPIO_ACTIVE_LOW>; - }; - - wps { - label = "wps"; - linux,code = ; - gpios = <&pio 102 GPIO_ACTIVE_LOW>; - }; - }; - - gpio-leds { - compatible = "gpio-leds"; - - mesh_green { - label = "green:mesh"; - gpios = <&pio 79 GPIO_ACTIVE_LOW>; - }; - - mesh_red { - label = "red:mesh"; - gpios = <&pio 82 GPIO_ACTIVE_LOW>; - }; - - led_system: system_blue { - label = "blue:system"; - gpios = <&pio 81 GPIO_ACTIVE_LOW>; - default-state = "on"; - }; - }; - - memory { - reg = <0 0x40000000 0 0x40000000>; - }; -}; - -ð { - status = "okay"; - - pinctrl-names = "default"; - pinctrl-0 = <ð_pins>; - - gmac0: mac@0 { - compatible = "mediatek,eth-mac"; - reg = <0>; - phy-connection-type = "2500base-x"; - fixed-link { - speed = <2500>; - full-duplex; - pause; - }; - }; - - mdio: mdio-bus { - #address-cells = <1>; - #size-cells = <0>; - - switch@0 { - compatible = "mediatek,mt7531"; - reg = <0>; - reset-gpios = <&pio 54 GPIO_ACTIVE_HIGH>; - - interrupt-controller; - #interrupt-cells = <2>; - interrupt-parent = <&pio>; - interrupts = <53 IRQ_TYPE_LEVEL_HIGH>; - - ports { - #address-cells = <1>; - #size-cells = <0>; - - port@0 { - reg = <0>; - label = "lan1"; - }; - - port@1 { - reg = <1>; - label = "lan2"; - }; - - port@2 { - reg = <2>; - label = "lan3"; - }; - - port@3 { - reg = <3>; - label = "lan4"; - }; - - wan: port@4 { - reg = <4>; - label = "wan"; - }; - - port@6 { - reg = <6>; - label = "cpu"; - ethernet = <&gmac0>; - phy-mode = "2500base-x"; - - fixed-link { - speed = <2500>; - full-duplex; - pause; - }; - }; - }; - }; - }; -}; - -&pcie0 { - status = "okay"; - - pinctrl-names = "default"; - pinctrl-0 = <&pcie0_pins>; -}; - -&slot0 { - wifi@0,0 { - compatible = "mediatek,mt76"; - reg = <0x0000 0 0 0 0>; - mediatek,mtd-eeprom = <&factory 0x5000>; - ieee80211-freq-limit = <5000000 6000000>; - mediatek,disable-radar-background; - }; -}; - -&pio { - epa_elna_pins: epa-elna-pins { - mux { - function = "antsel"; - groups = "antsel0", "antsel1", "antsel2", "antsel3", - "antsel4", "antsel5", "antsel6", "antsel7", - "antsel8", "antsel9", "antsel12", "antsel13", - "antsel14", "antsel15", "antsel16", "antsel17"; - }; - }; - - eth_pins: eth-pins { - mux { - function = "eth"; - groups = "mdc_mdio", "rgmii_via_gmac2"; - }; - }; - - pcie0_pins: pcie0-pins { - mux { - function = "pcie"; - groups = "pcie0_pad_perst", - "pcie0_0_waken", - "pcie0_0_clkreq"; - }; - }; - - pmic_bus_pins: pmic-bus-pins { - mux { - function = "pmic"; - groups = "pmic_bus"; - }; - }; - - spi_nor_pins: spi-nor-pins { - mux { - function = "flash"; - groups = "spi_nor"; - }; - }; - - uart0_pins: uart0-pins { - mux { - function = "uart"; - groups = "uart0_0_tx_rx"; - }; - }; - - watchdog_pins: watchdog-pins { - mux { - function = "watchdog"; - groups = "watchdog"; - }; - }; -}; - -&pwrap { - status = "okay"; - - pinctrl-names = "default"; - pinctrl-0 = <&pmic_bus_pins>; }; &nor_flash { @@ -302,24 +74,6 @@ }; }; -&rtc { - status = "disabled"; -}; - -&uart0 { - status = "okay"; - - pinctrl-names = "default"; - pinctrl-0 = <&uart0_pins>; -}; - -&watchdog { - status = "okay"; - - pinctrl-names = "default"; - pinctrl-0 = <&watchdog_pins>; -}; - &wmac { status = "okay"; @@ -327,3 +81,13 @@ pinctrl-0 = <&epa_elna_pins>; mediatek,mtd-eeprom = <&factory 0x0>; }; + +&slot0 { + wifi@0,0 { + compatible = "mediatek,mt76"; + reg = <0x0000 0 0 0 0>; + mediatek,mtd-eeprom = <&factory 0x5000>; + ieee80211-freq-limit = <5000000 6000000>; + mediatek,disable-radar-background; + }; +}; diff --git a/target/linux/mediatek/dts/mt7622-totolink-a8000ru.dts b/target/linux/mediatek/dts/mt7622-totolink-a8000ru.dts index b634e2878..5ec07128b 100644 --- a/target/linux/mediatek/dts/mt7622-totolink-a8000ru.dts +++ b/target/linux/mediatek/dts/mt7622-totolink-a8000ru.dts @@ -2,6 +2,7 @@ /dts-v1/; #include +#include #include #include "mt7622.dtsi" @@ -57,7 +58,8 @@ compatible = "gpio-leds"; led_status: status_red { - label = "red:status"; + function = LED_FUNCTION_STATUS; + color = ; gpios = <&pio 81 GPIO_ACTIVE_LOW>; default-state = "on"; }; @@ -284,6 +286,20 @@ label = "factory"; reg = <0x1c0000 0x40000>; read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + macaddr_factory_24: macaddr@24 { + reg = <0x24 0x6>; + }; + + macaddr_factory_2a: macaddr@2a { + reg = <0x2a 0x6>; + }; + }; }; partition@200000 { @@ -305,20 +321,6 @@ }; }; -&factory { - compatible = "nvmem-cells"; - #address-cells = <1>; - #size-cells = <1>; - - macaddr_factory_24: macaddr@24 { - reg = <0x24 0x6>; - }; - - macaddr_factory_2a: macaddr@2a { - reg = <0x2a 0x6>; - }; -}; - &ssusb { vusb33-supply = <®_3p3v>; vbus-supply = <®_5v>; diff --git a/target/linux/mediatek/dts/mt7622-ubnt-unifi-6-lr-v1-ubootmod.dts b/target/linux/mediatek/dts/mt7622-ubnt-unifi-6-lr-v1-ubootmod.dts index 5b1fd1d9b..6e310d40b 100644 --- a/target/linux/mediatek/dts/mt7622-ubnt-unifi-6-lr-v1-ubootmod.dts +++ b/target/linux/mediatek/dts/mt7622-ubnt-unifi-6-lr-v1-ubootmod.dts @@ -5,6 +5,11 @@ / { model = "Ubiquiti UniFi 6 LR v1 (U-Boot mod)"; compatible = "ubnt,unifi-6-lr-v1-ubootmod", "mediatek,mt7622"; + + chosen { + rootdisk = <&rootdisk>; + bootargs = "earlycon=uart8250,mmio32,0x11002000 swiotlb=512 console=ttyS0,115200n8 root=/dev/fit0 rootwait"; + }; }; &nor_partitions { @@ -33,6 +38,20 @@ label = "eeprom"; reg = <0x110000 0x10000>; read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + macaddr_eeprom_0: macaddr@0 { + reg = <0x0 0x6>; + }; + + macaddr_eeprom_6: macaddr@6 { + reg = <0x6 0x6>; + }; + }; }; partition@120000 { @@ -40,7 +59,7 @@ reg = <0x120000 0xee0000>; }; - partition@1000000 { + rootdisk: partition@1000000 { compatible = "denx,fit"; label = "firmware"; reg = <0x1000000 0x3000000>; @@ -68,17 +87,3 @@ nvmem-cells = <&macaddr_eeprom_0>; nvmem-cell-names = "mac-address"; }; - -&eeprom { - compatible = "nvmem-cells"; - #address-cells = <1>; - #size-cells = <1>; - - macaddr_eeprom_0: macaddr@0 { - reg = <0x0 0x6>; - }; - - macaddr_eeprom_6: macaddr@6 { - reg = <0x6 0x6>; - }; -}; diff --git a/target/linux/mediatek/dts/mt7622-ubnt-unifi-6-lr-v1.dts b/target/linux/mediatek/dts/mt7622-ubnt-unifi-6-lr-v1.dts index 95f19af4c..7e07e1ba6 100644 --- a/target/linux/mediatek/dts/mt7622-ubnt-unifi-6-lr-v1.dts +++ b/target/linux/mediatek/dts/mt7622-ubnt-unifi-6-lr-v1.dts @@ -38,6 +38,20 @@ label = "eeprom"; reg = <0x110000 0x10000>; read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + macaddr_eeprom_0: macaddr@0 { + reg = <0x0 0x6>; + }; + + macaddr_eeprom_6: macaddr@6 { + reg = <0x6 0x6>; + }; + }; }; partition@120000 { @@ -84,17 +98,3 @@ nvmem-cells = <&macaddr_eeprom_0>; nvmem-cell-names = "mac-address"; }; - -&eeprom { - compatible = "nvmem-cells"; - #address-cells = <1>; - #size-cells = <1>; - - macaddr_eeprom_0: macaddr@0 { - reg = <0x0 0x6>; - }; - - macaddr_eeprom_6: macaddr@6 { - reg = <0x6 0x6>; - }; -}; diff --git a/target/linux/mediatek/dts/mt7622-ubnt-unifi-6-lr-v1.dtsi b/target/linux/mediatek/dts/mt7622-ubnt-unifi-6-lr-v1.dtsi index b3299a988..91719865d 100644 --- a/target/linux/mediatek/dts/mt7622-ubnt-unifi-6-lr-v1.dtsi +++ b/target/linux/mediatek/dts/mt7622-ubnt-unifi-6-lr-v1.dtsi @@ -1,5 +1,30 @@ #include "mt7622-ubnt-unifi-6-lr.dtsi" +ð { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <ð_pins>; + + gmac0: mac@0 { + compatible = "mediatek,eth-mac"; + reg = <0>; + + phy-mode = "2500base-x"; + phy-handle = <&phy0>; + phy-connection-type = "2500base-x"; + }; + + mdio: mdio-bus { + #address-cells = <1>; + #size-cells = <0>; + + phy0: ethernet-phy@8 { + compatible = "ethernet-phy-ieee802.3-c45"; + reg = <0x8>; + }; + }; +}; + &i2c0 { pinctrl-names = "default"; pinctrl-0 = <&i2c0_pins>; diff --git a/target/linux/mediatek/dts/mt7622-ubnt-unifi-6-lr-v2-ubootmod.dts b/target/linux/mediatek/dts/mt7622-ubnt-unifi-6-lr-v2-ubootmod.dts index 6a7b6868c..501e09a69 100644 --- a/target/linux/mediatek/dts/mt7622-ubnt-unifi-6-lr-v2-ubootmod.dts +++ b/target/linux/mediatek/dts/mt7622-ubnt-unifi-6-lr-v2-ubootmod.dts @@ -5,6 +5,11 @@ / { model = "Ubiquiti UniFi 6 LR v2 (U-Boot mod)"; compatible = "ubnt,unifi-6-lr-v2-ubootmod", "mediatek,mt7622"; + + chosen { + rootdisk = <&rootdisk>; + bootargs = "earlycon=uart8250,mmio32,0x11002000 swiotlb=512 console=ttyS0,115200n8 root=/dev/fit0 rootwait"; + }; }; &nor_partitions { @@ -33,6 +38,20 @@ label = "eeprom"; reg = <0x110000 0x10000>; read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + macaddr_eeprom_0: macaddr@0 { + reg = <0x0 0x6>; + }; + + macaddr_eeprom_6: macaddr@6 { + reg = <0x6 0x6>; + }; + }; }; partition@120000 { @@ -40,7 +59,7 @@ reg = <0x120000 0xee0000>; }; - partition@1000000 { + rootdisk: partition@1000000 { compatible = "denx,fit"; label = "firmware"; reg = <0x1000000 0x3000000>; @@ -68,17 +87,3 @@ nvmem-cells = <&macaddr_eeprom_0>; nvmem-cell-names = "mac-address"; }; - -&eeprom { - compatible = "nvmem-cells"; - #address-cells = <1>; - #size-cells = <1>; - - macaddr_eeprom_0: macaddr@0 { - reg = <0x0 0x6>; - }; - - macaddr_eeprom_6: macaddr@6 { - reg = <0x6 0x6>; - }; -}; diff --git a/target/linux/mediatek/dts/mt7622-ubnt-unifi-6-lr-v2.dts b/target/linux/mediatek/dts/mt7622-ubnt-unifi-6-lr-v2.dts index f40e8e632..9fef3d672 100644 --- a/target/linux/mediatek/dts/mt7622-ubnt-unifi-6-lr-v2.dts +++ b/target/linux/mediatek/dts/mt7622-ubnt-unifi-6-lr-v2.dts @@ -38,6 +38,20 @@ label = "eeprom"; reg = <0x110000 0x10000>; read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + macaddr_eeprom_0: macaddr@0 { + reg = <0x0 0x6>; + }; + + macaddr_eeprom_6: macaddr@6 { + reg = <0x6 0x6>; + }; + }; }; partition@120000 { @@ -84,17 +98,3 @@ nvmem-cells = <&macaddr_eeprom_0>; nvmem-cell-names = "mac-address"; }; - -&eeprom { - compatible = "nvmem-cells"; - #address-cells = <1>; - #size-cells = <1>; - - macaddr_eeprom_0: macaddr@0 { - reg = <0x0 0x6>; - }; - - macaddr_eeprom_6: macaddr@6 { - reg = <0x6 0x6>; - }; -}; diff --git a/target/linux/mediatek/dts/mt7622-ubnt-unifi-6-lr-v2.dtsi b/target/linux/mediatek/dts/mt7622-ubnt-unifi-6-lr-v2.dtsi index 4d278805d..ab3c59292 100644 --- a/target/linux/mediatek/dts/mt7622-ubnt-unifi-6-lr-v2.dtsi +++ b/target/linux/mediatek/dts/mt7622-ubnt-unifi-6-lr-v2.dtsi @@ -22,3 +22,29 @@ }; }; }; + +ð { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <ð_pins>; + + gmac0: mac@0 { + compatible = "mediatek,eth-mac"; + reg = <0>; + + phy-mode = "2500base-x"; + phy-handle = <&phy0>; + phy-connection-type = "2500base-x"; + }; + + mdio: mdio-bus { + #address-cells = <1>; + #size-cells = <0>; + + phy0: ethernet-phy@8 { + compatible = "ethernet-phy-ieee802.3-c45"; + reg = <0x8>; + }; + }; +}; + diff --git a/target/linux/mediatek/dts/mt7622-ubnt-unifi-6-lr-v3-ubootmod.dts b/target/linux/mediatek/dts/mt7622-ubnt-unifi-6-lr-v3-ubootmod.dts new file mode 100644 index 000000000..8c90c734d --- /dev/null +++ b/target/linux/mediatek/dts/mt7622-ubnt-unifi-6-lr-v3-ubootmod.dts @@ -0,0 +1,89 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "mt7622-ubnt-unifi-6-lr-v3.dtsi" + +/ { + model = "Ubiquiti UniFi 6 LR v3 (U-Boot mod)"; + compatible = "ubnt,unifi-6-lr-v3-ubootmod", "mediatek,mt7622"; + + chosen { + rootdisk = <&rootdisk>; + bootargs = "earlycon=uart8250,mmio32,0x11002000 swiotlb=512 console=ttyS0,115200n8 root=/dev/fit0 rootwait"; + }; +}; + +&nor_partitions { + partition@0 { + label = "bl2"; + reg = <0x0 0x20000>; + }; + + partition@20000 { + label = "fip"; + reg = <0x20000 0xa0000>; + }; + + partition@c0000 { + label = "u-boot-env"; + reg = <0xc0000 0x10000>; + }; + + factory: partition@d0000 { + label = "factory"; + reg = <0xd0000 0x40000>; + read-only; + }; + + eeprom: partition@110000 { + label = "eeprom"; + reg = <0x110000 0x10000>; + read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + macaddr_eeprom_0: macaddr@0 { + reg = <0x0 0x6>; + }; + + macaddr_eeprom_6: macaddr@6 { + reg = <0x6 0x6>; + }; + }; + }; + + partition@120000 { + label = "recovery"; + reg = <0x120000 0xee0000>; + }; + + rootdisk: partition@1000000 { + compatible = "denx,fit"; + label = "firmware"; + reg = <0x1000000 0x3000000>; + }; +}; + +&wmac { + mediatek,mtd-eeprom = <&factory 0x0>; + nvmem-cells = <&macaddr_eeprom_0>; + nvmem-cell-names = "mac-address"; + status = "okay"; +}; + +&slot0 { + wifi@0,0 { + reg = <0x0 0 0 0 0>; + mediatek,mtd-eeprom = <&factory 0x20000>; + nvmem-cells = <&macaddr_eeprom_6>; + nvmem-cell-names = "mac-address"; + ieee80211-freq-limit = <5000000 6000000>; + }; +}; + +&gmac0 { + nvmem-cells = <&macaddr_eeprom_0>; + nvmem-cell-names = "mac-address"; +}; diff --git a/target/linux/mediatek/dts/mt7622-ubnt-unifi-6-lr-v3.dts b/target/linux/mediatek/dts/mt7622-ubnt-unifi-6-lr-v3.dts new file mode 100644 index 000000000..71ee9f0ce --- /dev/null +++ b/target/linux/mediatek/dts/mt7622-ubnt-unifi-6-lr-v3.dts @@ -0,0 +1,100 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "mt7622-ubnt-unifi-6-lr-v3.dtsi" + +/ { + model = "Ubiquiti UniFi 6 LR v3"; + compatible = "ubnt,unifi-6-lr-v3", "mediatek,mt7622"; +}; + +&nor_partitions { + partition@0 { + label = "preloader"; + reg = <0x0 0x40000>; + }; + + partition@40000 { + label = "atf"; + reg = <0x40000 0x20000>; + }; + + partition@60000 { + label = "u-boot"; + reg = <0x60000 0x60000>; + }; + + partition@c0000 { + label = "u-boot-env"; + reg = <0xc0000 0x10000>; + }; + + factory: partition@d0000 { + label = "factory"; + reg = <0xd0000 0x40000>; + read-only; + }; + + eeprom: partition@110000 { + label = "eeprom"; + reg = <0x110000 0x10000>; + read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + macaddr_eeprom_0: macaddr@0 { + reg = <0x0 0x6>; + }; + + macaddr_eeprom_6: macaddr@6 { + reg = <0x6 0x6>; + }; + }; + }; + + partition@120000 { + label = "bs"; + reg = <0x120000 0x10000>; + }; + + partition@130000 { + label = "cfg"; + reg = <0x130000 0x100000>; + read-only; + }; + + partition@230000 { + compatible = "denx,fit"; + label = "firmware"; + reg = <0x230000 0x1ee0000>; + }; + + partition@2110000 { + label = "kernel1"; + reg = <0x2110000 0x1ee0000>; + }; +}; + +&wmac { + mediatek,mtd-eeprom = <&factory 0x0>; + nvmem-cells = <&macaddr_eeprom_0>; + nvmem-cell-names = "mac-address"; + status = "okay"; +}; + +&slot0 { + wifi@0,0 { + reg = <0x0 0 0 0 0>; + mediatek,mtd-eeprom = <&factory 0x20000>; + nvmem-cells = <&macaddr_eeprom_6>; + nvmem-cell-names = "mac-address"; + ieee80211-freq-limit = <5000000 6000000>; + }; +}; + +&gmac0 { + nvmem-cells = <&macaddr_eeprom_0>; + nvmem-cell-names = "mac-address"; +}; diff --git a/target/linux/mediatek/dts/mt7622-ubnt-unifi-6-lr-v3.dtsi b/target/linux/mediatek/dts/mt7622-ubnt-unifi-6-lr-v3.dtsi new file mode 100644 index 000000000..c581bd7d9 --- /dev/null +++ b/target/linux/mediatek/dts/mt7622-ubnt-unifi-6-lr-v3.dtsi @@ -0,0 +1,50 @@ +#include "mt7622-ubnt-unifi-6-lr.dtsi" + +/ { + aliases { + led-boot = &led_white; + led-failsafe = &led_white; + led-running = &led_blue; + led-upgrade = &led_blue; + }; + + gpio-leds { + compatible = "gpio-leds"; + + led_white: dome_white { + label = "white:dome"; + gpios = <&pio 0x43 GPIO_ACTIVE_LOW>; + }; + + led_blue: dome_blue { + label = "blue:dome"; + gpios = <&pio 0x44 GPIO_ACTIVE_HIGH>; + }; + }; +}; + +ð { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <ð_pins>; + + gmac0: mac@0 { + compatible = "mediatek,eth-mac"; + reg = <0>; + + phy-mode = "sgmii"; + phy-handle = <&phy0>; + phy-connection-type = "sgmii"; + managed = "in-band-status"; + }; + + mdio: mdio-bus { + #address-cells = <1>; + #size-cells = <0>; + + phy0: ethernet-phy@0 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <0x0>; + }; + }; +}; diff --git a/target/linux/mediatek/dts/mt7622-ubnt-unifi-6-lr.dtsi b/target/linux/mediatek/dts/mt7622-ubnt-unifi-6-lr.dtsi index 4231cc1f7..783b0c388 100644 --- a/target/linux/mediatek/dts/mt7622-ubnt-unifi-6-lr.dtsi +++ b/target/linux/mediatek/dts/mt7622-ubnt-unifi-6-lr.dtsi @@ -151,31 +151,6 @@ status = "disabled"; }; -ð { - status = "okay"; - pinctrl-names = "default"; - pinctrl-0 = <ð_pins>; - - gmac0: mac@0 { - compatible = "mediatek,eth-mac"; - reg = <0>; - - phy-mode = "2500base-x"; - phy-handle = <&phy0>; - phy-connection-type = "2500base-x"; - }; - - mdio: mdio-bus { - #address-cells = <1>; - #size-cells = <0>; - - phy0: ethernet-phy@8 { - compatible = "ethernet-phy-ieee802.3-c45"; - reg = <0x8>; - }; - }; -}; - &pwrap { pinctrl-names = "default"; pinctrl-0 = <&pmic_bus_pins>; diff --git a/target/linux/mediatek/dts/mt7622-xiaomi-redmi-router-ax6s.dts b/target/linux/mediatek/dts/mt7622-xiaomi-redmi-router-ax6s.dts index 9661d0c7f..ebc8731bc 100644 --- a/target/linux/mediatek/dts/mt7622-xiaomi-redmi-router-ax6s.dts +++ b/target/linux/mediatek/dts/mt7622-xiaomi-redmi-router-ax6s.dts @@ -2,6 +2,7 @@ /dts-v1/; #include +#include #include #include "mt7622.dtsi" @@ -21,7 +22,8 @@ chosen { stdout-path = "serial0:115200n8"; - bootargs = "earlycon=uart8250,mmio32,0x11002000 console=ttyS0,115200n8 swiotlb=512"; + rootdisk = <&ubi_rootfs>; + bootargs = "earlycon=uart8250,mmio32,0x11002000 swiotlb=512 ubi.block=0,fit root=/dev/fit0"; }; memory { @@ -32,12 +34,14 @@ compatible = "gpio-leds"; led_power_blue: power_blue { - label = "blue:power"; + function = LED_FUNCTION_POWER; + color = ; gpios = <&pio 18 GPIO_ACTIVE_LOW>; }; led_power_amber: power_amber { - label = "amber:power"; + function = LED_FUNCTION_POWER; + color = ; gpios = <&pio 17 GPIO_ACTIVE_LOW>; }; @@ -146,9 +150,8 @@ phy-connection-type = "2500base-x"; - nvmem-cells = <&macaddr_factory_4>; + nvmem-cells = <&macaddr_factory_4 (-1)>; nvmem-cell-names = "mac-address"; - mac-address-increment = <(-1)>; fixed-link { speed = <2500>; @@ -161,9 +164,9 @@ #address-cells = <1>; #size-cells = <0>; - switch@0 { + switch@1f { compatible = "mediatek,mt7531"; - reg = <0>; + reg = <31>; interrupt-controller; #interrupt-cells = <1>; interrupt-parent = <&pio>; @@ -196,7 +199,6 @@ port@6 { reg = <6>; - label = "cpu"; ethernet = <&gmac0>; phy-mode = "2500base-x"; @@ -229,7 +231,7 @@ mediatek,bmt-v2; mediatek,bmt-table-size = <0x1000>; - mediatek,bmt-remap-range = <0x0 0x6c0000>; + mediatek,bmt-remap-range = <0x0 0x340000>; partitions { compatible = "fixed-partitions"; @@ -269,12 +271,16 @@ reg = <0x1c0000 0x80000>; read-only; - compatible = "nvmem-cells"; - #address-cells = <1>; - #size-cells = <1>; + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; - macaddr_factory_4: macaddr@4 { - reg = <0x4 0x6>; + macaddr_factory_4: macaddr@4 { + compatible = "mac-base"; + reg = <0x4 0x6>; + #nvmem-cell-cells = <1>; + }; }; }; @@ -290,12 +296,9 @@ read-only; }; - /* Shrunk and renamed from "firmware" - * as to not break luci size checks - */ partition@2c0000 { - label = "kernel"; - reg = <0x2c0000 0x400000>; + label = "ubi-loader"; + reg = <0x2c0000 0x80000>; }; /* ubi partition is the result of squashing @@ -305,9 +308,16 @@ * - overlay * - obr */ - partition@6c0000 { + partition@340000 { label = "ubi"; - reg = <0x6C0000 0x6f00000>; + reg = <0x340000 0x7280000>; + compatible = "linux,ubi"; + + volumes { + ubi_rootfs: ubi-volume-fit { + volname = "fit"; + }; + }; }; }; }; diff --git a/target/linux/mediatek/dts/mt7623a-unielec-u7623-02.dts b/target/linux/mediatek/dts/mt7623a-unielec-u7623-02.dts index bcd81ba6d..2dbb98e23 100644 --- a/target/linux/mediatek/dts/mt7623a-unielec-u7623-02.dts +++ b/target/linux/mediatek/dts/mt7623a-unielec-u7623-02.dts @@ -9,4 +9,26 @@ / { model = "UniElec U7623-02 eMMC"; compatible = "unielec,u7623-02", "mediatek,mt7623"; + + chosen { + stdout-path = "serial0:115200n8"; + bootargs = "earlycon=uart8250,mmio32,0x11004000 root=/dev/fit0 rootwait"; + rootdisk = <&emmc_rootdisk>; + }; +}; + +&mmc0 { + card@0 { + compatible = "mmc-card"; + reg = <0>; + + block { + compatible = "block-device"; + partitions { + emmc_rootdisk: block-partition-env { + partno = <3>; + }; + }; + }; + }; }; diff --git a/target/linux/mediatek/dts/mt7623a-unielec-u7623-02.dtsi b/target/linux/mediatek/dts/mt7623a-unielec-u7623-02.dtsi index 50c7f3e88..fedf8b859 100644 --- a/target/linux/mediatek/dts/mt7623a-unielec-u7623-02.dtsi +++ b/target/linux/mediatek/dts/mt7623a-unielec-u7623-02.dtsi @@ -121,17 +121,16 @@ #address-cells = <1>; #size-cells = <0>; - mt7530: switch@0 { - compatible = "mediatek,mt7530"; + mt7530: switch@1f { }; }; }; &mt7530 { compatible = "mediatek,mt7530"; + reg = <31>; #address-cells = <1>; #size-cells = <0>; - reg = <0>; pinctrl-names = "default"; mediatek,mcm; resets = <ðsys 2>; @@ -178,7 +177,6 @@ cpu_port0: port@6 { reg = <6>; - label = "cpu"; ethernet = <&gmac0>; phy-mode = "trgmii"; diff --git a/target/linux/mediatek/dts/mt7629-iptime-a6004mx.dts b/target/linux/mediatek/dts/mt7629-iptime-a6004mx.dts new file mode 100644 index 000000000..7a3fa4def --- /dev/null +++ b/target/linux/mediatek/dts/mt7629-iptime-a6004mx.dts @@ -0,0 +1,298 @@ +// SPDX-License-Identifier: GPL-2.0 + +/dts-v1/; +#include +#include +#include "mt7629.dtsi" + +/ { + model = "ipTIME A6004MX"; + compatible = "iptime,a6004mx", "mediatek,mt7629"; + + aliases { + led-boot = &led_cpu; + led-failsafe = &led_cpu; + led-running = &led_cpu; + led-upgrade = &led_cpu; + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + bootargs-override = "console=ttyS0,115200n8"; + }; + + leds { + compatible = "gpio-leds"; + + led_cpu: cpu { + function = LED_FUNCTION_CPU; + color = ; + gpios = <&pio 57 GPIO_ACTIVE_LOW>; + }; + + wlan5g { + label = "orange:wlan5g"; + gpios = <&pio 22 GPIO_ACTIVE_LOW>; + // linux,default-trigger = "phy0radio"; + }; + + wlan2g { + label = "orange:wlan2g"; + gpios = <&pio 21 GPIO_ACTIVE_LOW>; + // linux,default-trigger = "phy1radio"; + }; + + wan { + function = LED_FUNCTION_WAN; + color = ; + gpios = <&pio 12 GPIO_ACTIVE_HIGH>; + }; + }; + + keys { + compatible = "gpio-keys"; + + reset { + label = "factory"; + linux,code = ; + gpios = <&pio 60 GPIO_ACTIVE_LOW>; + }; + + wps { + label = "wps"; + linux,code = ; + gpios = <&pio 58 GPIO_ACTIVE_LOW>; + }; + }; + + memory@40000000 { + device_type = "memory"; + reg = <0x40000000 0x10000000>; + }; + + reg_3p3v: regulator-3p3v { + compatible = "regulator-fixed"; + regulator-name = "fixed-3.3V"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + regulator-always-on; + }; + + reg_5v: regulator-5v { + compatible = "regulator-fixed"; + regulator-name = "fixed-5V"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-boot-on; + regulator-always-on; + }; +}; + +ð { + pinctrl-names = "default"; + pinctrl-0 = <ð_pins>; + pinctrl-1 = <&ephy_leds_pins>; + status = "okay"; + + gmac0: mac@0 { + compatible = "mediatek,eth-mac"; + reg = <0>; + phy-mode = "2500base-x"; + nvmem-cells = <&macaddr_factory_4 3>; + nvmem-cell-names = "mac-address"; + + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; + }; + + gmac1: mac@1 { + compatible = "mediatek,eth-mac"; + reg = <1>; + phy-mode = "gmii"; + phy-handle = <&phy0>; + nvmem-cells = <&macaddr_factory_4 1>; + nvmem-cell-names = "mac-address"; + }; + + mdio: mdio-bus { + #address-cells = <1>; + #size-cells = <0>; + + phy0: ethernet-phy@0 { + reg = <0>; + }; + + switch@1f { + compatible = "mediatek,mt7531"; + reg = <31>; + reset-gpios = <&pio 28 0>; + interrupt-controller; + #interrupt-cells = <1>; + interrupt-parent = <&pio>; + interrupts = <6 IRQ_TYPE_LEVEL_HIGH>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + label = "lan1"; + }; + + port@1 { + reg = <1>; + label = "lan2"; + }; + + port@2 { + reg = <2>; + label = "lan3"; + }; + + port@3 { + reg = <3>; + label = "lan4"; + }; + + port@6 { + reg = <6>; + ethernet = <&gmac0>; + phy-mode = "2500base-x"; + + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; + }; + }; + }; + }; +}; + +&bch { + status = "okay"; +}; + +&snfi { + pinctrl-names = "default"; + pinctrl-0 = <&serial_nand_pins>; + status = "okay"; + flash@0 { + compatible = "spi-nand"; + reg = <0>; + spi-tx-bus-width = <4>; + spi-rx-bus-width = <4>; + nand-ecc-engine = <&snfi>; + mediatek,bmt-v2; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "Bootloader"; + reg = <0x0 0x100000>; + read-only; + }; + + partition@100000 { + label = "Config"; + reg = <0x100000 0x40000>; + }; + + partition@140000 { + label = "factory"; + reg = <0x140000 0x80000>; + read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + macaddr_factory_4: macaddr@4 { + compatible = "mac-base"; + reg = <0x4 0x6>; + #nvmem-cell-cells = <1>; + }; + }; + }; + + partition@1c0000 { + label = "firmware"; + reg = <0x1c0000 0x7400000>; + compatible = "denx,fit"; + openwrt,fit-offset = <0x800>; + }; + }; + }; +}; + +&pio { + eth_pins: eth-pins { + mux { + function = "eth"; + groups = "mdc_mdio"; + }; + }; + + ephy_leds_pins: ephy-leds-pins { + mux { + function = "led"; + groups = "ephy_leds"; + }; + }; + + /* Serial NAND is shared pin with SPI-NOR */ + serial_nand_pins: serial-nand-pins { + mux { + function = "flash"; + groups = "snfi"; + }; + }; + + uart0_pins: uart0-pins { + mux { + function = "uart"; + groups = "uart0_txd_rxd" ; + }; + }; + + watchdog_pins: watchdog-pins { + mux { + function = "watchdog"; + groups = "watchdog"; + }; + }; +}; + +&ssusb { + vusb33-supply = <®_3p3v>; + vbus-supply = <®_5v>; + status = "okay"; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins>; + status = "okay"; +}; + +&watchdog { + pinctrl-names = "default"; + pinctrl-0 = <&watchdog_pins>; + status = "okay"; + + interrupt-controller; + #interrupt-cells = <1>; + interrupt-parent = <&pio>; + interrupts = ; +}; diff --git a/target/linux/mediatek/dts/mt7629-netgear-ex6250-v2.dts b/target/linux/mediatek/dts/mt7629-netgear-ex6250-v2.dts new file mode 100644 index 000000000..99d3a7cef --- /dev/null +++ b/target/linux/mediatek/dts/mt7629-netgear-ex6250-v2.dts @@ -0,0 +1,242 @@ +// SPDX-License-Identifier: GPL-2.0 + +/dts-v1/; +#include +#include +#include "mt7629.dtsi" + +/ { + model = "Netgear EX6250 v2"; + compatible = "netgear,ex6250-v2", "mediatek,mt7629"; + + aliases { + led-boot = &led_power_green; + led-failsafe = &led_power_red; + led-running = &led_power_green; + led-upgrade = &led_power_red; + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + bootargs-override = "console=ttyS0,115200n8"; + }; + + keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + gpios = <&pio 60 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + + wps { + label = "wps"; + gpios = <&pio 58 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + + ap_mode { + label = "ap_mode"; + gpios = <&pio 54 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + + extender_mode { + label = "extender_mode"; + gpios = <&pio 53 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + leds { + compatible = "gpio-leds"; + + led_power_green: power_green { + function = LED_FUNCTION_POWER; + color = ; + gpios = <&pio 21 GPIO_ACTIVE_LOW>; + }; + + led_power_red: power_red { + function = LED_FUNCTION_POWER; + color = ; + gpios = <&pio 61 GPIO_ACTIVE_LOW>; + }; + + client_green { + label = "green:client"; + gpios = <&pio 59 GPIO_ACTIVE_LOW>; + }; + + client_red { + label = "red:client"; + gpios = <&pio 24 GPIO_ACTIVE_LOW>; + }; + + router_green { + label = "green:router"; + gpios = <&pio 55 GPIO_ACTIVE_LOW>; + }; + + router_red { + label = "red:router"; + gpios = <&pio 56 GPIO_ACTIVE_LOW>; + }; + + wps_green { + function = LED_FUNCTION_WPS; + color = ; + gpios = <&pio 57 GPIO_ACTIVE_LOW>; + }; + + eth_green { + label = "green:eth"; + gpios = <&pio 16 GPIO_ACTIVE_LOW>; + }; + + eth_yellow { + label = "yellow:eth"; + gpios = <&pio 12 GPIO_ACTIVE_LOW>; + }; + }; +}; + +ð { + pinctrl-names = "default"; + pinctrl-0 = <ð_pins>; + pinctrl-1 = <&ephy_leds_pins>; + status = "okay"; + + mac@1 { + compatible = "mediatek,eth-mac"; + reg = <1>; + phy-mode = "gmii"; + phy-handle = <&phy0>; + }; + + mdio-bus { + #address-cells = <1>; + #size-cells = <0>; + + phy0: ethernet-phy@0 { + reg = <0>; + }; + }; +}; + +&qspi { + status = "okay"; + + pinctrl-names = "default"; + pinctrl-0 = <&qspi_pins>; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "Bootloader"; + reg = <0x0 0x60000>; + read-only; + }; + + partition@60000 { + label = "Config"; + reg = <0x60000 0x10000>; + read-only; + }; + + partition@70000 { + label = "Factory"; + reg = <0x70000 0x10000>; + read-only; + }; + + partition@80000 { + label = "firmware"; + reg = <0x80000 0xcd0000>; + compatible = "denx,fit"; + }; + + partition@d50000 { + label = "CFG"; + reg = <0xd50000 0x80000>; + read-only; + }; + + partition@dd0000 { + label = "RAE"; + reg = <0xdd0000 0x200000>; + read-only; + }; + + partition@fd0000 { + label = "POT"; + reg = <0xfd0000 0x10000>; + read-only; + }; + + partition@fe0000 { + label = "LOG"; + reg = <0xfe0000 0x20000>; + read-only; + }; + }; + }; +}; + +&pio { + eth_pins: eth-pins { + mux { + function = "eth"; + groups = "mdc_mdio"; + }; + }; + + ephy_leds_pins: ephy-leds-pins { + mux { + function = "led"; + groups = "ephy_leds"; + }; + }; + + qspi_pins: qspi-pins { + mux { + function = "flash"; + groups = "spi_nor"; + }; + }; + + uart0_pins: uart0-pins { + mux { + function = "uart"; + groups = "uart0_txd_rxd" ; + }; + }; + + watchdog_pins: watchdog-pins { + mux { + function = "watchdog"; + groups = "watchdog"; + }; + }; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins>; + status = "okay"; +}; + +&watchdog { + pinctrl-names = "default"; + pinctrl-0 = <&watchdog_pins>; + status = "okay"; +}; diff --git a/target/linux/mediatek/dts/mt7629-tplink_eap225-v5.dts b/target/linux/mediatek/dts/mt7629-tplink_eap225-v5.dts new file mode 100644 index 000000000..bab3ad573 --- /dev/null +++ b/target/linux/mediatek/dts/mt7629-tplink_eap225-v5.dts @@ -0,0 +1,196 @@ +// SPDX-License-Identifier: GPL-2.0 + +/dts-v1/; +#include +#include +#include "mt7629.dtsi" + +/ { + model = "TP-Link EAP225 v5"; + compatible = "tplink,eap225-v5", "mediatek,mt7629"; + + aliases { + led-boot = &led_status_green; + led-failsafe = &led_status_amber; + led-running = &led_status_green; + led-upgrade = &led_status_amber; + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + bootargs-override = "console=ttyS0,115200n8"; + }; + + keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + gpios = <&pio 21 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + leds { + compatible = "gpio-leds"; + + led_status_green: status_green { + function = LED_FUNCTION_STATUS; + color = ; + gpios = <&pio 55 GPIO_ACTIVE_HIGH>; + default-state = "on"; + }; + + led_status_amber: status_amber { + function = LED_FUNCTION_STATUS; + color = ; + gpios = <&pio 56 GPIO_ACTIVE_HIGH>; + }; + }; +}; + +ð { + pinctrl-names = "default"; + pinctrl-0 = <ð_pins>; + pinctrl-1 = <&ephy_leds_pins>; + status = "okay"; + + mac@1 { + compatible = "mediatek,eth-mac"; + reg = <1>; + phy-mode = "gmii"; + phy-handle = <&phy0>; + nvmem-cells = <&macaddr_factory_8>; + nvmem-cell-names = "mac-address"; + }; + + mdio-bus { + #address-cells = <1>; + #size-cells = <0>; + + phy0: ethernet-phy@0 { + reg = <0>; + }; + }; +}; + +&qspi { + status = "okay"; + + pinctrl-names = "default"; + pinctrl-0 = <&qspi_pins>; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "Bootloader"; + reg = <0x0 0x00080000>; + read-only; + }; + + partition@80000 { + label = "Partition"; + reg = <0x00080000 0x00010000>; + read-only; + }; + + partition@90000 { + label = "Factory"; + reg = <0x00090000 0x00010000>; + read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + macaddr_factory_8: macaddr@8 { + reg = <0x8 0x6>; + }; + }; + }; + + partition@A0000 { + label = "Radio"; + reg = <0x000A0000 0x00010000>; + read-only; + }; + + partition@B0000 { + label = "Extra"; + reg = <0x000B0000 0x00010000>; + read-only; + }; + + /* Vendor layout: kernel (0x000C0000 0x001A0000) - rootfs (0x00260000 0x00BE0000) */ + /* OpenWrt flash layout: combine kernel and rootfs from OEM layout */ + partition@C0000 { + label = "firmware"; + reg = <0x000C0000 0x00D80000>; + }; + + partition@E40000 { + label = "Config"; + reg = <0x00E40000 0x0001B0000>; + read-only; + }; + }; + }; +}; + +&pio { + eth_pins: eth-pins { + mux { + function = "eth"; + groups = "mdc_mdio"; + }; + }; + + ephy_leds_pins: ephy-leds-pins { + mux { + function = "led"; + groups = "ephy_leds"; + }; + }; + + qspi_pins: qspi-pins { + mux { + function = "flash"; + groups = "spi_nor"; + }; + }; + + uart0_pins: uart0-pins { + mux { + function = "uart"; + groups = "uart0_txd_rxd" ; + }; + }; + + watchdog_pins: watchdog-pins { + mux { + function = "watchdog"; + groups = "watchdog"; + }; + }; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins>; + status = "okay"; +}; + +&watchdog { + pinctrl-names = "default"; + pinctrl-0 = <&watchdog_pins>; + status = "okay"; +}; diff --git a/target/linux/mediatek/dts/mt7981b-abt-asr3000.dts b/target/linux/mediatek/dts/mt7981a-comfast-cf-e393ax.dts similarity index 56% rename from target/linux/mediatek/dts/mt7981b-abt-asr3000.dts rename to target/linux/mediatek/dts/mt7981a-comfast-cf-e393ax.dts index b089f3d27..6ff061b1e 100644 --- a/target/linux/mediatek/dts/mt7981b-abt-asr3000.dts +++ b/target/linux/mediatek/dts/mt7981a-comfast-cf-e393ax.dts @@ -1,28 +1,27 @@ // SPDX-License-Identifier: GPL-2.0-or-later OR MIT /dts-v1/; -#include -#include - #include "mt7981.dtsi" / { - model = "ABT ASR3000"; - compatible = "abt,asr3000", "mediatek,mt7981"; + model = "COMFAST CF-E393AX"; + compatible = "comfast,cf-e393ax", "mediatek,mt7981"; aliases { serial0 = &uart0; - led-boot = &led_wps; - led-upgrade = &led_wps; - label-mac-device = &gmac0; + led-boot = &led_red; + led-failsafe = &led_red; + led-running = &led_blue; + led-upgrade = &led_green; }; chosen { + bootargs-override = "console=ttyS0,115200n8"; stdout-path = "serial0:115200n8"; }; memory { - reg = <0 0x40000000 0 0x10000000>; + reg = <0 0x40000000 0 0x10000000>; // 256mb }; gpio-keys { @@ -33,25 +32,27 @@ linux,code = ; gpios = <&pio 1 GPIO_ACTIVE_LOW>; }; - - mesh { - label = "mesh"; - linux,code = ; - gpios = <&pio 0 GPIO_ACTIVE_HIGH>; - }; }; leds { compatible = "gpio-leds"; - wan { - label = "green:wan"; + led_blue: blue { gpios = <&pio 8 GPIO_ACTIVE_LOW>; + color = ; + function = LED_FUNCTION_STATUS; }; - led_wps: wps { - label = "green:wps"; - gpios = <&pio 15 GPIO_ACTIVE_HIGH>; + led_red: red { + gpios = <&pio 34 GPIO_ACTIVE_LOW>; + color = ; + function = LED_FUNCTION_STATUS; + }; + + led_green: green { + gpios = <&pio 35 GPIO_ACTIVE_LOW>; + color = ; + function = LED_FUNCTION_STATUS; }; }; }; @@ -60,11 +61,11 @@ status = "okay"; gmac0: mac@0 { + /* LAN */ compatible = "mediatek,eth-mac"; reg = <0>; phy-mode = "2500base-x"; - - nvmem-cells = <&macaddr_art_0>; + nvmem-cells = <&macaddr_factory_e000 0>; nvmem-cell-names = "mac-address"; fixed-link { @@ -75,44 +76,78 @@ }; gmac1: mac@1 { + /* WAN */ compatible = "mediatek,eth-mac"; reg = <1>; phy-mode = "gmii"; phy-handle = <&int_gbe_phy>; - - nvmem-cells = <&macaddr_art_0>; + nvmem-cells = <&macaddr_factory_e000 1>; nvmem-cell-names = "mac-address"; - mac-address-increment = <0x500000>; }; }; &mdio_bus { - switch: switch@0 { + switch: switch@1f { compatible = "mediatek,mt7531"; reg = <31>; - reset-gpios = <&pio 39 GPIO_ACTIVE_HIGH>; interrupt-controller; #interrupt-cells = <1>; interrupt-parent = <&pio>; interrupts = <38 IRQ_TYPE_LEVEL_HIGH>; + reset-gpios = <&pio 5 GPIO_ACTIVE_HIGH>; }; }; +&crypto { + status = "okay"; +}; + +&pio { + spi0_flash_pins: spi0-pins { + mux { + function = "spi"; + groups = "spi0", "spi0_wp_hold"; + }; + conf-pu { + pins = "SPI0_CS", "SPI0_HOLD", "SPI0_WP"; + drive-strength = ; + bias-pull-up = ; + }; + conf-pd { + pins = "SPI0_CLK", "SPI0_MOSI", "SPI0_MISO"; + drive-strength = ; + bias-pull-down = ; + }; + }; + +}; + &spi0 { pinctrl-names = "default"; pinctrl-0 = <&spi0_flash_pins>; + cs-gpios = <0>, <0>; + #address-cells = <1>; + #size-cells = <0>; status = "okay"; + #address-cells = <1>; + #size-cells = <0>; - spi_nand@0 { - compatible = "spi-nand"; + spi_nand: spi_nand@0 { #address-cells = <1>; #size-cells = <1>; - reg = <0>; - + compatible = "spi-nand"; + reg = <1>; spi-max-frequency = <52000000>; + + spi-cal-enable; + spi-cal-mode = "read-data"; + spi-cal-datalen = <7>; + spi-cal-data = /bits/ 8 <0x53 0x50 0x49 0x4E 0x41 0x4E 0x44>; + spi-cal-addrlen = <5>; + spi-cal-addr = /bits/ 32 <0x0 0x0 0x0 0x0 0x0>; + spi-tx-bus-width = <4>; spi-rx-bus-width = <4>; - mediatek,nmbm; mediatek,bmt-max-ratio = <1>; mediatek,bmt-max-reserved-blocks = <64>; @@ -124,48 +159,48 @@ partition@0 { label = "BL2"; - reg = <0x0000000 0x0100000>; + reg = <0x00000 0x0100000>; read-only; }; partition@100000 { label = "u-boot-env"; reg = <0x0100000 0x0080000>; - }; - - partition@180000 { - label = "art"; - reg = <0x0180000 0x0100000>; read-only; - - compatible = "nvmem-cells"; - #address-cells = <1>; - #size-cells = <1>; - - macaddr_art_0: macaddr@0 { - reg = <0x0 0x6>; - }; - - macaddr_art_6: macaddr@6 { - reg = <0x6 0x6>; - }; }; - factory: partition@280000 { + factory: partition@180000 { label = "Factory"; - reg = <0x0280000 0x0100000>; + reg = <0x180000 0x0200000>; read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + eeprom_factory_0: eeprom@0 { + reg = <0x0 0x1000>; + }; + + macaddr_factory_e000: macaddr@e000 { + compatible = "mac-base"; + reg = <0xe000 0x6>; + #nvmem-cell-cells = <1>; + }; + }; }; partition@380000 { label = "FIP"; - reg = <0x0380000 0x0200000>; + reg = <0x380000 0x0200000>; read-only; }; partition@580000 { label = "ubi"; - reg = <0x0580000 0x7000000>; + reg = <0x580000 0x4000000>; + compatible = "linux,ubi"; }; }; }; @@ -178,16 +213,6 @@ port@0 { reg = <0>; - label = "lan3"; - }; - - port@1 { - reg = <1>; - label = "lan2"; - }; - - port@2 { - reg = <2>; label = "lan1"; }; @@ -206,34 +231,6 @@ }; }; -&pio { - spi0_flash_pins: spi0-pins { - mux { - function = "spi"; - groups = "spi0", "spi0_wp_hold"; - }; - - conf-pu { - pins = "SPI0_CS", "SPI0_HOLD", "SPI0_WP"; - drive-strength = <8>; - mediatek,pull-up-adv = <0>; /* bias-disable */ - }; - - conf-pd { - pins = "SPI0_CLK", "SPI0_MOSI", "SPI0_MISO"; - drive-strength = <8>; - mediatek,pull-up-adv = <0>; /* bias-disable */ - }; - }; - - wf_led_pins: wf-led-pins { - mux { - function = "led"; - groups = "wf2g_led1", "wf5g_led1"; - }; - }; -}; - &uart0 { status = "okay"; }; @@ -244,12 +241,7 @@ &wifi { status = "okay"; - pinctrl-0 = <&wifi_dbdc_pins>, <&wf_led_pins>; - nvmem-cells = <&macaddr_art_6>; - nvmem-cell-names = "mac-address"; - mediatek,mtd-eeprom = <&factory 0x0>; - - led { - led-active-low; - }; + nvmem-cells = <&eeprom_factory_0>; + nvmem-cell-names = "eeprom"; }; + diff --git a/target/linux/mediatek/dts/mt7981a-edgecore-eap111.dts b/target/linux/mediatek/dts/mt7981a-edgecore-eap111.dts new file mode 100644 index 000000000..c306a5eb7 --- /dev/null +++ b/target/linux/mediatek/dts/mt7981a-edgecore-eap111.dts @@ -0,0 +1,201 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +/dts-v1/; + +#include +#include "mt7981.dtsi" + +/ { + model = "Edgecore EAP111"; + compatible = "edgecore,eap111", "mediatek,mt7981"; + + aliases { + serial0 = &uart0; + led-boot = &led_green; + led-failsafe = &led_green; + led-running = &led_green; + led-upgrade = &led_green; + }; + + chosen { + bootargs-override = "console=ttyS0,115200n8"; + stdout-path = "serial0:115200n8"; + }; + + gpio-keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + linux,code = ; + gpios = <&pio 1 GPIO_ACTIVE_LOW>; + }; + }; + + leds { + compatible = "gpio-leds"; + + led_green: led-green { + gpios = <&pio 9 GPIO_ACTIVE_HIGH>; + color = ; + function = LED_FUNCTION_INDICATOR; + }; + + led_orange: led-orange { + gpios = <&pio 34 GPIO_ACTIVE_HIGH>; + color = ; + function = LED_FUNCTION_INDICATOR; + }; + + led_blue: led-blue { + gpios = <&pio 35 GPIO_ACTIVE_HIGH>; + color = ; + function = LED_FUNCTION_INDICATOR; + }; + }; +}; + +&uart0 { + status = "okay"; +}; + +&watchdog { + status = "okay"; +}; + +&pio { + spi0_flash_pins: spi0-pins { + mux { + function = "spi"; + groups = "spi0", "spi0_wp_hold"; + }; + }; +}; + +&spi0 { + pinctrl-names = "default"; + pinctrl-0 = <&spi0_flash_pins>; + cs-gpios = <0>, <0>; + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + + flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "spi-nand"; + reg = <0>; + spi-max-frequency = <52000000>; + + spi-cal-enable; + spi-cal-mode = "read-data"; + spi-cal-datalen = <7>; + spi-cal-data = /bits/ 8 <0x53 0x50 0x49 0x4E 0x41 0x4E 0x44>; + spi-cal-addrlen = <5>; + spi-cal-addr = /bits/ 32 <0x0 0x0 0x0 0x0 0x0>; + + spi-tx-bus-width = <4>; + spi-rx-bus-width = <4>; + mediatek,nmbm; + mediatek,bmt-max-ratio = <1>; + mediatek,bmt-max-reserved-blocks = <64>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "BL2"; + reg = <0x00000 0x100000>; + read-only; + }; + + partition@100000 { + label = "u-boot-env"; + reg = <0x100000 0x80000>; + }; + + partition@180000 { + label = "Factory"; + reg = <0x180000 0x200000>; + read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + eeprom_factory: eeprom@0 { + reg = <0x0 0x1000>; + }; + + macaddr_wan: macaddr@2a { + reg = <0x2a 0x6>; + }; + + macaddr_lan: macaddr@24 { + reg = <0x24 0x6>; + }; + }; + }; + + partition@380000 { + label = "FIP"; + reg = <0x380000 0x200000>; + read-only; + }; + + partition@580000 { + label = "ubi"; + reg = <0x580000 0x4000000>; + compatible = "linux,ubi"; + }; + }; + }; +}; + +&mdio_bus { + reset-gpios = <&pio 39 GPIO_ACTIVE_LOW>; + reset-delay-us = <10000>; + reset-post-delay-us = <10000>; + + en8801sc: ethernet-phy@24 { + reg = <24>; + compatible = "ethernet-phy-id03a2.9471"; + phy-mode = "sgmii"; + }; +}; + +ð { + pinctrl-names = "default"; + pinctrl-0 = <&mdio_pins>; + status = "okay"; + + gmac0: mac@0 { + compatible = "mediatek,eth-mac"; + reg = <0>; + phy-mode = "sgmii"; + phy-handle = <&en8801sc>; + managed = "in-band-status"; + nvmem-cells = <&macaddr_lan>; + nvmem-cell-names = "mac-address"; + }; + + gmac1: mac@1 { + compatible = "mediatek,eth-mac"; + reg = <1>; + phy-mode = "gmii"; + phy-handle = <&int_gbe_phy>; + nvmem-cells = <&macaddr_wan>; + nvmem-cell-names = "mac-address"; + }; +}; + +&wifi { + nvmem-cells = <&eeprom_factory>; + nvmem-cell-names = "eeprom"; + status = "okay"; +}; diff --git a/target/linux/mediatek/dts/mt7981a-glinet-gl-x3000-xe3000-common.dtsi b/target/linux/mediatek/dts/mt7981a-glinet-gl-x3000-xe3000-common.dtsi new file mode 100644 index 000000000..e9050e02e --- /dev/null +++ b/target/linux/mediatek/dts/mt7981a-glinet-gl-x3000-xe3000-common.dtsi @@ -0,0 +1,273 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +/dts-v1/; + +#include "mt7981.dtsi" + +/ { + chosen { + bootargs = "console=ttyS0,115200n8 root=PARTLABEL=rootfs rootwait"; + }; + + aliases { + label-mac-device = &gmac0; + led-boot = &led_power; + led-failsafe = &led_power; + led-running = &led_power; + led-upgrade = &led_power; + }; + + reg_5v: regulator-5v { + compatible = "regulator-fixed"; + regulator-name = "fixed-5V"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-boot-on; + regulator-always-on; + }; + + fan_5v: regulator-fan-5v { + compatible = "regulator-fixed"; + regulator-name = "fan"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + gpios = <&pio 28 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + + gpio-keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + linux,code = ; + gpios = <&pio 1 GPIO_ACTIVE_LOW>; + }; + }; + + gpio-export { + compatible = "gpio-export"; + + hub_power { + gpio-export,name = "hub_power"; + gpio-export,output = <1>; + gpios = <&pio 5 GPIO_ACTIVE_HIGH>; + }; + + 5G_power { + gpio-export,name = "5G_power"; + gpio-export,output = <1>; + gpios = <&pio 11 GPIO_ACTIVE_HIGH>; + }; + + 5G_control { + gpio-export,name = "5G_control"; + gpio-export,output = <1>; + gpios = <&pio 9 GPIO_ACTIVE_HIGH>; + }; + + 5G_reset { + gpio-export,name = "5G_reset"; + gpio-export,output = <0>; + gpios = <&pio 10 GPIO_ACTIVE_HIGH>; + }; + }; + + leds { + compatible = "gpio-leds"; + + wifi2g { + label = "green:wifi2g"; + gpios = <&pio 30 GPIO_ACTIVE_LOW>; + }; + + wifi5g { + label = "green:wifi5g"; + gpios = <&pio 38 GPIO_ACTIVE_LOW>; + }; + + 5g_led1 { + label = "green:5g:led1"; + gpios = <&pio 6 GPIO_ACTIVE_LOW>; + }; + + 5g_led2 { + label = "green:5g:led2"; + gpios = <&pio 7 GPIO_ACTIVE_LOW>; + }; + + 5g_led3 { + label = "green:5g:led3"; + gpios = <&pio 8 GPIO_ACTIVE_LOW>; + }; + + 5g_led4 { + label = "green:5g:led4"; + gpios = <&pio 4 GPIO_ACTIVE_HIGH>; + }; + + led_power: power { + label = "green:power"; + gpios = <&pio 39 GPIO_ACTIVE_LOW>; + }; + + wan { + label = "green:wan"; + gpios = <&pio 31 GPIO_ACTIVE_LOW>; + }; + }; +}; + +&uart0 { + status = "okay"; +}; + +&watchdog { + status = "okay"; +}; + +&mmc0 { + pinctrl-names = "default", "state_uhs"; + pinctrl-0 = <&mmc0_pins_default>; + pinctrl-1 = <&mmc0_pins_uhs>; + bus-width = <8>; + max-frequency = <52000000>; + cap-mmc-highspeed; + vmmc-supply = <®_3p3v>; + non-removable; + status = "okay"; + + card@0 { + compatible = "mmc-card"; + reg = <0>; + + block { + compatible = "block-device"; + partitions { + block-partition-env { + partname = "u-boot-env"; + + nvmem-layout { + compatible = "u-boot,env-layout"; + }; + }; + + block-partition-factory { + partname = "factory"; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + eeprom_factory_0: eeprom@0 { + reg = <0x0 0x1000>; + }; + + macaddr_factory_a: macaddr@a { + compatible = "mac-base"; + reg = <0xa 0x6>; + #nvmem-cell-cells = <1>; + }; + }; + }; + }; + }; + }; +}; + +&mdio_bus { + reset-gpios = <&pio 14 GPIO_ACTIVE_LOW>; + reset-delay-us = <600>; + reset-post-delay-us = <20000>; + + phy5: ethernet-phy@5 { + reg = <5>; + compatible = "ethernet-phy-ieee802.3-c45"; + }; +}; + +ð { + status = "okay"; + + gmac0: mac@0 { + compatible = "mediatek,eth-mac"; + reg = <0>; + phy-mode = "2500base-x"; + phy-handle = <&phy5>; + nvmem-cells = <&macaddr_factory_a 0>; + nvmem-cell-names = "mac-address"; + }; + + gmac1: mac@1 { + compatible = "mediatek,eth-mac"; + reg = <1>; + phy-mode = "gmii"; + phy-handle = <&int_gbe_phy>; + nvmem-cells = <&macaddr_factory_a 1>; + nvmem-cell-names = "mac-address"; + }; +}; + +&pio { + mmc0_pins_default: mmc0-pins-default { + mux { + function = "flash"; + groups = "emmc_8"; + }; + }; + mmc0_pins_uhs: mmc0-pins-uhs { + mux { + function = "flash"; + groups = "emmc_8"; + }; + }; + pcie_pins: pcie-pins { + mux { + function = "pcie"; + groups = "pcie_pereset", "pcie_clk", "pcie_wake"; + }; + }; + pwm0_pin: pwm0-pin-g0 { + mux { + function = "pwm"; + groups = "pwm0_1"; + }; + }; +}; + +&xhci { + phys = <&u2port0 PHY_TYPE_USB2>; + vbus-supply = <®_5v>; + mediatek,u3p-dis-msk = <0x01>; + status = "okay"; +}; + +&usb_phy { + status = "okay"; +}; + +&pcie { + pinctrl-names = "default"; + pinctrl-0 = <&pcie_pins>; + status = "okay"; +}; + +&pwm { + pinctrl-names = "default"; + pinctrl-0 = <&pwm0_pin>; +}; + +&wifi { + nvmem-cells = <&eeprom_factory_0>; + nvmem-cell-names = "eeprom"; + status = "okay"; +}; + +&fan { + pwms = <&pwm 0 40000 0>; + fan-supply = <&fan_5v>; + interrupt-parent = <&pio>; + interrupts = <29 IRQ_TYPE_EDGE_RISING>; + status = "okay"; +}; diff --git a/target/linux/mediatek/dts/mt7981a-glinet-gl-x3000.dts b/target/linux/mediatek/dts/mt7981a-glinet-gl-x3000.dts new file mode 100644 index 000000000..bee1ecd89 --- /dev/null +++ b/target/linux/mediatek/dts/mt7981a-glinet-gl-x3000.dts @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "mt7981a-glinet-gl-x3000-xe3000-common.dtsi" + +/ { + model = "GL.iNet GL-X3000"; + compatible = "glinet,gl-x3000", "mediatek,mt7981"; +}; diff --git a/target/linux/mediatek/dts/mt7981a-glinet-gl-xe3000.dts b/target/linux/mediatek/dts/mt7981a-glinet-gl-xe3000.dts new file mode 100644 index 000000000..e14b944bc --- /dev/null +++ b/target/linux/mediatek/dts/mt7981a-glinet-gl-xe3000.dts @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "mt7981a-glinet-gl-x3000-xe3000-common.dtsi" + +/ { + model = "GL.iNet GL-XE3000"; + compatible = "glinet,gl-xe3000", "mediatek,mt7981"; +}; + +&uart1 { + pinctrl-names = "default"; + pinctrl-0 = <&uart1_pins>; + status = "okay"; +}; + +&pio { + uart1_pins: uart1-pins-g1 { + mux { + function = "uart"; + groups = "uart1_3"; + }; + }; +}; diff --git a/target/linux/mediatek/dts/mt7981a-ubnt-unifi-6-plus.dts b/target/linux/mediatek/dts/mt7981a-ubnt-unifi-6-plus.dts new file mode 100644 index 000000000..48fe2f2fc --- /dev/null +++ b/target/linux/mediatek/dts/mt7981a-ubnt-unifi-6-plus.dts @@ -0,0 +1,170 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +/dts-v1/; +#include "mt7981.dtsi" + +/ { + model = "Ubiquiti UniFi 6 Plus"; + compatible = "ubnt,unifi-6-plus", "mediatek,mt7981"; + + aliases { + serial0 = &uart0; + led-boot = &led_white; + led-failsafe = &led_white; + led-running = &led_blue; + led-upgrade = &led_blue; + label-mac-device = &gmac1; + }; + + chosen { + bootargs-override = "console=ttyS0,115200n8 rootwait root=/dev/mmcblk0p7"; + stdout-path = "serial0:115200n8"; + }; + + gpio-keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + linux,code = ; + gpios = <&pio 1 GPIO_ACTIVE_LOW>; + }; + }; + + + leds { + compatible = "gpio-leds"; + + led_blue: dome-blue { + label = "blue:dome"; + gpios = <&pio 9 GPIO_ACTIVE_HIGH>; + }; + + led_white: dome-white { + label = "white:dome"; + gpios = <&pio 34 GPIO_ACTIVE_HIGH>; + }; + }; +}; + +&uart0 { + status = "okay"; +}; + +&watchdog { + status = "okay"; +}; + +&pio { + spi2_flash_pins: spi2-pins { + mux { + function = "spi"; + groups = "spi2", "spi2_wp_hold"; + }; + + conf-pu { + pins = "SPI2_CS", "SPI2_HOLD", "SPI2_WP"; + drive-strength = <8>; + bias-pull-up = <103>; + }; + + conf-pd { + pins = "SPI2_CLK", "SPI2_MOSI", "SPI2_MISO"; + drive-strength = <8>; + bias-pull-down = <103>; + }; + }; + + mmc0_pins_default: mmc0-pins-default { + mux { + function = "flash"; + groups = "emmc_45"; + }; + }; + + mmc0_pins_uhs: mmc0-pins-uhs { + mux { + function = "flash"; + groups = "emmc_45"; + }; + }; +}; + +&spi2 { + pinctrl-names = "default"; + pinctrl-0 = <&spi2_flash_pins>; + status = "okay"; + + flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "jedec,spi-nor"; + reg = <0>; + + spi-max-frequency = <52000000>; + spi-tx-bus-width = <4>; + spi-rx-bus-width = <4>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + eeprom: partition@00000 { + label = "EEPROM"; + reg = <0x00000 0x10000>; + read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + macaddr_eeprom_0: macaddr@0 { + reg = <0x0 0x6>; + }; + + macaddr_eeprom_6: macaddr@6 { + reg = <0x6 0x6>; + }; + }; + }; + + partition@10000 { + label = "u-boot-env"; + reg = <0x10000 0x80000>; + }; + }; + }; +}; + +&mmc0 { + pinctrl-names = "default", "state_uhs"; + pinctrl-0 = <&mmc0_pins_default>; + pinctrl-1 = <&mmc0_pins_uhs>; + bus-width = <8>; + max-frequency = <52000000>; + cap-mmc-highspeed; + vmmc-supply = <®_3p3v>; + non-removable; + status = "okay"; +}; + +ð { + pinctrl-names = "default"; + pinctrl-0 = <&mdio_pins>; + status = "okay"; + + gmac1: mac@1 { + compatible = "mediatek,eth-mac"; + reg = <1>; + phy-mode = "gmii"; + phy-handle = <&int_gbe_phy>; + nvmem-cell-names = "mac-address"; + nvmem-cells = <&macaddr_eeprom_0>; + }; +}; + +&wifi { + status = "okay"; +}; diff --git a/target/linux/mediatek/dts/mt7981b-cetron-ct3003-mod.dts b/target/linux/mediatek/dts/mt7981b-cetron-ct3003-mod.dts deleted file mode 100644 index b59ee4d20..000000000 --- a/target/linux/mediatek/dts/mt7981b-cetron-ct3003-mod.dts +++ /dev/null @@ -1,23 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later OR MIT - -/dts-v1/; -#include "mt7981b-cetron-ct3003.dts" - -/ { - model = "Cetron CT3003 (U-Boot mod)"; - compatible = "cetron,ct3003-mod", "mediatek,mt7981"; -}; - -&spi0 { - spi_nand@0 { - partitions { - partition@580000 { - label = "ubi"; - reg = <0x0580000 0x7000000>; - }; - - /delete-node/ partition@2580000; - /delete-node/ partition@4580000; - }; - }; -}; diff --git a/target/linux/mediatek/dts/mt7981b-cetron-ct3003.dts b/target/linux/mediatek/dts/mt7981b-cetron-ct3003.dts index ee77b3768..919c20891 100644 --- a/target/linux/mediatek/dts/mt7981b-cetron-ct3003.dts +++ b/target/linux/mediatek/dts/mt7981b-cetron-ct3003.dts @@ -3,6 +3,7 @@ /dts-v1/; #include #include +#include #include "mt7981.dtsi" @@ -12,6 +13,7 @@ aliases { serial0 = &uart0; + label-mac-device = &gmac0; led-boot = &led_status_red; led-failsafe = &led_status_red; led-running = &led_status_green; @@ -46,12 +48,14 @@ compatible = "gpio-leds"; led_status_red: led_status_red { - label = "red:status"; + function = LED_FUNCTION_STATUS; + color = ; gpios = <&pio 3 GPIO_ACTIVE_LOW>; }; led_status_green: led_status_green { - label = "green:status"; + function = LED_FUNCTION_STATUS; + color = ; gpios = <&pio 7 GPIO_ACTIVE_LOW>; }; }; @@ -65,7 +69,7 @@ reg = <0>; phy-mode = "2500base-x"; - nvmem-cells = <&macaddr_art_0>; + nvmem-cells = <&macaddr_art_0 0>; nvmem-cell-names = "mac-address"; fixed-link { @@ -77,7 +81,7 @@ }; &mdio_bus { - switch: switch@0 { + switch: switch@1f { compatible = "mediatek,mt7531"; reg = <31>; reset-gpios = <&pio 39 GPIO_ACTIVE_HIGH>; @@ -128,12 +132,16 @@ reg = <0x0180000 0x0100000>; read-only; - compatible = "nvmem-cells"; - #address-cells = <1>; - #size-cells = <1>; + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; - macaddr_art_0: macaddr@0 { - reg = <0x0 0x6>; + macaddr_art_0: macaddr@0 { + compatible = "mac-base"; + reg = <0x0 0x6>; + #nvmem-cell-cells = <1>; + }; }; }; @@ -190,9 +198,8 @@ port@3 { reg = <3>; label = "wan"; - nvmem-cells = <&macaddr_art_0>; + nvmem-cells = <&macaddr_art_0 3>; nvmem-cell-names = "mac-address"; - mac-address-increment = <3>; }; port@6 { diff --git a/target/linux/mediatek/dts/mt7981b-cmcc-rax3000m-emmc.dts b/target/linux/mediatek/dts/mt7981b-cmcc-rax3000m-emmc.dts deleted file mode 100644 index c1ce4d130..000000000 --- a/target/linux/mediatek/dts/mt7981b-cmcc-rax3000m-emmc.dts +++ /dev/null @@ -1,42 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later OR MIT - -/dts-v1/; -#include "mt7981b-cmcc-rax3000m.dts" - -/ { - model = "CMCC RAX3000M (eMMC version)"; - compatible = "cmcc,rax3000m-emmc", "mediatek,mt7981"; - - chosen { - bootargs = "root=PARTLABEL=rootfs rootwait rootfstype=squashfs,f2fs"; - }; -}; - -&mmc0 { - bus-width = <8>; - max-frequency = <26000000>; - no-sd; - no-sdio; - non-removable; - pinctrl-names = "default", "state_uhs"; - pinctrl-0 = <&mmc0_pins_default>; - pinctrl-1 = <&mmc0_pins_uhs>; - vmmc-supply = <®_3p3v>; - status = "okay"; -}; - -&pio { - mmc0_pins_default: mmc0-pins { - mux { - function = "flash"; - groups = "emmc_45"; - }; - }; - - mmc0_pins_uhs: mmc0-uhs-pins { - mux { - function = "flash"; - groups = "emmc_45"; - }; - }; -}; diff --git a/target/linux/mediatek/dts/mt7981b-cmcc-rax3000m-emmc.dtso b/target/linux/mediatek/dts/mt7981b-cmcc-rax3000m-emmc.dtso new file mode 100644 index 000000000..c1c9c75c2 --- /dev/null +++ b/target/linux/mediatek/dts/mt7981b-cmcc-rax3000m-emmc.dtso @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +/dts-v1/; +/plugin/; + +/ { + compatible = "cmcc,rax3000m", "mediatek,mt7981"; + + fragment@0 { + target = <&mmc0>; + __overlay__ { + bus-width = <8>; + max-frequency = <26000000>; + no-sd; + no-sdio; + non-removable; + pinctrl-names = "default", "state_uhs"; + pinctrl-0 = <&mmc0_pins_default>; + pinctrl-1 = <&mmc0_pins_uhs>; + vmmc-supply = <®_3p3v>; + status = "okay"; + }; + }; + + fragment@1 { + target = <&pio>; + __overlay__ { + mmc0_pins_default: mmc0-pins { + mux { + function = "flash"; + groups = "emmc_45"; + }; + }; + + mmc0_pins_uhs: mmc0-uhs-pins { + mux { + function = "flash"; + groups = "emmc_45"; + }; + }; + }; + }; +}; diff --git a/target/linux/mediatek/dts/mt7981b-cmcc-rax3000m-nand.dts b/target/linux/mediatek/dts/mt7981b-cmcc-rax3000m-nand.dts deleted file mode 100644 index 086a4223d..000000000 --- a/target/linux/mediatek/dts/mt7981b-cmcc-rax3000m-nand.dts +++ /dev/null @@ -1,92 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later OR MIT - -/dts-v1/; -#include "mt7981b-cmcc-rax3000m.dts" - -/ { - model = "CMCC RAX3000M (NAND version)"; - compatible = "cmcc,rax3000m-nand", "mediatek,mt7981"; - - aliases { - label-mac-device = &gmac1; - }; -}; - -&spi0 { - pinctrl-names = "default"; - pinctrl-0 = <&spi0_flash_pins>; - status = "okay"; - - spi_nand: flash@0 { - #address-cells = <1>; - #size-cells = <1>; - compatible = "spi-nand"; - reg = <0>; - - spi-max-frequency = <52000000>; - spi-tx-bus-width = <4>; - spi-rx-bus-width = <4>; - mediatek,nmbm; - mediatek,bmt-max-ratio = <1>; - mediatek,bmt-max-reserved-blocks = <64>; - - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - partition@0 { - label = "bl2"; - reg = <0x00000 0x0100000>; - read-only; - }; - - partition@100000 { - label = "u-boot-env"; - reg = <0x100000 0x80000>; - }; - - factory: partition@180000 { - label = "factory"; - reg = <0x180000 0x200000>; - read-only; - }; - - partition@380000 { - label = "fip"; - reg = <0x380000 0x200000>; - read-only; - }; - - partition@580000 { - label = "ubi"; - reg = <0x580000 0x7200000>; - }; - }; - }; -}; - -&pio { - spi0_flash_pins: spi0-pins { - mux { - function = "spi"; - groups = "spi0", "spi0_wp_hold"; - }; - - conf-pu { - pins = "SPI0_CS", "SPI0_HOLD", "SPI0_WP"; - drive-strength = <8>; - mediatek,pull-up-adv = <0>; /* bias-disable */ - }; - - conf-pd { - pins = "SPI0_CLK", "SPI0_MOSI", "SPI0_MISO"; - drive-strength = <8>; - mediatek,pull-up-adv = <0>; /* bias-disable */ - }; - }; -}; - -&wifi { - mediatek,mtd-eeprom = <&factory 0x0>; -}; diff --git a/target/linux/mediatek/dts/mt7981b-cmcc-rax3000m-nand.dtso b/target/linux/mediatek/dts/mt7981b-cmcc-rax3000m-nand.dtso new file mode 100644 index 000000000..4d2b01cb6 --- /dev/null +++ b/target/linux/mediatek/dts/mt7981b-cmcc-rax3000m-nand.dtso @@ -0,0 +1,127 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +/dts-v1/; +/plugin/; + +/ { + compatible = "cmcc,rax3000m", "mediatek,mt7981"; + + fragment@0 { + target = <&gmac0>; + __overlay__ { + nvmem-cells = <&macaddr_factory_2a 0>; + nvmem-cell-names = "mac-address"; + }; + }; + + fragment@1 { + target = <&gmac1>; + __overlay__ { + nvmem-cells = <&macaddr_factory_24 0>; + nvmem-cell-names = "mac-address"; + }; + }; + + fragment@2 { + target = <&pio>; + __overlay__ { + spi0_flash_pins: spi0-pins { + mux { + function = "spi"; + groups = "spi0", "spi0_wp_hold"; + }; + + conf-pu { + pins = "SPI0_CS", "SPI0_HOLD", "SPI0_WP"; + drive-strength = <8>; + mediatek,pull-up-adv = <0>; /* bias-disable */ + }; + + conf-pd { + pins = "SPI0_CLK", "SPI0_MOSI", "SPI0_MISO"; + drive-strength = <8>; + mediatek,pull-up-adv = <0>; /* bias-disable */ + }; + }; + }; + }; + + fragment@3 { + target = <&spi0>; + __overlay__ { + pinctrl-names = "default"; + pinctrl-0 = <&spi0_flash_pins>; + status = "okay"; + + spi_nand@0 { + compatible = "spi-nand"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0>; + + spi-max-frequency = <52000000>; + spi-tx-bus-width = <4>; + spi-rx-bus-width = <4>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "bl2"; + reg = <0x00000 0x0100000>; + read-only; + }; + + partition@100000 { + label = "u-boot-env"; + reg = <0x100000 0x80000>; + }; + + factory: partition@180000 { + label = "factory"; + reg = <0x180000 0x200000>; + read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + macaddr_factory_24: macaddr@24 { + compatible = "mac-base"; + reg = <0x24 0x6>; + #nvmem-cell-cells = <1>; + }; + + macaddr_factory_2a: macaddr@2a { + compatible = "mac-base"; + reg = <0x2a 0x6>; + #nvmem-cell-cells = <1>; + }; + }; + }; + + partition@380000 { + label = "fip"; + reg = <0x380000 0x200000>; + read-only; + }; + + partition@580000 { + label = "ubi"; + reg = <0x580000 0x7200000>; + }; + }; + }; + }; + }; + + fragment@4 { + target = <&wifi>; + __overlay__ { + mediatek,mtd-eeprom = <&factory 0x0>; + }; + }; +}; diff --git a/target/linux/mediatek/dts/mt7981b-cmcc-rax3000m.dts b/target/linux/mediatek/dts/mt7981b-cmcc-rax3000m.dts index 3f330f40f..c8db5b58f 100644 --- a/target/linux/mediatek/dts/mt7981b-cmcc-rax3000m.dts +++ b/target/linux/mediatek/dts/mt7981b-cmcc-rax3000m.dts @@ -6,6 +6,7 @@ /dts-v1/; #include #include +#include #include "mt7981.dtsi" @@ -50,17 +51,20 @@ compatible = "gpio-leds"; green_led: led-0 { - label = "green:status"; + function = LED_FUNCTION_STATUS; + color = ; gpios = <&pio 9 GPIO_ACTIVE_LOW>; }; led-1 { - label = "blue:status"; + function = LED_FUNCTION_STATUS; + color = ; gpios = <&pio 12 GPIO_ACTIVE_LOW>; }; red_led: led-2 { - label = "red:status"; + function = LED_FUNCTION_STATUS; + color = ; gpios = <&pio 35 GPIO_ACTIVE_LOW>; }; }; diff --git a/target/linux/mediatek/dts/mt7981b-confiabits-mt7981.dts b/target/linux/mediatek/dts/mt7981b-confiabits-mt7981.dts new file mode 100644 index 000000000..8b9c7a754 --- /dev/null +++ b/target/linux/mediatek/dts/mt7981b-confiabits-mt7981.dts @@ -0,0 +1,296 @@ +// SPDX-License-Identifier: GPL-2.0-only OR MIT +/dts-v1/; + +#include "mt7981.dtsi" +#include +#include +#include + +/ { + model = "Confiabits MT7981"; + compatible = "confiabits,mt7981", "mediatek,mt7981"; + + aliases { + led-boot = &led_power; + led-failsafe = &led_power; + led-running = &led_power; + led-upgrade = &led_power; + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + gpio-keys { + compatible = "gpio-keys"; + + button-mesh { + label = "mesh"; + linux,input-type = ; + linux,code = ; + gpios = <&pio 0 GPIO_ACTIVE_HIGH>; + debounce-interval = <60>; + }; + + button-reset { + label = "reset"; + linux,code = ; + gpios = <&pio 1 GPIO_ACTIVE_LOW>; + }; + }; + + leds { + compatible = "gpio-leds"; + + led-wlan5g { + color = ; + function = LED_FUNCTION_WLAN; + function-enumerator = <5>; + gpios = <&pio 5 GPIO_ACTIVE_LOW>; + linux,default-trigger = "phy1tpt"; + }; + + led-wan-red { + color = ; + function = LED_FUNCTION_WAN; + gpios = <&pio 6 GPIO_ACTIVE_LOW>; + }; + + led_power: led-power { + color = ; + function = LED_FUNCTION_POWER; + gpios = <&pio 7 GPIO_ACTIVE_LOW>; + }; + + led-lan1 { + color = ; + function = LED_FUNCTION_LAN; + function-enumerator = <1>; + gpios = <&pio 9 GPIO_ACTIVE_LOW>; + }; + + led-lan2 { + color = ; + function = LED_FUNCTION_LAN; + function-enumerator = <2>; + gpios = <&pio 10 GPIO_ACTIVE_LOW>; + }; + + led-lan3 { + color = ; + function = LED_FUNCTION_LAN; + function-enumerator = <3>; + gpios = <&pio 11 GPIO_ACTIVE_LOW>; + }; + + led-wan-blue { + color = ; + function = LED_FUNCTION_WAN; + gpios = <&pio 12 GPIO_ACTIVE_LOW>; + }; + + led-wlan2g { + color = ; + function = LED_FUNCTION_WLAN; + function-enumerator = <2>; + gpios = <&pio 34 GPIO_ACTIVE_LOW>; + linux,default-trigger = "phy0tpt"; + }; + + led-mesh { + color = ; + function = "mesh"; // no LED_FUNCTION_MESH yet + gpios = <&pio 35 GPIO_ACTIVE_LOW>; + }; + }; +}; + +&uart0 { + status = "okay"; +}; + +&watchdog { + status = "okay"; +}; + +ð { + pinctrl-names = "default"; + pinctrl-0 = <&mdio_pins>; + + status = "okay"; + + gmac0: mac@0 { + compatible = "mediatek,eth-mac"; + reg = <0>; + phy-mode = "2500base-x"; + + nvmem-cell-names = "mac-address"; + nvmem-cells = <&macaddr_factory_4 0>; + + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; + }; +}; + + +&mdio_bus { + #address-cells = <1>; + #size-cells = <0>; + + switch: switch@1f { + compatible = "mediatek,mt7531"; + reg = <31>; + reset-gpios = <&pio 39 GPIO_ACTIVE_HIGH>; + }; +}; + +&switch { + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + label = "lan1"; + }; + + port@2 { + reg = <2>; + label = "lan2"; + }; + + port@3 { + reg = <3>; + label = "lan3"; + }; + + port@4 { + reg = <4>; + label = "wan"; + + nvmem-cell-names = "mac-address"; + nvmem-cells = <&macaddr_factory_4 1>; + }; + + port@6 { + reg = <6>; + label = "cpu"; + ethernet = <&gmac0>; + phy-mode = "2500base-x"; + + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; + }; + }; +}; + +&spi0 { + pinctrl-names = "default"; + pinctrl-0 = <&spi0_flash_pins>; + status = "okay"; + + spi_nand: flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "spi-nand"; + reg = <0>; + spi-max-frequency = <52000000>; + + spi-cal-enable; + spi-cal-mode = "read-data"; + spi-cal-datalen = <7>; + spi-cal-data = /bits/ 8 <0x53 0x50 0x49 0x4E 0x41 0x4E 0x44>; + spi-cal-addrlen = <5>; + spi-cal-addr = /bits/ 32 <0x0 0x0 0x0 0x0 0x0>; + + spi-tx-bus-width = <4>; + spi-rx-bus-width = <4>; + mediatek,nmbm; + mediatek,bmt-max-ratio = <1>; + mediatek,bmt-max-reserved-blocks = <64>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "BL2"; + reg = <0x00000 0x0100000>; + read-only; + }; + + partition@100000 { + label = "u-boot-env"; + reg = <0x0100000 0x0080000>; + read-only; + }; + + factory: partition@180000 { + label = "Factory"; + reg = <0x180000 0x0200000>; + read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + eeprom_factory_0: eeprom@0 { + reg = <0x0 0x1000>; + }; + + macaddr_factory_4: macaddr@4 { + compatible = "mac-base"; + reg = <0x4 0x6>; + #nvmem-cell-cells = <1>; + }; + }; + }; + + partition@380000 { + label = "FIP"; + reg = <0x380000 0x0200000>; + read-only; + }; + + partition@580000 { + label = "ubi"; + reg = <0x580000 0x4000000>; + compatible = "linux,ubi"; + }; + }; + }; +}; + +&pio { + spi0_flash_pins: spi0-pins { + mux { + function = "spi"; + groups = "spi0", "spi0_wp_hold"; + }; + }; + +}; + +&usb_phy { + status = "okay"; +}; + +&xhci { + status = "okay"; + mediatek,u3p-dis-msk = <0x1>; +}; + +&wifi { + status = "okay"; + nvmem-cells = <&eeprom_factory_0>; + nvmem-cell-names = "eeprom"; +}; diff --git a/target/linux/mediatek/dts/mt7981b-cudy-m3000-v1.dts b/target/linux/mediatek/dts/mt7981b-cudy-m3000-v1.dts new file mode 100644 index 000000000..85bdabe47 --- /dev/null +++ b/target/linux/mediatek/dts/mt7981b-cudy-m3000-v1.dts @@ -0,0 +1,214 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) + +/dts-v1/; + +#include "mt7981.dtsi" + +/ { + model = "Cudy M3000 v1"; + compatible = "cudy,m3000-v1", "mediatek,mt7981-spim-snand-rfb"; + + aliases { + label-mac-device = &gmac0; + led-boot = &led_status; + led-failsafe = &led_status; + led-running = &led_status; + led-upgrade = &led_status; + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + gpio-keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + gpios = <&pio 1 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + + wps { + label = "wps"; + gpios = <&pio 0 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + leds { + compatible = "gpio-leds"; + + led_status: internet-white { + function = LED_FUNCTION_WAN_ONLINE; + color = ; + gpios = <&pio 10 GPIO_ACTIVE_LOW>; + }; + + internet-red { + function = LED_FUNCTION_WAN_ONLINE; + color = ; + gpios = <&pio 4 GPIO_ACTIVE_LOW>; + }; + + wan { + function = LED_FUNCTION_WAN; + color = ; + gpios = <&pio 5 GPIO_ACTIVE_LOW>; + }; + + lan { + function = LED_FUNCTION_LAN; + color = ; + gpios = <&pio 9 GPIO_ACTIVE_LOW>; + }; + }; +}; + +&uart0 { + status = "okay"; +}; + +&watchdog { + status = "okay"; +}; + +ð { + pinctrl-names = "default"; + pinctrl-0 = <&mdio_pins>; + + status = "okay"; + + gmac0: mac@0 { + compatible = "mediatek,eth-mac"; + reg = <0>; + phy-mode = "2500base-x"; + phy-handle = <&rtl8221b_phy>; + + nvmem-cell-names = "mac-address"; + nvmem-cells = <&macaddr_bdinfo_de00 1>; + }; + + gmac1: mac@1 { + compatible = "mediatek,eth-mac"; + reg = <1>; + phy-mode = "gmii"; + phy-handle = <&int_gbe_phy>; + + nvmem-cell-names = "mac-address"; + nvmem-cells = <&macaddr_bdinfo_de00 0>; + }; +}; + +&mdio_bus { + rtl8221b_phy: ethernet-phy@1 { + compatible = "ethernet-phy-ieee802.3-c45"; + reg = <1>; + + reset-gpios = <&pio 39 GPIO_ACTIVE_LOW>; + + interrupts = <38 IRQ_TYPE_LEVEL_LOW>; + reset-assert-us = <100000>; + reset-deassert-us = <100000>; + }; +}; + +&spi0 { + pinctrl-names = "default"; + pinctrl-0 = <&spi0_flash_pins>; + + status = "okay"; + + spi_nand: spi_nand@0 { + compatible = "spi-nand"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0>; + + spi-max-frequency = <52000000>; + spi-tx-buswidth = <4>; + spi-rx-buswidth = <4>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + mediatek,nmbm; + mediatek,bmt-max-ratio = <1>; + mediatek,bmt-max-reserved-blocks = <64>; + + partition@0 { + label = "BL2"; + reg = <0x0000000 0x0100000>; + read-only; + }; + + partition@100000 { + label = "u-boot-env"; + reg = <0x0100000 0x0080000>; + }; + + factory: partition@180000 { + label = "Factory"; + reg = <0x0180000 0x0200000>; + read-only; + }; + + bdinfo: partition@380000 { + label = "bdinfo"; + reg = <0x0380000 0x0040000>; + read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + macaddr_bdinfo_de00: macaddr@de00 { + #nvmem-cell-cells = <1>; + compatible = "mac-base"; + reg = <0xde00 0x6>; + }; + }; + }; + + partition@3c0000 { + label = "FIP"; + reg = <0x03c0000 0x0200000>; + }; + + partition@5c0000 { + label = "ubi"; + reg = <0x05c0000 0x4000000>; + }; + }; + }; +}; + +&pio { + spi0_flash_pins: spi0-pins { + mux { + function = "spi"; + groups = "spi0", "spi0_wp_hold"; + }; + + conf-pu { + pins = "SPI0_CS", "SPI0_HOLD", "SPI0_WP"; + drive-strength = ; + bias-pull-up = ; + }; + + conf-pd { + pins = "SPI0_CLK", "SPI0_MOSI", "SPI0_MISO"; + drive-strength = ; + bias-pull-down = ; + }; + }; +}; + +&wifi { + status = "okay"; + mediatek,mtd-eeprom = <&factory 0x0>; +}; diff --git a/target/linux/mediatek/dts/mt7981b-cudy-re3000-v1.dts b/target/linux/mediatek/dts/mt7981b-cudy-re3000-v1.dts new file mode 100644 index 000000000..4025e5aaa --- /dev/null +++ b/target/linux/mediatek/dts/mt7981b-cudy-re3000-v1.dts @@ -0,0 +1,221 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) + +/dts-v1/; + +#include +#include +#include + +#include "mt7981.dtsi" + +/ { + model = "Cudy RE3000 v1"; + compatible = "cudy,re3000-v1", "mediatek,mt7981"; + + aliases { + serial0 = &uart0; + label-mac-device = &gmac1; + led-boot = &led_status; + led-failsafe = &led_status; + led-running = &led_status; + led-upgrade = &led_status; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + gpio-keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + linux,code = ; + gpios = <&pio 1 GPIO_ACTIVE_LOW>; + }; + + wps { + label = "wps"; + linux,code = ; + gpios = <&pio 0 GPIO_ACTIVE_LOW>; + }; + }; + + leds { + compatible = "gpio-leds"; + + led_status: led@0 { + function = LED_FUNCTION_STATUS; + color = ; + gpios = <&pio 10 GPIO_ACTIVE_LOW>; + }; + + led@1 { + label = "red:wifi5"; + gpios = <&pio 7 GPIO_ACTIVE_LOW>; + linux,default-trigger = "phy1tpt"; + }; + + led@2 { + label = "white:wifi2"; + gpios = <&pio 6 GPIO_ACTIVE_LOW>; + linux,default-trigger = "phy0tpt"; + }; + + led@3 { + function = LED_FUNCTION_LAN; + color = ; + gpios = <&pio 9 GPIO_ACTIVE_LOW>; + }; + + led@4 { + function = LED_FUNCTION_WPS; + color = ; + gpios = <&pio 11 GPIO_ACTIVE_LOW>; + }; + }; +}; + +&uart0 { + status = "okay"; +}; + +&watchdog { + status = "okay"; +}; + +ð { + pinctrl-names = "default"; + pinctrl-0 = <&mdio_pins>; + status = "okay"; + + gmac1: mac@1 { + compatible = "mediatek,eth-mac"; + reg = <1>; + phy-mode = "gmii"; + phy-handle = <&int_gbe_phy>; + nvmem-cell-names = "mac-address"; + nvmem-cells = <&macaddr_bdinfo_de00 0>; + }; +}; + +&mdio_bus { + switch: switch@1f { + compatible = "mediatek,mt7531"; + reg = <31>; + reset-gpios = <&pio 39 GPIO_ACTIVE_HIGH>; + }; +}; + +&spi0 { + status = "disabled"; +}; + +&spi2 { + pinctrl-names = "default"; + pinctrl-0 = <&spi2_flash_pins>; + status = "okay"; + + flash@0 { + #address-cells = <1>; + #size-cells = <1>; + + compatible = "jedec,spi-nor"; + reg = <0>; + + spi-max-frequency = <25000000>; + spi-tx-bus-width = <4>; + spi-rx-bus-width = <4>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@00000 { + label = "BL2"; + reg = <0x00000 0x40000>; + read-only; + }; + + partition@40000 { + label = "u-boot-env"; + reg = <0x40000 0x10000>; + read-only; + }; + + factory: partition@50000 { + label = "Factory"; + reg = <0x50000 0x10000>; + read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + eeprom_factory_0: eeprom@0 { + reg = <0x0 0x1000>; + }; + }; + }; + + bdinfo: partition@60000 { + label = "bdinfo"; + reg = <0x60000 0x10000>; + read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + macaddr_bdinfo_de00: macaddr@de00 { + compatible = "mac-base"; + reg = <0xde00 0x6>; + #nvmem-cell-cells = <1>; + }; + }; + }; + + partition@70000 { + label = "FIP"; + reg = <0x70000 0x80000>; + read-only; + }; + + partition@f0000 { + compatible = "denx,fit"; + label = "firmware"; + reg = <0xf0000 0xf10000>; + }; + }; + }; +}; + +&pio { + spi2_flash_pins: spi2-pins { + mux { + function = "spi"; + groups = "spi2", "spi2_wp_hold"; + }; + + conf-pu { + pins = "SPI2_CS", "SPI2_HOLD", "SPI2_WP"; + drive-strength = <8>; + bias-pull-up = <103>; + }; + + conf-pd { + pins = "SPI2_CLK", "SPI2_MOSI", "SPI2_MISO"; + drive-strength = <8>; + bias-pull-down = <103>; + }; + }; +}; + +&wifi { + status = "okay"; + nvmem-cells = <&eeprom_factory_0>; + nvmem-cell-names = "eeprom"; +}; diff --git a/target/linux/mediatek/dts/mt7981b-cudy-tr3000-v1.dts b/target/linux/mediatek/dts/mt7981b-cudy-tr3000-v1.dts new file mode 100644 index 000000000..1f03b42b1 --- /dev/null +++ b/target/linux/mediatek/dts/mt7981b-cudy-tr3000-v1.dts @@ -0,0 +1,232 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) + +/dts-v1/; + +#include + +#include "mt7981.dtsi" + +/ { + model = "Cudy TR3000 v1"; + compatible = "cudy,tr3000-v1", "mediatek,mt7981-spim-snand-rfb"; + + aliases { + label-mac-device = &gmac1; + led-boot = &led_status; + led-failsafe = &led_status; + led-running = &led_status; + led-upgrade = &led_status; + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + gpio-keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + linux,code = ; + gpios = <&pio 1 GPIO_ACTIVE_LOW>; + }; + + mode { + label = "mode"; + linux,input-type = ; + linux,code = ; + gpios = <&pio 0 GPIO_ACTIVE_LOW>; + debounce-interval = <60>; + }; + }; + + leds { + compatible = "gpio-leds"; + + led_status: led_0 { + function = LED_FUNCTION_POWER; + color = ; + gpios = <&pio 11 GPIO_ACTIVE_LOW>; + }; + + led_1 { + function = LED_FUNCTION_STATUS; + color = ; + gpios = <&pio 10 GPIO_ACTIVE_LOW>; + }; + + }; + + usb_vbus: regulator-usb { + compatible = "regulator-fixed"; + + regulator-name = "usb-vbus"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + + gpios = <&pio 9 GPIO_ACTIVE_LOW>; + regulator-boot-on; + }; +}; + +&uart0 { + status = "okay"; +}; + +&watchdog { + status = "okay"; +}; + +ð { + pinctrl-names = "default"; + pinctrl-0 = <&mdio_pins>; + + status = "okay"; + + gmac0: mac@0 { + compatible = "mediatek,eth-mac"; + reg = <0>; + phy-mode = "2500base-x"; + phy-handle = <&phy1>; + nvmem-cell-names = "mac-address"; + nvmem-cells = <&macaddr_bdinfo_de00 1>; + }; + + gmac1: mac@1 { + compatible = "mediatek,eth-mac"; + reg = <1>; + phy-mode = "gmii"; + phy-handle = <&int_gbe_phy>; + nvmem-cell-names = "mac-address"; + nvmem-cells = <&macaddr_bdinfo_de00 0>; + }; +}; + +&mdio_bus { + phy1: phy@1 { + reg = <1>; + compatible = "ethernet-phy-ieee802.3-c45"; + phy-mode = "2500base-x"; + reset-gpios = <&pio 39 GPIO_ACTIVE_LOW>; + interrupts = <38 IRQ_TYPE_LEVEL_LOW>; + reset-assert-us = <100000>; + reset-deassert-us = <100000>; + realtek,aldps-enable; + }; +}; + +&spi0 { + pinctrl-names = "default"; + pinctrl-0 = <&spi0_flash_pins>; + status = "okay"; + + spi_nand: flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "spi-nand"; + reg = <0>; + spi-max-frequency = <52000000>; + + spi-cal-enable; + spi-cal-mode = "read-data"; + spi-cal-datalen = <7>; + spi-cal-data = /bits/ 8 <0x53 0x50 0x49 0x4E 0x41 0x4E 0x44>; + spi-cal-addrlen = <5>; + spi-cal-addr = /bits/ 32 <0x0 0x0 0x0 0x0 0x0>; + + spi-tx-bus-width = <4>; + spi-rx-bus-width = <4>; + mediatek,nmbm; + mediatek,bmt-max-ratio = <1>; + mediatek,bmt-max-reserved-blocks = <64>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "BL2"; + reg = <0x00000 0x0100000>; + read-only; + }; + + partition@100000 { + label = "u-boot-env"; + reg = <0x0100000 0x0080000>; + read-only; + }; + + factory: partition@180000 { + label = "Factory"; + reg = <0x180000 0x0200000>; + read-only; + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + eeprom_factory_0: eeprom@0 { + reg = <0x0 0x1000>; + }; + }; + }; + + partition@380000 { + label = "bdinfo"; + reg = <0x380000 0x0040000>; + read-only; + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + macaddr_bdinfo_de00: macaddr@de00 { + compatible = "mac-base"; + reg = <0xde00 0x6>; + #nvmem-cell-cells = <1>; + }; + }; + + }; + + partition@3C0000 { + label = "FIP"; + reg = <0x3C0000 0x0200000>; + read-only; + }; + + partition@580000 { + label = "ubi"; + reg = <0x5C0000 0x4000000>; + compatible = "linux,ubi"; + }; + }; + }; +}; + + +&pio { + spi0_flash_pins: spi0-pins { + mux { + function = "spi"; + groups = "spi0", "spi0_wp_hold"; + }; + }; +}; + +&usb_phy { + status = "okay"; +}; + +&xhci { + status = "okay"; + vbus-supply = <&usb_vbus>; +}; + +&wifi { + status = "okay"; + nvmem-cells = <&eeprom_factory_0>; + nvmem-cell-names = "eeprom"; +}; diff --git a/target/linux/mediatek/dts/mt7981b-cudy-wr3000-v1.dts b/target/linux/mediatek/dts/mt7981b-cudy-wr3000-v1.dts new file mode 100644 index 000000000..1ded8b5a6 --- /dev/null +++ b/target/linux/mediatek/dts/mt7981b-cudy-wr3000-v1.dts @@ -0,0 +1,279 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) + +/dts-v1/; + +#include + +#include "mt7981.dtsi" + +/ { + model = "Cudy WR3000 v1"; + compatible = "cudy,wr3000-v1", "mediatek,mt7981"; + + aliases { + ethernet0 = &gmac0; + label-mac-device = &gmac0; + led-boot = &led_status; + led-failsafe = &led_status; + led-running = &led_status; + led-upgrade = &led_status; + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + gpio-keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + linux,code = ; + gpios = <&pio 1 GPIO_ACTIVE_LOW>; + }; + + wps { + label = "wps"; + linux,code = ; + gpios = <&pio 0 GPIO_ACTIVE_LOW>; + }; + }; + + leds { + compatible = "gpio-leds"; + + led_status: led@0 { + function = LED_FUNCTION_STATUS; + color = ; + gpios = <&pio 10 GPIO_ACTIVE_LOW>; + }; + + led@1 { + label = "blue:internet"; + gpios = <&pio 11 GPIO_ACTIVE_LOW>; + }; + + led@2 { + function = LED_FUNCTION_WAN; + color = ; + gpios = <&pio 5 GPIO_ACTIVE_LOW>; + }; + + led@3 { + function = LED_FUNCTION_LAN; + color = ; + gpios = <&pio 9 GPIO_ACTIVE_LOW>; + }; + + led@4 { + label = "blue:wifi2"; + gpios = <&pio 6 GPIO_ACTIVE_LOW>; + linux,default-trigger = "phy0tpt"; + }; + + led@5 { + label = "blue:wifi5"; + gpios = <&pio 7 GPIO_ACTIVE_LOW>; + linux,default-trigger = "phy1tpt"; + }; + }; +}; + +&uart0 { + status = "okay"; +}; + +&watchdog { + status = "okay"; +}; + +ð { + pinctrl-names = "default"; + pinctrl-0 = <&mdio_pins>; + + status = "okay"; + + gmac0: mac@0 { + compatible = "mediatek,eth-mac"; + reg = <0>; + phy-mode = "2500base-x"; + + nvmem-cell-names = "mac-address"; + nvmem-cells = <&macaddr_bdinfo_de00 0>; + + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; + }; + + gmac1: mac@1 { + compatible = "mediatek,eth-mac"; + reg = <1>; + status = "disabled"; + }; +}; + +&mdio_bus { + switch: switch@1f { + compatible = "mediatek,mt7531"; + reg = <31>; + reset-gpios = <&pio 39 GPIO_ACTIVE_HIGH>; + }; +}; + +&spi0 { + pinctrl-names = "default"; + pinctrl-0 = <&spi0_flash_pins>; + status = "disabled"; +}; + +&spi2 { + pinctrl-names = "default"; + pinctrl-0 = <&spi2_flash_pins>; + status = "okay"; + + flash@0 { + #address-cells = <1>; + #size-cells = <1>; + + compatible = "jedec,spi-nor"; + reg = <0>; + + spi-max-frequency = <25000000>; + spi-tx-bus-width = <4>; + spi-rx-bus-width = <4>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@00000 { + label = "BL2"; + reg = <0x00000 0x40000>; + read-only; + }; + + partition@40000 { + label = "u-boot-env"; + reg = <0x40000 0x10000>; + read-only; + }; + + factory: partition@50000 { + label = "Factory"; + reg = <0x50000 0x10000>; + read-only; + }; + + bdinfo: partition@60000 { + label = "bdinfo"; + reg = <0x60000 0x10000>; + read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + macaddr_bdinfo_de00: macaddr@de00 { + compatible = "mac-base"; + reg = <0xde00 0x6>; + #nvmem-cell-cells = <1>; + }; + }; + }; + + partition@70000 { + label = "FIP"; + reg = <0x70000 0x80000>; + read-only; + }; + + partition@f0000 { + compatible = "denx,fit"; + label = "firmware"; + reg = <0xf0000 0xf10000>; + }; + }; + }; +}; + +&pio { + spi0_flash_pins: spi0-pins { + mux { + function = "spi"; + groups = "spi0", "spi0_wp_hold"; + }; + }; + + spi2_flash_pins: spi2-pins { + mux { + function = "spi"; + groups = "spi2", "spi2_wp_hold"; + }; + + conf-pu { + pins = "SPI2_CS", "SPI2_HOLD", "SPI2_WP"; + drive-strength = <8>; + bias-pull-up = <103>; + }; + + conf-pd { + pins = "SPI2_CLK", "SPI2_MOSI", "SPI2_MISO"; + drive-strength = <8>; + bias-pull-down = <103>; + }; + }; +}; + +&switch { + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + label = "wan"; + + nvmem-cell-names = "mac-address"; + nvmem-cells = <&macaddr_bdinfo_de00 1>; + }; + + port@1 { + reg = <1>; + label = "lan1"; + }; + + port@2 { + reg = <2>; + label = "lan2"; + }; + + port@3 { + reg = <3>; + label = "lan3"; + }; + + port@6 { + reg = <6>; + label = "cpu"; + ethernet = <&gmac0>; + phy-mode = "2500base-x"; + + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; + }; + }; +}; + +&wifi { + status = "okay"; + mediatek,mtd-eeprom = <&factory 0x0>; +}; diff --git a/target/linux/mediatek/dts/mt7981b-dlink-aquila-pro-ai-m30-a1.dts b/target/linux/mediatek/dts/mt7981b-dlink-aquila-pro-ai-m30-a1.dts new file mode 100644 index 000000000..dc14fce2b --- /dev/null +++ b/target/linux/mediatek/dts/mt7981b-dlink-aquila-pro-ai-m30-a1.dts @@ -0,0 +1,310 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) + +/dts-v1/; + +#include "mt7981.dtsi" + +/ { + model = "D-Link AQUILA PRO AI M30 A1"; + compatible = "dlink,aquila-pro-ai-m30-a1", "mediatek,mt7981"; + + aliases { + label-mac-device = &gmac0; + led-boot = &led_status_white; + led-failsafe = &led_status_red; + led-running = &led_status_white; + led-upgrade = &led_status_blue; + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + gpio-keys { + compatible = "gpio-keys"; + + button-reset { + label = "reset"; + linux,code = ; + gpios = <&pio 0 GPIO_ACTIVE_LOW>; + }; + + button-wps { + label = "wps"; + linux,code = ; + gpios = <&pio 1 GPIO_ACTIVE_LOW>; + }; + + button-leds-on-off { + label = "leds-on-off"; + linux,code = ; + gpios = <&pio 4 GPIO_ACTIVE_LOW>; + }; + }; +}; + +&uart0 { + status = "okay"; +}; + +&watchdog { + status = "okay"; +}; + +ð { + pinctrl-names = "default"; + pinctrl-0 = <&mdio_pins>; + + status = "okay"; + + gmac0: mac@0 { + compatible = "mediatek,eth-mac"; + reg = <0>; + phy-mode = "2500base-x"; + + nvmem-cells = <&macaddr_odm 1>; + nvmem-cell-names = "mac-address"; + + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; + }; + + gmac1: mac@1 { + compatible = "mediatek,eth-mac"; + reg = <1>; + phy-mode = "gmii"; + phy-handle = <&int_gbe_phy>; + label = "internet"; + + nvmem-cells = <&macaddr_odm 0>; + nvmem-cell-names = "mac-address"; + }; +}; + +&mdio_bus { + switch: switch@1f { + compatible = "mediatek,mt7531"; + reg = <31>; + reset-gpios = <&pio 39 GPIO_ACTIVE_HIGH>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + label = "lan1"; + }; + + port@1 { + reg = <1>; + label = "lan2"; + }; + + port@2 { + reg = <2>; + label = "lan3"; + }; + + port@3 { + reg = <3>; + label = "lan4"; + }; + + port@6 { + reg = <6>; + label = "cpu"; + ethernet = <&gmac0>; + phy-mode = "2500base-x"; + + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; + }; + }; + }; +}; + +&spi0 { + pinctrl-names = "default"; + pinctrl-0 = <&spi0_flash_pins>; + status = "okay"; + + spi_nand@0 { + compatible = "spi-nand"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0>; + + spi-max-frequency = <52000000>; + spi-tx-bus-width = <4>; + spi-rx-bus-width = <4>; + + mediatek,nmbm; + mediatek,bmt-max-ratio = <1>; + mediatek,bmt-max-reserved-blocks = <64>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "BL2"; + reg = <0x00 0x100000>; + read-only; + }; + + partition@100000 { + label = "u-boot-env"; + reg = <0x100000 0x80000>; + }; + + partition@180000 { + label = "Factory"; + reg = <0x180000 0x200000>; + read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + eeprom_factory_0: eeprom@0 { + reg = <0x0 0x1000>; + }; + }; + }; + + partition@380000 { + label = "FIP"; + reg = <0x380000 0x200000>; + read-only; + }; + + partition@580000 { + label = "ubi"; + reg = <0x580000 0x3200000>; + }; + + partition@3780000 { + label = "ubi1"; + reg = <0x3780000 0x3200000>; + read-only; + }; + + partition@6980000 { + label = "Odm"; + reg = <0x6980000 0x40000>; + read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + macaddr_odm: macaddr@81 { + compatible = "mac-base"; + reg = <0x81 0x6>; + #nvmem-cell-cells = <1>; + }; + }; + + }; + + partition@69c0000 { + label = "Config1"; + reg = <0x69c0000 0x80000>; + read-only; + }; + + partition@6a40000 { + label = "Config2"; + reg = <0x6a40000 0x80000>; + read-only; + }; + + partition@6ac0000 { + label = "Storage"; + reg = <0x6ac0000 0xA00000>; + read-only; + }; + }; + }; +}; + +&pio { + spi0_flash_pins: spi0-pins { + mux { + function = "spi"; + groups = "spi0", "spi0_wp_hold"; + }; + + conf-pu { + pins = "SPI0_CS", "SPI0_HOLD", "SPI0_WP"; + drive-strength = ; + bias-pull-down = ; + }; + + conf-pd { + pins = "SPI0_CLK", "SPI0_MOSI", "SPI0_MISO"; + drive-strength = ; + bias-pull-down = ; + }; + }; + + i2c_pins_g0: i2c-pins-g0 { + mux { + function = "i2c"; + groups = "i2c0_1"; + }; + }; +}; + +&wifi { + status = "okay"; + + nvmem-cells = <&eeprom_factory_0>, <&macaddr_odm 2>; + nvmem-cell-names = "eeprom", "mac-address"; +}; + +&i2c0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c_pins_g0>; + + gca230718@40 { + compatible = "unknown,gca230718"; + reg = <0x40>; + + led_status_red: led@0 { + color = ; + function = LED_FUNCTION_STATUS; + reg = <0>; + }; + + led@1 { + color = ; + function = LED_FUNCTION_STATUS; + reg = <1>; + }; + + led_status_blue: led@2 { + color = ; + function = LED_FUNCTION_STATUS; + reg = <2>; + }; + + led_status_white: led@3 { + color = ; + function = LED_FUNCTION_STATUS; + reg = <3>; + }; + }; +}; diff --git a/target/linux/mediatek/dts/mt7981b-fzs-5gcpe-p3.dts b/target/linux/mediatek/dts/mt7981b-fzs-5gcpe-p3.dts deleted file mode 100644 index d1813a7fc..000000000 --- a/target/linux/mediatek/dts/mt7981b-fzs-5gcpe-p3.dts +++ /dev/null @@ -1,268 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later OR MIT - -/dts-v1/; -#include -#include - -#include "mt7981.dtsi" - -/ { - model = "FZS 5GCPE P3"; - compatible = "fzs,5gcpe-p3", "mediatek,mt7981"; - - aliases { - serial0 = &uart0; - led-boot = &led_wifi; - led-upgrade = &led_wifi; - }; - - chosen { - stdout-path = "serial0:115200n8"; - }; - - memory { - reg = <0 0x40000000 0 0x10000000>; - }; - - gpio-keys { - compatible = "gpio-keys"; - - reset { - label = "reset"; - linux,code = ; - gpios = <&pio 1 GPIO_ACTIVE_LOW>; - }; - - wps { - label = "wps"; - linux,code = ; - gpios = <&pio 0 GPIO_ACTIVE_LOW>; - }; - }; - - leds { - compatible = "gpio-leds"; - - led_wifi: wifi { - label = "green:wifi"; - gpios = <&pio 15 GPIO_ACTIVE_LOW>; - linux,default-trigger = "phy1tpt"; - }; - - 4g { - label = "green:4g"; - gpios = <&pio 34 GPIO_ACTIVE_LOW>; - }; - - 5g { - label = "green:5g"; - gpios = <&pio 35 GPIO_ACTIVE_LOW>; - }; - }; -}; - -ð { - status = "okay"; - - gmac0: mac@0 { - compatible = "mediatek,eth-mac"; - reg = <0>; - phy-mode = "2500base-x"; - - nvmem-cells = <&macaddr_factory_2a>; - nvmem-cell-names = "mac-address"; - - fixed-link { - speed = <2500>; - full-duplex; - pause; - }; - }; -}; - -&mdio_bus { - switch: switch@0 { - compatible = "mediatek,mt7531"; - reg = <31>; - reset-gpios = <&pio 39 GPIO_ACTIVE_HIGH>; - interrupt-controller; - #interrupt-cells = <1>; - interrupt-parent = <&pio>; - interrupts = <38 IRQ_TYPE_LEVEL_HIGH>; - }; -}; - -&spi0 { - pinctrl-names = "default"; - pinctrl-0 = <&spi0_flash_pins>; - status = "okay"; - - spi_nand@0 { - compatible = "spi-nand"; - #address-cells = <1>; - #size-cells = <1>; - reg = <0>; - - spi-max-frequency = <52000000>; - spi-tx-bus-width = <4>; - spi-rx-bus-width = <4>; - - mediatek,nmbm; - mediatek,bmt-max-ratio = <1>; - mediatek,bmt-max-reserved-blocks = <64>; - - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - partition@0 { - label = "BL2"; - reg = <0x000000 0x0100000>; - read-only; - }; - - partition@100000 { - label = "u-boot-env"; - reg = <0x100000 0x0080000>; - }; - - factory: partition@180000 { - label = "Factory"; - reg = <0x180000 0x0200000>; - read-only; - }; - - partition@380000 { - label = "FIP"; - reg = <0x380000 0x0200000>; - read-only; - }; - - partition@580000 { - label = "ubi"; - reg = <0x580000 0x7000000>; - }; - }; - }; -}; - -&switch { - ports { - #address-cells = <1>; - #size-cells = <0>; - - port@1 { - reg = <1>; - label = "lan1"; - }; - - port@2 { - reg = <2>; - label = "lan2"; - }; - - port@3 { - reg = <3>; - label = "wan"; - nvmem-cells = <&macaddr_factory_24>; - nvmem-cell-names = "mac-address"; - }; - - port@6 { - reg = <6>; - label = "cpu"; - ethernet = <&gmac0>; - phy-mode = "2500base-x"; - - fixed-link { - speed = <2500>; - full-duplex; - pause; - }; - }; - }; -}; - -&pio { - spi0_flash_pins: spi0-pins { - mux { - function = "spi"; - groups = "spi0", "spi0_wp_hold"; - }; - - conf-pu { - pins = "SPI0_CS", "SPI0_HOLD", "SPI0_WP"; - drive-strength = <8>; - mediatek,pull-up-adv = <0>; /* bias-disable */ - }; - - conf-pd { - pins = "SPI0_CLK", "SPI0_MOSI", "SPI0_MISO"; - drive-strength = <8>; - mediatek,pull-up-adv = <0>; /* bias-disable */ - }; - }; - - uart1_pins: uart1-pins { - mux { - function = "uart"; - groups = "uart1_1"; - }; - }; - - uart2_pins: uart2-pins { - mux { - function = "uart"; - groups = "uart2_1"; - }; - }; -}; - -&uart0 { - status = "okay"; -}; - -&uart1 { - pinctrl-names = "default"; - pinctrl-0 = <&uart1_pins>; - status = "okay"; -}; - -&uart2 { - pinctrl-names = "default"; - pinctrl-0 = <&uart2_pins>; - status = "okay"; -}; - -&usb_phy { - status = "okay"; -}; - -&xhci { - status = "okay"; -}; - -&watchdog { - status = "okay"; -}; - -&wifi { - status = "okay"; - - mediatek,mtd-eeprom = <&factory 0x0>; -}; - -&factory { - compatible = "nvmem-cells"; - #address-cells = <1>; - #size-cells = <1>; - - macaddr_factory_24: macaddr@24 { - reg = <0x24 0x6>; - }; - - macaddr_factory_2a: macaddr@2a { - reg = <0x2a 0x6>; - }; -}; diff --git a/target/linux/mediatek/dts/mt7981b-glinet-gl-mt2500.dts b/target/linux/mediatek/dts/mt7981b-glinet-gl-mt2500.dts index 068dd0f23..15818a90f 100644 --- a/target/linux/mediatek/dts/mt7981b-glinet-gl-mt2500.dts +++ b/target/linux/mediatek/dts/mt7981b-glinet-gl-mt2500.dts @@ -57,7 +57,7 @@ regulator-min-microvolt = <5000000>; regulator-max-microvolt = <5000000>; - gpio = <&pio 12 GPIO_ACTIVE_HIGH>; + gpios = <&pio 12 GPIO_ACTIVE_HIGH>; enable-active-high; regulator-boot-on; }; @@ -103,6 +103,8 @@ gmac0: mac@0 { compatible = "mediatek,eth-mac"; + nvmem-cells = <&macaddr_boot1_a 0>; + nvmem-cell-names = "mac-address"; reg = <0>; phy-mode = "2500base-x"; @@ -111,6 +113,8 @@ gmac1: mac@1 { compatible = "mediatek,eth-mac"; + nvmem-cells = <&macaddr_boot1_a 1>; + nvmem-cell-names = "mac-address"; reg = <1>; phy-mode = "gmii"; phy-handle = <&int_gbe_phy>; @@ -148,4 +152,54 @@ vmmc-supply = <®_3p3v>; cap-mmc-highspeed; non-removable; + + card@0 { + compatible = "mmc-card"; + reg = <0>; + + block { + compatible = "block-device"; + + partitions { + block-partition-u-boot-env { + partname = "u-boot-env"; + nvmem-layout { + compatible = "u-boot,env-layout"; + }; + }; + }; + }; + + boot1 { + compatible = "block-device"; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + macaddr_boot1_a: macaddr@a { + compatible = "mac-base"; + reg = <0xa 0x6>; + #nvmem-cell-cells = <1>; + }; + + ddns@10 { + reg = <0x10 0x10>; + }; + + sn-bak@20 { + reg = <0x20 0x10>; + }; + + sn@30 { + reg = <0x30 0x10>; + }; + + country-code@88 { + reg = <0x88 0x10>; + }; + }; + }; + }; }; diff --git a/target/linux/mediatek/dts/mt7981b-glinet-gl-mt3000.dts b/target/linux/mediatek/dts/mt7981b-glinet-gl-mt3000.dts index bc0016684..727179892 100644 --- a/target/linux/mediatek/dts/mt7981b-glinet-gl-mt3000.dts +++ b/target/linux/mediatek/dts/mt7981b-glinet-gl-mt3000.dts @@ -7,10 +7,11 @@ compatible = "glinet,gl-mt3000", "mediatek,mt7981"; aliases { - led-boot = &led_run; - led-failsafe = &led_run; + label-mac-device = &gmac0; + led-boot = &led_lightblue; + led-failsafe = &led_lightblue; led-running = &led_white; - led-upgrade = &led_run; + led-upgrade = &led_lightblue; serial0 = &uart0; }; @@ -39,12 +40,12 @@ leds { compatible = "gpio-leds"; - led_run: run { + led_lightblue: led@0 { label = "blue:run"; gpios = <&pio 31 GPIO_ACTIVE_LOW>; }; - led_white: system { + led_white: led@1 { label = "white:system"; gpios = <&pio 30 GPIO_ACTIVE_LOW>; }; @@ -55,7 +56,7 @@ regulator-name = "fan"; regulator-min-microvolt = <5000000>; regulator-max-microvolt = <5000000>; - gpio = <&pio 28 GPIO_ACTIVE_HIGH>; + gpios = <&pio 28 GPIO_ACTIVE_HIGH>; enable-active-high; regulator-boot-on; }; @@ -65,7 +66,7 @@ regulator-name = "usb_vbus"; regulator-min-microvolt = <5000000>; regulator-max-microvolt = <5000000>; - gpio = <&pio 12 GPIO_ACTIVE_HIGH>; + gpios = <&pio 12 GPIO_ACTIVE_HIGH>; enable-active-high; regulator-boot-on; }; @@ -90,7 +91,7 @@ reg = <0>; phy-mode = "2500base-x"; phy-handle = <&phy0>; - nvmem-cells = <&macaddr>; + nvmem-cells = <&macaddr 0>; nvmem-cell-names = "mac-address"; }; @@ -99,9 +100,8 @@ reg = <1>; phy-mode = "gmii"; phy-handle = <&int_gbe_phy>; - nvmem-cells = <&macaddr>; + nvmem-cells = <&macaddr 1>; nvmem-cell-names = "mac-address"; - mac-address-increment = <1>; }; }; @@ -176,18 +176,25 @@ factory: partition@180000 { label = "Factory"; reg = <0x180000 0x0200000>; - compatible = "nvmem-cells"; - #address-cells = <1>; - #size-cells = <1>; + read-only; - macaddr: macaddr@a { - reg = <0xa 0x6>; + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + macaddr: macaddr@a { + compatible = "mac-base"; + reg = <0xa 0x6>; + #nvmem-cell-cells = <1>; + }; }; }; partition@380000 { label = "FIP"; reg = <0x380000 0x0200000>; + read-only; }; partition@580000 { diff --git a/target/linux/mediatek/dts/mt7981b-h3c-magic-nx30-pro.dts b/target/linux/mediatek/dts/mt7981b-h3c-magic-nx30-pro.dts index 4d405b539..030cc2504 100644 --- a/target/linux/mediatek/dts/mt7981b-h3c-magic-nx30-pro.dts +++ b/target/linux/mediatek/dts/mt7981b-h3c-magic-nx30-pro.dts @@ -3,6 +3,7 @@ /dts-v1/; #include #include +#include #include "mt7981.dtsi" @@ -12,7 +13,6 @@ aliases { serial0 = &uart0; - led-boot = &led_status_green; led-failsafe = &led_status_red; led-running = &led_status_green; @@ -47,12 +47,14 @@ compatible = "gpio-leds"; led_status_green: green { - label = "green:status"; + function = LED_FUNCTION_STATUS; + color = ; gpios = <&pio 4 GPIO_ACTIVE_LOW>; }; led_status_red: red { - label = "red:status"; + function = LED_FUNCTION_STATUS; + color = ; gpios = <&pio 5 GPIO_ACTIVE_LOW>; }; }; @@ -82,7 +84,7 @@ }; &mdio_bus { - switch: switch@0 { + switch: switch@1f { compatible = "mediatek,mt7531"; reg = <31>; reset-gpios = <&pio 39 GPIO_ACTIVE_HIGH>; @@ -108,10 +110,6 @@ spi-tx-bus-width = <4>; spi-rx-bus-width = <4>; - mediatek,nmbm; - mediatek,bmt-max-ratio = <1>; - mediatek,bmt-max-reserved-blocks = <64>; - partitions { compatible = "fixed-partitions"; #address-cells = <1>; @@ -196,7 +194,6 @@ port@6 { reg = <6>; - label = "cpu"; ethernet = <&gmac0>; phy-mode = "2500base-x"; diff --git a/target/linux/mediatek/dts/mt7981b-jcg-q30-pro.dts b/target/linux/mediatek/dts/mt7981b-jcg-q30-pro.dts index d9fec68bc..c8b9aeba4 100644 --- a/target/linux/mediatek/dts/mt7981b-jcg-q30-pro.dts +++ b/target/linux/mediatek/dts/mt7981b-jcg-q30-pro.dts @@ -3,6 +3,7 @@ /dts-v1/; #include #include +#include #include "mt7981.dtsi" @@ -41,12 +42,14 @@ compatible = "gpio-leds"; led_status_red: red { - label = "red:status"; + function = LED_FUNCTION_STATUS; + color = ; gpios = <&pio 8 GPIO_ACTIVE_HIGH>; }; led_status_blue: blue { - label = "blue:status"; + function = LED_FUNCTION_STATUS; + color = ; gpios = <&pio 13 GPIO_ACTIVE_LOW>; }; }; @@ -72,7 +75,7 @@ }; &mdio_bus { - switch: switch@0 { + switch: switch@1f { compatible = "mediatek,mt7531"; reg = <31>; reset-gpios = <&pio 39 GPIO_ACTIVE_HIGH>; @@ -98,10 +101,6 @@ spi-tx-bus-width = <4>; spi-rx-bus-width = <4>; - mediatek,nmbm; - mediatek,bmt-max-ratio = <1>; - mediatek,bmt-max-reserved-blocks = <64>; - partitions { compatible = "fixed-partitions"; #address-cells = <1>; @@ -122,6 +121,20 @@ label = "Factory"; reg = <0x0180000 0x0200000>; read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + macaddr_wan: macaddr@a0024 { + reg = <0xa0024 0x6>; + }; + + macaddr_lan: macaddr@a002a { + reg = <0xa002a 0x6>; + }; + }; }; partition@380000 { @@ -167,7 +180,6 @@ port@6 { reg = <6>; - label = "cpu"; ethernet = <&gmac0>; phy-mode = "2500base-x"; @@ -214,17 +226,3 @@ mediatek,mtd-eeprom = <&factory 0x0>; }; - -&factory { - compatible = "nvmem-cells"; - #address-cells = <1>; - #size-cells = <1>; - - macaddr_wan: macaddr@a0024 { - reg = <0xa0024 0x6>; - }; - - macaddr_lan: macaddr@a002a { - reg = <0xa002a 0x6>; - }; -}; diff --git a/target/linux/mediatek/dts/mt7981b-nokia-ea0326gmp.dts b/target/linux/mediatek/dts/mt7981b-nokia-ea0326gmp.dts index bab81b1da..1ac815d8b 100644 --- a/target/linux/mediatek/dts/mt7981b-nokia-ea0326gmp.dts +++ b/target/linux/mediatek/dts/mt7981b-nokia-ea0326gmp.dts @@ -3,7 +3,7 @@ /dts-v1/; #include #include - +#include #include "mt7981.dtsi" / { @@ -11,76 +11,83 @@ compatible = "nokia,ea0326gmp", "mediatek,mt7981"; aliases { - serial0 = &uart0; - - led-boot = &led_power; - led-failsafe = &led_power; - led-running = &led_power; - led-upgrade = &led_power; + led-boot = &power_led; + led-running = &power_led; + led-failsafe = &power_led; + led-upgrade = &power_led; label-mac-device = &gmac1; + serial0 = &uart0; }; chosen { + rootdisk = <&ubi_rootdisk>; stdout-path = "serial0:115200n8"; }; - memory { + memory@40000000 { reg = <0 0x40000000 0 0x10000000>; }; gpio-keys { compatible = "gpio-keys"; - reset { + button-reset { label = "reset"; linux,code = ; gpios = <&pio 1 GPIO_ACTIVE_LOW>; }; - wps { + button-wps { label = "wps"; linux,code = ; gpios = <&pio 0 GPIO_ACTIVE_LOW>; }; }; - leds { + gpio-leds { compatible = "gpio-leds"; - led_power: power { - label = "green:power"; + power_led: led-0 { + color = ; + function = LED_FUNCTION_POWER; gpios = <&pio 4 GPIO_ACTIVE_LOW>; }; - wan_green { - label = "green:wan"; + led-1 { + color = ; + function = LED_FUNCTION_WAN; gpios = <&pio 5 GPIO_ACTIVE_LOW>; }; - wan_red { - label = "red:wan"; + led-2 { + color = ; + function = LED_FUNCTION_WAN; gpios = <&pio 6 GPIO_ACTIVE_LOW>; }; - lan { - label = "green:lan"; + led-3 { + color = ; + function = LED_FUNCTION_LAN; gpios = <&pio 7 GPIO_ACTIVE_LOW>; }; - wifi { - label = "green:wifi"; + led-4 { + color = ; + function = LED_FUNCTION_WLAN; gpios = <&pio 8 GPIO_ACTIVE_LOW>; - linux,default-trigger = "phy1tpt"; }; - wps { - label = "green:wps"; + led-5 { + color = ; + function = LED_FUNCTION_WPS; gpios = <&pio 9 GPIO_ACTIVE_LOW>; }; }; }; ð { + pinctrl-names = "default"; + pinctrl-0 = <&mdio_pins>; status = "okay"; gmac0: mac@0 { @@ -88,7 +95,7 @@ reg = <0>; phy-mode = "2500base-x"; - nvmem-cells = <&macaddr_factory_28>; + nvmem-cells = <&macaddr_factory_28 0>; nvmem-cell-names = "mac-address"; fixed-link { @@ -104,14 +111,13 @@ phy-mode = "gmii"; phy-handle = <&int_gbe_phy>; - nvmem-cells = <&macaddr_factory_28>; + nvmem-cells = <&macaddr_factory_28 3>; nvmem-cell-names = "mac-address"; - mac-address-increment = <3>; }; }; &mdio_bus { - switch: switch@0 { + switch: switch@1f { compatible = "mediatek,mt7531"; reg = <31>; reset-gpios = <&pio 39 GPIO_ACTIVE_HIGH>; @@ -122,33 +128,50 @@ }; }; +&pio { + spi0_flash_pins: spi0-pins { + mux { + function = "spi"; + groups = "spi0", "spi0_wp_hold"; + }; + + conf-pu { + pins = "SPI0_CS", "SPI0_HOLD", "SPI0_WP"; + drive-strength = <8>; + mediatek,pull-up-adv = <0>; /* bias-disable */ + }; + + conf-pd { + pins = "SPI0_CLK", "SPI0_MOSI", "SPI0_MISO"; + drive-strength = <8>; + mediatek,pull-up-adv = <0>; /* bias-disable */ + }; + }; +}; + &spi0 { pinctrl-names = "default"; pinctrl-0 = <&spi0_flash_pins>; status = "okay"; - spi_nand@0 { - compatible = "spi-nand"; + spi_nand: flash@0 { #address-cells = <1>; #size-cells = <1>; + compatible = "spi-nand"; reg = <0>; spi-max-frequency = <52000000>; spi-tx-bus-width = <4>; spi-rx-bus-width = <4>; - mediatek,nmbm; - mediatek,bmt-max-ratio = <1>; - mediatek,bmt-max-reserved-blocks = <64>; - partitions { compatible = "fixed-partitions"; #address-cells = <1>; #size-cells = <1>; partition@0 { - label = "BL2"; - reg = <0x0000000 0x0100000>; + label = "bl2"; + reg = <0x00000 0x0100000>; read-only; }; @@ -157,45 +180,56 @@ reg = <0x0100000 0x0080000>; }; - factory: partition@180000 { - label = "Factory"; - reg = <0x0180000 0x0200000>; + partition@180000 { + label = "factory"; + reg = <0x180000 0x0200000>; read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + eeprom_factory_0: eeprom@0 { + reg = <0x0 0x1000>; + }; + + macaddr_factory_28: macaddr@28 { + compatible = "mac-base"; + reg = <0x28 0x6>; + #nvmem-cell-cells = <1>; + }; + }; }; partition@380000 { - label = "FIP"; - reg = <0x0380000 0x0200000>; + label = "fip"; + reg = <0x380000 0x0200000>; read-only; }; partition@580000 { - label = "Config"; - reg = <0x0580000 0x0200000>; + label = "config"; + reg = <0x580000 0x200000>; read-only; }; partition@780000 { - label = "Config2"; - reg = <0x0780000 0x0200000>; + label = "config2"; + reg = <0x780000 0x200000>; read-only; }; partition@980000 { - label = "Aos-net"; - reg = <0x0980000 0x0c00000>; - read-only; - }; - - partition@1580000 { - label = "bvasPlugin"; - reg = <0x1580000 0x0c00000>; - read-only; - }; - - partition@2180000 { + compatible = "linux,ubi"; label = "ubi"; - reg = <0x2180000 0x5680000>; + reg = <0x980000 0x7680000>; + + volumes { + ubi_rootdisk: ubi-volume-fit { + volname = "fit"; + }; + }; }; }; }; @@ -223,7 +257,6 @@ port@6 { reg = <6>; - label = "cpu"; ethernet = <&gmac0>; phy-mode = "2500base-x"; @@ -236,27 +269,6 @@ }; }; -&pio { - spi0_flash_pins: spi0-pins { - mux { - function = "spi"; - groups = "spi0", "spi0_wp_hold"; - }; - - conf-pu { - pins = "SPI0_CS", "SPI0_HOLD", "SPI0_WP"; - drive-strength = <8>; - mediatek,pull-up-adv = <0>; /* bias-disable */ - }; - - conf-pd { - pins = "SPI0_CLK", "SPI0_MOSI", "SPI0_MISO"; - drive-strength = <8>; - mediatek,pull-up-adv = <0>; /* bias-disable */ - }; - }; -}; - &uart0 { status = "okay"; }; @@ -266,20 +278,7 @@ }; &wifi { + nvmem-cells = <&eeprom_factory_0>; + nvmem-cell-names = "eeprom"; status = "okay"; - - mediatek,mtd-eeprom = <&factory 0x0>; - nvmem-cells = <&macaddr_factory_28>; - nvmem-cell-names = "mac-address"; - mac-address-increment = <1>; -}; - -&factory { - compatible = "nvmem-cells"; - #address-cells = <1>; - #size-cells = <1>; - - macaddr_factory_28: macaddr@28 { - reg = <0x28 0x6>; - }; }; diff --git a/target/linux/mediatek/dts/mt7981b-openembed-som7981.dts b/target/linux/mediatek/dts/mt7981b-openembed-som7981.dts new file mode 100644 index 000000000..0e9dea1dd --- /dev/null +++ b/target/linux/mediatek/dts/mt7981b-openembed-som7981.dts @@ -0,0 +1,227 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +/dts-v1/; + +#include +#include +#include +#include "mt7981.dtsi" + +/ { + model = "OpenEmbed SOM7981"; + compatible = "openembed,som7981", "mediatek,mt7981"; + + aliases { + led-boot = &wlan2g_led; + led-failsafe = &wlan2g_led; + led-upgrade = &wlan2g_led; + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + memory@40000000 { + reg = <0 0x40000000 0 0x40000000>; + }; + + gpio-keys { + compatible = "gpio-keys"; + + button-reset { + label = "reset"; + linux,code = ; + gpios = <&pio 1 GPIO_ACTIVE_LOW>; + }; + + button-wps { + label = "wps"; + linux,code = ; + gpios = <&pio 0 GPIO_ACTIVE_LOW>; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + led-0 { + function = LED_FUNCTION_LAN; + color = ; + gpios = <&pio 8 GPIO_ACTIVE_LOW>; + }; + + led-1 { + function = LED_FUNCTION_LAN; + color = ; + gpios = <&pio 13 GPIO_ACTIVE_LOW>; + }; + + wlan2g_led: led-2 { + function = LED_FUNCTION_WLAN_2GHZ; + color = ; + gpios = <&pio 34 GPIO_ACTIVE_LOW>; + linux,default-trigger = "phy0tpt"; + }; + + led-3 { + function = LED_FUNCTION_WLAN_5GHZ; + color = ; + gpios = <&pio 35 GPIO_ACTIVE_LOW>; + linux,default-trigger = "phy1tpt"; + }; + }; +}; + +ð { + pinctrl-names = "default"; + pinctrl-0 = <&mdio_pins>; + status = "okay"; + + gmac0: mac@0 { + compatible = "mediatek,eth-mac"; + reg = <0>; + phy-mode = "2500base-x"; + phy-handle = <&phy0>; + nvmem-cells = <&macaddr_factory_a 0>; + nvmem-cell-names = "mac-address"; + }; + + gmac1: mac@1 { + compatible = "mediatek,eth-mac"; + reg = <1>; + phy-mode = "gmii"; + phy-handle = <&int_gbe_phy>; + nvmem-cells = <&macaddr_factory_a 1>; + nvmem-cell-names = "mac-address"; + }; +}; + +&mdio_bus { + phy0: ethernet-phy@5 { + reg = <5>; + compatible = "ethernet-phy-ieee802.3-c45"; + phy-mode = "2500base-x"; + reset-gpios = <&pio 14 GPIO_ACTIVE_LOW>; + reset-assert-us = <10000>; + reset-deassert-us = <50000>; + realtek,aldps-enable; + }; +}; + +&spi0 { + pinctrl-names = "default"; + pinctrl-0 = <&spi0_flash_pins>; + status = "okay"; + + spi_nand: flash@0 { + compatible = "spi-nand"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0>; + + spi-max-frequency = <52000000>; + spi-tx-bus-width = <4>; + spi-rx-bus-width = <4>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "bl2"; + reg = <0x000000 0x100000>; + read-only; + }; + + partition@100000 { + label = "u-boot-env"; + reg = <0x100000 0x80000>; + }; + + partition@180000 { + compatible = "nvmem-cells"; + label = "factory"; + reg = <0x180000 0x100000>; + read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + eeprom_factory_0: eeprom@0 { + reg = <0x0 0x1000>; + }; + + macaddr_factory_a: macaddr@a { + compatible = "mac-base"; + reg = <0xa 0x6>; + #nvmem-cell-cells = <1>; + }; + }; + }; + + partition@280000 { + label = "config"; + reg = <0x280000 0x100000>; + read-only; + }; + + partition@380000 { + label = "fip"; + reg = <0x380000 0x200000>; + read-only; + }; + + partition@580000 { + label = "ubi"; + reg = <0x580000 0xf880000>; + }; + }; + }; +}; + +&pio { + spi0_flash_pins: spi0-pins { + mux { + function = "spi"; + groups = "spi0", "spi0_wp_hold"; + }; + + conf-pu { + pins = "SPI0_CS", "SPI0_HOLD", "SPI0_WP"; + drive-strength = <8>; + mediatek,pull-up-adv = <0>; + }; + + conf-pd { + pins = "SPI0_CLK", "SPI0_MOSI", "SPI0_MISO"; + drive-strength = <8>; + mediatek,pull-down-adv = <0>; + }; + }; +}; + +&uart0 { + status = "okay"; +}; + +&usb_phy { + status = "okay"; +}; + +&watchdog { + status = "okay"; +}; + +&wifi { + nvmem-cells = <&eeprom_factory_0>; + nvmem-cell-names = "eeprom"; + status = "okay"; +}; + +&xhci { + status = "okay"; +}; diff --git a/target/linux/mediatek/dts/mt7981b-openwrt-one.dts b/target/linux/mediatek/dts/mt7981b-openwrt-one.dts new file mode 100644 index 000000000..b2223f8d7 --- /dev/null +++ b/target/linux/mediatek/dts/mt7981b-openwrt-one.dts @@ -0,0 +1,457 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) + +/dts-v1/; +#include "mt7981.dtsi" + +/ { + model = "OpenWrt One"; + compatible = "openwrt,one", "mediatek,mt7981"; + + aliases { + ethernet0 = &gmac0; + ethernet1 = &gmac1; + serial0 = &uart0; + led-boot = &led_status_white; + led-failsafe = &led_status_red; + led-running = &led_status_green; + led-upgrade = &led_status_green; + }; + + chosen { + stdout-path = "serial0:115200n8"; + rootdisk = <&ubi_fit_volume>; + }; + + memory { + reg = <0 0x40000000 0 0x40000000>; + }; + + reg_3p3v: regulator-3p3v { + compatible = "regulator-fixed"; + regulator-name = "fixed-3.3V"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + regulator-always-on; + }; + + reg_5v: regulator-5v { + compatible = "regulator-fixed"; + regulator-name = "fixed-5V"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-boot-on; + regulator-always-on; + }; + + gpio-keys { + compatible = "gpio-keys"; + + user { + label = "user"; + linux,code = ; + gpios = <&pio 0 GPIO_ACTIVE_HIGH>; + }; + + reset { + label = "reset"; + linux,code = ; + gpios = <&pio 1 GPIO_ACTIVE_LOW>; + }; + }; + + pwm-leds { + compatible = "pwm-leds"; + + led_status_white: led-0 { + color = ; + function = LED_FUNCTION_STATUS; + pwms = <&pwm 0 10000>; + linux,default-trigger = "pattern"; + led-pattern = <0 500 25 500>; + }; + + led_status_green: led-1 { + color = ; + function = LED_FUNCTION_STATUS; + pwms = <&pwm 1 10000>; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + led_status_red: led-0 { + color = ; + function = LED_FUNCTION_STATUS; + gpios = <&pio 9 GPIO_ACTIVE_HIGH>; + }; + + led-1 { + function = LED_FUNCTION_LAN; + color = ; + gpios = <&pio 34 GPIO_ACTIVE_LOW>; + }; + + led-2 { + function = LED_FUNCTION_LAN; + color = ; + gpios = <&pio 35 GPIO_ACTIVE_LOW>; + }; + }; + + gpio-export { + compatible = "gpio-export"; + + gpio-0 { + gpio-export,name = "mikrobus-reset"; + gpio-export,output = <1>; + gpios = <&pio 2 GPIO_ACTIVE_HIGH>; + }; + + gpio-1 { + gpio-export,name = "watchdog-enable"; + gpio-export,output = <1>; + gpios = <&pio 11 GPIO_ACTIVE_HIGH>; + }; + + gpio-2 { + gpio-export,name = "usb-enable"; + gpio-export,output = <1>; + gpios = <&pio 14 GPIO_ACTIVE_HIGH>; + }; + }; + + gpio-watchdog { + compatible = "linux,wdt-gpio"; + gpios = <&pio 8 GPIO_ACTIVE_LOW>; + hw_algo = "toggle"; + hw_margin_ms = <25000>; + always-running; + }; +}; + +ð { + status = "okay"; + + gmac0: mac@0 { + compatible = "mediatek,eth-mac"; + reg = <0>; + phy-handle = <&phy15>; + phy-mode = "2500base-x"; + nvmem-cell-names = "mac-address"; + nvmem-cells = <&macaddr_factory_4>; + }; + + gmac1: mac@1 { + compatible = "mediatek,eth-mac"; + reg = <1>; + phy-mode = "gmii"; + phy-handle = <&int_gbe_phy>; + nvmem-cell-names = "mac-address"; + nvmem-cells = <&macaddr_factory_a>; + }; +}; + +&mdio_bus { + phy15: phy@f { + reg = <0xf>; + + airoha,pnswap-rx; + + interrupt-parent = <&pio>; + interrupts = <38 IRQ_TYPE_EDGE_FALLING>; + reset-gpios = <&pio 39 GPIO_ACTIVE_LOW>; + reset-assert-us = <10000>; + reset-deassert-us = <20000>; + + phy-mode = "2500base-x"; + full-duplex; + pause; + + leds { + #address-cells = <1>; + #size-cells = <0>; + + led@0 { + reg = <0>; + function = LED_FUNCTION_WAN; + color = ; + }; + + led@1 { + reg = <1>; + function = LED_FUNCTION_WAN; + color = ; + }; + }; + }; +}; + +&crypto { + status = "okay"; +}; + +&pio { + spi0_flash_pins: spi0-pins { + mux { + function = "spi"; + groups = "spi0", "spi0_wp_hold"; + }; + + conf-pu { + pins = "SPI0_CS", "SPI0_HOLD", "SPI0_WP"; + drive-strength = ; + bias-pull-up = ; + }; + + conf-pd { + pins = "SPI0_CLK", "SPI0_MOSI", "SPI0_MISO"; + drive-strength = ; + bias-pull-down = ; + }; + }; + + spi1_flash_pins: spi1-pins { + mux { + function = "spi"; + groups = "spi1_1"; + }; + + conf-pu { + pins = "SPI1_CS"; + drive-strength = ; + bias-pull-up = ; + }; + + conf-pd { + pins = "SPI1_CLK", "SPI1_MOSI", "SPI1_MISO"; + drive-strength = ; + bias-pull-down = ; + }; + }; + + spi2_flash_pins: spi2-pins { + mux { + function = "spi"; + groups = "spi2"; + }; + + conf-pu { + pins = "SPI2_CS", "SPI2_WP"; + drive-strength = ; + bias-pull-up = ; + }; + + conf-pd { + pins = "SPI2_CLK", "SPI2_MOSI", "SPI2_MISO"; + drive-strength = ; + bias-pull-down = ; + }; + }; + + i2c_pins: i2c-pins { + mux { + function = "i2c"; + groups = "i2c0_0"; + }; + }; + + uart2_pins: uart2-pins { + mux { + function = "uart"; + groups = "uart2_0_tx_rx"; + }; + }; + + pwm_pins: pwm-pins { + mux { + function = "pwm"; + groups = "pwm0_0", "pwm1_1"; + }; + }; + + pcie_pins: pcie-pins { + mux { + function = "pcie"; + groups = "pcie_pereset"; + }; + }; +}; + +&pwm { + pinctrl-names = "default"; + pinctrl-0 = <&pwm_pins>; + status = "okay"; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c_pins>; + status = "okay"; + + rtc@51 { + compatible = "nxp,pcf8563"; + reg = <0x51>; + }; +}; + +&spi0 { + pinctrl-names = "default"; + pinctrl-0 = <&spi0_flash_pins>; + cs-gpios = <0>, <0>; + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "spi-nand"; + reg = <1>; + spi-max-frequency = <52000000>; + + spi-cal-enable; + spi-cal-mode = "read-data"; + spi-cal-datalen = <7>; + spi-cal-data = /bits/ 8 <0x53 0x50 0x49 0x4E 0x41 0x4E 0x44>; + spi-cal-addrlen = <5>; + spi-cal-addr = /bits/ 32 <0x0 0x0 0x0 0x0 0x0>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "bl2"; + reg = <0x0 0x100000>; + read-only; + }; + + partition@580000 { + label = "ubi"; + reg = <0x100000 0x7F00000>; + compatible = "linux,ubi"; + + volumes { + ubi_fit_volume: ubi-volume-fit { + volname = "fit"; + }; + }; + }; + }; + }; +}; + +&spi1 { + pinctrl-names = "default"; + pinctrl-0 = <&spi1_flash_pins>; + status = "okay"; +}; + +&spi2 { + pinctrl-names = "default"; + pinctrl-0 = <&spi2_flash_pins>; + status = "okay"; + + flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "jedec,spi-nor"; + reg = <0>; + + spi-max-frequency = <52000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "bl2-nor"; + reg = <0x00000 0x40000>; + }; + + partition@40000 { + label = "factory"; + reg = <0x40000 0xc0000>; + read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + eeprom_factory_0: eeprom@0 { + reg = <0x0 0x1000>; + }; + + macaddr_factory_4: macaddr@4 { + compatible = "mac-base"; + reg = <0x24 0x6>; + #nvmem-cell-cells = <1>; + }; + + macaddr_factory_a: macaddr@a { + compatible = "mac-base"; + reg = <0x2a 0x6>; + #nvmem-cell-cells = <1>; + }; + }; + }; + + partition@100000 { + label = "fip-nor"; + reg = <0x100000 0x80000>; + }; + + partition@180000 { + label = "recovery"; + reg = <0x180000 0xc80000>; + }; + }; + }; +}; + +&xhci { + phys = <&u2port0 PHY_TYPE_USB2>; + vusb33-supply = <®_3p3v>; + vbus-supply = <®_5v>; + mediatek,u3p-dis-msk = <0x01>; + status = "okay"; +}; + +&uart0 { + status = "okay"; +}; + +&uart2 { + pinctrl-names = "default"; + pinctrl-0 = <&uart2_pins>; + status = "okay"; +}; + +&usb_phy { + status = "okay"; +}; + +&watchdog { + status = "okay"; +}; + +&wifi { + nvmem-cells = <&eeprom_factory_0>; + nvmem-cell-names = "eeprom"; + status = "okay"; +}; + +&pcie { + pinctrl-names = "default"; + pinctrl-0 = <&pcie_pins>; + status = "okay"; +}; + +&sgmiisys0 { + /delete-node/ mediatek,pnswap; +}; diff --git a/target/linux/mediatek/dts/mt7981b-qihoo-360t7.dts b/target/linux/mediatek/dts/mt7981b-qihoo-360t7.dts index b937c43b6..3925f80ba 100644 --- a/target/linux/mediatek/dts/mt7981b-qihoo-360t7.dts +++ b/target/linux/mediatek/dts/mt7981b-qihoo-360t7.dts @@ -3,6 +3,7 @@ /dts-v1/; #include #include +#include #include "mt7981.dtsi" @@ -12,7 +13,6 @@ aliases { serial0 = &uart0; - led-boot = &led_status_red; led-failsafe = &led_status_red; led-running = &led_status_green; @@ -47,12 +47,14 @@ compatible = "gpio-leds"; led_status_red: red { - label = "red:status"; + function = LED_FUNCTION_STATUS; + color = ; gpios = <&pio 3 GPIO_ACTIVE_LOW>; }; led_status_green: green { - label = "green:status"; + function = LED_FUNCTION_STATUS; + color = ; gpios = <&pio 7 GPIO_ACTIVE_LOW>; }; }; @@ -75,7 +77,7 @@ }; &mdio_bus { - switch: switch@0 { + switch: switch@1f { compatible = "mediatek,mt7531"; reg = <31>; reset-gpios = <&pio 39 GPIO_ACTIVE_HIGH>; @@ -101,10 +103,6 @@ spi-tx-bus-width = <4>; spi-rx-bus-width = <4>; - mediatek,nmbm; - mediatek,bmt-max-ratio = <1>; - mediatek,bmt-max-reserved-blocks = <64>; - partitions { compatible = "fixed-partitions"; #address-cells = <1>; @@ -186,7 +184,6 @@ port@6 { reg = <6>; - label = "cpu"; ethernet = <&gmac0>; phy-mode = "2500base-x"; diff --git a/target/linux/mediatek/dts/mt7981b-routerich-ax3000.dts b/target/linux/mediatek/dts/mt7981b-routerich-ax3000.dts new file mode 100644 index 000000000..dfe44843b --- /dev/null +++ b/target/linux/mediatek/dts/mt7981b-routerich-ax3000.dts @@ -0,0 +1,337 @@ +// SPDX-License-Identifier: GPL-2.0-only OR MIT + +/dts-v1/; +#include +#include +#include + +#include "mt7981.dtsi" + +/ { + model = "Routerich AX3000"; + compatible = "routerich,ax3000", "mediatek,mt7981"; + + aliases { + label-mac-device = &wan; + + led-boot = &led_power_blue; + led-failsafe = &led_power_blue; + led-running = &led_power_blue; + led-upgrade = &led_power_blue; + + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + gpio-keys { + compatible = "gpio-keys"; + + button-0 { + label = "mesh"; + linux,input-type = ; + linux,code = ; + gpios = <&pio 0 GPIO_ACTIVE_LOW>; + debounce-interval = <60>; + }; + + button-1 { + label = "reset"; + gpios = <&pio 1 GPIO_ACTIVE_LOW>; + linux,code = ; + debounce-interval = <60>; + }; + }; + + leds { + compatible = "gpio-leds"; + + led-0 { + color = ; + function = LED_FUNCTION_WLAN; + function-enumerator = <50>; + gpios = <&pio 5 GPIO_ACTIVE_LOW>; + linux,default-trigger = "phy1tpt"; + }; + + led-1 { + color = ; + function = LED_FUNCTION_WAN; + gpios = <&pio 6 GPIO_ACTIVE_HIGH>; + }; + + led_power_blue: led-2 { + color = ; + function = LED_FUNCTION_POWER; + gpios = <&pio 7 GPIO_ACTIVE_LOW>; + }; + + led-3 { + color = ; + function = LED_FUNCTION_LAN; + function-enumerator = <1>; + gpios = <&pio 9 GPIO_ACTIVE_LOW>; + }; + + led-4 { + color = ; + function = LED_FUNCTION_LAN; + function-enumerator = <2>; + gpios = <&pio 10 GPIO_ACTIVE_LOW>; + }; + + led-5 { + color = ; + function = LED_FUNCTION_LAN; + function-enumerator = <3>; + gpios = <&pio 11 GPIO_ACTIVE_LOW>; + }; + + led-6 { + color = ; + function = LED_FUNCTION_WAN; + gpios = <&pio 12 GPIO_ACTIVE_LOW>; + }; + + led-7 { + color = ; + function = LED_FUNCTION_WLAN; + function-enumerator = <24>; + gpios = <&pio 34 GPIO_ACTIVE_LOW>; + linux,default-trigger = "phy0tpt"; + }; + + led-8 { + color = ; + /* LED_FUNCTION_MESH isn't implemented yet */ + function = "mesh"; + gpios = <&pio 35 GPIO_ACTIVE_LOW>; + }; + }; + + memory { + reg = <0 0x40000000 0 0x10000000>; + }; +}; + +ð { + status = "okay"; + + gmac0: mac@0 { + compatible = "mediatek,eth-mac"; + reg = <0>; + phy-mode = "2500base-x"; + + nvmem-cell-names = "mac-address"; + nvmem-cells = <&macaddr_factory_4 (-1)>; + + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; + }; +}; + +&mdio_bus { + switch: switch@1f { + compatible = "mediatek,mt7531"; + reg = <0x1f>; + reset-gpios = <&pio 39 GPIO_ACTIVE_HIGH>; + interrupt-controller; + #interrupt-cells = <1>; + interrupt-parent = <&pio>; + interrupts = <38 IRQ_TYPE_LEVEL_HIGH>; + }; +}; + +&spi0 { + pinctrl-names = "default"; + pinctrl-0 = <&spi0_flash_pins>; + status = "okay"; + + /* ESMT F50L1G41LB (128M) */ + spi_nand@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "spi-nand"; + reg = <0>; + + spi-max-frequency = <52000000>; + spi-tx-bus-width = <4>; + spi-rx-bus-width = <4>; + + spi-cal-enable; + spi-cal-mode = "read-data"; + spi-cal-datalen = <7>; + spi-cal-data = /bits/ 8 <0x53 0x50 0x49 0x4e 0x41 0x4e 0x44>; + spi-cal-addrlen = <5>; + spi-cal-addr = /bits/ 32 <0x0 0x0 0x0 0x0 0x0>; + + mediatek,nmbm; + mediatek,bmt-max-ratio = <1>; + mediatek,bmt-max-reserved-blocks = <64>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0_all { + label = "spi0.0"; + reg = <0x0 0x8000000>; + read-only; + }; + + partition@0 { + label = "BL2"; + reg = <0x0 0x100000>; + read-only; + }; + + partition@100000 { + label = "u-boot-env"; + reg = <0x100000 0x80000>; + }; + + partition@180000 { + label = "Factory"; + reg = <0x180000 0x200000>; + read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + eeprom_factory_0: eeprom@0 { + reg = <0x0 0x1000>; + }; + + macaddr_factory_4: macaddr@4 { + compatible = "mac-base"; + reg = <0x4 0x6>; + #nvmem-cell-cells = <1>; + }; + }; + }; + + partition@380000 { + label = "FIP"; + reg = <0x380000 0x200000>; + read-only; + }; + + partition@580000 { + label = "ubi"; + reg = <0x580000 0x4000000>; + }; + + partition@4580000 { + label = "firmware_backup"; + reg = <0x4580000 0x2000000>; + read-only; + }; + + partition@6580000 { + label = "zrsave"; + reg = <0x6580000 0x100000>; + read-only; + }; + + partition@6680000 { + label = "config2"; + reg = <0x6680000 0x100000>; + read-only; + }; + }; + }; +}; + +&switch { + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + label = "lan1"; + }; + + port@2 { + reg = <2>; + label = "lan2"; + }; + + port@3 { + reg = <3>; + label = "lan3"; + }; + + wan: port@4 { + reg = <4>; + label = "wan"; + + nvmem-cell-names = "mac-address"; + nvmem-cells = <&macaddr_factory_4 (-2)>; + }; + + port@6 { + reg = <6>; + ethernet = <&gmac0>; + phy-mode = "2500base-x"; + + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; + }; + }; +}; + +&pio { + spi0_flash_pins: spi0-pins { + mux { + function = "spi"; + groups = "spi0", "spi0_wp_hold"; + }; + + conf-pu { + pins = "SPI0_CS", "SPI0_HOLD", "SPI0_WP"; + drive-strength = ; + bias-pull-up = ; + }; + + conf-pd { + pins = "SPI0_CLK", "SPI0_MOSI", "SPI0_MISO"; + drive-strength = ; + bias-pull-down = ; + }; + }; +}; + +&uart0 { + status = "okay"; +}; + +&usb_phy { + status = "okay"; +}; + +&watchdog { + status = "okay"; +}; + +&wifi { + status = "okay"; + nvmem-cell-names = "eeprom"; + nvmem-cells = <&eeprom_factory_0>; +}; + +&xhci { + status = "okay"; + mediatek,u3p-dis-msk = <0x1>; +}; diff --git a/target/linux/mediatek/dts/mt7981b-unielec-u7981-01-emmc.dts b/target/linux/mediatek/dts/mt7981b-unielec-u7981-01-emmc.dts new file mode 100644 index 000000000..abd4d4e59 --- /dev/null +++ b/target/linux/mediatek/dts/mt7981b-unielec-u7981-01-emmc.dts @@ -0,0 +1,99 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT +/* + * Copyright (C) 2023 Allen Zhao + */ + +/dts-v1/; +#include "mt7981b-unielec-u7981-01.dtsi" +/ { + model = "Unielec U7981-01 (EMMC)"; + compatible = "unielec,u7981-01-emmc", "mediatek,mt7981"; +}; + +&mmc0 { + pinctrl-names = "default", "state_uhs"; + pinctrl-0 = <&mmc0_pins_default>; + pinctrl-1 = <&mmc0_pins_uhs>; + bus-width = <8>; + max-frequency = <52000000>; + cap-mmc-highspeed; + vmmc-supply = <®_3p3v>; + non-removable; + status = "okay"; + + card@0 { + compatible = "mmc-card"; + reg = <0>; + + block { + compatible = "block-device"; + partitions { + block-partition-env { + partname = "u-boot-env"; + + nvmem-layout { + compatible = "u-boot,env-layout"; + }; + }; + + block-partition-factory { + partname = "factory"; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + eeprom_factory_0: eeprom@0 { + reg = <0x0 0x1000>; + }; + + macaddr_factory_4: macaddr@4 { + compatible = "mac-base"; + reg = <0x4 0x6>; + #nvmem-cell-cells = <1>; + }; + + macaddr_factory_1000: macaddr@1000 { + compatible = "mac-base"; + reg = <0x1000 0x6>; + #nvmem-cell-cells = <1>; + }; + }; + }; + }; + }; + }; +}; + +&pio { + mmc0_pins_default: mmc0-pins-default { + mux { + function = "flash"; + groups = "emmc_45"; + }; + }; + + mmc0_pins_uhs: mmc0-pins-uhs { + mux { + function = "flash"; + groups = "emmc_45"; + }; + }; +}; + +&gmac0 { + nvmem-cells = <&macaddr_factory_1000 0>; + nvmem-cell-names = "mac-address"; +}; + +&gmac1 { + nvmem-cells = <&macaddr_factory_1000 1>; + nvmem-cell-names = "mac-address"; +}; + +&wifi { + nvmem-cells = <&eeprom_factory_0>; + nvmem-cell-names = "eeprom"; + status = "okay"; +}; diff --git a/target/linux/mediatek/dts/mt7981b-unielec-u7981-01-nand.dts b/target/linux/mediatek/dts/mt7981b-unielec-u7981-01-nand.dts new file mode 100644 index 000000000..230a612a3 --- /dev/null +++ b/target/linux/mediatek/dts/mt7981b-unielec-u7981-01-nand.dts @@ -0,0 +1,116 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT +/* + * Copyright (C) 2023 Allen Zhao + */ + +/dts-v1/; +#include "mt7981b-unielec-u7981-01.dtsi" +/ { + model = "Unielec U7981-01 (NAND)"; + compatible = "unielec,u7981-01-nand", "mediatek,mt7981"; +}; + +&spi0 { + pinctrl-names = "default"; + pinctrl-0 = <&spi0_flash_pins>; + status = "okay"; + spi_nand: spi_nand@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "spi-nand"; + reg = <0>; + spi-max-frequency = <52000000>; + spi-tx-buswidth = <4>; + spi-rx-buswidth = <4>; + + mediatek,nmbm; + mediatek,bmt-max-ratio = <1>; + mediatek,bmt-max-reserved-blocks = <64>; + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "bl2"; + reg = <0x00000 0x0100000>; + read-only; + }; + + partition@100000 { + label = "u-boot-env"; + reg = <0x0100000 0x0080000>; + }; + + factory: partition@180000 { + label = "factory"; + reg = <0x180000 0x200000>; + read-only; + + compatible = "nvmem-cells"; + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + eeprom_factory_0: eeprom@0 { + reg = <0x0 0x1000>; + }; + + macaddr_factory_1000: macaddr@1000 { + compatible = "mac-base"; + reg = <0x1000 0x6>; + #nvmem-cell-cells = <1>; + }; + }; + }; + + partition@380000 { + label = "fip"; + reg = <0x380000 0x0200000>; + }; + + partition@580000 { + label = "ubi"; + reg = <0x580000 0x4000000>; + }; + }; + }; +}; + +&pio { + spi0_flash_pins: spi0-pins { + mux { + function = "spi"; + groups = "spi0", "spi0_wp_hold"; + }; + + conf-pu { + pins = "SPI0_CS", "SPI0_HOLD", "SPI0_WP"; + drive-strength = <8>; + mediatek,pull-up-adv = <0>; /* bias-disable */ + }; + + conf-pd { + pins = "SPI0_CLK", "SPI0_MOSI", "SPI0_MISO"; + drive-strength = <8>; + mediatek,pull-up-adv = <0>; /* bias-disable */ + }; + }; +}; + +&gmac0 { + nvmem-cells = <&macaddr_factory_1000 0>; + nvmem-cell-names = "mac-address"; +}; + +&gmac1 { + nvmem-cells = <&macaddr_factory_1000 1>; + nvmem-cell-names = "mac-address"; +}; + +&wifi { + nvmem-cells = <&eeprom_factory_0>; + nvmem-cell-names = "eeprom"; + status = "okay"; +}; diff --git a/target/linux/mediatek/dts/mt7981b-unielec-u7981-01.dtsi b/target/linux/mediatek/dts/mt7981b-unielec-u7981-01.dtsi new file mode 100644 index 000000000..6e6150ba2 --- /dev/null +++ b/target/linux/mediatek/dts/mt7981b-unielec-u7981-01.dtsi @@ -0,0 +1,124 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT +/* + * Copyright (C) 2023 Allen Zhao + */ + +/dts-v1/; +#include "mt7981.dtsi" +/ { + model = "Unielec U7981-01 (EMMC)"; + compatible = "unielec,u7981-01-emmc", "mediatek,mt7981"; + + chosen { + bootargs = "console=ttyS0,115200n1 loglevel=8 \ + earlycon=uart8250,mmio32,0x11002000 \ + "; + }; + + gpio-keys { + compatible = "gpio-keys"; + reset { + label = "reset"; + linux,code = ; + gpios = <&pio 1 GPIO_ACTIVE_LOW>; + }; + }; +}; + +&uart0 { + status = "okay"; +}; + +&watchdog { + status = "okay"; +}; + +ð { + pinctrl-names = "default"; + pinctrl-0 = <&mdio_pins &gbe_led0_pins &gbe_led1_pins>; + status = "okay"; + + gmac0: mac@0 { + /* LAN */ + compatible = "mediatek,eth-mac"; + reg = <0>; + phy-mode = "2500base-x"; + + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; + }; + + gmac1: mac@1 { + /* WAN */ + compatible = "mediatek,eth-mac"; + reg = <1>; + phy-mode = "gmii"; + phy-handle = <&int_gbe_phy>; + }; +}; + +&mdio_bus { + switch: switch@1f { + compatible = "mediatek,mt7531"; + reg = <31>; + reset-gpios = <&pio 39 GPIO_ACTIVE_HIGH>; + interrupt-controller; + #interrupt-cells = <1>; + interrupt-parent = <&pio>; + interrupts = <38 IRQ_TYPE_LEVEL_HIGH>; + }; +}; + +&switch { + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + label = "lan1"; + }; + + port@1 { + reg = <1>; + label = "lan2"; + }; + + port@2 { + reg = <2>; + label = "lan3"; + }; + + port@3 { + reg = <3>; + label = "lan4"; + }; + + port@6 { + reg = <6>; + label = "cpu"; + ethernet = <&gmac0>; + phy-mode = "2500base-x"; + + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; + }; + }; +}; + +&usb_phy { + status = "okay"; +}; + +&xhci { + mediatek,u3p-dis-msk = <0x0>; + phys = <&u2port0 PHY_TYPE_USB2>, + <&u3port0 PHY_TYPE_USB3>; + status = "okay"; +}; diff --git a/target/linux/mediatek/dts/mt7981b-wavlink-wl-wn586x3.dts b/target/linux/mediatek/dts/mt7981b-wavlink-wl-wn586x3.dts new file mode 100644 index 000000000..62be0faa4 --- /dev/null +++ b/target/linux/mediatek/dts/mt7981b-wavlink-wl-wn586x3.dts @@ -0,0 +1,270 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) + +/dts-v1/; + +#include "mt7981.dtsi" + +/ { + model = "WAVLINK WL-WN586X3"; + compatible = "wavlink,wl-wn586x3", "mediatek,mt7981"; + + aliases { + label-mac-device = &wifi; + led-boot = &led_status_blue; + led-failsafe = &led_status_blue; + led-running = &led_status_blue; + led-upgrade = &led_status_blue; + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + gpio-keys { + compatible = "gpio-keys"; + + button-reset { + label = "reset"; + linux,code = ; + gpios = <&pio 11 GPIO_ACTIVE_LOW>; + }; + }; + + leds { + compatible = "gpio-leds"; + + led-0 { + color = ; + function = LED_FUNCTION_WAN; + gpios = <&pio 5 GPIO_ACTIVE_LOW>; + }; + + led-1 { + color = ; + function = LED_FUNCTION_WLAN; + gpios = <&pio 9 GPIO_ACTIVE_LOW>; + linux,default-trigger = "phy1tpt"; + }; + + led_status_blue: led-2 { + color = ; + function = LED_FUNCTION_STATUS; + gpios = <&pio 10 GPIO_ACTIVE_LOW>; + }; + + led-3 { + color = ; + function = LED_FUNCTION_LAN; + function-enumerator = <1>; + gpios = <&pio 12 GPIO_ACTIVE_LOW>; + }; + + led-4 { + color = ; + function = LED_FUNCTION_LAN; + function-enumerator = <2>; + gpios = <&pio 13 GPIO_ACTIVE_LOW>; + }; + + }; +}; + +&uart0 { + status = "okay"; +}; + +&watchdog { + status = "okay"; +}; + +ð { + status = "okay"; + + gmac0: mac@0 { + compatible = "mediatek,eth-mac"; + reg = <0>; + phy-mode = "2500base-x"; + nvmem-cells = <&macaddr_hw_44e 0>; + nvmem-cell-names = "mac-address"; + + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; + }; + + gmac1: mac@1 { + compatible = "mediatek,eth-mac"; + reg = <1>; + phy-mode = "gmii"; + phy-handle = <&int_gbe_phy>; + nvmem-cells = <&macaddr_hw_44e 1>; + nvmem-cell-names = "mac-address"; + }; +}; + +&mdio_bus { + switch: switch@1f { + compatible = "mediatek,mt7531"; + reg = <31>; + reset-gpios = <&pio 39 GPIO_ACTIVE_HIGH>; + interrupt-controller; + #interrupt-cells = <1>; + interrupt-parent = <&pio>; + interrupts = <38 IRQ_TYPE_LEVEL_HIGH>; + }; +}; + +&spi0 { + pinctrl-names = "default"; + pinctrl-0 = <&spi0_flash_pins>; + status = "disabled"; +}; + +&spi2 { + pinctrl-names = "default"; + pinctrl-0 = <&spi2_flash_pins>; + status = "okay"; + + flash@0 { + #address-cells = <1>; + #size-cells = <1>; + + compatible = "jedec,spi-nor"; + reg = <0>; + + spi-max-frequency = <25000000>; + spi-tx-bus-width = <4>; + spi-rx-bus-width = <4>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@00000 { + label = "bl2"; + reg = <0x00000 0x40000>; + read-only; + }; + + partition@40000 { + label = "u-boot-env"; + reg = <0x40000 0x10000>; + read-only; + }; + + factory: partition@50000 { + label = "factory"; + reg = <0x50000 0xb0000>; + read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + macaddr_factory_4: macaddr@4 { + compatible = "mac-base"; + reg = <0x4 0x6>; + #nvmem-cell-cells = <1>; + }; + }; + }; + + partition@100000 { + label = "fip"; + reg = <0x100000 0x80000>; + read-only; + }; + + partition@f0000 { + label = "firmware"; + reg = <0x180000 0xe00000>; + }; + + partition@f80000 { + label = "hw"; + reg = <0xf80000 0x80000>; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + macaddr_hw_44e: macaddr@44e { + compatible = "mac-base"; + reg = <0x44e 0x11>; + #nvmem-cell-cells = <1>; + }; + }; + }; + }; + }; +}; + +&pio { + spi0_flash_pins: spi0-pins { + mux { + function = "spi"; + groups = "spi0", "spi0_wp_hold"; + }; + }; + + spi2_flash_pins: spi2-pins { + mux { + function = "spi"; + groups = "spi2", "spi2_wp_hold"; + }; + + conf-pu { + pins = "SPI2_CS", "SPI2_HOLD", "SPI2_WP"; + drive-strength = <8>; + bias-pull-up = <103>; + }; + + conf-pd { + pins = "SPI2_CLK", "SPI2_MOSI", "SPI2_MISO"; + drive-strength = <8>; + bias-pull-down = <103>; + }; + }; +}; + +&switch { + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@1 { + reg = <1>; + label = "lan2"; + }; + + port@2 { + reg = <2>; + label = "lan1"; + }; + + port@6 { + reg = <6>; + ethernet = <&gmac0>; + phy-mode = "2500base-x"; + + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; + }; + }; +}; + +&wifi { + status = "okay"; + mediatek,mtd-eeprom = <&factory 0x0>; + nvmem-cells = <&macaddr_factory_4 0>; + nvmem-cell-names = "mac-address"; +}; diff --git a/target/linux/mediatek/dts/mt7981b-xiaomi-ax3000t.dts b/target/linux/mediatek/dts/mt7981b-xiaomi-ax3000t.dts deleted file mode 100644 index 96f7680ef..000000000 --- a/target/linux/mediatek/dts/mt7981b-xiaomi-ax3000t.dts +++ /dev/null @@ -1,49 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later OR MIT - -/dts-v1/; - -#include "mt7981b-xiaomi_mi-router.dtsi" - -/ { - model = "Xiaomi Mi Router AX3000T"; - compatible = "xiaomi,mi-router-ax3000t", "mediatek,mt7981"; -}; - -&gmac0 { - nvmem-cells = <&macaddr_factory_4>; - nvmem-cell-names = "mac-address"; - mac-address-increment = <(-2)>; -}; - -&i2c0 { - pinctrl-names = "default"; - pinctrl-0 = <&i2c_pins>; - status = "okay"; - - nfc@57 { - compatible = "nt082c"; - reg = <0x57>; - }; -}; - -&partitions { - partition@600000 { - label = "ubi"; - reg = <0x0600000 0x6400000>; - }; - - partition@6a00000 { - label = "data"; - reg = <0x6a00000 0x0c00000>; - read-only; - }; -}; - -&pio { - i2c_pins: i2c-pins { - mux { - function = "i2c"; - groups = "i2c0_1"; - }; - }; -}; diff --git a/target/linux/mediatek/dts/mt7981b-xiaomi-mi-router-ax3000t-ubootmod.dts b/target/linux/mediatek/dts/mt7981b-xiaomi-mi-router-ax3000t-ubootmod.dts new file mode 100644 index 000000000..809e625ce --- /dev/null +++ b/target/linux/mediatek/dts/mt7981b-xiaomi-mi-router-ax3000t-ubootmod.dts @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +/dts-v1/; +#include "mt7981b-xiaomi-mi-router-ax3000t.dtsi" + +/ { + model = "Xiaomi Mi Router AX3000T (OpenWrt U-Boot layout)"; + compatible = "xiaomi,mi-router-ax3000t-ubootmod", "mediatek,mt7981"; +}; + +&partitions { + partition@600000 { + label = "ubi"; + reg = <0x600000 0x7000000>; + }; +}; diff --git a/target/linux/mediatek/dts/mt7981b-xiaomi-mi-router-ax3000t.dts b/target/linux/mediatek/dts/mt7981b-xiaomi-mi-router-ax3000t.dts new file mode 100644 index 000000000..cc0d44fdf --- /dev/null +++ b/target/linux/mediatek/dts/mt7981b-xiaomi-mi-router-ax3000t.dts @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +/dts-v1/; +#include "mt7981b-xiaomi-mi-router-ax3000t.dtsi" + +/ { + model = "Xiaomi Mi Router AX3000T"; + compatible = "xiaomi,mi-router-ax3000t", "mediatek,mt7981"; +}; + +&spi_nand { + mediatek,nmbm; + mediatek,bmt-max-ratio = <1>; + mediatek,bmt-max-reserved-blocks = <64>; +}; + +&partitions { + // ubi_kernel is the ubi partition in stock. + partition@600000 { + label = "ubi_kernel"; + reg = <0x600000 0x2200000>; + }; + + /* ubi is the result of squashing + * consecutive stock partitions: + * - ubi1 + * - overlay + * - data + */ + partition@2800000 { + label = "ubi"; + reg = <0x2800000 0x4e00000>; + }; +}; diff --git a/target/linux/mediatek/dts/mt7981b-xiaomi-mi-router-ax3000t.dtsi b/target/linux/mediatek/dts/mt7981b-xiaomi-mi-router-ax3000t.dtsi new file mode 100644 index 000000000..7b6fde846 --- /dev/null +++ b/target/linux/mediatek/dts/mt7981b-xiaomi-mi-router-ax3000t.dtsi @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +/dts-v1/; +#include "mt7981b-xiaomi-mi-router-common.dtsi" + +&gmac0 { + nvmem-cell-names = "mac-address"; + nvmem-cells = <&macaddr_factory_4 (-2)>; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c_pins>; + status = "okay"; + + nfc@57 { + compatible = "nt082c"; + reg = <0x57>; + }; +}; + +&pio { + i2c_pins: i2c-pins { + mux { + function = "i2c"; + groups = "i2c0_1"; + }; + }; +}; diff --git a/target/linux/mediatek/dts/mt7981b-xiaomi_mi-router.dtsi b/target/linux/mediatek/dts/mt7981b-xiaomi-mi-router-common.dtsi similarity index 69% rename from target/linux/mediatek/dts/mt7981b-xiaomi_mi-router.dtsi rename to target/linux/mediatek/dts/mt7981b-xiaomi-mi-router-common.dtsi index bb97b5588..d6872395a 100644 --- a/target/linux/mediatek/dts/mt7981b-xiaomi_mi-router.dtsi +++ b/target/linux/mediatek/dts/mt7981b-xiaomi-mi-router-common.dtsi @@ -1,17 +1,18 @@ // SPDX-License-Identifier: GPL-2.0-or-later OR MIT -#include +/dts-v1/; #include +#include #include "mt7981.dtsi" / { aliases { serial0 = &uart0; - led-boot = &led_system_orange; - led-failsafe = &led_system_blue; - led-running = &led_system_blue; - led-upgrade = &led_system_orange; + led-boot = &led_status_yellow; + led-failsafe = &led_status_yellow; + led-running = &led_status_blue; + led-upgrade = &led_status_yellow; }; chosen { @@ -25,30 +26,32 @@ gpio-keys { compatible = "gpio-keys"; - reset { - label = "reset"; - linux,code = ; - gpios = <&pio 1 GPIO_ACTIVE_LOW>; - }; - - mesh { + button-mesh { label = "mesh"; + gpios = <&pio 0 GPIO_ACTIVE_LOW>; linux,code = ; linux,input-type = ; - gpios = <&pio 0 GPIO_ACTIVE_LOW>; + }; + + button-reset { + label = "reset"; + gpios = <&pio 1 GPIO_ACTIVE_LOW>; + linux,code = ; }; }; leds: leds { compatible = "gpio-leds"; - led_system_blue: system_blue { - label = "blue:system"; + led_status_blue: led-status-blue { + color = ; + function = LED_FUNCTION_STATUS; gpios = <&pio 9 GPIO_ACTIVE_LOW>; }; - led_system_orange: system_orange { - label = "orange:system"; + led_status_yellow: led-status-yellow { + color = ; + function = LED_FUNCTION_STATUS; gpios = <&pio 10 GPIO_ACTIVE_LOW>; }; }; @@ -71,7 +74,7 @@ }; &mdio_bus { - switch: switch@0 { + switch: switch@1f { compatible = "mediatek,mt7531"; reg = <31>; reset-gpios = <&pio 39 GPIO_ACTIVE_HIGH>; @@ -82,89 +85,6 @@ }; }; -&spi0 { - pinctrl-names = "default"; - pinctrl-0 = <&spi0_flash_pins>; - status = "okay"; - - spi_nand@0 { - compatible = "spi-nand"; - #address-cells = <1>; - #size-cells = <1>; - reg = <0>; - - spi-max-frequency = <52000000>; - spi-tx-bus-width = <4>; - spi-rx-bus-width = <4>; - - mediatek,nmbm; - mediatek,bmt-max-ratio = <1>; - mediatek,bmt-max-reserved-blocks = <64>; - - partitions: partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - partition@0 { - label = "BL2"; - reg = <0x0000000 0x0100000>; - read-only; - }; - - partition@100000 { - label = "Nvram"; - reg = <0x0100000 0x0040000>; - read-only; - }; - - partition@140000 { - label = "Bdata"; - reg = <0x0140000 0x0040000>; - read-only; - }; - - factory: partition@180000 { - label = "Factory"; - reg = <0x0180000 0x0200000>; - read-only; - - compatible = "nvmem-cells"; - #address-cells = <1>; - #size-cells = <1>; - - macaddr_factory_4: macaddr@4 { - reg = <0x4 0x6>; - }; - }; - - partition@380000 { - label = "FIP"; - reg = <0x0380000 0x0200000>; - read-only; - }; - - partition@580000 { - label = "crash"; - reg = <0x0580000 0x0040000>; - read-only; - }; - - partition@5c0000 { - label = "crash_log"; - reg = <0x05c0000 0x0040000>; - read-only; - }; - - partition@7600000 { - label = "KF"; - reg = <0x7600000 0x0040000>; - read-only; - }; - }; - }; -}; - &switch { ports { #address-cells = <1>; @@ -192,7 +112,6 @@ port@6 { reg = <6>; - label = "cpu"; ethernet = <&gmac0>; phy-mode = "2500base-x"; @@ -205,6 +124,91 @@ }; }; +&spi0 { + pinctrl-names = "default"; + pinctrl-0 = <&spi0_flash_pins>; + status = "okay"; + + spi_nand: flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "spi-nand"; + reg = <0>; + + spi-max-frequency = <52000000>; + spi-tx-bus-width = <4>; + spi-rx-bus-width = <4>; + + partitions: partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "BL2"; + reg = <0x00 0x100000>; + read-only; + }; + + partition@100000 { + label = "Nvram"; + reg = <0x100000 0x40000>; + }; + + partition@140000 { + label = "Bdata"; + reg = <0x140000 0x40000>; + }; + + factory: partition@180000 { + label = "Factory"; + reg = <0x180000 0x200000>; + read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + eeprom_factory_0: eeprom@0 { + reg = <0x0 0x1000>; + }; + + macaddr_factory_4: macaddr@4 { + compatible = "mac-base"; + reg = <0x4 0x6>; + #nvmem-cell-cells = <1>; + }; + }; + }; + + partition@380000 { + label = "FIP"; + reg = <0x380000 0x200000>; + read-only; + }; + + partition@580000 { + label = "crash"; + reg = <0x580000 0x40000>; + read-only; + }; + + partition@5c0000 { + label = "crash_log"; + reg = <0x5c0000 0x40000>; + read-only; + }; + + partition@7600000 { + label = "KF"; + reg = <0x7600000 0x40000>; + read-only; + }; + }; + }; +}; + &pio { spi0_flash_pins: spi0-pins { mux { @@ -214,18 +218,24 @@ conf-pu { pins = "SPI0_CS", "SPI0_HOLD", "SPI0_WP"; - drive-strength = <8>; - mediatek,pull-up-adv = <0>; /* bias-disable */ + drive-strength = ; + bias-pull-up = ; }; conf-pd { pins = "SPI0_CLK", "SPI0_MOSI", "SPI0_MISO"; - drive-strength = <8>; - mediatek,pull-up-adv = <0>; /* bias-disable */ + drive-strength = ; + bias-pull-down = ; }; }; }; +&wifi { + status = "okay"; + nvmem-cells = <&eeprom_factory_0>; + nvmem-cell-names = "eeprom"; +}; + &uart0 { status = "okay"; }; @@ -233,9 +243,3 @@ &watchdog { status = "okay"; }; - -&wifi { - status = "okay"; - - mediatek,mtd-eeprom = <&factory 0x0>; -}; diff --git a/target/linux/mediatek/dts/mt7981b-xiaomi-mi-router-wr30u-stock.dts b/target/linux/mediatek/dts/mt7981b-xiaomi-mi-router-wr30u-stock.dts new file mode 100644 index 000000000..7faa6e84e --- /dev/null +++ b/target/linux/mediatek/dts/mt7981b-xiaomi-mi-router-wr30u-stock.dts @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +/dts-v1/; +#include "mt7981b-xiaomi-mi-router-wr30u.dtsi" + +/ { + model = "Xiaomi Mi Router WR30U (stock layout)"; + compatible = "xiaomi,mi-router-wr30u-stock", "mediatek,mt7981"; +}; + +&spi_nand { + mediatek,nmbm; + mediatek,bmt-max-ratio = <1>; + mediatek,bmt-max-reserved-blocks = <64>; +}; + +&partitions { + // ubi_kernel is the ubi partition in stock. + partition@600000 { + label = "ubi_kernel"; + reg = <0x600000 0x2200000>; + }; + + /* ubi is the result of squashing + * consecutive stock partitions: + * - ubi1 + * - overlay + * - data + */ + partition@2800000 { + label = "ubi"; + reg = <0x2800000 0x4e00000>; + }; +}; diff --git a/target/linux/mediatek/dts/mt7981b-xiaomi-mi-router-wr30u-ubootmod.dts b/target/linux/mediatek/dts/mt7981b-xiaomi-mi-router-wr30u-ubootmod.dts new file mode 100644 index 000000000..6d0f3feb4 --- /dev/null +++ b/target/linux/mediatek/dts/mt7981b-xiaomi-mi-router-wr30u-ubootmod.dts @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +/dts-v1/; +#include "mt7981b-xiaomi-mi-router-wr30u.dtsi" + +/ { + model = "Xiaomi Mi Router WR30U (OpenWrt U-Boot layout)"; + compatible = "xiaomi,mi-router-wr30u-ubootmod", "mediatek,mt7981"; +}; + +&partitions { + partition@600000 { + label = "ubi"; + reg = <0x600000 0x7000000>; + }; +}; diff --git a/target/linux/mediatek/dts/mt7981b-xiaomi-mi-router-wr30u.dtsi b/target/linux/mediatek/dts/mt7981b-xiaomi-mi-router-wr30u.dtsi new file mode 100644 index 000000000..87a2493a2 --- /dev/null +++ b/target/linux/mediatek/dts/mt7981b-xiaomi-mi-router-wr30u.dtsi @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +/dts-v1/; +#include "mt7981b-xiaomi-mi-router-common.dtsi" + +&gmac0 { + nvmem-cell-names = "mac-address"; + nvmem-cells = <&macaddr_factory_4 (-1)>; +}; + +&leds { + led-wan-blue { + color = ; + function = LED_FUNCTION_WAN; + gpios = <&pio 11 GPIO_ACTIVE_LOW>; + }; + + led-wan-yellow { + color = ; + function = LED_FUNCTION_WAN; + gpios = <&pio 12 GPIO_ACTIVE_LOW>; + }; +}; diff --git a/target/linux/mediatek/dts/mt7981b-xiaomi-wr30u.dts b/target/linux/mediatek/dts/mt7981b-xiaomi-wr30u.dts deleted file mode 100644 index f1cfcf1a3..000000000 --- a/target/linux/mediatek/dts/mt7981b-xiaomi-wr30u.dts +++ /dev/null @@ -1,35 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later OR MIT - -/dts-v1/; - -#include "mt7981b-xiaomi_mi-router.dtsi" - -/ { - model = "Xiaomi Mi Router WR30U"; - compatible = "xiaomi,mi-router-wr30u", "mediatek,mt7981"; -}; - -&gmac0 { - nvmem-cells = <&macaddr_factory_4>; - nvmem-cell-names = "mac-address"; - mac-address-increment = <(-1)>; -}; - -&leds { - internet_blue { - label = "blue:internet"; - gpios = <&pio 11 GPIO_ACTIVE_LOW>; - }; - - internet_orange { - label = "orange:internet"; - gpios = <&pio 12 GPIO_ACTIVE_LOW>; - }; -}; - -&partitions { - partition@600000 { - label = "ubi"; - reg = <0x600000 0x7000000>; - }; -}; diff --git a/target/linux/mediatek/dts/mt7981b-yuncore-ax835.dts b/target/linux/mediatek/dts/mt7981b-yuncore-ax835.dts new file mode 100644 index 000000000..5f98e6178 --- /dev/null +++ b/target/linux/mediatek/dts/mt7981b-yuncore-ax835.dts @@ -0,0 +1,257 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) + +/dts-v1/; + +#include "mt7981.dtsi" + +/ { + compatible = "yuncore,ax835", "mediatek,mt7981"; + model = "YunCore AX835"; + + aliases { + led-boot = &led_system; + led-failsafe = &led_system; + led-running = &led_system; + led-upgrade = &led_system; + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + gpio-keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + linux,code = ; + gpios = <&pio 1 GPIO_ACTIVE_LOW>; + }; + }; + + reg_led_vbus { + compatible = "regulator-fixed"; + regulator-name = "led_vbus"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + gpios = <&pio 5 GPIO_ACTIVE_HIGH>; + }; + + leds { + compatible = "gpio-leds"; + + led_system: led_system { + label = "red:system"; + gpios = <&pio 4 GPIO_ACTIVE_LOW>; + }; + + led_wifi24 { + label = "green:wifi2"; + gpios = <&pio 34 GPIO_ACTIVE_LOW>; + linux,default-trigger = "phy0tpt"; + }; + + led_wifi5 { + label = "blue:wifi5"; + gpios = <&pio 35 GPIO_ACTIVE_LOW>; + linux,default-trigger = "phy1tpt"; + }; + + led_hwwatchdog { + // a gpio-wdt watchdog couldn't be made to work. + // the device rebooted after 5 minutes. + label = "hwwatchdog"; + gpios = <&pio 7 GPIO_ACTIVE_LOW>; + linux,default-trigger = "timer"; + led-pattern = <1000>, <1000>; + }; + + // there's another "syswatchdog" on gpio2 + }; +}; + +ð { + pinctrl-names = "default"; + pinctrl-0 = <&mdio_pins>; + + status = "okay"; + + gmac0: mac@0 { + compatible = "mediatek,eth-mac"; + reg = <0>; + phy-mode = "2500base-x"; + + nvmem-cell-names = "mac-address"; + nvmem-cells = <&macaddr_factory_2a>; + + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; + }; +}; + +&mdio_bus { + switch: switch@1f { + compatible = "mediatek,mt7531"; + reg = <31>; + reset-gpios = <&pio 39 GPIO_ACTIVE_HIGH>; + }; +}; + +&pio { + spi0_flash_pins: spi0-pins { + mux { + function = "spi"; + groups = "spi0", "spi0_wp_hold"; + }; + }; + + spi2_flash_pins: spi2-pins { + mux { + function = "spi"; + groups = "spi2", "spi2_wp_hold"; + }; + + conf-pu { + pins = "SPI2_CS", "SPI2_HOLD", "SPI2_WP"; + drive-strength = <8>; + bias-pull-up = <103>; + }; + + conf-pd { + pins = "SPI2_CLK", "SPI2_MOSI", "SPI2_MISO"; + drive-strength = <8>; + bias-pull-down = <103>; + }; + }; +}; + +&spi0 { + pinctrl-names = "default"; + pinctrl-0 = <&spi0_flash_pins>; + status = "disabled"; +}; + +&spi2 { + pinctrl-names = "default"; + pinctrl-0 = <&spi2_flash_pins>; + status = "okay"; + + flash@0 { + #address-cells = <1>; + #size-cells = <1>; + + compatible = "jedec,spi-nor"; + reg = <0>; + + spi-max-frequency = <52000000>; + spi-tx-bus-width = <4>; + spi-rx-bus-width = <4>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@00000 { + label = "BL2"; + reg = <0x00000 0x40000>; + read-only; + }; + + partition@40000 { + label = "u-boot-env"; + reg = <0x40000 0x10000>; + read-only; + }; + + factory: partition@50000 { + label = "Factory"; + reg = <0x50000 0x10000>; + read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + eeprom_factory: eeprom@0 { + reg = <0x0 0x1000>; + }; + + macaddr_factory_4: macaddr@4 { + reg = <0x4 0x6>; + }; + + macaddr_factory_24: macaddr@24 { + reg = <0x24 0x6>; + }; + + macaddr_factory_2a: macaddr@2a { + reg = <0x2a 0x6>; + }; + }; + }; + + partition@100000 { + label = "FIP"; + reg = <0x100000 0x80000>; + read-only; + }; + + partition@180000 { + compatible = "denx,fit"; + label = "firmware"; + reg = <0x180000 0xe00000>; + }; + }; + }; +}; + +&switch { + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@3 { + reg = <3>; + label = "lan"; + }; + + port@4 { + reg = <4>; + label = "wan"; + }; + + port@6 { + reg = <6>; + label = "cpu"; + ethernet = <&gmac0>; + phy-mode = "2500base-x"; + + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; + }; + }; +}; + +&uart0 { + status = "okay"; +}; + +&watchdog { + status = "okay"; +}; + +&wifi { + status = "okay"; + nvmem-cells = <&eeprom_factory 0>; + nvmem-cell-names = "eeprom"; +}; diff --git a/target/linux/mediatek/dts/mt7981b-zbtlink-zbt-z8102ax.dts b/target/linux/mediatek/dts/mt7981b-zbtlink-zbt-z8102ax.dts new file mode 100644 index 000000000..f4d5271f9 --- /dev/null +++ b/target/linux/mediatek/dts/mt7981b-zbtlink-zbt-z8102ax.dts @@ -0,0 +1,326 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +/dts-v1/; + +#include "mt7981.dtsi" + +/ { + model = "Zbtlink ZBT-Z8102AX"; + compatible = "zbtlink,zbt-z8102ax", "mediatek,mt7981"; + + aliases { + serial0 = &uart0; + led-boot = &led_status_green; + led-failsafe = &led_status_red; + led-running = &led_status_green; + led-upgrade = &led_status_green; + label-mac-device = &gmac0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + bootargs = "earlycon=uart8250,mmio32,0x11002000 console=ttyS0,115200n8 loglevel=8"; + }; + + memory { + reg = <0 0x40000000 0 0x40000000>; + }; + + gpio-keys { + compatible = "gpio-keys"; + + button-reset { + label = "reset"; + linux,code = ; + gpios = <&pio 1 GPIO_ACTIVE_LOW>; + }; + + button-mesh { + label = "mesh"; + linux,code = ; + gpios = <&pio 0 GPIO_ACTIVE_HIGH>; + }; + + button-hub { + label = "hub"; + linux,code = ; + gpios = <&pio 12 GPIO_ACTIVE_HIGH>; + }; + }; + + leds { + compatible = "gpio-leds"; + + led_status_red: red { + gpios = <&pio 9 GPIO_ACTIVE_HIGH>; + color = ; + function = LED_FUNCTION_STATUS; + }; + + led_status_green: green { + gpios = <&pio 10 GPIO_ACTIVE_LOW>; + color = ; + function = LED_FUNCTION_STATUS; + }; + + blue { + gpios = <&pio 11 GPIO_ACTIVE_LOW>; + color = ; + function = LED_FUNCTION_STATUS; + }; + + 4g { + gpios = <&pio 8 GPIO_ACTIVE_LOW>; + color = ; + function = LED_FUNCTION_USB; + function-enumerator = <0>; + }; + + 4g2 { + gpios = <&pio 14 GPIO_ACTIVE_LOW>; + color = ; + function = LED_FUNCTION_USB; + function-enumerator = <1>; + }; + }; + + watchdog { + compatible = "linux,wdt-gpio"; + gpios = <&pio 2 GPIO_ACTIVE_HIGH>; + hw_algo = "toggle"; + hw_margin_ms = <1000>; + }; + + gpio-export { + compatible = "gpio-export"; + #size-cells = <0>; + + pcie { + gpio-export,name = "pcie_power"; + gpio-export,output = <1>; + gpios = <&pio 3 GPIO_ACTIVE_HIGH>; + }; + + 5g1 { + gpio-export,name = "5g1"; + gpio-export,output = <1>; + gpios = <&pio 4 GPIO_ACTIVE_HIGH>; + }; + + 5g2 { + gpio-export,name = "5g2"; + gpio-export,output = <1>; + gpios = <&pio 5 GPIO_ACTIVE_HIGH>; + }; + + sim1 { + gpio-export,name = "sim1"; + gpio-export,output = <1>; + gpios = <&pio 6 GPIO_ACTIVE_HIGH>; + }; + + sim2 { + gpio-export,name = "sim2"; + gpio-export,output = <1>; + gpios = <&pio 7 GPIO_ACTIVE_HIGH>; + }; + }; +}; + +ð { + status = "okay"; + + gmac0: mac@0 { + /* LAN */ + compatible = "mediatek,eth-mac"; + reg = <0>; + phy-mode = "2500base-x"; + + nvmem-cell-names = "mac-address"; + nvmem-cells = <&macaddr_factory_4 2>; + + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; + }; + + gmac1: mac@1 { + /* WAN */ + compatible = "mediatek,eth-mac"; + reg = <1>; + phy-mode = "gmii"; + phy-handle = <&int_gbe_phy>; + + nvmem-cell-names = "mac-address"; + nvmem-cells = <&macaddr_factory_4 3>; + }; +}; + +&mdio_bus { + switch: switch@1f { + compatible = "mediatek,mt7531"; + reg = <31>; + reset-gpios = <&pio 39 GPIO_ACTIVE_HIGH>; + interrupt-controller; + #interrupt-cells = <1>; + interrupt-parent = <&pio>; + interrupts = <38 IRQ_TYPE_LEVEL_HIGH>; + }; +}; + +&spi0 { + pinctrl-names = "default"; + pinctrl-0 = <&spi0_flash_pins>; + status = "okay"; + + spi_nand@0 { + compatible = "spi-nand"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0>; + + spi-max-frequency = <52000000>; + spi-tx-bus-width = <4>; + spi-rx-bus-width = <4>; + + mediatek,nmbm; + mediatek,bmt-max-ratio = <1>; + mediatek,bmt-max-reserved-blocks = <64>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "bl2"; + reg = <0x0000000 0x0100000>; + read-only; + }; + + partition@100000 { + label = "u-boot-env"; + reg = <0x100000 0x80000>; + }; + + partition@180000 { + label = "Factory"; + reg = <0x180000 0x200000>; + read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + eeprom_factory: eeprom@0 { + reg = <0x0 0x1000>; + }; + + macaddr_factory_4: macaddr@4 { + compatible = "mac-base"; + reg = <0x4 0x6>; + #nvmem-cell-cells = <1>; + }; + }; + }; + + partition@380000 { + label = "FIP"; + reg = <0x380000 0x200000>; + read-only; + }; + + partition@580000 { + label = "ubi"; + reg = <0x580000 0x4000000>; + }; + }; + }; +}; + +&switch { + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + label = "lan1"; + }; + + port@1 { + reg = <1>; + label = "lan2"; + }; + + port@2 { + reg = <2>; + label = "lan3"; + }; + + port@3 { + reg = <3>; + label = "lan4"; + }; + + port@6 { + reg = <6>; + label = "cpu"; + ethernet = <&gmac0>; + phy-mode = "2500base-x"; + + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; + }; + }; +}; + +&pio { + spi0_flash_pins: spi0-pins { + mux { + function = "spi"; + groups = "spi0", "spi0_wp_hold"; + }; + + conf-pu { + pins = "SPI0_CS", "SPI0_HOLD", "SPI0_WP"; + drive-strength = <8>; + bias-pull-up = <103>; + }; + + conf-pd { + pins = "SPI0_CLK", "SPI0_MOSI", "SPI0_MISO"; + drive-strength = <8>; + bias-pull-down = <103>; + }; + }; +}; + +&uart0 { + status = "okay"; +}; + +&watchdog { + status = "okay"; +}; + +&usb_phy { + status = "okay"; +}; + +&xhci { + status = "okay"; +}; + +&wifi { + status = "okay"; + + nvmem-cells = <&eeprom_factory>; + nvmem-cell-names = "eeprom"; +}; diff --git a/target/linux/mediatek/dts/mt7981b-imou-lc-hx3001.dts b/target/linux/mediatek/dts/mt7981b-zbtlink-zbt-z8103ax.dts similarity index 51% rename from target/linux/mediatek/dts/mt7981b-imou-lc-hx3001.dts rename to target/linux/mediatek/dts/mt7981b-zbtlink-zbt-z8103ax.dts index 5371e2ae0..2b079f5bc 100644 --- a/target/linux/mediatek/dts/mt7981b-imou-lc-hx3001.dts +++ b/target/linux/mediatek/dts/mt7981b-zbtlink-zbt-z8103ax.dts @@ -1,26 +1,25 @@ -// SPDX-License-Identifier: GPL-2.0-or-later OR MIT +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT /dts-v1/; -#include -#include #include "mt7981.dtsi" / { - model = "IMOU LC-HX3001"; - compatible = "imou,lc-hx3001", "mediatek,mt7981"; + model = "Zbtlink ZBT-Z8103AX"; + compatible = "zbtlink,zbt-z8103ax", "mediatek,mt7981"; aliases { serial0 = &uart0; - - led-boot = &led_power; - led-failsafe = &led_power; - led-running = &led_power; - led-upgrade = &led_power; + led-boot = &led_status_green; + led-failsafe = &led_status_red; + led-running = &led_status_green; + led-upgrade = &led_status_green; + label-mac-device = &gmac0; }; chosen { stdout-path = "serial0:115200n8"; + bootargs = "earlycon=uart8250,mmio32,0x11002000 console=ttyS0,115200n8 loglevel=8"; }; memory { @@ -30,47 +29,62 @@ gpio-keys { compatible = "gpio-keys"; - reset { + button-mesh { + label = "mesh"; + linux,code = ; + linux,input-type = ; + gpios = <&pio 0 GPIO_ACTIVE_HIGH>; + }; + + button-reset { label = "reset"; linux,code = ; gpios = <&pio 1 GPIO_ACTIVE_LOW>; }; - - wps { - label = "wps"; - linux,code = ; - gpios = <&pio 0 GPIO_ACTIVE_LOW>; - }; }; leds { compatible = "gpio-leds"; - led_power: power { - label = "green:power"; - gpios = <&pio 4 GPIO_ACTIVE_LOW>; - }; - - wifi { - label = "green:wifi"; - gpios = <&pio 5 GPIO_ACTIVE_LOW>; - linux,default-trigger = "phy1tpt"; - }; - - wan_red { - label = "red:wan"; - gpios = <&pio 6 GPIO_ACTIVE_LOW>; - }; - - wan_green { - label = "green:wan"; - gpios = <&pio 7 GPIO_ACTIVE_LOW>; - }; - - lan { - label = "green:lan"; + led-wan { + color = ; + function = LED_FUNCTION_WAN; gpios = <&pio 8 GPIO_ACTIVE_LOW>; }; + + led-status-blue { + color = ; + function = LED_FUNCTION_STATUS; + gpios = <&pio 23 GPIO_ACTIVE_HIGH>; + }; + + led_status_green: led-status-green { + color = ; + function = LED_FUNCTION_STATUS; + gpios = <&pio 24 GPIO_ACTIVE_LOW>; + }; + + led_status_red: led-status-red { + color = ; + function = LED_FUNCTION_STATUS; + gpios = <&pio 25 GPIO_ACTIVE_LOW>; + }; + + led-wlan2g { + color = ; + function = LED_FUNCTION_WLAN; + gpios = <&pio 34 GPIO_ACTIVE_LOW>; + function-enumerator = <0>; + linux,default-trigger = "phy0tpt"; + }; + + led-wlan5g { + color = ; + function = LED_FUNCTION_WLAN; + gpios = <&pio 35 GPIO_ACTIVE_LOW>; + function-enumerator = <1>; + linux,default-trigger = "phy1tpt"; + }; }; }; @@ -78,10 +92,14 @@ status = "okay"; gmac0: mac@0 { + /* LAN */ compatible = "mediatek,eth-mac"; reg = <0>; phy-mode = "2500base-x"; + nvmem-cell-names = "mac-address"; + nvmem-cells = <&macaddr_factory_4 2>; + fixed-link { speed = <2500>; full-duplex; @@ -90,15 +108,19 @@ }; gmac1: mac@1 { + /* WAN */ compatible = "mediatek,eth-mac"; reg = <1>; phy-mode = "gmii"; phy-handle = <&int_gbe_phy>; + + nvmem-cell-names = "mac-address"; + nvmem-cells = <&macaddr_factory_4 3>; }; }; &mdio_bus { - switch: switch@0 { + switch: switch@1f { compatible = "mediatek,mt7531"; reg = <31>; reset-gpios = <&pio 39 GPIO_ACTIVE_HIGH>; @@ -124,41 +146,53 @@ spi-tx-bus-width = <4>; spi-rx-bus-width = <4>; - mediatek,nmbm; - mediatek,bmt-max-ratio = <1>; - mediatek,bmt-max-reserved-blocks = <64>; - partitions { compatible = "fixed-partitions"; #address-cells = <1>; #size-cells = <1>; partition@0 { - label = "BL2"; + label = "bl2"; reg = <0x0000000 0x0100000>; read-only; }; partition@100000 { label = "u-boot-env"; - reg = <0x0100000 0x0080000>; + reg = <0x100000 0x80000>; }; - factory: partition@180000 { + partition@180000 { label = "Factory"; - reg = <0x0180000 0x0200000>; + reg = <0x180000 0x200000>; read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + eeprom_factory: eeprom@0 { + reg = <0x0 0x1000>; + }; + + macaddr_factory_4: macaddr@4 { + compatible = "mac-base"; + reg = <0x4 0x6>; + #nvmem-cell-cells = <1>; + }; + }; }; partition@380000 { label = "FIP"; - reg = <0x0380000 0x0200000>; + reg = <0x380000 0x200000>; read-only; }; partition@580000 { label = "ubi"; - reg = <0x0580000 0x7280000>; + reg = <0x580000 0x4000000>; }; }; }; @@ -208,14 +242,14 @@ conf-pu { pins = "SPI0_CS", "SPI0_HOLD", "SPI0_WP"; - drive-strength = <8>; - mediatek,pull-up-adv = <0>; /* bias-disable */ + drive-strength = ; + bias-pull-up = ; }; conf-pd { pins = "SPI0_CLK", "SPI0_MOSI", "SPI0_MISO"; - drive-strength = <8>; - mediatek,pull-up-adv = <0>; /* bias-disable */ + drive-strength = ; + bias-pull-down = ; }; }; }; @@ -230,6 +264,6 @@ &wifi { status = "okay"; - - mediatek,mtd-eeprom = <&factory 0x0>; + nvmem-cells = <&eeprom_factory>; + nvmem-cell-names = "eeprom"; }; diff --git a/target/linux/mediatek/dts/mt7981b-zyxel-nwa50ax-pro.dts b/target/linux/mediatek/dts/mt7981b-zyxel-nwa50ax-pro.dts new file mode 100644 index 000000000..54df8c054 --- /dev/null +++ b/target/linux/mediatek/dts/mt7981b-zyxel-nwa50ax-pro.dts @@ -0,0 +1,229 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR MIT) +/dts-v1/; + +#include "mt7981.dtsi" + +/ { + model = "ZyXEL NWA50AX Pro"; + compatible = "zyxel,nwa50ax-pro", "mediatek,mt7981"; + + aliases { + led-boot = &led_green; + led-failsafe = &led_red; + led-running = &led_green; + led-upgrade = &led_red; + serial0 = &uart0; + label-mac-device = &gmac1; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + gpio-keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + linux,code = ; + gpios = <&pio 1 GPIO_ACTIVE_LOW>; + }; + }; + + leds { + compatible = "gpio-leds"; + + led_green: led@0 { + label = "green:system"; + gpios = <&pio 4 GPIO_ACTIVE_HIGH>; + }; + + led@1 { + label = "blue:system"; + gpios = <&pio 6 GPIO_ACTIVE_HIGH>; + }; + + led_red: led@2 { + label = "red:system"; + gpios = <&pio 7 GPIO_ACTIVE_HIGH>; + }; + }; +}; + +&uart0 { + status = "okay"; +}; + +&watchdog { + status = "okay"; +}; + +ð { + pinctrl-names = "default"; + pinctrl-0 = <&mdio_pins>; + + status = "okay"; + + gmac1: mac@1 { + compatible = "mediatek,eth-mac"; + reg = <1>; + phy-mode = "2500base-x"; + + phy-handle = <&phy0>; + + nvmem-cells = <&macaddr_mrd_1fff8>; + nvmem-cell-names = "mac-address"; + }; +}; + +&mdio_bus { + reset-gpios = <&pio 12 GPIO_ACTIVE_LOW>; + reset-delay-us = <1500000>; + reset-post-delay-us = <1000000>; + + phy0: ethernet-phy@5 { + reg = <5>; + compatible = "ethernet-phy-ieee802.3-c45"; + + /* LED0: Amber ; LED1: nc ; LED2: nc ; LED3: Green */ + mxl,led-config = <0x3b0 0x0 0x0 0x3c0>; + }; +}; + +&spi0 { + pinctrl-names = "default"; + pinctrl-0 = <&spi0_flash_pins>; + status = "okay"; + + spi_nand: flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "spi-nand"; + reg = <0>; + spi-max-frequency = <52000000>; + + spi-cal-enable; + spi-cal-mode = "read-data"; + spi-cal-datalen = <7>; + spi-cal-data = /bits/ 8 <0x53 0x50 0x49 0x4E 0x41 0x4E 0x44>; + spi-cal-addrlen = <5>; + spi-cal-addr = /bits/ 32 <0x0 0x0 0x0 0x0 0x0>; + + spi-tx-bus-width = <4>; + spi-rx-bus-width = <4>; + mediatek,nmbm; + mediatek,bmt-max-ratio = <1>; + mediatek,bmt-max-reserved-blocks = <64>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "BL2"; + reg = <0x00000 0x0100000>; + read-only; + }; + + partition@100000 { + label = "u-boot-env"; + reg = <0x0100000 0x0080000>; + }; + + factory: partition@180000 { + label = "Factory"; + reg = <0x180000 0x0200000>; + read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + macaddr: macaddr@a { + reg = <0xa 0x6>; + }; + }; + }; + + partition@380000 { + label = "FIP"; + reg = <0x380000 0x0200000>; + read-only; + }; + + partition@580000 { + label = "ubi"; + reg = <0x580000 0x3200000>; + }; + + partition@3780000 { + label = "ubi_1"; + reg = <0x3780000 0x3200000>; + read-only; + }; + + partition@6980000 { + label = "rootfs-data"; + reg = <0x6980000 0x3c00000>; + read-only; + }; + + partition@a580000 { + label = "logs"; + reg = <0xa580000 0x3a80000>; + read-only; + }; + + partition@e000000 { + label = "myzyxel"; + reg = <0xe000000 0xf00000>; + read-only; + }; + + partition@ef00000 { + label = "bootconfig"; + reg = <0xef00000 0x80000>; + }; + + partition@ef80000 { + label = "mrd"; + reg = <0xef80000 0x80000>; + read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + macaddr_mrd_1fff8: macaddr@1fff8 { + reg = <0x1fff8 0x6>; + }; + }; + }; + }; + }; +}; + +&pio { + spi0_flash_pins: spi0-pins { + mux { + function = "spi"; + groups = "spi0", "spi0_wp_hold"; + }; + }; + + pwm_pins: pwm0-pins { + mux { + function = "pwm"; + groups = "pwm0_1"; + }; + }; +}; + +&wifi { + status = "okay"; + + mediatek,mtd-eeprom = <&factory 0x0>; +}; diff --git a/target/linux/mediatek/dts/mt7986a-acelink-ew-7886cax.dts b/target/linux/mediatek/dts/mt7986a-acelink-ew-7886cax.dts new file mode 100644 index 000000000..1bf5d7317 --- /dev/null +++ b/target/linux/mediatek/dts/mt7986a-acelink-ew-7886cax.dts @@ -0,0 +1,238 @@ +// SPDX-License-Identifier: GPL-2.0-only OR MIT + +/dts-v1/; +#include +#include +#include + +#include "mt7986a.dtsi" + +/ { + compatible = "acelink,ew-7886cax", "mediatek,mt7986a"; + model = "Acelink EW-7886CAX"; + + aliases { + serial0 = &uart0; + led-boot = &led_status_blue; + led-running = &led_status_green; + led-upgrade = &led_status_red; + led-failsafe = &led_status_red; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + memory@40000000 { + reg = <0 0x40000000 0 0x20000000>; + device_type = "memory"; + }; + + keys { + compatible = "gpio-keys"; + + key-restart { + label = "Reset"; + gpios = <&pio 7 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + leds { + compatible = "gpio-leds"; + + led_status_red: led-0 { + function = LED_FUNCTION_STATUS; + color = ; + gpios = <&pio 18 GPIO_ACTIVE_HIGH>; + }; + + led_status_green: led-1 { + function = LED_FUNCTION_STATUS; + color = ; + gpios = <&pio 19 GPIO_ACTIVE_HIGH>; + }; + + led_status_blue: led-2 { + function = LED_FUNCTION_STATUS; + color = ; + gpios = <&pio 20 GPIO_ACTIVE_HIGH>; + }; + }; +}; + +&crypto { + status = "okay"; +}; + +ð { + status = "okay"; + + mac@1 { + compatible = "mediatek,eth-mac"; + reg = <1>; + phy-mode = "2500base-x"; + phy-handle = <&phy6>; + nvmem-cells = <&macaddr>; + nvmem-cell-names = "mac-address"; + }; + + mdio-bus { + reset-gpios = <&pio 6 GPIO_ACTIVE_LOW>; + reset-delay-us = <50000>; + reset-post-delay-us = <20000>; + #address-cells = <1>; + #size-cells = <0>; + + /* Maxlinear GPY211C */ + phy6: phy@6 { + compatible = "ethernet-phy-ieee802.3-c45"; + reg = <6>; + }; + }; +}; + +&pcie_phy { + status = "okay"; +}; + +&pio { + spi_flash_pins: spi-flash-pins-33-to-38 { + mux { + function = "spi"; + groups = "spi0", "spi0_wp_hold"; + }; + conf-pu { + pins = "SPI2_CS", "SPI2_HOLD", "SPI2_WP"; + drive-strength = <8>; + mediatek,pull-up-adv = <0>; /* bias-disable */ + }; + conf-pd { + pins = "SPI2_CLK", "SPI2_MOSI", "SPI2_MISO"; + drive-strength = <8>; + mediatek,pull-down-adv = <0>; /* bias-disable */ + }; + }; + + wf_2g_5g_pins: wf_2g_5g-pins { + mux { + function = "wifi"; + groups = "wf_2g", "wf_5g"; + }; + conf { + pins = "WF0_HB1", "WF0_HB2", "WF0_HB3", "WF0_HB4", + "WF0_HB0", "WF0_HB0_B", "WF0_HB5", "WF0_HB6", + "WF0_HB7", "WF0_HB8", "WF0_HB9", "WF0_HB10", + "WF0_TOP_CLK", "WF0_TOP_DATA", "WF1_HB1", + "WF1_HB2", "WF1_HB3", "WF1_HB4", "WF1_HB0", + "WF1_HB5", "WF1_HB6", "WF1_HB7", "WF1_HB8", + "WF1_TOP_CLK", "WF1_TOP_DATA"; + drive-strength = <4>; + }; + }; + + wf_dbdc_pins: wf-dbdc-pins { + mux { + function = "wifi"; + groups = "wf_dbdc"; + }; + conf { + pins = "WF0_HB1", "WF0_HB2", "WF0_HB3", "WF0_HB4", + "WF0_HB0", "WF0_HB0_B", "WF0_HB5", "WF0_HB6", + "WF0_HB7", "WF0_HB8", "WF0_HB9", "WF0_HB10", + "WF0_TOP_CLK", "WF0_TOP_DATA", "WF1_HB1", + "WF1_HB2", "WF1_HB3", "WF1_HB4", "WF1_HB0", + "WF1_HB5", "WF1_HB6", "WF1_HB7", "WF1_HB8", + "WF1_TOP_CLK", "WF1_TOP_DATA"; + drive-strength = <4>; + }; + }; +}; + +&spi0 { + pinctrl-names = "default"; + pinctrl-0 = <&spi_flash_pins>; + status = "okay"; + + flash@0 { + compatible = "spi-nand"; + reg = <0>; + #address-cells = <1>; + #size-cells = <1>; + spi-max-frequency = <52000000>; + spi-rx-bus-width = <4>; + spi-tx-bus-width = <4>; + mediatek,nmbm; + mediatek,bmt-max-ratio = <1>; + mediatek,bmt-max-reserved-blocks = <64>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + reg = <0x0 0x100000>; + label = "bootloader"; + read-only; + }; + + partition@100000 { + reg = <0x100000 0x80000>; + label = "u-boot-env"; + }; + + partition@180000 { + compatible = "nvmem-cells"; + reg = <0x180000 0x200000>; + label = "factory"; + read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + eeprom: eeprom@0 { + reg = <0x0 0x1000>; + }; + + macaddr: macaddr@4 { + reg = <0x4 0x6>; + }; + }; + }; + + partition@380000 { + reg = <0x380000 0x200000>; + label = "fip"; + }; + + partition@580000 { + reg = <0x580000 0x4000000>; + label = "ubi"; + }; + }; + }; +}; + +&trng { + status = "okay"; +}; + +&uart0 { + status = "okay"; +}; + +&watchdog { + status = "okay"; +}; + +&wifi { + pinctrl-names = "default", "dbdc"; + pinctrl-0 = <&wf_2g_5g_pins>; + pinctrl-1 = <&wf_dbdc_pins>; + nvmem-cells = <&eeprom>; + nvmem-cell-names = "eeprom"; + status = "okay"; +}; diff --git a/target/linux/mediatek/dts/mt7986a-acer-predator-w6.dts b/target/linux/mediatek/dts/mt7986a-acer-predator-w6.dts new file mode 100644 index 000000000..612f3c733 --- /dev/null +++ b/target/linux/mediatek/dts/mt7986a-acer-predator-w6.dts @@ -0,0 +1,507 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) + +/dts-v1/; +#include +#include +#include + +#include "mt7986a.dtsi" + +/ { + model = "Acer Predator W6"; + compatible = "acer,predator-w6", "mediatek,mt7986a"; + + aliases { + serial0 = &uart0; + led-boot = &led_status; + led-failsafe = &led_status; + led-running = &led_status; + led-upgrade = &led_status; + }; + + chosen { + stdout-path = "serial0:115200n8"; + bootargs = "dm-mod.create=\"dm-verity,,,ro,0 31544 verity 1 PARTLABEL=rootfs PARTLABEL=rootfs 4096 4096 3943 3944 sha256 2f969fa9e9e4e20b37746f22633e85b178f5db7c143e11f92733a704299cc933 2dd56e34b15c6c84573cf26c4392028421061d2c808975217b45e9a5b49d2087\" rootfstype=squashfs,ext4 rootwait root=/dev/mmcblk0p6 fstools_ignore_partname=1"; + }; + + memory { + reg = <0 0x40000000 0 0x20000000>; + }; + + reg_1p8v: regulator-1p8v { + compatible = "regulator-fixed"; + regulator-name = "fixed-1.8V"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-boot-on; + regulator-always-on; + }; + + reg_3p3v: regulator-3p3v { + compatible = "regulator-fixed"; + regulator-name = "fixed-3.3V"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + regulator-always-on; + }; + + reg_5v: regulator-5v { + compatible = "regulator-fixed"; + regulator-name = "fixed-5V"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-boot-on; + regulator-always-on; + }; + + gpio-keys { + compatible = "gpio-keys"; + + factory { + label = "factory"; + linux,code = ; + gpios = <&pio 9 GPIO_ACTIVE_LOW>; + }; + + wps { + label = "wps"; + linux,code = ; + gpios = <&pio 10 GPIO_ACTIVE_LOW>; + }; + }; + + + leds { + compatible = "gpio-leds"; + + led_status: led@0 { + label = "ant0:red"; + gpios = <&pio 1 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + led@1 { + label = "ant0:green"; + gpios = <&pio 2 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + led@2 { + label = "ant0:blue"; + gpios = <&pio 36 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + led@3 { + label = "ant1:red"; + gpios = <&pio 35 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + led@4 { + label = "ant1:green"; + gpios = <&pio 34 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + led@5 { + label = "ant1:blue"; + gpios = <&pio 33 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + led@6 { + label = "ant2:red"; + gpios = <&pio 38 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + led@7 { + label = "ant2:green"; + gpios = <&pio 37 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + led@8 { + label = "ant2:blue"; + gpios = <&pio 26 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + led@9 { + label = "ant3:red"; + gpios = <&pio 25 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + led@10 { + label = "ant3:green"; + gpios = <&pio 24 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + led@11 { + label = "ant3:blue"; + gpios = <&pio 23 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + led@12 { + label = "ant4:red"; + gpios = <&pio 28 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + led@13 { + label = "ant4:green"; + gpios = <&pio 27 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + led@14 { + label = "ant4:blue"; + gpios = <&pio 32 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + led@15 { + label = "ant5:red"; + gpios = <&pio 45 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + led@16 { + label = "ant5:green"; + gpios = <&pio 44 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + led@17 { + label = "ant5:blue"; + gpios = <&pio 43 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + }; + +}; + +ð { + status = "okay"; + + gmac0: mac@0 { + /* LAN */ + compatible = "mediatek,eth-mac"; + reg = <0>; + phy-mode = "2500base-x"; + + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; + }; + + gmac1: mac@1 { + /* WAN */ + compatible = "mediatek,eth-mac"; + reg = <1>; + phy-mode = "2500base-x"; + phy-handle = <&phy6>; + }; + + mdio: mdio-bus { + #address-cells = <1>; + #size-cells = <0>; + }; +}; + +&mdio { + phy6: phy@6 { + compatible = "ethernet-phy-ieee802.3-c45"; + reg = <6>; + + reset-gpios = <&pio 6 GPIO_ACTIVE_LOW>; + reset-assert-us = <10000>; + reset-deassert-us = <10000>; + + /* LED0: nc ; LED1: nc ; LED2: Amber ; LED3: Green */ + mxl,led-config = <0x0 0x0 0x370 0x80>; + }; + + switch: switch@1f { + compatible = "mediatek,mt7531"; + reg = <31>; + + reset-gpios = <&pio 5 GPIO_ACTIVE_HIGH>; + reset-assert-us = <10000>; + reset-deassert-us = <10000>; + }; +}; + +&pio { + mmc0_pins_default: mmc0-pins { + mux { + function = "emmc"; + groups = "emmc_51"; + }; + conf-cmd-dat { + pins = "EMMC_DATA_0", "EMMC_DATA_1", "EMMC_DATA_2", + "EMMC_DATA_3", "EMMC_DATA_4", "EMMC_DATA_5", + "EMMC_DATA_6", "EMMC_DATA_7", "EMMC_CMD"; + input-enable; + drive-strength = <4>; + mediatek,pull-up-adv = <1>; /* pull-up 10K */ + }; + conf-clk { + pins = "EMMC_CK"; + drive-strength = <6>; + mediatek,pull-down-adv = <2>; /* pull-down 50K */ + }; + conf-ds { + pins = "EMMC_DSL"; + mediatek,pull-down-adv = <2>; /* pull-down 50K */ + }; + conf-rst { + pins = "EMMC_RSTB"; + drive-strength = <4>; + mediatek,pull-up-adv = <1>; /* pull-up 10K */ + }; + }; + + mmc0_pins_uhs: mmc0-uhs-pins { + mux { + function = "emmc"; + groups = "emmc_51"; + }; + conf-cmd-dat { + pins = "EMMC_DATA_0", "EMMC_DATA_1", "EMMC_DATA_2", + "EMMC_DATA_3", "EMMC_DATA_4", "EMMC_DATA_5", + "EMMC_DATA_6", "EMMC_DATA_7", "EMMC_CMD"; + input-enable; + drive-strength = <4>; + mediatek,pull-up-adv = <1>; /* pull-up 10K */ + }; + conf-clk { + pins = "EMMC_CK"; + drive-strength = <6>; + mediatek,pull-down-adv = <2>; /* pull-down 50K */ + }; + conf-ds { + pins = "EMMC_DSL"; + mediatek,pull-down-adv = <2>; /* pull-down 50K */ + }; + conf-rst { + pins = "EMMC_RSTB"; + drive-strength = <4>; + mediatek,pull-up-adv = <1>; /* pull-up 10K */ + }; + }; + + pcie_pins: pcie-pins { + mux { + function = "pcie"; + groups = "pcie_pereset"; + }; + }; + + wf_2g_5g_pins: wf_2g_5g-pins { + mux { + function = "wifi"; + groups = "wf_2g", "wf_5g"; + }; + conf { + pins = "WF0_HB1", "WF0_HB2", "WF0_HB3", "WF0_HB4", + "WF0_HB0", "WF0_HB0_B", "WF0_HB5", "WF0_HB6", + "WF0_HB7", "WF0_HB8", "WF0_HB9", "WF0_HB10", + "WF0_TOP_CLK", "WF0_TOP_DATA", "WF1_HB1", + "WF1_HB2", "WF1_HB3", "WF1_HB4", "WF1_HB0", + "WF1_HB5", "WF1_HB6", "WF1_HB7", "WF1_HB8", + "WF1_TOP_CLK", "WF1_TOP_DATA"; + drive-strength = <4>; + }; + }; + + wf_dbdc_pins: wf-dbdc-pins { + mux { + function = "wifi"; + groups = "wf_dbdc"; + }; + conf { + pins = "WF0_HB1", "WF0_HB2", "WF0_HB3", "WF0_HB4", + "WF0_HB0", "WF0_HB0_B", "WF0_HB5", "WF0_HB6", + "WF0_HB7", "WF0_HB8", "WF0_HB9", "WF0_HB10", + "WF0_TOP_CLK", "WF0_TOP_DATA", "WF1_HB1", + "WF1_HB2", "WF1_HB3", "WF1_HB4", "WF1_HB0", + "WF1_HB5", "WF1_HB6", "WF1_HB7", "WF1_HB8", + "WF1_TOP_CLK", "WF1_TOP_DATA"; + drive-strength = <4>; + }; + }; +}; + +&switch { + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + label = "game"; + phy-handle = <&swphy0>; + }; + + port@1 { + reg = <1>; + label = "lan1"; + phy-handle = <&swphy1>; + }; + + port@2 { + reg = <2>; + label = "lan2"; + phy-handle = <&swphy2>; + }; + + port@3 { + reg = <3>; + label = "lan3"; + phy-handle = <&swphy3>; + }; + + port@6 { + reg = <6>; + label = "cpu"; + ethernet = <&gmac0>; + phy-mode = "2500base-x"; + + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; + }; + }; + + mdio { + #address-cells = <1>; + #size-cells = <0>; + + swphy0: phy@0 { + reg = <0>; + + mediatek,led-config = < + 0x21 0x8009 /* BASIC_CTRL */ + 0x22 0x0c00 /* ON_DURATION */ + 0x23 0x1400 /* BLINK_DURATION */ + 0x24 0xc001 /* LED0_ON_CTRL */ + 0x25 0x0000 /* LED0_BLINK_CTRL */ + 0x26 0xc007 /* LED1_ON_CTRL */ + 0x27 0x003f /* LED1_BLINK_CTRL */ + >; + }; + + swphy1: phy@1 { + reg = <1>; + + mediatek,led-config = < + 0x21 0x8009 /* BASIC_CTRL */ + 0x22 0x0c00 /* ON_DURATION */ + 0x23 0x1400 /* BLINK_DURATION */ + 0x24 0xc001 /* LED0_ON_CTRL */ + 0x25 0x0000 /* LED0_BLINK_CTRL */ + 0x26 0xc007 /* LED1_ON_CTRL */ + 0x27 0x003f /* LED1_BLINK_CTRL */ + >; + }; + + swphy2: phy@2 { + reg = <2>; + + mediatek,led-config = < + 0x21 0x8009 /* BASIC_CTRL */ + 0x22 0x0c00 /* ON_DURATION */ + 0x23 0x1400 /* BLINK_DURATION */ + 0x24 0xc001 /* LED0_ON_CTRL */ + 0x25 0x0000 /* LED0_BLINK_CTRL */ + 0x26 0xc007 /* LED1_ON_CTRL */ + 0x27 0x003f /* LED1_BLINK_CTRL */ + >; + }; + + swphy3: phy@3 { + reg = <3>; + + mediatek,led-config = < + 0x21 0x8009 /* BASIC_CTRL */ + 0x22 0x0c00 /* ON_DURATION */ + 0x23 0x1400 /* BLINK_DURATION */ + 0x24 0xc001 /* LED0_ON_CTRL */ + 0x25 0x0000 /* LED0_BLINK_CTRL */ + 0x26 0xc007 /* LED1_ON_CTRL */ + 0x27 0x003f /* LED1_BLINK_CTRL */ + >; + }; + }; +}; + +&wifi { + status = "okay"; + pinctrl-names = "default", "dbdc"; + pinctrl-0 = <&wf_2g_5g_pins>; + pinctrl-1 = <&wf_dbdc_pins>; +}; + +&trng { + status = "okay"; +}; + +&watchdog { + status = "okay"; +}; + +&crypto { + status = "okay"; +}; + +&uart0 { + status = "okay"; +}; + +&ssusb { + vusb33-supply = <®_3p3v>; + vbus-supply = <®_5v>; + status = "okay"; +}; + +&usb_phy { + status = "okay"; +}; + +&mmc0 { + status = "okay"; + pinctrl-names = "default", "state_uhs"; + pinctrl-0 = <&mmc0_pins_default>; + pinctrl-1 = <&mmc0_pins_uhs>; + bus-width = <0x08>; + max-frequency = <200000000>; + cap-mmc-highspeed; + mmc-hs200-1_8v; + mmc-hs400-1_8v; + hs400-ds-delay = <0x14014>; + vmmc-supply = <®_3p3v>; + vqmmc-supply = <®_1p8v>; + non-removable; + no-sd; + no-sdio; +}; + +&pcie { + pinctrl-names = "default"; + pinctrl-0 = <&pcie_pins>; + status = "okay"; +}; + +&pcie_phy { + status = "okay"; +}; diff --git a/target/linux/mediatek/dts/mt7986a-asus-rt-ax59u.dts b/target/linux/mediatek/dts/mt7986a-asus-rt-ax59u.dts new file mode 100644 index 000000000..0034ad828 --- /dev/null +++ b/target/linux/mediatek/dts/mt7986a-asus-rt-ax59u.dts @@ -0,0 +1,309 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) + +/dts-v1/; +#include +#include +#include + +#include "mt7986a.dtsi" + +/ { + + model = "ASUS RT-AX59U"; + compatible = "asus,rt-ax59u", "mediatek,mt7986a"; + + aliases { + serial0 = &uart0; + label-mac-device = &gmac0; + led-boot = &led_status_green; + led-failsafe = &led_status_red; + led-running = &led_status_green; + led-upgrade = &led_status_blue; + }; + + chosen { + stdout-path = "serial0:115200n8"; + bootargs-override = ""; + }; + + memory { + reg = <0 0x40000000 0 0x20000000>; + }; + + keys { + compatible = "gpio-keys"; + + button-0 { + label = "wps"; + gpios = <&pio 9 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + + button-1 { + label = "reset"; + gpios = <&pio 10 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + leds { + compatible = "gpio-leds"; + + led_status_green: led-0 { + color = ; + function = LED_FUNCTION_STATUS; + gpios = <&pio 11 GPIO_ACTIVE_LOW>; + }; + + led_status_red: led-1 { + color = ; + function = LED_FUNCTION_STATUS; + gpios = <&pio 12 GPIO_ACTIVE_LOW>; + }; + + led_status_blue: led-2 { + color = ; + function = LED_FUNCTION_STATUS; + gpios = <&pio 13 GPIO_ACTIVE_LOW>; + }; + }; + + gpio-export { + compatible = "gpio-export"; + + out { + gpio-export,name = "led-light"; + gpio-export,output = <0>; + gpios = <&pio 22 GPIO_ACTIVE_LOW>; + }; + }; +}; + +&crypto { + status = "okay"; +}; + +ð { + status = "okay"; + + gmac0: mac@0 { + /* LAN */ + compatible = "mediatek,eth-mac"; + reg = <0>; + nvmem-cells = <&macaddr_factory_4>; + nvmem-cell-names = "mac-address"; + phy-mode = "2500base-x"; + + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; + }; + + mdio: mdio-bus { + #address-cells = <1>; + #size-cells = <0>; + + switch@1f { + compatible = "mediatek,mt7531"; + reg = <31>; + reset-gpios = <&pio 5 GPIO_ACTIVE_HIGH>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@1 { + reg = <1>; + label = "wan"; + }; + + port@2 { + reg = <2>; + label = "lan1"; + }; + + port@3 { + reg = <3>; + label = "lan2"; + }; + + port@4 { + reg = <4>; + label = "lan3"; + }; + + port@6 { + reg = <6>; + label = "cpu"; + ethernet = <&gmac0>; + phy-mode = "2500base-x"; + + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; + }; + }; + }; + }; +}; + +&pio { + spi_flash_pins: spi-flash-pins-33-to-38 { + mux { + function = "spi"; + groups = "spi0", "spi0_wp_hold"; + }; + conf-pu { + pins = "SPI2_CS", "SPI2_HOLD", "SPI2_WP"; + drive-strength = <8>; + mediatek,pull-up-adv = <0>; /* bias-disable */ + }; + conf-pd { + pins = "SPI2_CLK", "SPI2_MOSI", "SPI2_MISO"; + drive-strength = <8>; + mediatek,pull-down-adv = <0>; /* bias-disable */ + }; + }; + + wf_2g_5g_pins: wf_2g_5g-pins { + mux { + function = "wifi"; + groups = "wf_2g", "wf_5g"; + }; + conf { + pins = "WF0_HB1", "WF0_HB2", "WF0_HB3", "WF0_HB4", + "WF0_HB0", "WF0_HB0_B", "WF0_HB5", "WF0_HB6", + "WF0_HB7", "WF0_HB8", "WF0_HB9", "WF0_HB10", + "WF0_TOP_CLK", "WF0_TOP_DATA", "WF1_HB1", + "WF1_HB2", "WF1_HB3", "WF1_HB4", "WF1_HB0", + "WF1_HB5", "WF1_HB6", "WF1_HB7", "WF1_HB8", + "WF1_TOP_CLK", "WF1_TOP_DATA"; + drive-strength = <4>; + }; + }; + + wf_dbdc_pins: wf-dbdc-pins { + mux { + function = "wifi"; + groups = "wf_dbdc"; + }; + conf { + pins = "WF0_HB1", "WF0_HB2", "WF0_HB3", "WF0_HB4", + "WF0_HB0", "WF0_HB0_B", "WF0_HB5", "WF0_HB6", + "WF0_HB7", "WF0_HB8", "WF0_HB9", "WF0_HB10", + "WF0_TOP_CLK", "WF0_TOP_DATA", "WF1_HB1", + "WF1_HB2", "WF1_HB3", "WF1_HB4", "WF1_HB0", + "WF1_HB5", "WF1_HB6", "WF1_HB7", "WF1_HB8", + "WF1_TOP_CLK", "WF1_TOP_DATA"; + drive-strength = <4>; + }; + }; +}; + +&spi0 { + pinctrl-names = "default"; + pinctrl-0 = <&spi_flash_pins>; + status = "okay"; + + spi_nand: flash@0 { + compatible = "spi-nand"; + reg = <0>; + #address-cells = <1>; + #size-cells = <1>; + + spi-max-frequency = <20000000>; + spi-tx-bus-width = <4>; + spi-rx-bus-width = <4>; + + /* + * ASUS bootloader tries to replace the partitions defined in + * Device Tree and by that also deletes all additional properties + * needed for UBI and NVMEM-on-UBI. + * Prevent this from happening by tricking the loader to delete and + * replace a bait node instead. + */ + partitions: dummy { + compatible = "u-boot-dummy-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + reg = <0x0 0x0>; + label = "remove_me"; + }; + }; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + reg = <0x0 0x400000>; + label = "u-boot"; + read-only; + }; + + partition@400000 { + compatible = "linux,ubi"; + reg = <0x400000 0xfc00000>; + label = "UBI_DEV"; + + volumes { + ubi_factory: ubi-volume-factory { + volname = "Factory"; + }; + }; + }; + }; + }; +}; + +&ubi_factory { + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + eeprom_factory_0: eeprom@0 { + reg = <0x0 0x1000>; + }; + + macaddr_factory_4: macaddr@4 { + reg = <0x4 0x6>; + }; + }; +}; + +&watchdog { + status = "okay"; +}; + +&wifi { + nvmem-cells = <&eeprom_factory_0>; + nvmem-cell-names = "eeprom"; + pinctrl-0 = <&wf_2g_5g_pins>; + pinctrl-1 = <&wf_dbdc_pins>; + pinctrl-names = "default", "dbdc"; + status = "okay"; +}; + +&trng { + status = "okay"; +}; + +&uart0 { + status = "okay"; +}; + +&ssusb { + status = "okay"; +}; + +&usb_phy { + status = "okay"; +}; diff --git a/target/linux/mediatek/dts/mt7986a-asus-tuf-ax4200.dts b/target/linux/mediatek/dts/mt7986a-asus-tuf-ax4200.dts index bcbe0d2a9..e40602fa2 100644 --- a/target/linux/mediatek/dts/mt7986a-asus-tuf-ax4200.dts +++ b/target/linux/mediatek/dts/mt7986a-asus-tuf-ax4200.dts @@ -13,6 +13,7 @@ aliases { serial0 = &uart0; + label-mac-device = &gmac0; led-boot = &led_system; led-failsafe = &led_system; led-running = &led_system; @@ -21,7 +22,7 @@ chosen { stdout-path = "serial0:115200n8"; - bootargs-override = "ubi.mtd=UBI_DEV"; + bootargs-override = ""; }; memory { @@ -65,7 +66,8 @@ }; wan-red { - label = "red:wan"; + function = LED_FUNCTION_WAN; + color = ; gpios = <&pio 12 GPIO_ACTIVE_LOW>; }; }; @@ -100,6 +102,8 @@ /* LAN */ compatible = "mediatek,eth-mac"; reg = <0>; + nvmem-cells = <&macaddr_factory_4>; + nvmem-cell-names = "mac-address"; phy-mode = "2500base-x"; fixed-link { @@ -136,7 +140,7 @@ mxl,led-config = <0x03f0 0x0 0x0 0x0>; }; - switch: switch@0 { + switch: switch@1f { compatible = "mediatek,mt7531"; reg = <31>; @@ -214,25 +218,66 @@ spi-tx-bus-width = <4>; spi-rx-bus-width = <4>; - partitions: partitions { + /* + * ASUS bootloader tries to replace the partitions defined in + * Device Tree and by that also deletes all additional properties + * needed for UBI and NVMEM-on-UBI. + * Prevent this from happening by tricking the loader to delete and + * replace a bait node instead. + */ + partitions: dummy { + compatible = "u-boot-dummy-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + reg = <0x0 0x0>; + label = "remove_me"; + }; + }; + + partitions { compatible = "fixed-partitions"; #address-cells = <1>; #size-cells = <1>; partition@0 { - label = "bootloader"; reg = <0x0 0x400000>; + label = "bootloader"; read-only; }; partition@400000 { - label = "UBI_DEV"; + compatible = "linux,ubi"; reg = <0x400000 0xfc00000>; + label = "UBI_DEV"; + + volumes { + ubi_factory: ubi-volume-factory { + volname = "Factory"; + }; + }; }; }; }; }; +&ubi_factory { + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + eeprom_factory_0: eeprom@0 { + reg = <0x0 0x1000>; + }; + + macaddr_factory_4: macaddr@4 { + reg = <0x4 0x6>; + }; + }; +}; + &switch { ports { #address-cells = <1>; @@ -241,21 +286,25 @@ port@1 { reg = <1>; label = "lan1"; + phy-handle = <&swphy1>; }; port@2 { reg = <2>; label = "lan2"; + phy-handle = <&swphy2>; }; port@3 { reg = <3>; label = "lan3"; + phy-handle = <&swphy3>; }; port@4 { reg = <4>; label = "lan4"; + phy-handle = <&swphy4>; }; port@6 { @@ -276,7 +325,7 @@ #address-cells = <1>; #size-cells = <0>; - phy@1 { + swphy1: phy@1 { reg = <1>; mediatek,led-config = < @@ -290,7 +339,7 @@ >; }; - phy@2 { + swphy2: phy@2 { reg = <2>; mediatek,led-config = < @@ -304,7 +353,7 @@ >; }; - phy@3 { + swphy3: phy@3 { reg = <3>; mediatek,led-config = < @@ -318,7 +367,7 @@ >; }; - phy@4 { + swphy4: phy@4 { reg = <4>; mediatek,led-config = < @@ -339,10 +388,12 @@ }; &wifi { - status = "okay"; - pinctrl-names = "default", "dbdc"; + nvmem-cells = <&eeprom_factory_0>; + nvmem-cell-names = "eeprom"; pinctrl-0 = <&wf_2g_5g_pins>; pinctrl-1 = <&wf_dbdc_pins>; + pinctrl-names = "default", "dbdc"; + status = "okay"; }; &trng { diff --git a/target/linux/mediatek/dts/mt7986a-asus-tuf-ax6000.dts b/target/linux/mediatek/dts/mt7986a-asus-tuf-ax6000.dts new file mode 100644 index 000000000..891d56853 --- /dev/null +++ b/target/linux/mediatek/dts/mt7986a-asus-tuf-ax6000.dts @@ -0,0 +1,435 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) + +/dts-v1/; +#include +#include +#include + +#include "mt7986a.dtsi" + +/ { + model = "ASUS TUF-AX6000"; + compatible = "asus,tuf-ax6000", "mediatek,mt7986a"; + + aliases { + serial0 = &uart0; + label-mac-device = &gmac0; + led-boot = &led_system; + led-failsafe = &led_system; + led-running = &led_system; + led-upgrade = &led_system; + }; + + chosen { + stdout-path = "serial0:115200n8"; + bootargs-override = ""; + }; + + memory { + reg = <0 0x40000000 0 0x20000000>; + }; + + keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + gpios = <&pio 9 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + + mesh { + label = "wps"; + gpios = <&pio 10 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + leds { + compatible = "gpio-leds"; + + wlan { + function = LED_FUNCTION_WLAN; + color = ; + gpios = <&pio 2 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "phy1tpt"; + }; + + led_system: system { + label = "white:system"; + gpios = <&pio 11 GPIO_ACTIVE_HIGH>; + }; + + wan-red { + function = LED_FUNCTION_WAN; + color = ; + gpios = <&pio 12 GPIO_ACTIVE_LOW>; + }; + + cover-blue { + label = "blue:cover"; + gpios = <&pio 20 GPIO_ACTIVE_HIGH>; + }; + }; + + reg_3p3v: regulator-3p3v { + compatible = "regulator-fixed"; + regulator-name = "fixed-3.3V"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + regulator-always-on; + }; + + reg_5v: regulator-5v { + compatible = "regulator-fixed"; + regulator-name = "fixed-5V"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-boot-on; + regulator-always-on; + }; +}; + +&crypto { + status = "okay"; +}; + +ð { + status = "okay"; + + gmac0: mac@0 { + /* LAN */ + compatible = "mediatek,eth-mac"; + reg = <0>; + nvmem-cells = <&macaddr_factory_4>; + nvmem-cell-names = "mac-address"; + phy-mode = "2500base-x"; + + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; + }; + + gmac1: mac@1 { + /* WAN */ + compatible = "mediatek,eth-mac"; + reg = <1>; + phy-mode = "2500base-x"; + phy-handle = <&phy6>; + }; + + mdio: mdio-bus { + #address-cells = <1>; + #size-cells = <0>; + }; +}; + +&mdio { + reset-gpios = <&pio 6 GPIO_ACTIVE_LOW>; + reset-delay-us = <50000>; + reset-post-delay-us = <20000>; + + phy5: phy@5 { + compatible = "ethernet-phy-ieee802.3-c45"; + reg = <5>; + + mxl,led-drive-vdd; + mxl,led-config = <0x03f0 0x0 0x0 0x0>; + }; + + phy6: phy@6 { + compatible = "ethernet-phy-ieee802.3-c45"; + reg = <6>; + + /* LED0: CONN (WAN white) */ + mxl,led-config = <0x03f0 0x0 0x0 0x0>; + }; + + switch: switch@1f { + compatible = "mediatek,mt7531"; + reg = <31>; + + reset-gpios = <&pio 5 GPIO_ACTIVE_HIGH>; + reset-assert-us = <10000>; + reset-deassert-us = <10000>; + }; +}; + +&pio { + spi_flash_pins: spi-flash-pins-33-to-38 { + mux { + function = "spi"; + groups = "spi0", "spi0_wp_hold"; + }; + conf-pu { + pins = "SPI2_CS", "SPI2_HOLD", "SPI2_WP"; + drive-strength = <8>; + mediatek,pull-up-adv = <0>; /* bias-disable */ + }; + conf-pd { + pins = "SPI2_CLK", "SPI2_MOSI", "SPI2_MISO"; + drive-strength = <8>; + mediatek,pull-down-adv = <0>; /* bias-disable */ + }; + }; + + wf_2g_5g_pins: wf_2g_5g-pins { + mux { + function = "wifi"; + groups = "wf_2g", "wf_5g"; + }; + conf { + pins = "WF0_HB1", "WF0_HB2", "WF0_HB3", "WF0_HB4", + "WF0_HB0", "WF0_HB0_B", "WF0_HB5", "WF0_HB6", + "WF0_HB7", "WF0_HB8", "WF0_HB9", "WF0_HB10", + "WF0_TOP_CLK", "WF0_TOP_DATA", "WF1_HB1", + "WF1_HB2", "WF1_HB3", "WF1_HB4", "WF1_HB0", + "WF1_HB5", "WF1_HB6", "WF1_HB7", "WF1_HB8", + "WF1_TOP_CLK", "WF1_TOP_DATA"; + drive-strength = <4>; + }; + }; + + wf_dbdc_pins: wf-dbdc-pins { + mux { + function = "wifi"; + groups = "wf_dbdc"; + }; + conf { + pins = "WF0_HB1", "WF0_HB2", "WF0_HB3", "WF0_HB4", + "WF0_HB0", "WF0_HB0_B", "WF0_HB5", "WF0_HB6", + "WF0_HB7", "WF0_HB8", "WF0_HB9", "WF0_HB10", + "WF0_TOP_CLK", "WF0_TOP_DATA", "WF1_HB1", + "WF1_HB2", "WF1_HB3", "WF1_HB4", "WF1_HB0", + "WF1_HB5", "WF1_HB6", "WF1_HB7", "WF1_HB8", + "WF1_TOP_CLK", "WF1_TOP_DATA"; + drive-strength = <4>; + }; + }; +}; + +&pcie_phy { + status = "okay"; +}; + +&spi0 { + pinctrl-names = "default"; + pinctrl-0 = <&spi_flash_pins>; + status = "okay"; + + spi_nand_flash: flash@0 { + compatible = "spi-nand"; + reg = <0>; + #address-cells = <1>; + #size-cells = <1>; + + spi-max-frequency = <20000000>; + spi-tx-bus-width = <4>; + spi-rx-bus-width = <4>; + + /* + * ASUS bootloader tries to replace the partitions defined in + * Device Tree and by that also deletes all additional properties + * needed for UBI and NVMEM-on-UBI. + * Prevent this from happening by tricking the loader to delete and + * replace a bait node instead. + */ + partitions: dummy { + compatible = "u-boot-dummy-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + reg = <0x0 0x0>; + label = "remove_me"; + }; + }; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + reg = <0x0 0x400000>; + label = "bootloader"; + read-only; + }; + + partition@400000 { + compatible = "linux,ubi"; + reg = <0x400000 0xfc00000>; + label = "UBI_DEV"; + + volumes { + ubi_factory: ubi-volume-factory { + volname = "Factory"; + }; + }; + }; + }; + }; +}; + +&ubi_factory { + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + eeprom_factory_0: eeprom@0 { + reg = <0x0 0x1000>; + }; + + macaddr_factory_4: macaddr@4 { + reg = <0x4 0x6>; + }; + }; +}; + +&switch { + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@1 { + reg = <1>; + label = "lan4"; + phy-handle = <&swphy1>; + }; + + port@2 { + reg = <2>; + label = "lan3"; + phy-handle = <&swphy2>; + }; + + port@3 { + reg = <3>; + label = "lan2"; + phy-handle = <&swphy3>; + }; + + port@4 { + reg = <4>; + label = "lan1"; + phy-handle = <&swphy4>; + }; + + port@5 { + reg = <5>; + label = "lan5"; + phy-mode = "2500base-x"; + phy-handle = <&phy5>; + + }; + + port@6 { + reg = <6>; + label = "cpu"; + ethernet = <&gmac0>; + phy-mode = "2500base-x"; + + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; + }; + }; + + mdio { + #address-cells = <1>; + #size-cells = <0>; + + swphy1: phy@1 { + reg = <1>; + + mediatek,led-config = < + 0x21 0x8009 /* BASIC_CTRL */ + 0x22 0x0c00 /* ON_DURATION */ + 0x23 0x1400 /* BLINK_DURATION */ + 0x24 0x8000 /* LED0_ON_CTRL */ + 0x25 0x0000 /* LED0_BLINK_CTRL */ + 0x26 0xc007 /* LED1_ON_CTRL */ + 0x27 0x003f /* LED1_BLINK_CTRL */ + >; + }; + + swphy2: phy@2 { + reg = <2>; + + mediatek,led-config = < + 0x21 0x8009 /* BASIC_CTRL */ + 0x22 0x0c00 /* ON_DURATION */ + 0x23 0x1400 /* BLINK_DURATION */ + 0x24 0x8000 /* LED0_ON_CTRL */ + 0x25 0x0000 /* LED0_BLINK_CTRL */ + 0x26 0xc007 /* LED1_ON_CTRL */ + 0x27 0x003f /* LED1_BLINK_CTRL */ + >; + }; + + swphy3: phy@3 { + reg = <3>; + + mediatek,led-config = < + 0x21 0x8009 /* BASIC_CTRL */ + 0x22 0x0c00 /* ON_DURATION */ + 0x23 0x1400 /* BLINK_DURATION */ + 0x24 0x8000 /* LED0_ON_CTRL */ + 0x25 0x0000 /* LED0_BLINK_CTRL */ + 0x26 0xc007 /* LED1_ON_CTRL */ + 0x27 0x003f /* LED1_BLINK_CTRL */ + >; + }; + + swphy4: phy@4 { + reg = <4>; + + mediatek,led-config = < + 0x21 0x8009 /* BASIC_CTRL */ + 0x22 0x0c00 /* ON_DURATION */ + 0x23 0x1400 /* BLINK_DURATION */ + 0x24 0x8000 /* LED0_ON_CTRL */ + 0x25 0x0000 /* LED0_BLINK_CTRL */ + 0x26 0xc007 /* LED1_ON_CTRL */ + 0x27 0x003f /* LED1_BLINK_CTRL */ + >; + }; + }; +}; + +&watchdog { + status = "okay"; +}; + +&wifi { + nvmem-cells = <&eeprom_factory_0>; + nvmem-cell-names = "eeprom"; + pinctrl-names = "default", "dbdc"; + pinctrl-0 = <&wf_2g_5g_pins>; + pinctrl-1 = <&wf_dbdc_pins>; + status = "okay"; +}; + +&trng { + status = "okay"; +}; + +&uart0 { + status = "okay"; +}; + +&ssusb { + vusb33-supply = <®_3p3v>; + vbus-supply = <®_5v>; + status = "okay"; +}; + +&usb_phy { + status = "okay"; +}; diff --git a/target/linux/mediatek/dts/mt7986a-bananapi-bpi-r3-mini.dts b/target/linux/mediatek/dts/mt7986a-bananapi-bpi-r3-mini.dts new file mode 100644 index 000000000..09a557c0c --- /dev/null +++ b/target/linux/mediatek/dts/mt7986a-bananapi-bpi-r3-mini.dts @@ -0,0 +1,715 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT +/* + * Copyright (C) 2023 Tianling Shen + */ + +/dts-v1/; +#include +#include +#include + +#include "mt7986a.dtsi" + +/ { + model = "Bananapi BPi-R3 Mini"; + chassis-type = "embedded"; + compatible = "bananapi,bpi-r3-mini", "mediatek,mt7986a"; + + aliases { + ethernet0 = &gmac0; + ethernet1 = &gmac1; + serial0 = &uart0; + + led-boot = &status_led; + led-failsafe = &status_led; + led-running = &status_led; + led-upgrade = &status_led; + }; + + chosen { + stdout-path = "serial0:115200n8"; + rootdisk-emmc = <&emmc_rootdisk>; + rootdisk-spim-nand = <&nand_rootdisk>; + }; + + memory { + reg = <0 0x40000000 0 0x80000000>; + }; + + gpio-keys { + compatible = "gpio-keys"; + + button-reset { + label = "reset"; + linux,code = ; + gpios = <&pio 7 GPIO_ACTIVE_LOW>; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + status_led: led-0 { + function = LED_FUNCTION_STATUS; + color = ; + gpios = <&pio 19 GPIO_ACTIVE_HIGH>; + }; + + led-1 { + function = LED_FUNCTION_WLAN; + color = ; + function-enumerator = <1>; + gpios = <&pio 1 GPIO_ACTIVE_HIGH>; + }; + + led-2 { + function = LED_FUNCTION_WLAN; + color = ; + function-enumerator = <2>; + gpios = <&pio 2 GPIO_ACTIVE_HIGH>; + }; + }; + + fan: pwm-fan { + compatible = "pwm-fan"; + #cooling-cells = <2>; + cooling-levels = <255 128 80 0>; + pwms = <&pwm 0 10000 0>; + status = "okay"; + }; + + reg_1p8v: regulator-1p8v { + compatible = "regulator-fixed"; + regulator-name = "fixed-1.8V"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-boot-on; + regulator-always-on; + }; + + reg_3p3v: regulator-3p3v { + compatible = "regulator-fixed"; + regulator-name = "fixed-3.3V"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + regulator-always-on; + }; + + reg_5v: regulator-5v { + compatible = "regulator-fixed"; + regulator-name = "fixed-5V"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-boot-on; + regulator-always-on; + }; + + usb_vbus: regulator-usb-vbus { + compatible = "regulator-fixed"; + regulator-name = "usb_vbus"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + gpios = <&pio 20 GPIO_ACTIVE_LOW>; + regulator-boot-on; + }; +}; + +&auxadc { + status = "okay"; +}; + +&cpu_thermal { + cooling-maps { + cpu-active-low { + cooling-device = <&fan 1 1>; + trip = <&cpu_trip_active_low>; + }; + + cpu-active-med { + cooling-device = <&fan 2 2>; + trip = <&cpu_trip_active_med>; + }; + + cpu-active-high { + cooling-device = <&fan 3 3>; + trip = <&cpu_trip_active_high>; + }; + }; +}; + +&crypto { + status = "okay"; +}; + +ð { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <ð_pins>; + + gmac0: mac@0 { + compatible = "mediatek,eth-mac"; + reg = <0>; + phy-handle = <&phy14>; + phy-mode = "2500base-x"; + }; + + gmac1: mac@1 { + compatible = "mediatek,eth-mac"; + reg = <1>; + phy-handle = <&phy15>; + phy-mode = "2500base-x"; + }; + + mdio: mdio-bus { + #address-cells = <1>; + #size-cells = <0>; + + phy14: phy@e { + compatible = "ethernet-phy-id03a2.a411"; + reg = <14>; + pinctrl-names = "default"; + pinctrl-0 = <&en8811_pwr_a>; + + airoha,pnswap-rx; + + interrupt-parent = <&pio>; + interrupts = <48 IRQ_TYPE_EDGE_FALLING>; + reset-gpios = <&pio 49 GPIO_ACTIVE_LOW>; + reset-assert-us = <10000>; + reset-deassert-us = <20000>; + + phy-mode = "2500base-x"; + full-duplex; + pause; + + leds { + #address-cells = <1>; + #size-cells = <0>; + + led@0 { + reg = <0>; + function = LED_FUNCTION_LAN; + color = ; + }; + + led@1 { + reg = <1>; + function = LED_FUNCTION_LAN; + color = ; + }; + }; + }; + + phy15: phy@f { + compatible = "ethernet-phy-id03a2.a411"; + reg = <15>; + pinctrl-names = "default"; + pinctrl-0 = <&en8811_pwr_b>; + + airoha,pnswap-rx; + + interrupt-parent = <&pio>; + interrupts = <46 IRQ_TYPE_EDGE_FALLING>; + reset-gpios = <&pio 47 GPIO_ACTIVE_LOW>; + reset-assert-us = <10000>; + reset-deassert-us = <20000>; + + phy-mode = "2500base-x"; + full-duplex; + pause; + + leds { + #address-cells = <1>; + #size-cells = <0>; + + led@0 { + reg = <0>; + function = LED_FUNCTION_WAN; + color = ; + }; + + led@1 { + reg = <1>; + function = LED_FUNCTION_WAN; + color = ; + }; + }; + }; + }; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c_pins>; + status = "okay"; + + eeprom@50 { + compatible = "atmel,24c02"; + reg = <0x50>; + pagesize = <8>; + size = <256>; + }; +}; + +&mmc0 { + pinctrl-names = "default", "state_uhs"; + pinctrl-0 = <&mmc0_pins_default>; + pinctrl-1 = <&mmc0_pins_uhs>; + bus-width = <8>; + max-frequency = <200000000>; + cap-mmc-highspeed; + mmc-hs200-1_8v; + mmc-hs400-1_8v; + hs400-ds-delay = <0x14014>; + vmmc-supply = <®_3p3v>; + vqmmc-supply = <®_1p8v>; + non-removable; + no-sd; + no-sdio; + status = "okay"; + + card@0 { + compatible = "mmc-card"; + reg = <0>; + + block { + compatible = "block-device"; + partitions { + emmc_rootdisk: block-partition-production { + partname = "production"; + }; + }; + }; + }; +}; + +&pcie { + pinctrl-names = "default"; + pinctrl-0 = <&pcie_pins>; + status = "okay"; +}; + +&pcie_phy { + status = "okay"; +}; + +&pio { + en8811_pwr_a: en8811-pwr-a { + pins = "GPIO_11"; + drive-strength = <8>; + mediatek,pull-down-adv = <1>; + output-low; + }; + + en8811_pwr_b: en8811-pwr-b { + pins = "GPIO_12"; + drive-strength = <8>; + mediatek,pull-down-adv = <1>; + output-low; + }; + + eth_pins: eth-pins { + mux { + function = "eth"; + groups = "mdc_mdio"; + }; + }; + + i2c_pins: i2c-pins { + mux { + function = "i2c"; + groups = "i2c"; + }; + }; + + mmc0_pins_default: mmc0-pins-default { + mux { + function = "emmc"; + groups = "emmc_51"; + }; + conf-cmd-dat { + pins = "EMMC_DATA_0", "EMMC_DATA_1", "EMMC_DATA_2", + "EMMC_DATA_3", "EMMC_DATA_4", "EMMC_DATA_5", + "EMMC_DATA_6", "EMMC_DATA_7", "EMMC_CMD"; + input-enable; + drive-strength = <4>; + mediatek,pull-up-adv = <1>; + }; + conf-clk { + pins = "EMMC_CK"; + drive-strength = <6>; + mediatek,pull-down-adv = <2>; + }; + conf-ds { + pins = "EMMC_DSL"; + mediatek,pull-down-adv = <2>; + }; + conf-rst { + pins = "EMMC_RSTB"; + drive-strength = <4>; + mediatek,pull-up-adv = <1>; + }; + }; + + mmc0_pins_uhs: mmc0-uhs-pins { + mux { + function = "emmc"; + groups = "emmc_51"; + }; + conf-cmd-dat { + pins = "EMMC_DATA_0", "EMMC_DATA_1", "EMMC_DATA_2", + "EMMC_DATA_3", "EMMC_DATA_4", "EMMC_DATA_5", + "EMMC_DATA_6", "EMMC_DATA_7", "EMMC_CMD"; + input-enable; + drive-strength = <4>; + mediatek,pull-up-adv = <1>; + }; + conf-clk { + pins = "EMMC_CK"; + drive-strength = <6>; + mediatek,pull-down-adv = <2>; + }; + conf-ds { + pins = "EMMC_DSL"; + mediatek,pull-down-adv = <2>; + }; + conf-rst { + pins = "EMMC_RSTB"; + drive-strength = <4>; + mediatek,pull-up-adv = <1>; + }; + }; + + pcie_pins: pcie-pins { + mux { + function = "pcie"; + groups = "pcie_clk", "pcie_wake", "pcie_pereset"; + }; + }; + + pwm_pins: pwm-pins { + mux { + function = "pwm"; + groups = "pwm0", "pwm1_0"; + }; + }; + + spi_flash_pins: spi-flash-pins { + mux { + function = "spi"; + groups = "spi0", "spi0_wp_hold"; + }; + conf-pu { + pins = "SPI2_CS", "SPI2_HOLD", "SPI2_WP"; + drive-strength = <8>; + mediatek,pull-up-adv = <0>; + }; + conf-pd { + pins = "SPI2_CLK", "SPI2_MOSI", "SPI2_MISO"; + drive-strength = <8>; + mediatek,pull-down-adv = <0>; + }; + }; + + spic_pins: spic-pins { + mux { + function = "spi"; + groups = "spi1_2"; + }; + }; + + uart1_pins: uart1-pins { + mux { + function = "uart"; + groups = "uart1"; + }; + }; + + usb_ngff_pins: usb-ngff-pins { + ngff-gnss-off { + pins = "GPIO_6"; + drive-strength = <8>; + mediatek,pull-up-adv = <1>; + }; + ngff-pe-rst { + pins = "GPIO_7"; + drive-strength = <8>; + mediatek,pull-up-adv = <1>; + }; + ngff-wwan-off { + pins = "GPIO_8"; + drive-strength = <8>; + mediatek,pull-up-adv = <1>; + }; + ngff-pwr-off { + pins = "GPIO_9"; + drive-strength = <8>; + mediatek,pull-up-adv = <1>; + }; + ngff-rst { + pins = "GPIO_10"; + drive-strength = <8>; + mediatek,pull-up-adv = <1>; + }; + ngff-coex { + pins = "SPI1_CS"; + drive-strength = <8>; + mediatek,pull-up-adv = <1>; + }; + }; + + wf_2g_5g_pins: wf-2g-5g-pins { + mux { + function = "wifi"; + groups = "wf_2g", "wf_5g"; + }; + conf { + pins = "WF0_HB1", "WF0_HB2", "WF0_HB3", "WF0_HB4", + "WF0_HB0", "WF0_HB0_B", "WF0_HB5", "WF0_HB6", + "WF0_HB7", "WF0_HB8", "WF0_HB9", "WF0_HB10", + "WF0_TOP_CLK", "WF0_TOP_DATA", "WF1_HB1", + "WF1_HB2", "WF1_HB3", "WF1_HB4", "WF1_HB0", + "WF1_HB5", "WF1_HB6", "WF1_HB7", "WF1_HB8", + "WF1_TOP_CLK", "WF1_TOP_DATA"; + drive-strength = <4>; + }; + }; + + wf_dbdc_pins: wf-dbdc-pins { + mux { + function = "wifi"; + groups = "wf_dbdc"; + }; + conf { + pins = "WF0_HB1", "WF0_HB2", "WF0_HB3", "WF0_HB4", + "WF0_HB0", "WF0_HB0_B", "WF0_HB5", "WF0_HB6", + "WF0_HB7", "WF0_HB8", "WF0_HB9", "WF0_HB10", + "WF0_TOP_CLK", "WF0_TOP_DATA", "WF1_HB1", + "WF1_HB2", "WF1_HB3", "WF1_HB4", "WF1_HB0", + "WF1_HB5", "WF1_HB6", "WF1_HB7", "WF1_HB8", + "WF1_TOP_CLK", "WF1_TOP_DATA"; + drive-strength = <4>; + }; + }; +}; + +&pwm { + pinctrl-names = "default"; + pinctrl-0 = <&pwm_pins>; + status = "okay"; +}; + +&spi0 { + pinctrl-names = "default"; + pinctrl-0 = <&spi_flash_pins>; + status = "okay"; + + flash@0 { + compatible = "spi-nand"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0>; + + spi-max-frequency = <20000000>; + spi-tx-bus-width = <4>; + spi-rx-bus-width = <4>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "bl2"; + reg = <0x0 0x200000>; + read-only; + }; + + partition@200000 { + label = "ubi"; + reg = <0x200000 0x7e00000>; + compatible = "linux,ubi"; + + volumes { + nand_rootdisk: ubi-volume-fit { + volname = "fit"; + }; + }; + }; + }; + }; +}; + +&spi1 { + pinctrl-names = "default"; + pinctrl-0 = <&spic_pins>; + /* conflicts with M.2 pin */ + status = "disabled"; +}; + +&ssusb { + pinctrl-names = "default"; + pinctrl-0 = <&usb_ngff_pins>; + vusb33-supply = <®_3p3v>; + vbus-supply = <&usb_vbus>; + status = "okay"; +}; + +&trng { + status = "okay"; +}; + +&uart0 { + status = "okay"; +}; + +&uart1 { + pinctrl-names = "default"; + pinctrl-0 = <&uart1_pins>; + status = "okay"; +}; + +&usb_phy { + status = "okay"; +}; + +&watchdog { + status = "okay"; +}; + +&wifi { + pinctrl-names = "default", "dbdc"; + pinctrl-0 = <&wf_2g_5g_pins>; + pinctrl-1 = <&wf_dbdc_pins>; + status = "okay"; + + mediatek,eeprom-data = <0x86790200 0x000c4326 0x60000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x125b486c 0x00280000 0x05d00000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x0c000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000012 0x12120000 0x00000000 0x00000000 0x00002222 0x22223333 0x33333333 + 0x33333333 0x33333333 0x33333333 0x33333333 0x33333333 0x33330000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00292929 0x29282828 0x28282828 0x28282828 0x28282828 0x28282828 0x28000000 0x00000000 + 0x00000000 0x00242424 0x24222222 0x22242424 0x24222222 0x22242424 0x24222222 0x22242424 + 0x24222222 0x22000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x007f7f7f 0xd1d1dddd 0xe9e9f5f5 0x01010909 0x1515d1d1 0xdddde9e9 0xf5f5fdfd + 0x09091515 0xd1d1dddd 0xe9e9f5f5 0xfdfd0909 0x1515d1d1 0xdddde9e9 0xf5f5fdfd 0x09091515 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x0efefc00 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x021e021e 0x02000200 0x02370237 0x02370237 + 0x02370237 0x02370237 0x02370237 0x02370237 0x02370237 0x02370237 0x02370237 0x02370237 + 0x02370237 0x02370237 0x02370237 0x02370237 0x002200c6 0xc6c4c4c3 0x0000c1c2 0xc1838383 + 0x838686c1 0xc1838383 0x838686c2 0xc1c18181 0x82838585 0x8686c1c1 0x81818283 0x85858686 + 0xc1c18181 0x82838585 0x8686c1c1 0x81818283 0x85858686 0xc1c18181 0x82838585 0x8686c5c5 + 0xc3c100c2 0xc3c2c200 0x81828383 0xc2c2c200 0x81828383 0xc3c1c1c1 0x81828384 0x84c2c2c2 + 0xc2008182 0x83838585 0xc2c2c200 0x81828383 0x8585c1c1 0xc1818283 0x84848686 0x82828484 + 0x85868787 0x8989c2c2 0xc2008182 0x83838585 0xc2c2c200 0x81828383 0x8585c2c2 0xc2008182 + 0x83838585 0xc4c4c2c1 0x00c3c3c3 0xc1008183 0x838686c3 0xc3c3c100 0x81838386 0x86c2c2c2 + 0x00818284 0x84868682 0x82828485 0x8688888b 0x8bc3c3c3 0xc1008183 0x838686c3 0xc3c3c100 + 0x81838386 0x86c3c3c3 0xc1008183 0x83868600 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00bd0000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00c50000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00495256 0x55555555 0x004a5251 0x51515151 0x004a5355 0x56565656 0x0049504e 0x51515151 + 0x00495150 0x54545454 0x00495051 0x51515151 0x00495251 0x50505050 0x00495251 0x51515151 + 0x00495251 0x54545454 0x00495150 0x54545454 0x00495352 0x51515151 0x00495353 0x52525252 + 0x00495150 0x50505050 0x00495152 0x54545454 0x00495251 0x53535353 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0xd1d1dddd 0xe9e9f5f5 0xfdfd1414 0x1d1d0000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x85840000 0xc3c4c382 0x828281c1 0xc4c5c400 0x0000c1c3 0xc4c4c481 0x8181c1c2 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0xc0bbc0bb 0xc0bbc0bb 0x40c5c0c4 0xc0c3c0c3 0x40c340c5 0x40c4c0c3 0x40c3c0c2 0xc0c5c0c4 + 0x40c440c4 0xc0c3c0c5 0xc0c440c4 0x40c4c0c3 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x40c640c6 0x40c640c6 0x40c640c6 0x40c640c6 0x40c640c6 0x40c640c6 + 0x40c640c6 0x40c640c6 0x40c640c6 0x40c640c6 0x40c640c6 0x40c640c6 0x40c640c6 0x40c640c6 + 0x40c640c6 0x40c640c6 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000>; +}; diff --git a/target/linux/mediatek/dts/mt7986a-glinet-gl-mt6000.dts b/target/linux/mediatek/dts/mt7986a-glinet-gl-mt6000.dts index a8c1235cb..fd0e1a691 100644 --- a/target/linux/mediatek/dts/mt7986a-glinet-gl-mt6000.dts +++ b/target/linux/mediatek/dts/mt7986a-glinet-gl-mt6000.dts @@ -12,11 +12,12 @@ compatible = "glinet,gl-mt6000", "mediatek,mt7986a"; aliases { - led-boot = &led_run; - led-failsafe = &led_run; - led-running = &led_white; - led-upgrade = &led_run; serial0 = &uart0; + label-mac-device = &gmac1; + led-boot = &led_blue; + led-failsafe = &led_blue; + led-running = &led_white; + led-upgrade = &led_white; }; chosen { @@ -55,13 +56,12 @@ leds { compatible = "gpio-leds"; - led_run: run { + led_blue: led@0 { label = "blue:run"; gpios = <&pio 38 GPIO_ACTIVE_LOW>; - default-state = "on"; }; - led_white: system { + led_white: led@1 { label = "white:system"; gpios = <&pio 37 GPIO_ACTIVE_LOW>; }; @@ -85,6 +85,8 @@ compatible = "mediatek,eth-mac"; reg = <0>; phy-mode = "2500base-x"; + nvmem-cells = <&macaddr_factory_a 2>; + nvmem-cell-names = "mac-address"; fixed-link { speed = <2500>; @@ -96,6 +98,8 @@ gmac1: mac@1 { compatible = "mediatek,eth-mac"; reg = <1>; + nvmem-cells = <&macaddr_factory_a 0>; + nvmem-cell-names = "mac-address"; phy-mode = "2500base-x"; phy-handle = <&phy1>; }; @@ -126,7 +130,7 @@ realtek,aldps-enable; }; - switch: switch@31 { + switch: switch@1f { compatible = "mediatek,mt7531"; reg = <31>; reset-gpios = <&pio 18 GPIO_ACTIVE_HIGH>; @@ -286,6 +290,8 @@ }; &wifi { + nvmem-cells = <&eeprom_factory_0>; + nvmem-cell-names = "eeprom"; pinctrl-names = "default"; pinctrl-0 = <&wf_2g_5g_pins>; status = "okay"; @@ -307,4 +313,42 @@ no-sd; no-sdio; status = "okay"; + + card@0 { + compatible = "mmc-card"; + reg = <0>; + + block { + compatible = "block-device"; + partitions { + block-partition-env { + partname = "u-boot-env"; + + nvmem-layout { + compatible = "u-boot,env-layout"; + }; + }; + + block-partition-factory { + partname = "factory"; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + eeprom_factory_0: eeprom@0 { + reg = <0x0 0x1000>; + }; + + macaddr_factory_a: macaddr@a { + compatible = "mac-base"; + reg = <0xa 0x6>; + #nvmem-cell-cells = <1>; + }; + }; + }; + }; + }; + }; }; diff --git a/target/linux/mediatek/dts/mt7986a-hf-m7986r1-emmc.dts b/target/linux/mediatek/dts/mt7986a-hf-m7986r1-emmc.dts deleted file mode 100644 index eeeb63241..000000000 --- a/target/linux/mediatek/dts/mt7986a-hf-m7986r1-emmc.dts +++ /dev/null @@ -1,100 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later OR MIT - -/dts-v1/; -#include "mt7986a-hf-m7986r1.dtsi" - -/ { - model = "HF-M7986R1 eMMC version"; - compatible = "hf,m7986r1-emmc", "mediatek,mt7986a"; - - chosen { - bootargs = "root=PARTLABEL=rootfs rootwait rootfstype=squashfs,f2fs"; - }; - - reg_1p8v: regulator-1p8v { - compatible = "regulator-fixed"; - regulator-name = "fixed-1.8V"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - regulator-boot-on; - regulator-always-on; - }; -}; - -&mmc0 { - bus-width = <8>; - cap-mmc-highspeed; - hs400-ds-delay = <0x14014>; - max-frequency = <200000000>; - mmc-hs200-1_8v; - mmc-hs400-1_8v; - no-sd; - no-sdio; - non-removable; - pinctrl-names = "default", "state_uhs"; - pinctrl-0 = <&mmc0_pins_default>; - pinctrl-1 = <&mmc0_pins_uhs>; - vmmc-supply = <®_3p3v>; - vqmmc-supply = <®_1p8v>; - status = "okay"; -}; - -&pio { - mmc0_pins_default: mmc0-pins-default { - mux { - function = "emmc"; - groups = "emmc_51"; - }; - conf-cmd-dat { - pins = "EMMC_DATA_0", "EMMC_DATA_1", "EMMC_DATA_2", - "EMMC_DATA_3", "EMMC_DATA_4", "EMMC_DATA_5", - "EMMC_DATA_6", "EMMC_DATA_7", "EMMC_CMD"; - input-enable; - drive-strength = <4>; - mediatek,pull-up-adv = <1>; - }; - conf-clk { - pins = "EMMC_CK"; - drive-strength = <6>; - mediatek,pull-down-adv = <2>; - }; - conf-ds { - pins = "EMMC_DSL"; - mediatek,pull-down-adv = <2>; - }; - conf-rst { - pins = "EMMC_RSTB"; - drive-strength = <4>; - mediatek,pull-up-adv = <1>; - }; - }; - - mmc0_pins_uhs: mmc0-uhs-pins { - mux { - function = "emmc"; - groups = "emmc_51"; - }; - conf-cmd-dat { - pins = "EMMC_DATA_0", "EMMC_DATA_1", "EMMC_DATA_2", - "EMMC_DATA_3", "EMMC_DATA_4", "EMMC_DATA_5", - "EMMC_DATA_6", "EMMC_DATA_7", "EMMC_CMD"; - input-enable; - drive-strength = <4>; - mediatek,pull-up-adv = <1>; - }; - conf-clk { - pins = "EMMC_CK"; - drive-strength = <6>; - mediatek,pull-down-adv = <2>; - }; - conf-ds { - pins = "EMMC_DSL"; - mediatek,pull-down-adv = <2>; - }; - conf-rst { - pins = "EMMC_RSTB"; - drive-strength = <4>; - mediatek,pull-up-adv = <1>; - }; - }; -}; diff --git a/target/linux/mediatek/dts/mt7986a-hf-m7986r1-nand.dts b/target/linux/mediatek/dts/mt7986a-hf-m7986r1-nand.dts deleted file mode 100644 index 7427ec2fa..000000000 --- a/target/linux/mediatek/dts/mt7986a-hf-m7986r1-nand.dts +++ /dev/null @@ -1,76 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later OR MIT - -/dts-v1/; -#include "mt7986a-hf-m7986r1.dtsi" - -/ { - model = "HF-M7986R1 NAND version"; - compatible = "hf,m7986r1-nand", "mediatek,mt7986a"; -}; - -&pio { - spi_flash_pins: spi-flash-pins { - mux { - function = "spi"; - groups = "spi0", "spi0_wp_hold"; - }; - conf-pu { - pins = "SPI2_CS", "SPI2_HOLD", "SPI2_WP"; - drive-strength = <8>; - mediatek,pull-up-adv = <0>; - }; - conf-pd { - pins = "SPI2_CLK", "SPI2_MOSI", "SPI2_MISO"; - drive-strength = <8>; - mediatek,pull-down-adv = <0>; - }; - }; -}; - -&spi0 { - pinctrl-names = "default"; - pinctrl-0 = <&spi_flash_pins>; - status = "okay"; - - flash@0 { - compatible = "spi-nand"; - #address-cells = <1>; - #size-cells = <1>; - reg = <0>; - - spi-max-frequency = <20000000>; - spi-tx-bus-width = <4>; - spi-rx-bus-width = <4>; - - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - partition@0 { - label = "bl2"; - reg = <0x00000 0x100000>; - }; - - partition@100000 { - label = "u-boot-env"; - reg = <0x100000 0x80000>; - }; - - partition@180000 { - label = "factory"; - reg = <0x180000 0x200000>; - }; - - partition@380000 { - label = "fip"; - reg = <0x380000 0x200000>; - }; - - partition@580000 { - label = "ubi"; - reg = <0x580000 0x7a80000>; - }; - }; - }; -}; diff --git a/target/linux/mediatek/dts/mt7986a-hf-m7986r1.dtsi b/target/linux/mediatek/dts/mt7986a-hf-m7986r1.dtsi deleted file mode 100644 index f4c58812c..000000000 --- a/target/linux/mediatek/dts/mt7986a-hf-m7986r1.dtsi +++ /dev/null @@ -1,251 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later OR MIT - -/dts-v1/; -#include -#include -#include - -#include "mt7986a.dtsi" - -/ { - aliases { - serial0 = &uart0; - led-boot = &sys_led; - led-failsafe = &sys_led; - led-running = &sys_led; - led-upgrade = &sys_led; - }; - - chosen { - stdout-path = "serial0:115200n8"; - }; - - memory@40000000 { - reg = <0 0x40000000 0 0x40000000>; - }; - - gpio-keys { - compatible = "gpio-keys"; - - // seems to conflict with pcie_clk, needs investigate - button-reset { - label = "reset"; - linux,code = ; - gpios = <&pio 9 GPIO_ACTIVE_LOW>; - }; - }; - - gpio-leds { - compatible = "gpio-leds"; - - sys_led: led-0 { - label = "hf:sys"; - gpios = <&pio 15 GPIO_ACTIVE_LOW>; - }; - - led-1 { - label = "led-1"; - gpios = <&pio 16 GPIO_ACTIVE_LOW>; - }; - - led-2 { - label = "led-2"; - gpios = <&pio 17 GPIO_ACTIVE_LOW>; - }; - - led-3 { - label = "led-3"; - gpios = <&pio 18 GPIO_ACTIVE_LOW>; - }; - - led-4 { - label = "led-4"; - gpios = <&pio 19 GPIO_ACTIVE_LOW>; - }; - - led-5 { - label = "led-5"; - gpios = <&pio 20 GPIO_ACTIVE_LOW>; - }; - }; - - reg_3p3v: regulator-3p3v { - compatible = "regulator-fixed"; - regulator-name = "fixed-3.3V"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - regulator-boot-on; - regulator-always-on; - }; - - reg_5v: regulator-5v { - compatible = "regulator-fixed"; - regulator-name = "fixed-5V"; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; - regulator-boot-on; - regulator-always-on; - }; -}; - -&crypto { - status = "okay"; -}; - -ð { - status = "okay"; - - gmac0: mac@0 { - compatible = "mediatek,eth-mac"; - reg = <0>; - phy-mode = "2500base-x"; - - fixed-link { - speed = <2500>; - full-duplex; - pause; - }; - }; - - mdio: mdio-bus { - #address-cells = <1>; - #size-cells = <0>; - }; -}; - -&mdio { - switch: switch@1f { - compatible = "mediatek,mt7531"; - reg = <31>; - reset-gpios = <&pio 5 GPIO_ACTIVE_HIGH>; - interrupt-controller; - #interrupt-cells = <1>; - interrupt-parent = <&pio>; - interrupts = <66 IRQ_TYPE_LEVEL_HIGH>; - }; -}; - -&pcie { - pinctrl-names = "default"; - pinctrl-0 = <&pcie_pins>; - status = "okay"; - - pcie@0,0 { - reg = <0x0000 0 0 0 0>; - - wifi@0,0 { - compatible = "mediatek,mt76"; - reg = <0x0000 0 0 0 0>; - }; - }; -}; - -&pcie_phy { - status = "okay"; -}; - -&pio { - pcie_pins: pcie-pins { - power-pcie { - pins = "GPIO_7"; - drive-strength = <8>; - mediatek,pull-up-adv = <1>; - }; - - reset-pcie { - pins = "GPIO_9"; - drive-strength = <8>; - mediatek,pull-down-adv = <1>; - output-low; - }; - - mux { - function = "pcie"; - groups = "pcie_clk", "pcie_wake", "pcie_pereset"; - }; - }; - - usb_pins: usb-pins { - reset-sata { - pins = "GPIO_1"; - drive-strength = <8>; - mediatek,pull-up-adv = <1>; - }; - - power-m2 { - pins = "GPIO_6"; - drive-strength = <8>; - mediatek,pull-up-adv = <1>; - }; - - reset-m2 { - pins = "GPIO_8"; - drive-strength = <8>; - mediatek,pull-down-adv = <1>; - output-low; - }; - }; -}; - -&ssusb { - pinctrl-names = "default"; - pinctrl-0 = <&usb_pins>; - vusb33-supply = <®_3p3v>; - vbus-supply = <®_5v>; - status = "okay"; -}; - -&switch { - ports { - #address-cells = <1>; - #size-cells = <0>; - - port@0 { - reg = <0>; - label = "lan1"; - }; - - port@1 { - reg = <1>; - label = "lan2"; - }; - - port@2 { - reg = <2>; - label = "lan3"; - }; - - port@3 { - reg = <3>; - label = "lan4"; - }; - - port@6 { - reg = <6>; - ethernet = <&gmac0>; - phy-mode = "2500base-x"; - - fixed-link { - speed = <2500>; - full-duplex; - pause; - }; - }; - }; -}; - -&trng { - status = "okay"; -}; - -&uart0 { - status = "okay"; -}; - -&usb_phy { - status = "okay"; -}; - -&watchdog { - status = "okay"; -}; diff --git a/target/linux/mediatek/dts/mt7986a-jdcloud-re-cs-05.dts b/target/linux/mediatek/dts/mt7986a-jdcloud-re-cp-03.dts similarity index 65% rename from target/linux/mediatek/dts/mt7986a-jdcloud-re-cs-05.dts rename to target/linux/mediatek/dts/mt7986a-jdcloud-re-cp-03.dts index b9ac922d3..372d4ec22 100644 --- a/target/linux/mediatek/dts/mt7986a-jdcloud-re-cs-05.dts +++ b/target/linux/mediatek/dts/mt7986a-jdcloud-re-cp-03.dts @@ -1,59 +1,71 @@ // SPDX-License-Identifier: GPL-2.0-or-later OR MIT +/* + * Copyright (C) 2023 Tianling Shen + */ /dts-v1/; #include #include +#include #include "mt7986a.dtsi" / { - model = "JDCloud RE-CS-05"; - compatible = "jdcloud,re-cs-05", "mediatek,mt7986a"; + model = "JDCloud RE-CP-03"; + compatible = "jdcloud,re-cp-03", "mediatek,mt7986a"; aliases { + led-boot = &red_led; + led-failsafe = &red_led; + led-running = &green_led; + led-upgrade = &green_led; serial0 = &uart0; - led-boot = &led_status_green; - led-failsafe = &led_status_red; - led-running = &led_status_blue; - led-upgrade = &led_status_red; }; chosen { + bootargs-override = "root=/dev/fit0 rootwait"; stdout-path = "serial0:115200n8"; - bootargs = "console=ttyS0,115200n8 root=PARTLABEL=rootfs rootwait"; + rootdisk = <&emmc_rootdisk>; }; - keys { + memory@40000000 { + reg = <0 0x40000000 0 0x40000000>; + }; + + gpio-keys { compatible = "gpio-keys"; - reset { + button-joylink { + label = "joylink"; + linux,code = ; + gpios = <&pio 10 GPIO_ACTIVE_LOW>; + }; + + button-reset { label = "reset"; linux,code = ; gpios = <&pio 9 GPIO_ACTIVE_LOW>; }; - - wps { - label = "wps"; - linux,code = ; - gpios = <&pio 10 GPIO_ACTIVE_LOW>; - }; }; - leds { + gpio-leds { compatible = "gpio-leds"; - led_status_blue: blue { - label = "blue:status"; + led-0 { + color = ; + function = LED_FUNCTION_STATUS; gpios = <&pio 7 GPIO_ACTIVE_HIGH>; }; - led_status_red: red { - label = "red:status"; + red_led: led-1 { + color = ; + function = LED_FUNCTION_STATUS; gpios = <&pio 11 GPIO_ACTIVE_HIGH>; }; - led_status_green: green { - label = "green:status"; + green_led: led-2 { + color = ; + function = LED_FUNCTION_STATUS; gpios = <&pio 12 GPIO_ACTIVE_LOW>; }; }; @@ -89,6 +101,9 @@ reg = <0>; phy-mode = "2500base-x"; + nvmem-cells = <&macaddr_factory_2a 0>; + nvmem-cell-names = "mac-address"; + fixed-link { speed = <2500>; full-duplex; @@ -99,8 +114,11 @@ gmac1: mac@1 { compatible = "mediatek,eth-mac"; reg = <1>; - phy-handle = <&phy6>; phy-mode = "2500base-x"; + phy-handle = <&phy6>; + + nvmem-cells = <&macaddr_factory_24 0>; + nvmem-cell-names = "mac-address"; }; mdio: mdio-bus { @@ -110,16 +128,17 @@ }; &mdio { - phy6: ethernet-phy@6 { + phy6: phy@6 { compatible = "ethernet-phy-ieee802.3-c45"; reg = <6>; - reset-assert-us = <100000>; - reset-deassert-us = <100000>; + reset-gpios = <&pio 6 GPIO_ACTIVE_LOW>; + reset-assert-us = <10000>; + reset-deassert-us = <50000>; realtek,aldps-enable; }; - switch: switch@0 { + switch: switch@1f { compatible = "mediatek,mt7531"; reg = <31>; reset-gpios = <&pio 5 GPIO_ACTIVE_HIGH>; @@ -130,6 +149,142 @@ }; }; +&mmc0 { + bus-width = <8>; + cap-mmc-highspeed; + hs400-ds-delay = <0x14014>; + max-frequency = <200000000>; + mmc-hs200-1_8v; + mmc-hs400-1_8v; + no-sd; + no-sdio; + non-removable; + pinctrl-names = "default", "state_uhs"; + pinctrl-0 = <&mmc0_pins_default>; + pinctrl-1 = <&mmc0_pins_uhs>; + vmmc-supply = <®_3p3v>; + vqmmc-supply = <®_1p8v>; + status = "okay"; + + card@0 { + compatible = "mmc-card"; + reg = <0>; + + block { + compatible = "block-device"; + + partitions { + block-partition-factory { + partname = "factory"; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + eeprom_factory_0: eeprom@0 { + reg = <0x0 0x1000>; + }; + + macaddr_factory_24: macaddr@24 { + compatible = "mac-base"; + reg = <0x24 0x6>; + #nvmem-cell-cells = <1>; + }; + + macaddr_factory_2a: macaddr@2a { + compatible = "mac-base"; + reg = <0x2a 0x6>; + #nvmem-cell-cells = <1>; + }; + }; + }; + + emmc_rootdisk: block-partition-production { + partname = "production"; + }; + }; + }; + }; +}; + +&pio { + mmc0_pins_default: mmc0-pins-default { + mux { + function = "emmc"; + groups = "emmc_51"; + }; + conf-cmd-dat { + pins = "EMMC_DATA_0", "EMMC_DATA_1", "EMMC_DATA_2", + "EMMC_DATA_3", "EMMC_DATA_4", "EMMC_DATA_5", + "EMMC_DATA_6", "EMMC_DATA_7", "EMMC_CMD"; + input-enable; + drive-strength = <4>; + mediatek,pull-up-adv = <1>; + }; + conf-clk { + pins = "EMMC_CK"; + drive-strength = <6>; + mediatek,pull-down-adv = <2>; + }; + conf-ds { + pins = "EMMC_DSL"; + mediatek,pull-down-adv = <2>; + }; + conf-rst { + pins = "EMMC_RSTB"; + drive-strength = <4>; + mediatek,pull-up-adv = <1>; + }; + }; + + mmc0_pins_uhs: mmc0-uhs-pins { + mux { + function = "emmc"; + groups = "emmc_51"; + }; + conf-cmd-dat { + pins = "EMMC_DATA_0", "EMMC_DATA_1", "EMMC_DATA_2", + "EMMC_DATA_3", "EMMC_DATA_4", "EMMC_DATA_5", + "EMMC_DATA_6", "EMMC_DATA_7", "EMMC_CMD"; + input-enable; + drive-strength = <4>; + mediatek,pull-up-adv = <1>; + }; + conf-clk { + pins = "EMMC_CK"; + drive-strength = <6>; + mediatek,pull-down-adv = <2>; + }; + conf-ds { + pins = "EMMC_DSL"; + mediatek,pull-down-adv = <2>; + }; + conf-rst { + pins = "EMMC_RSTB"; + drive-strength = <4>; + mediatek,pull-up-adv = <1>; + }; + }; + + wf_2g_5g_pins: wf-2g-5g-pins { + mux { + function = "wifi"; + groups = "wf_2g", "wf_5g"; + }; + conf { + pins = "WF0_HB1", "WF0_HB2", "WF0_HB3", "WF0_HB4", + "WF0_HB0", "WF0_HB0_B", "WF0_HB5", "WF0_HB6", + "WF0_HB7", "WF0_HB8", "WF0_HB9", "WF0_HB10", + "WF0_TOP_CLK", "WF0_TOP_DATA", "WF1_HB1", + "WF1_HB2", "WF1_HB3", "WF1_HB4", "WF1_HB0", + "WF1_HB5", "WF1_HB6", "WF1_HB7", "WF1_HB8", + "WF1_TOP_CLK", "WF1_TOP_DATA"; + drive-strength = <4>; + }; + }; +}; + &switch { ports { #address-cells = <1>; @@ -169,99 +324,6 @@ }; }; -&mmc0 { - pinctrl-names = "default", "state_uhs"; - pinctrl-0 = <&mmc0_pins_default>; - pinctrl-1 = <&mmc0_pins_uhs>; - bus-width = <8>; - cap-mmc-highspeed; - hs400-ds-delay = <0x14014>; - max-frequency = <200000000>; - mmc-hs200-1_8v; - mmc-hs400-1_8v; - non-removable; - vmmc-supply = <®_3p3v>; - vqmmc-supply = <®_1p8v>; - status = "okay"; -}; - -&pio { - mmc0_pins_default: mmc0-pins { - mux { - function = "emmc"; - groups = "emmc_51"; - }; - conf-cmd-dat { - pins = "EMMC_DATA_0", "EMMC_DATA_1", "EMMC_DATA_2", - "EMMC_DATA_3", "EMMC_DATA_4", "EMMC_DATA_5", - "EMMC_DATA_6", "EMMC_DATA_7", "EMMC_CMD"; - input-enable; - drive-strength = <4>; - mediatek,pull-up-adv = <1>; /* pull-up 10K */ - }; - conf-clk { - pins = "EMMC_CK"; - drive-strength = <6>; - mediatek,pull-down-adv = <2>; /* pull-down 50K */ - }; - conf-ds { - pins = "EMMC_DSL"; - mediatek,pull-down-adv = <2>; /* pull-down 50K */ - }; - conf-rst { - pins = "EMMC_RSTB"; - drive-strength = <4>; - mediatek,pull-up-adv = <1>; /* pull-up 10K */ - }; - }; - - mmc0_pins_uhs: mmc0-uhs-pins { - mux { - function = "emmc"; - groups = "emmc_51"; - }; - conf-cmd-dat { - pins = "EMMC_DATA_0", "EMMC_DATA_1", "EMMC_DATA_2", - "EMMC_DATA_3", "EMMC_DATA_4", "EMMC_DATA_5", - "EMMC_DATA_6", "EMMC_DATA_7", "EMMC_CMD"; - input-enable; - drive-strength = <4>; - mediatek,pull-up-adv = <1>; /* pull-up 10K */ - }; - conf-clk { - pins = "EMMC_CK"; - drive-strength = <6>; - mediatek,pull-down-adv = <2>; /* pull-down 50K */ - }; - conf-ds { - pins = "EMMC_DSL"; - mediatek,pull-down-adv = <2>; /* pull-down 50K */ - }; - conf-rst { - pins = "EMMC_RSTB"; - drive-strength = <4>; - mediatek,pull-up-adv = <1>; /* pull-up 10K */ - }; - }; - - wf_2g_5g_pins: wf_2g_5g-pins { - mux { - function = "wifi"; - groups = "wf_2g", "wf_5g"; - }; - conf { - pins = "WF0_HB1", "WF0_HB2", "WF0_HB3", "WF0_HB4", - "WF0_HB0", "WF0_HB0_B", "WF0_HB5", "WF0_HB6", - "WF0_HB7", "WF0_HB8", "WF0_HB9", "WF0_HB10", - "WF0_TOP_CLK", "WF0_TOP_DATA", "WF1_HB1", - "WF1_HB2", "WF1_HB3", "WF1_HB4", "WF1_HB0", - "WF1_HB5", "WF1_HB6", "WF1_HB7", "WF1_HB8", - "WF1_TOP_CLK", "WF1_TOP_DATA"; - drive-strength = <4>; - }; - }; -}; - &trng { status = "okay"; }; @@ -275,7 +337,9 @@ }; &wifi { - status = "okay"; + nvmem-cells = <&eeprom_factory_0>; + nvmem-cell-names = "eeprom"; pinctrl-names = "default"; pinctrl-0 = <&wf_2g_5g_pins>; + status = "okay"; }; diff --git a/target/linux/mediatek/dts/mt7986a-netcore-n60.dts b/target/linux/mediatek/dts/mt7986a-netcore-n60.dts index 6863aeba0..b96b1e2ec 100644 --- a/target/linux/mediatek/dts/mt7986a-netcore-n60.dts +++ b/target/linux/mediatek/dts/mt7986a-netcore-n60.dts @@ -3,6 +3,7 @@ /dts-v1/; #include #include +#include #include "mt7986a.dtsi" @@ -46,13 +47,15 @@ leds { compatible = "gpio-leds"; - led_status_red: status_red { - label = "red:status"; + led_status_red: status-red { + color = ; + function = LED_FUNCTION_STATUS; gpios = <&pio 29 GPIO_ACTIVE_LOW>; }; - led_status_blue: status_blue { - label = "blue:status"; + led_status_blue: status-blue { + color = ; + function = LED_FUNCTION_STATUS; gpios = <&pio 32 GPIO_ACTIVE_LOW>; }; }; @@ -107,7 +110,7 @@ mxl,led-config = <0x0 0x0 0x0 0x3f0>; }; - switch: switch@0 { + switch: switch@1f { compatible = "mediatek,mt7531"; reg = <31>; reset-gpios = <&pio 5 GPIO_ACTIVE_HIGH>; @@ -145,7 +148,6 @@ port@6 { reg = <6>; - label = "cpu"; ethernet = <&gmac0>; phy-mode = "2500base-x"; @@ -173,10 +175,6 @@ spi-tx-bus-width = <4>; spi-rx-bus-width = <4>; - mediatek,nmbm; - mediatek,bmt-max-ratio = <1>; - mediatek,bmt-max-reserved-blocks = <64>; - partitions { compatible = "fixed-partitions"; #address-cells = <1>; @@ -270,15 +268,17 @@ }; &factory { - compatible = "nvmem-cells"; - #address-cells = <1>; - #size-cells = <1>; + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; - macaddr_lan: macaddr@1fef20 { - reg = <0x1fef20 0x6>; - }; + macaddr_lan: macaddr@1fef20 { + reg = <0x1fef20 0x6>; + }; - macaddr_wan: macaddr@1fef26 { - reg = <0x1fef26 0x6>; + macaddr_wan: macaddr@1fef26 { + reg = <0x1fef26 0x6>; + }; }; }; diff --git a/target/linux/mediatek/dts/mt7986a-ruijie-rg-x60-pro.dts b/target/linux/mediatek/dts/mt7986a-ruijie-rg-x60-pro.dts index 4bb983d7c..80b614ac2 100644 --- a/target/linux/mediatek/dts/mt7986a-ruijie-rg-x60-pro.dts +++ b/target/linux/mediatek/dts/mt7986a-ruijie-rg-x60-pro.dts @@ -1,15 +1,15 @@ // SPDX-License-Identifier: (GPL-2.0 OR MIT) /dts-v1/; -#include #include +#include #include #include "mt7986a.dtsi" / { - model = "Ruijie RG-X60 Pro"; compatible = "ruijie,rg-x60-pro", "mediatek,mt7986a"; + model = "Ruijie RG-X60 Pro"; aliases { serial0 = &uart0; @@ -23,37 +23,39 @@ bootargs = "console=ttyS0,115200n8 earlycon=uart8250,mmio32,0x11002000"; }; - memory { + memory@40000000 { reg = <0 0x40000000 0 0x20000000>; }; gpio-keys { compatible = "gpio-keys"; - reset { + button-0 { label = "reset"; gpios = <&pio 9 GPIO_ACTIVE_LOW>; linux,code = ; }; - mesh { + button-1 { label = "mesh"; gpios = <&pio 10 GPIO_ACTIVE_LOW>; linux,code = ; }; }; - leds { + leds-gpio { compatible = "gpio-leds"; - led_alarm: status_purple { - label = "purple:status"; - gpios = <&pio 11 GPIO_ACTIVE_LOW>; + led_system: led-0 { + color = ; + function = LED_FUNCTION_STATUS; + gpios = <&pio 22 GPIO_ACTIVE_LOW>; }; - led_system: status_white { - label = "white:status"; - gpios = <&pio 22 GPIO_ACTIVE_LOW>; + led_alarm: led-1 { + color = ; + function = LED_FUNCTION_STATUS; + gpios = <&pio 11 GPIO_ACTIVE_LOW>; }; }; }; @@ -65,7 +67,6 @@ compatible = "mediatek,eth-mac"; reg = <0>; phy-mode = "2500base-x"; - fixed-link { speed = <2500>; full-duplex; @@ -179,10 +180,20 @@ read-only; }; - factory: partition@180000 { + partition@180000 { label = "Factory"; reg = <0x180000 0x200000>; read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + eeprom_factory_0: eeprom@0 { + reg = <0x0 0x1000>; + }; + }; }; partition@380000 { @@ -256,7 +267,8 @@ pinctrl-names = "default"; pinctrl-0 = <&wf_2g_5g_pins>; - mediatek,mtd-eeprom = <&factory 0x0>; + nvmem-cells = <&eeprom_factory_0>; + nvmem-cell-names = "eeprom"; }; &uart0 { diff --git a/target/linux/mediatek/dts/mt7986a-smartrg-SDG-8612.dts b/target/linux/mediatek/dts/mt7986a-smartrg-SDG-8612.dts new file mode 100644 index 000000000..1537fc2c1 --- /dev/null +++ b/target/linux/mediatek/dts/mt7986a-smartrg-SDG-8612.dts @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* + * Copyright (C) 2022 SmartRG Inc. + * Author: Chad Monroe + */ + +#include "mt7986a-smartrg-bonanza-peak.dtsi" + +/ { + model = "SmartRG SDG-8612"; + compatible = "smartrg,sdg-8612", "mediatek,mt7986a"; +}; + +&gmac0 { + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; +}; + +&gmac1 { + phy-handle = <&phy6>; +}; + +&mdio { + switch: switch@1f { + compatible = "mediatek,mt7531"; + reg = <31>; + reset-gpios = <&pio 5 GPIO_ACTIVE_HIGH>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@1 { + reg = <1>; + label = "lan3"; + }; + + port@2 { + reg = <2>; + label = "lan2"; + }; + + port@3 { + reg = <3>; + label = "lan1"; + }; + + port5: port@5 { + reg = <5>; + label = "lan4"; + + phy-mode = "2500base-x"; + phy-handle = <&phy5>; + }; + + port@6 { + reg = <6>; + ethernet = <&gmac0>; + phy-mode = "2500base-x"; + + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; + }; + }; + }; +}; + +&wifi { + ieee80211-freq-limit = <2400000 2500000>, <5170000 5835000>; +}; diff --git a/target/linux/mediatek/dts/mt7986a-smartrg-SDG-8614.dts b/target/linux/mediatek/dts/mt7986a-smartrg-SDG-8614.dts new file mode 100644 index 000000000..15cfb1f12 --- /dev/null +++ b/target/linux/mediatek/dts/mt7986a-smartrg-SDG-8614.dts @@ -0,0 +1,124 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* + * Copyright (C) 2022 SmartRG Inc. + * Author: Chad Monroe + */ + +#include "mt7986a-smartrg-bonanza-peak.dtsi" + +/ { + model = "SmartRG SDG-8614"; + compatible = "smartrg,sdg-8614", "mediatek,mt7986a"; + + /* SFP1 cage (WAN) */ + i2c_sfp1: i2c-gpio-0 { + compatible = "i2c-gpio"; + sda-gpios = <&pio 62 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + scl-gpios = <&pio 63 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + i2c-gpio,delay-us = <2>; + #address-cells = <1>; + #size-cells = <0>; + }; + + sfp1: sfp1 { + compatible = "sff,sfp"; + i2c-bus = <&i2c_sfp1>; + los-gpios = <&pio 20 GPIO_ACTIVE_HIGH>; + mod-def0-gpios = <&pio 65 GPIO_ACTIVE_LOW>; + rate-select0-gpios = <&pio 9 GPIO_ACTIVE_HIGH>; + rate-select1-gpios = <&pio 28 GPIO_ACTIVE_HIGH>; + tx-disable-gpios = <&pio 64 GPIO_ACTIVE_HIGH>; + tx-fault-gpios = <&pio 7 GPIO_ACTIVE_HIGH>; + maximum-power-milliwatt = <3000>; + }; + + leds { + compatible = "gpio-leds"; + + sfp_red { + color = ; + function = "sfp"; + function-enumerator = <1>; + gpios = <&pio 16 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + sfp_green { + color = ; + function = "sfp"; + function-enumerator = <0>; + gpios = <&pio 19 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + }; +}; + +&mux_sel { + output-low; + /delete-node/ output-high; +}; + +&gmac0 { + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; +}; + +&gmac1 { + sfp = <&sfp1>; + managed = "in-band-status"; +}; + +&mdio { + switch: switch@1f { + compatible = "mediatek,mt7531"; + reg = <31>; + reset-gpios = <&pio 5 GPIO_ACTIVE_HIGH>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@1 { + reg = <1>; + label = "lan3"; + }; + + port@2 { + reg = <2>; + label = "lan2"; + }; + + port@3 { + reg = <3>; + label = "lan1"; + }; + + port5: port@5 { + reg = <5>; + label = "lan4"; + + phy-mode = "2500base-x"; + phy-handle = <&phy5>; + }; + + port@6 { + reg = <6>; + ethernet = <&gmac0>; + phy-mode = "2500base-x"; + + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; + }; + }; + }; +}; + +&wifi { + ieee80211-freq-limit = <2400000 2500000>, <5170000 5835000>; +}; diff --git a/target/linux/mediatek/dts/mt7986a-smartrg-SDG-8622.dts b/target/linux/mediatek/dts/mt7986a-smartrg-SDG-8622.dts new file mode 100644 index 000000000..2c28c8f7b --- /dev/null +++ b/target/linux/mediatek/dts/mt7986a-smartrg-SDG-8622.dts @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* + * Copyright (C) 2022 SmartRG Inc. + * Author: Chad Monroe + */ + +#include "mt7986a-smartrg-bonanza-peak.dtsi" + +/ { + model = "SmartRG SDG-8622"; + compatible = "smartrg,sdg-8622", "mediatek,mt7986a"; +}; + +&gmac0 { + phy-handle = <&phy5>; + + label = "lan"; +}; + +&gmac1 { + phy-handle = <&phy6>; +}; + +&pcie { + status = "okay"; +}; + +&pcie_phy { + status = "okay"; +}; + +&radio0 { + ieee80211-freq-limit = <5170000 5330000>; +}; + +&wifi { + ieee80211-freq-limit = <2400000 2500000>, <5490000 5835000>; +}; diff --git a/target/linux/mediatek/dts/mt7986a-smartrg-SDG-8632.dts b/target/linux/mediatek/dts/mt7986a-smartrg-SDG-8632.dts new file mode 100644 index 000000000..bc92f85aa --- /dev/null +++ b/target/linux/mediatek/dts/mt7986a-smartrg-SDG-8632.dts @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* + * Copyright (C) 2022 SmartRG Inc. + * Author: Chad Monroe + */ + +#include "mt7986a-smartrg-bonanza-peak.dtsi" + +/ { + model = "SmartRG SDG-8632"; + compatible = "smartrg,sdg-8632", "mediatek,mt7986a"; +}; + +&gmac0 { + phy-handle = <&phy5>; + + label = "lan"; +}; + +&gmac1 { + phy-handle = <&phy6>; +}; + +&pcie { + status = "okay"; +}; + +&pcie_phy { + status = "okay"; +}; + +&radio0 { + ieee80211-freq-limit = <5170000 5835000>; +}; + +&wifi { + ieee80211-freq-limit = <2400000 2500000>, <5945000 7125000>; +}; diff --git a/target/linux/mediatek/dts/mt7986a-smartrg-bonanza-peak.dtsi b/target/linux/mediatek/dts/mt7986a-smartrg-bonanza-peak.dtsi new file mode 100644 index 000000000..038a76ad7 --- /dev/null +++ b/target/linux/mediatek/dts/mt7986a-smartrg-bonanza-peak.dtsi @@ -0,0 +1,481 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* + * Copyright (C) 2022 SmartRG Inc. + * Author: Chad Monroe + */ + +/dts-v1/; +#include +#include +#include + +#include "mt7986a.dtsi" + +/ { + aliases { + serial0 = &uart0; + ethernet0 = &gmac0; + ethernet1 = &gmac1; + led-boot = &led_status_green; + led-failsafe = &led_status_red; + led-running = &led_status_white; + led-upgrade = &led_status_blue; + }; + + chosen { + stdout-path = "serial0:115200n8"; + bootargs = "root=/dev/mmcblk0p5"; + }; + + memory@40000000 { + device_type = "memory"; + reg = <0 0x40000000 0 0x40000000>; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + + /delete-node/ramoops@42ff0000; + + bootdata_reserved: bootdata@45000000 { + no-map; + reg = <0x0 0x45000000 0x0 0x00001000>; + }; + + ramoops_reserved: ramoops@45001000 { + no-map; + compatible = "ramoops"; + reg = <0x0 0x45001000 0x0 0x00140000>; + ftrace-size = <0x20000>; + record-size = <0x20000>; + console-size = <0x20000>; + pmsg-size = <0x80000>; + }; + }; + + bootdata { + compatible = "bootdata"; + memory-region = <&bootdata_reserved>; + }; + + reg_1p8v: regulator-1p8v { + compatible = "regulator-fixed"; + regulator-name = "fixed-1.8V"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-boot-on; + regulator-always-on; + }; + + reg_3p3v: regulator-3p3v { + compatible = "regulator-fixed"; + regulator-name = "fixed-3.3V"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + regulator-always-on; + }; + + reg_5v: regulator-5v { + compatible = "regulator-fixed"; + regulator-name = "fixed-5V"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-boot-on; + regulator-always-on; + }; + + fan: pwm-fan { + compatible = "pwm-fan"; + #cooling-cells = <2>; + pwms = <&pwm 1 40000 0>; + + /** + * set fan speed + * + * 0 = off + * 51 = 20% duty cycle (minimum supported) + * 61 = 24% duty cycle (2020 RPM) + * 77 = 30% duty cycle (3000 RPM) + * 102 = 40% duty cycle (3600 RPM) + * 255 = 100% duty cycle + */ + cooling-levels = <51 61 77 102>; + + interrupt-parent = <&pio>; + interrupts = <25 IRQ_TYPE_EDGE_FALLING>; + pulses-per-revolution = <2>; + + status = "okay"; + }; + + keys { + compatible = "gpio-keys"; + pinctrl-names = "default"; + pinctrl-0 = <&button_pins>; + + button-reset { + label = "reset"; + linux,code = ; + gpios = <&pio 17 GPIO_ACTIVE_LOW>; + }; + }; +}; + +&cpu_thermal { + cooling-maps { + cpu-active-high { + /* active: set fan to cooling level 3 */ + cooling-device = <&fan 3 3>; + trip = <&cpu_trip_active_high>; + }; + + cpu-active-medium { + /* active: set fan to cooling level 2 */ + cooling-device = <&fan 2 2>; + trip = <&cpu_trip_active_medium>; + }; + + cpu-active-low { + /* active: set fan to cooling level 1 */ + cooling-device = <&fan 1 1>; + trip = <&cpu_trip_active_low>; + }; + + cpu-active-silent { + /* active: set fan to cooling level 0 */ + cooling-device = <&fan 0 0>; + trip = <&cpu_trip_active_silent>; + }; + }; + + trips { + cpu_trip_active_high: active-high { + temperature = <110000>; + hysteresis = <2000>; + type = "active"; + }; + + cpu_trip_active_medium: active-medium { + temperature = <80000>; + hysteresis = <2000>; + type = "active"; + }; + + cpu_trip_active_low: active-low { + temperature = <60000>; + hysteresis = <2000>; + type = "active"; + }; + + cpu_trip_active_silent: active-silent { + temperature = <40000>; + hysteresis = <2000>; + type = "active"; + }; + }; +}; + +&crypto { + status = "okay"; +}; + +ð { + status = "okay"; + + gmac0: mac@0 { + compatible = "mediatek,eth-mac"; + reg = <0>; + + phy-mode = "2500base-x"; + }; + + gmac1: mac@1 { + label = "wan"; + + compatible = "mediatek,eth-mac"; + reg = <1>; + + phy-mode = "2500base-x"; + }; + + mdio: mdio-bus { + #address-cells = <1>; + #size-cells = <0>; + }; +}; + +&mdio { + #address-cells = <1>; + #size-cells = <0>; + + reset-gpios = <&pio 6 GPIO_ACTIVE_LOW>; + reset-delay-us = <1500000>; + reset-post-delay-us = <1000000>; + + phy5: ethernet-phy@5 { + /* GPY211 */ + compatible = "maxlinear,gpy211", "ethernet-phy-ieee802.3-c45"; + reg = <5>; + + mxl,led-drive-vdd; + mxl,led-config = <0x30 0x40 0x80 0x0>; + }; + + phy6: ethernet-phy@6 { + /* GPY211 */ + compatible = "maxlinear,gpy211", "ethernet-phy-ieee802.3-c45"; + reg = <6>; + + mxl,led-drive-vdd; + mxl,led-config = <0x30 0x40 0x80 0x0>; + }; +}; + +&crypto { + status = "okay"; +}; + +&mmc0 { + pinctrl-names = "default", "state_uhs"; + pinctrl-0 = <&mmc0_pins_default>; + pinctrl-1 = <&mmc0_pins_uhs>; + bus-width = <8>; + max-frequency = <200000000>; + cap-mmc-highspeed; + mmc-hs200-1_8v; + mmc-hs400-1_8v; + hs400-ds-delay = <0x14014>; + vmmc-supply = <®_3p3v>; + vqmmc-supply = <®_1p8v>; + non-removable; + no-sd; + no-sdio; + status = "okay"; +}; + +&pcie { + pinctrl-names = "default"; + pinctrl-0 = <&pcie_pins>; + status = "disabled"; + + slot0: pcie@0,0 { + reg = <0x0000 0 0 0 0>; + + radio0: mt7915@0,0 { + reg = <0x0000 0 0 0 0>; + }; + }; +}; + +&pcie_phy { + status = "disabled"; +}; + +&wifi { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&wf_2g_5g_pins>; +}; + +&pio { + mmc0_pins_default: mmc0-pins { + mux { + function = "emmc"; + groups = "emmc_51"; + }; + conf-cmd-dat { + pins = "EMMC_DATA_0", "EMMC_DATA_1", "EMMC_DATA_2", + "EMMC_DATA_3", "EMMC_DATA_4", "EMMC_DATA_5", + "EMMC_DATA_6", "EMMC_DATA_7", "EMMC_CMD"; + input-enable; + drive-strength = <4>; + mediatek,pull-up-adv = <1>; /* pull-up 10K */ + }; + conf-clk { + pins = "EMMC_CK"; + drive-strength = <6>; + mediatek,pull-down-adv = <2>; /* pull-down 50K */ + }; + conf-ds { + pins = "EMMC_DSL"; + mediatek,pull-down-adv = <2>; /* pull-down 50K */ + }; + conf-rst { + pins = "EMMC_RSTB"; + drive-strength = <4>; + mediatek,pull-up-adv = <1>; /* pull-up 10K */ + }; + }; + + mmc0_pins_uhs: mmc0-uhs-pins { + mux { + function = "emmc"; + groups = "emmc_51"; + }; + conf-cmd-dat { + pins = "EMMC_DATA_0", "EMMC_DATA_1", "EMMC_DATA_2", + "EMMC_DATA_3", "EMMC_DATA_4", "EMMC_DATA_5", + "EMMC_DATA_6", "EMMC_DATA_7", "EMMC_CMD"; + input-enable; + drive-strength = <4>; + mediatek,pull-up-adv = <1>; /* pull-up 10K */ + }; + conf-clk { + pins = "EMMC_CK"; + drive-strength = <6>; + mediatek,pull-down-adv = <2>; /* pull-down 50K */ + }; + conf-ds { + pins = "EMMC_DSL"; + mediatek,pull-down-adv = <2>; /* pull-down 50K */ + }; + conf-rst { + pins = "EMMC_RSTB"; + drive-strength = <4>; + mediatek,pull-up-adv = <1>; /* pull-up 10K */ + }; + }; + + pcie_pins: pcie-pins { + mux { + function = "pcie"; + groups = "pcie_clk", "pcie_pereset"; + }; + }; + + button_pins: button-pins { + pins = "GPIO_12"; + mediatek,pull-down-adv = <0>; /* bias-disable */ + }; + + uart1_pins: uart1-pins { + mux { + function = "uart"; + groups = "uart1_2_rx_tx", "uart1_2_cts_rts"; + }; + }; + + i2c0_pins: i2c0-pins { + mux { + function = "i2c"; + groups = "i2c"; + }; + }; + + pwm_pins: pwm-pins { + mux { + function = "pwm"; + groups = "pwm0", "pwm1_0"; + }; + }; + + wf_2g_5g_pins: wf-2g-5g-pins { + mux { + function = "wifi"; + groups = "wf_2g", "wf_5g"; + }; + conf { + pins = "WF0_HB1", "WF0_HB2", "WF0_HB3", "WF0_HB4", + "WF0_HB0", "WF0_HB0_B", "WF0_HB5", "WF0_HB6", + "WF0_HB7", "WF0_HB8", "WF0_HB9", "WF0_HB10", + "WF0_TOP_CLK", "WF0_TOP_DATA", "WF1_HB1", + "WF1_HB2", "WF1_HB3", "WF1_HB4", "WF1_HB0", + "WF1_HB5", "WF1_HB6", "WF1_HB7", "WF1_HB8", + "WF1_TOP_CLK", "WF1_TOP_DATA"; + drive-strength = <4>; + }; + }; + + mux_sel: mux-sel-hog { + gpio-hog; + gpios = <23 GPIO_ACTIVE_LOW>; + line-name = "mux-sel"; + output-high; + }; + + mux_oe: mux-oe-hog { + gpio-hog; + gpios = <24 GPIO_ACTIVE_LOW>; + line-name = "mux-oe"; + output-high; + }; +}; + +&ssusb { + vusb33-supply = <®_3p3v>; + vbus-supply = <®_5v>; + status = "okay"; +}; + +&trng { + status = "okay"; +}; + +&uart0 { + status = "okay"; +}; + +&uart1 { + pinctrl-names = "default"; + pinctrl-0 = <&uart1_pins>; + status = "okay"; + + /* DA14531MOD Bluetooth */ + bluetooth { + compatible = "renesas,DA14531"; + reset-gpios = <&pio 27 GPIO_ACTIVE_LOW>; + }; +}; + +&usb_phy { + status = "okay"; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins>; + status = "okay"; + + system-leds { + compatible = "srg,sysled"; + reg = <0x30>; + + led_status_red: led@1 { + color = ; + function = LED_FUNCTION_STATUS; + reg = <1>; + }; + + led_status_green: led@2 { + color = ; + function = LED_FUNCTION_STATUS; + reg = <2>; + }; + + led_status_blue: led@3 { + color = ; + function = LED_FUNCTION_STATUS; + reg = <3>; + }; + + led_status_white: led@4 { + color = ; + function = LED_FUNCTION_STATUS; + reg = <4>; + }; + }; +}; + +&pwm { + pinctrl-names = "default"; + pinctrl-0 = <&pwm_pins>; + status = "okay"; +}; + +&watchdog { + interrupts = ; + status = "okay"; +}; diff --git a/target/linux/mediatek/dts/mt7986a-tplink-tl-xdr-common.dtsi b/target/linux/mediatek/dts/mt7986a-tplink-tl-xdr-common.dtsi index 65d0eb51b..1649b0775 100644 --- a/target/linux/mediatek/dts/mt7986a-tplink-tl-xdr-common.dtsi +++ b/target/linux/mediatek/dts/mt7986a-tplink-tl-xdr-common.dtsi @@ -2,6 +2,7 @@ #include #include +#include #include "mt7986a.dtsi" @@ -16,6 +17,8 @@ }; chosen { + bootargs = "root=/dev/fit0 rootwait"; + rootdisk = <&ubi_rootdisk>; stdout-path = "serial0:115200n8"; }; @@ -67,12 +70,14 @@ compatible = "gpio-leds"; led_status_red: status_red { - label = "red:status"; + function = LED_FUNCTION_STATUS; + color = ; gpios = <&pio 7 GPIO_ACTIVE_HIGH>; }; led_status_green: status_green { - label = "green:status"; + function = LED_FUNCTION_STATUS; + color = ; gpios = <&pio 8 GPIO_ACTIVE_HIGH>; }; @@ -95,7 +100,7 @@ reg = <0>; phy-mode = "2500base-x"; - nvmem-cells = <&macaddr_config_1c>; + nvmem-cells = <&macaddr_config_1c 0>; nvmem-cell-names = "mac-address"; fixed-link { @@ -111,9 +116,8 @@ phy-handle = <&phy7>; phy-mode = "2500base-x"; - nvmem-cells = <&macaddr_config_1c>; + nvmem-cells = <&macaddr_config_1c 1>; nvmem-cell-names = "mac-address"; - mac-address-increment = <1>; }; mdio: mdio-bus { @@ -130,7 +134,6 @@ reset-deassert-us = <100000>; reset-gpios = <&pio 13 GPIO_ACTIVE_LOW>; realtek,aldps-enable; - realtek,led-link-select = <0xa7 0x0 0x0>; }; phy7: ethernet-phy@7 { @@ -140,10 +143,9 @@ reset-deassert-us = <100000>; reset-gpios = <&pio 17 GPIO_ACTIVE_LOW>; realtek,aldps-enable; - realtek,led-link-select = <0xa7 0x0 0x0>; }; - switch: switch@31 { + switch: switch@1f { compatible = "mediatek,mt7531"; reg = <31>; reset-gpios = <&pio 5 GPIO_ACTIVE_HIGH>; @@ -157,7 +159,6 @@ &spi0 { pinctrl-names = "default"; pinctrl-0 = <&spi_flash_pins>; - cs-gpios = <0>, <0>; status = "okay"; flash@0 { @@ -185,6 +186,18 @@ label = "config"; reg = <0x100000 0x0060000>; read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + macaddr_config_1c: macaddr@1c { + compatible = "mac-base"; + reg = <0x1c 0x6>; + #nvmem-cell-cells = <1>; + }; + }; }; factory: partition@160000 { @@ -201,13 +214,20 @@ partition@380000 { label = "fip"; - reg = <0x380000 0x0180000>; + reg = <0x380000 0x0200000>; read-only; }; - partition@500000 { + partition@580000 { + compatible = "linux,ubi"; + reg = <0x580000 0x7800000>; label = "ubi"; - reg = <0x500000 0x7300000>; + + volumes { + ubi_rootdisk: ubi-volume-fit { + volname = "fit"; + }; + }; }; }; }; @@ -256,17 +276,7 @@ &wifi { mediatek,mtd-eeprom = <&factory 0x0>; - nvmem-cells = <&macaddr_config_1c>; + nvmem-cells = <&macaddr_config_1c 2>; nvmem-cell-names = "mac-address"; status = "okay"; }; - -&config { - compatible = "nvmem-cells"; - #address-cells = <1>; - #size-cells = <1>; - - macaddr_config_1c: macaddr@1c { - reg = <0x1c 0x6>; - }; -}; diff --git a/target/linux/mediatek/dts/mt7986a-tplink-tl-xdr4288.dts b/target/linux/mediatek/dts/mt7986a-tplink-tl-xdr4288.dts index 33eca8f17..591d16195 100644 --- a/target/linux/mediatek/dts/mt7986a-tplink-tl-xdr4288.dts +++ b/target/linux/mediatek/dts/mt7986a-tplink-tl-xdr4288.dts @@ -15,22 +15,22 @@ port@0 { reg = <0>; - label = "lan4"; + label = "lan1"; }; port@1 { reg = <1>; - label = "lan3"; + label = "lan2"; }; port@2 { reg = <2>; - label = "lan2"; + label = "lan3"; }; port@3 { reg = <3>; - label = "lan1"; + label = "lan4"; }; port@5 { @@ -42,7 +42,6 @@ port@6 { reg = <6>; - label = "cpu"; ethernet = <&gmac0>; phy-mode = "2500base-x"; diff --git a/target/linux/mediatek/dts/mt7986a-tplink-tl-xdr6086.dts b/target/linux/mediatek/dts/mt7986a-tplink-tl-xdr6086.dts index 4b757045e..68a159a8e 100644 --- a/target/linux/mediatek/dts/mt7986a-tplink-tl-xdr6086.dts +++ b/target/linux/mediatek/dts/mt7986a-tplink-tl-xdr6086.dts @@ -27,7 +27,6 @@ port@6 { reg = <6>; - label = "cpu"; ethernet = <&gmac0>; phy-mode = "2500base-x"; diff --git a/target/linux/mediatek/dts/mt7986a-tplink-tl-xdr6088.dts b/target/linux/mediatek/dts/mt7986a-tplink-tl-xdr6088.dts index 85b5a3db2..751909a6a 100644 --- a/target/linux/mediatek/dts/mt7986a-tplink-tl-xdr6088.dts +++ b/target/linux/mediatek/dts/mt7986a-tplink-tl-xdr6088.dts @@ -15,22 +15,22 @@ port@0 { reg = <0>; - label = "lan4"; + label = "lan1"; }; port@1 { reg = <1>; - label = "lan3"; + label = "lan2"; }; port@2 { reg = <2>; - label = "lan2"; + label = "lan3"; }; port@3 { reg = <3>; - label = "lan1"; + label = "lan4"; }; port@5 { @@ -42,7 +42,6 @@ port@6 { reg = <6>; - label = "cpu"; ethernet = <&gmac0>; phy-mode = "2500base-x"; diff --git a/target/linux/mediatek/dts/mt7986a-tplink-tl-xtr8488.dts b/target/linux/mediatek/dts/mt7986a-tplink-tl-xtr8488.dts deleted file mode 100644 index 7bfcecdfd..000000000 --- a/target/linux/mediatek/dts/mt7986a-tplink-tl-xtr8488.dts +++ /dev/null @@ -1,228 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later OR MIT - -/dts-v1/; -#include "mt7986a-tplink-tl-xdr-common.dtsi" - -/ { - model = "TP-Link TL-XTR8488"; - compatible = "tplink,tl-xtr8488"; - - keys { - reset { - label = "reset"; - linux,code = ; - gpios = <&pio 15 GPIO_ACTIVE_LOW>; - }; - - wps { - label = "wps"; - linux,code = ; - gpios = <&pio 16 GPIO_ACTIVE_LOW>; - }; - }; - - leds { - turbo { - label = "green:turbo"; - gpios = <&pio 12 GPIO_ACTIVE_LOW>; - }; - }; -}; - -ð { - /delete-node/ mdio-bus; - - mdio: mdio-bus { - #address-cells = <1>; - #size-cells = <0>; - - phy5: phy@5 { - compatible = "ethernet-phy-ieee802.3-c45"; - reg = <5>; - realtek,aldps-enable; - realtek,led-link-select = <0xa7 0x0 0x0>; - }; - - phy7: phy@7 { - compatible = "ethernet-phy-ieee802.3-c45"; - reg = <7>; - realtek,aldps-enable; - realtek,led-link-select = <0xa7 0x0 0x0>; - }; - - switch: switch@0 { - compatible = "mediatek,mt7531"; - reg = <31>; - reset-gpios = <&pio 6 GPIO_ACTIVE_HIGH>; - interrupt-controller; - #interrupt-cells = <1>; - interrupt-parent = <&pio>; - interrupts = <66 IRQ_TYPE_LEVEL_HIGH>; - }; - }; -}; - -&switch { - ports { - #address-cells = <1>; - #size-cells = <0>; - - port@0 { - reg = <0>; - label = "lan4"; - }; - - port@1 { - reg = <1>; - label = "lan3"; - }; - - port@2 { - reg = <2>; - label = "lan2"; - }; - - port@3 { - reg = <3>; - label = "lan1"; - }; - - port@5 { - reg = <5>; - label = "lan5"; - phy-handle = <&phy5>; - phy-mode = "2500base-x"; - }; - - port@6 { - reg = <6>; - label = "cpu"; - ethernet = <&gmac0>; - phy-mode = "2500base-x"; - - fixed-link { - speed = <2500>; - full-duplex; - pause; - }; - }; - }; -}; - -&spi0 { - flash@0 { - /delete-node/ partitions; - - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - partition@0 { - label = "bl2"; - reg = <0x000000 0x0100000>; - read-only; - }; - - config: partition@100000 { - label = "config"; - reg = <0x100000 0x0040000>; - read-only; - }; - - factory: partition@140000 { - label = "factory"; - reg = <0x140000 0x0040000>; - read-only; - }; - - partition@180000 { - label = "reserved"; - reg = <0x180000 0x0180000>; - read-only; - }; - - partition@300000 { - label = "u-boot-env"; - reg = <0x300000 0x0080000>; - }; - - partition@380000 { - label = "fip"; - reg = <0x380000 0x0200000>; - read-only; - }; - - partition@580000 { - label = "ubi"; - reg = <0x580000 0x7800000>; - }; - }; - }; -}; - -&pcie { - pinctrl-names = "default"; - pinctrl-0 = <&pcie_pins>; - status = "okay"; - - pcie@0,0 { - reg = <0x0000 0 0 0 0>; - - wifi@0,0 { - compatible = "mediatek,mt76"; - reg = <0x0000 0 0 0 0>; - mediatek,mtd-eeprom = <&factory 0x1000>; - ieee80211-freq-limit = <5470000 5875000>; - - nvmem-cells = <&macaddr_config_1c>; - nvmem-cell-names = "mac-address"; - mac-address-increment = <3>; - }; - }; -}; - -&pcie_phy { - status = "okay"; -}; - -&pio { - pcie_pins: pcie-pins { - mux { - function = "pcie"; - groups = "pcie_clk", "pcie_wake", "pcie_pereset"; - }; - }; - - wf_2g_5g_pins: wf_2g_5g-pins { - mux { - function = "wifi"; - groups = "wf_2g", "wf_5g"; - }; - conf { - pins = "WF0_HB1", "WF0_HB2", "WF0_HB3", "WF0_HB4", - "WF0_HB0", "WF0_HB0_B", "WF0_HB5", "WF0_HB6", - "WF0_HB7", "WF0_HB8", "WF0_HB9", "WF0_HB10", - "WF0_TOP_CLK", "WF0_TOP_DATA", "WF1_HB1", - "WF1_HB2", "WF1_HB3", "WF1_HB4", "WF1_HB0", - "WF1_HB5", "WF1_HB6", "WF1_HB7", "WF1_HB8", - "WF1_TOP_CLK", "WF1_TOP_DATA"; - drive-strength = <4>; - }; - }; -}; - -&wifi { - pinctrl-names = "default"; - pinctrl-0 = <&wf_2g_5g_pins>; -}; - -&config { - compatible = "nvmem-cells"; - #address-cells = <1>; - #size-cells = <1>; - - macaddr_config_1c: macaddr@1c { - reg = <0x1c 0x6>; - }; -}; diff --git a/target/linux/mediatek/dts/mt7986a-xiaomi-redmi-router-ax6000-stock.dts b/target/linux/mediatek/dts/mt7986a-xiaomi-redmi-router-ax6000-stock.dts new file mode 100644 index 000000000..114076dff --- /dev/null +++ b/target/linux/mediatek/dts/mt7986a-xiaomi-redmi-router-ax6000-stock.dts @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) + +/dts-v1/; +#include "mt7986a-xiaomi-redmi-router-ax6000.dtsi" + +/ { + model = "Xiaomi Redmi Router AX6000 (stock layout)"; + compatible = "xiaomi,redmi-router-ax6000-stock", "mediatek,mt7986a"; +}; + +&spi_nand_flash { + mediatek,nmbm; + mediatek,bmt-max-ratio = <1>; + mediatek,bmt-max-reserved-blocks = <64>; +}; + +&partitions { + partition@580000 { + label = "crash"; + reg = <0x580000 0x40000>; + read-only; + }; + + partition@5c0000 { + label = "crash_log"; + reg = <0x5c0000 0x40000>; + read-only; + }; + + partition@600000 { + label = "ubi_kernel"; + reg = <0x600000 0x1e00000>; + }; + + partition@2400000 { + label = "ubi"; + reg = <0x2400000 0x5000000>; + }; +}; diff --git a/target/linux/mediatek/dts/mt7986a-xiaomi-redmi-router-ax6000-ubootmod.dts b/target/linux/mediatek/dts/mt7986a-xiaomi-redmi-router-ax6000-ubootmod.dts new file mode 100644 index 000000000..f26ab1a88 --- /dev/null +++ b/target/linux/mediatek/dts/mt7986a-xiaomi-redmi-router-ax6000-ubootmod.dts @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) + +/dts-v1/; +#include "mt7986a-xiaomi-redmi-router-ax6000.dtsi" + +/ { + model = "Xiaomi Redmi Router AX6000 (OpenWrt U-Boot layout)"; + compatible = "xiaomi,redmi-router-ax6000-ubootmod", "mediatek,mt7986a"; +}; + +&chosen { + rootdisk = <&ubi_rootdisk>; + bootargs-append = " root=/dev/fit0 rootwait"; +}; + +&partitions { + partition@580000 { + compatible = "linux,ubi"; + reg = <0x580000 0x7a80000>; + label = "ubi"; + + volumes { + ubi_rootdisk: ubi-volume-fit { + volname = "fit"; + }; + }; + }; +}; diff --git a/target/linux/mediatek/dts/mt7986a-xiaomi-redmi-router-ax6000.dts b/target/linux/mediatek/dts/mt7986a-xiaomi-redmi-router-ax6000.dtsi similarity index 80% rename from target/linux/mediatek/dts/mt7986a-xiaomi-redmi-router-ax6000.dts rename to target/linux/mediatek/dts/mt7986a-xiaomi-redmi-router-ax6000.dtsi index f3f05474e..c26246110 100644 --- a/target/linux/mediatek/dts/mt7986a-xiaomi-redmi-router-ax6000.dts +++ b/target/linux/mediatek/dts/mt7986a-xiaomi-redmi-router-ax6000.dtsi @@ -8,9 +8,6 @@ #include "mt7986a.dtsi" / { - model = "Xiaomi Redmi Router AX6000"; - compatible = "xiaomi,redmi-router-ax6000", "mediatek,mt7986a"; - aliases { serial0 = &uart0; led-boot = &led_status_rgb; @@ -19,7 +16,7 @@ led-upgrade = &led_status_rgb; }; - chosen { + chosen: chosen { stdout-path = "serial0:115200n8"; }; @@ -57,9 +54,8 @@ reg = <0>; phy-mode = "2500base-x"; - nvmem-cells = <&macaddr_factory_4>; + nvmem-cells = <&macaddr_factory_4 (-1)>; nvmem-cell-names = "mac-address"; - mac-address-increment = <(-1)>; fixed-link { speed = <2500>; @@ -75,7 +71,7 @@ }; &mdio { - switch: switch@0 { + switch: switch@1f { compatible = "mediatek,mt7531"; reg = <31>; reset-gpios = <&pio 5 GPIO_ACTIVE_HIGH>; @@ -132,10 +128,9 @@ &spi0 { pinctrl-names = "default"; pinctrl-0 = <&spi_flash_pins>; - cs-gpios = <0>, <0>; status = "okay"; - flash@0 { + spi_nand_flash: flash@0 { compatible = "spi-nand"; #address-cells = <1>; #size-cells = <1>; @@ -145,11 +140,7 @@ spi-tx-bus-width = <4>; spi-rx-bus-width = <4>; - mediatek,nmbm; - mediatek,bmt-max-ratio = <1>; - mediatek,bmt-max-reserved-blocks = <64>; - - partitions { + partitions: partitions { compatible = "fixed-partitions"; #address-cells = <1>; #size-cells = <1>; @@ -163,13 +154,11 @@ partition@100000 { label = "Nvram"; reg = <0x100000 0x40000>; - read-only; }; partition@140000 { label = "Bdata"; reg = <0x140000 0x40000>; - read-only; }; factory: partition@180000 { @@ -177,12 +166,16 @@ reg = <0x180000 0x200000>; read-only; - compatible = "nvmem-cells"; - #address-cells = <1>; - #size-cells = <1>; + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; - macaddr_factory_4: macaddr@4 { - reg = <0x4 0x6>; + macaddr_factory_4: macaddr@4 { + compatible = "mac-base"; + reg = <0x4 0x6>; + #nvmem-cell-cells = <1>; + }; }; }; @@ -191,31 +184,6 @@ reg = <0x380000 0x200000>; read-only; }; - - partition@580000 { - label = "crash"; - reg = <0x580000 0x40000>; - read-only; - }; - - partition@5c0000 { - label = "crash_log"; - reg = <0x5c0000 0x40000>; - read-only; - }; - - /* ubi partition is the result of squashing - * consecutive stock partitions: - * - ubi - * - ubi1 - * - overlay - */ - partition@600000 { - label = "ubi"; - reg = <0x600000 0x6e00000>; - }; - - /* last 12 MiB is reserved for NMBM bad block table */ }; }; }; @@ -234,13 +202,18 @@ led_status_rgb: led@0 { reg = <0>; - label = "rgb:status"; + function = LED_FUNCTION_STATUS; + color = ; color-index = ; }; led_network_rgb: led@1 { reg = <1>; - label = "rgb:network"; + + /* Hardcoding here for backward compatibility */ + function = "network"; + + color = ; color-index = ; }; }; @@ -273,7 +246,6 @@ port@6 { reg = <6>; - label = "cpu"; ethernet = <&gmac0>; phy-mode = "2500base-x"; diff --git a/target/linux/mediatek/dts/mt7986a-zyxel-ex5601-t0-common.dtsi b/target/linux/mediatek/dts/mt7986a-zyxel-ex5601-t0-common.dtsi new file mode 100644 index 000000000..335ee9398 --- /dev/null +++ b/target/linux/mediatek/dts/mt7986a-zyxel-ex5601-t0-common.dtsi @@ -0,0 +1,435 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* + * Copyright (C) 2021 MediaTek Inc. + * Author: Sam.Shih + */ + +#include "mt7986a.dtsi" +#include +#include +#include + +/ { + aliases { + serial0 = &uart0; + label-mac-device = &gmac0; + led-boot = &led_status_green; + led-failsafe = &led_status_red; + led-running = &led_status_green; + led-upgrade = &led_status_red; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + memory { + reg = <0 0x40000000 0 0x40000000>; + }; + + reg_1p8v: regulator-1p8v { + compatible = "regulator-fixed"; + regulator-name = "fixed-1.8V"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-boot-on; + regulator-always-on; + }; + + reg_3p3v: regulator-3p3v { + compatible = "regulator-fixed"; + regulator-name = "fixed-3.3V"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + regulator-always-on; + }; + + reg_5v: regulator-5v { + compatible = "regulator-fixed"; + regulator-name = "fixed-5V"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-boot-on; + regulator-always-on; + }; + + gpio-keys { + compatible = "gpio-keys"; + poll-interval = <20>; + + reset-button { + label = "reset"; + gpios = <&pio 21 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + + wlan-button { + label = "wlan"; + gpios = <&pio 11 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + wps-button { + label = "wps"; + gpios = <&pio 56 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + leds { + compatible = "gpio-leds"; + + led_green_wifi24g { + label = "green:wifi24g"; + gpios = <&pio 1 GPIO_ACTIVE_LOW>; + default-state = "off"; + }; + + led_green_wifi5g { + label = "green:wifi5g"; + gpios = <&pio 2 GPIO_ACTIVE_LOW>; + default-state = "off"; + }; + + led_green_inet { + label = "green:inet"; + gpios = <&pio 14 GPIO_ACTIVE_LOW>; + default-state = "off"; + }; + + led_red_inet { + label = "red:inet"; + gpios = <&pio 15 GPIO_ACTIVE_LOW>; + default-state = "off"; + }; + + led_status_green: led_green_pwr { + label = "green:pwr"; + gpios = <&pio 13 GPIO_ACTIVE_LOW>; + linux,default-trigger = "timer"; /* Default blinking */ + led-pattern = <125 125>; /* Fast blink is 4 HZ */ + }; + + led_status_red: led_red_pwr { + label = "red:pwr"; + gpios = <&pio 12 GPIO_ACTIVE_LOW>; + default-state = "off"; + }; + + led_green_fxs { + label = "green:fxs"; + gpios = <&pio 16 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + led_amber_fxs { + label = "amber:fxs"; + gpios = <&pio 17 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + led_amber_wps24g { + label = "amber:wps24g"; + gpios = <&pio 18 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + led_amber_wps5g { + label = "amber:wps5g"; + gpios = <&pio 19 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + led_green_lan { + function = LED_FUNCTION_LAN; + color = ; + gpios = <&pio 20 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + led_green_sfp { + label = "green:sfp"; + gpios = <&pio 24 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + }; +}; + +&spi0 { + pinctrl-names = "default"; + pinctrl-0 = <&spi_flash_pins>; + cs-gpios = <0>, <0>; + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + spi_nand: spi_nand@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "spi-nand"; + reg = <1>; + spi-max-frequency = <10000000>; + spi-tx-bus-width = <4>; + spi-rx-bus-width = <4>; + + nand_partitions: partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + }; + }; +}; + +ð { + pinctrl-names = "default"; + pinctrl-0 = <ð_pins>; + status = "okay"; + + gmac0: mac@0 { + compatible = "mediatek,eth-mac"; + reg = <0>; + phy-mode = "2500base-x"; + + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; + }; + + gmac1: mac@1 { + compatible = "mediatek,eth-mac"; + reg = <1>; + phy-mode = "2500base-x"; + phy = <&phy6>; + }; + + mdio: mdio-bus { + #address-cells = <1>; + #size-cells = <0>; + reset-gpios = <&pio 6 GPIO_ACTIVE_LOW>; + reset-delay-us = <1500000>; + reset-post-delay-us = <1000000>; + + phy5: phy@5 { + compatible = "ethernet-phy-ieee802.3-c45"; + reg = <5>; + mxl,led-config = <0x03f0 0x0 0x0 0x0>; + }; + + phy6: phy@6 { + compatible = "ethernet-phy-ieee802.3-c45"; + reg = <6>; + mxl,led-config = <0x00f0 0x0 0x0 0x0>; + }; + + switch@1f { + compatible = "mediatek,mt7531"; + reg = <31>; + reset-gpios = <&pio 5 GPIO_ACTIVE_HIGH>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@1 { + reg = <1>; + label = "lan2"; + }; + + port@2 { + reg = <2>; + label = "lan3"; + }; + + port@3 { + reg = <3>; + label = "lan4"; + }; + + port@5 { + reg = <5>; + label = "lan1"; + phy-mode = "2500base-x"; + phy = <&phy5>; + }; + + port@6 { + reg = <6>; + ethernet = <&gmac0>; + phy-mode = "2500base-x"; + + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; + }; + }; + }; + }; +}; + +&watchdog { + status = "okay"; +}; + +&wifi { + status = "okay"; + pinctrl-names = "default", "dbdc"; + pinctrl-0 = <&wf_2g_5g_pins>; + pinctrl-1 = <&wf_dbdc_pins>; +}; + +&crypto { + status = "okay"; +}; + +&pio { + eth_pins: eth-pins { + mux { + function = "eth"; + groups = "switch_int", "mdc_mdio"; + }; + }; + + spic_pins_g2: spic-pins-29-to-32 { + mux { + function = "spi"; + groups = "spi1_2"; + }; + }; + + spi_flash_pins: spi-flash-pins-33-to-38 { + mux { + function = "spi"; + groups = "spi0", "spi0_wp_hold"; + }; + conf-pu { + pins = "SPI2_CS", "SPI2_HOLD", "SPI2_WP"; + drive-strength = <8>; + mediatek,pull-up-adv = <0>; /* bias-disable */ + }; + conf-pd { + pins = "SPI2_CLK", "SPI2_MOSI", "SPI2_MISO"; + drive-strength = <8>; + mediatek,pull-down-adv = <0>; /* bias-disable */ + }; + }; + + uart0_pins: uart0-pins { + mux { + function = "uart"; + groups = "uart0"; + }; + }; + + uart1_pins: uart1-pins { + mux { + function = "uart"; + groups = "uart1"; + }; + }; + + uart2_pins: uart2-pins { + mux { + function = "uart"; + groups = "uart2"; + }; + }; + + wf_2g_5g_pins: wf_2g_5g-pins { + mux { + function = "wifi"; + groups = "wf_2g", "wf_5g"; + }; + conf { + pins = "WF0_HB1", "WF0_HB2", "WF0_HB3", "WF0_HB4", + "WF0_HB0", "WF0_HB0_B", "WF0_HB5", "WF0_HB6", + "WF0_HB7", "WF0_HB8", "WF0_HB9", "WF0_HB10", + "WF0_TOP_CLK", "WF0_TOP_DATA", "WF1_HB1", + "WF1_HB2", "WF1_HB3", "WF1_HB4", "WF1_HB0", + "WF1_HB5", "WF1_HB6", "WF1_HB7", "WF1_HB8", + "WF1_TOP_CLK", "WF1_TOP_DATA"; + drive-strength = <4>; + }; + }; + + wf_dbdc_pins: wf_dbdc-pins { + mux { + function = "wifi"; + groups = "wf_dbdc"; + }; + conf { + pins = "WF0_HB1", "WF0_HB2", "WF0_HB3", "WF0_HB4", + "WF0_HB0", "WF0_HB0_B", "WF0_HB5", "WF0_HB6", + "WF0_HB7", "WF0_HB8", "WF0_HB9", "WF0_HB10", + "WF0_TOP_CLK", "WF0_TOP_DATA", "WF1_HB1", + "WF1_HB2", "WF1_HB3", "WF1_HB4", "WF1_HB0", + "WF1_HB5", "WF1_HB6", "WF1_HB7", "WF1_HB8", + "WF1_TOP_CLK", "WF1_TOP_DATA"; + drive-strength = <4>; + }; + }; + + usb-oc-hog { + gpio-hog; + gpios = <7 GPIO_ACTIVE_LOW>; + input; + line-name = "usb-oc"; + }; +}; + +&spi1 { + pinctrl-names = "default"; + pinctrl-0 = <&spic_pins_g2>; + status = "okay"; + + proslic_spi: proslic_spi@0 { + compatible = "silabs,proslic_spi"; + reg = <0>; + spi-max-frequency = <10000000>; + spi-cpha = <1>; + spi-cpol = <1>; + channel_count = <1>; + debug_level = <4>; /* 1 = TRC, 2 = DBG, 4 = ERR */ + reset_gpio = <&pio 25 GPIO_ACTIVE_HIGH>; + ig,enable-spi = <1>; /* 1: Enable, 0: Disable */ + }; +}; + +&ssusb { + vusb33-supply = <®_3p3v>; + vbus-supply = <®_5v>; + status = "okay"; +}; + +&trng { + status = "okay"; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins>; + status = "okay"; +}; + +&uart1 { + pinctrl-names = "default"; + pinctrl-0 = <&uart1_pins>; + status = "disabled"; + + /* EFR32MG21 Zigbee (BOOT)*/ +}; + +&uart2 { + pinctrl-names = "default"; + pinctrl-0 = <&uart2_pins>; + status = "disabled"; + + /* EFR32MG21 Zigbee */ +}; + +&usb_phy { + status = "okay"; +}; diff --git a/target/linux/mediatek/dts/mt7986a-zyxel-ex5601-t0-stock.dts b/target/linux/mediatek/dts/mt7986a-zyxel-ex5601-t0-stock.dts new file mode 100644 index 000000000..4dbbd1367 --- /dev/null +++ b/target/linux/mediatek/dts/mt7986a-zyxel-ex5601-t0-stock.dts @@ -0,0 +1,119 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* + * Copyright (C) 2021 MediaTek Inc. + * Author: Sam.Shih + */ + +/dts-v1/; +#include "mt7986a.dtsi" +#include "mt7986a-zyxel-ex5601-t0-common.dtsi" +#include +#include + +/ { + model = "Zyxel EX5601-T0"; + compatible = "zyxel,ex5601-t0", "mediatek,mt7986a-rfb-snand"; + + memory@40000000 { + device_type = "memory"; + reg = <0x40000000 0x20000000>; + }; +}; + +&spi_nand { + mediatek,nmbm; + mediatek,bmt-max-ratio = <1>; + mediatek,bmt-max-reserved-blocks = <64>; +}; + +&nand_partitions { + + partition@0 { + label = "BL2"; + reg = <0x00000 0x0100000>; + read-only; + }; + + partition@100000 { + label = "u-boot-env"; + reg = <0x0100000 0x0080000>; + }; + + factory: partition@180000 { + label = "Factory"; + reg = <0x180000 0x0200000>; + read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + eeprom_factory: eeprom@0 { + #size-cells = <1>; + reg = <0x0 0x1000>; + }; + + macaddr_factory_0004: macaddr@0004 { + compatible = "mac-base"; + reg = <0x0004 0x6>; + #nvmem-cell-cells = <1>; + }; + + macaddr_factory_0024: macaddr@0024 { + compatible = "mac-base"; + reg = <0x0024 0x6>; + #nvmem-cell-cells = <1>; + }; + + macaddr_factory_002a: macaddr@002a { + compatible = "mac-base"; + reg = <0x002a 0x6>; + #nvmem-cell-cells = <1>; + }; + }; + }; + + partition@380000 { + label = "FIP"; + reg = <0x380000 0x01C0000>; + read-only; + }; + + partition@540000 { + label = "zloader"; + reg = <0x540000 0x0040000>; + read-only; + }; + + partition@580000 { + label = "ubi"; + reg = <0x580000 0x4000000>; + }; + + partition@4580000 { + label = "ubi2"; + reg = <0x4580000 0x4000000>; + read-only; + }; + + partition@8580000 { + label = "zyubi"; + reg = <0x8580000 0x15A80000>; + }; +}; + +&gmac0 { + nvmem-cells = <&macaddr_factory_002a 0>; + nvmem-cell-names = "mac-address"; +}; + +&gmac1 { + nvmem-cells = <&macaddr_factory_0024 0>; + nvmem-cell-names = "mac-address"; +}; + +&wifi { + nvmem-cells = <&eeprom_factory>; + nvmem-cell-names = "eeprom"; +}; diff --git a/target/linux/mediatek/dts/mt7986a-zyxel-ex5601-t0-ubootmod.dts b/target/linux/mediatek/dts/mt7986a-zyxel-ex5601-t0-ubootmod.dts new file mode 100644 index 000000000..62ce50ed2 --- /dev/null +++ b/target/linux/mediatek/dts/mt7986a-zyxel-ex5601-t0-ubootmod.dts @@ -0,0 +1,101 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* + * Copyright (C) 2021 MediaTek Inc. + * Author: Sam.Shih + */ + +/dts-v1/; +#include "mt7986a.dtsi" +#include "mt7986a-zyxel-ex5601-t0-common.dtsi" +#include +#include + +/ { + model = "Zyxel EX5601-T0 ubootmod"; + compatible = "zyxel,ex5601-t0-ubootmod", "mediatek,mt7986a"; + memory@40000000 { + device_type = "memory"; + reg = <0x40000000 0x20000000>; + }; +}; + +&nand_partitions { + partition@0 { + label = "bl2"; + reg = <0x0 0x100000>; + read-only; + }; + + partition@100000 { + label = "u-boot-env"; + reg = <0x0100000 0x0080000>; + read-only; + }; + + factory: partition@180000 { + label = "Factory"; + reg = <0x180000 0x0200000>; + read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + eeprom_factory: eeprom@0 { + #size-cells = <1>; + reg = <0x0 0x1000>; + }; + + macaddr_factory_0004: macaddr@0004 { + compatible = "mac-base"; + reg = <0x0004 0x6>; + #nvmem-cell-cells = <1>; + }; + + macaddr_factory_0024: macaddr@0024 { + compatible = "mac-base"; + reg = <0x0024 0x6>; + #nvmem-cell-cells = <1>; + }; + + macaddr_factory_002a: macaddr@002a { + compatible = "mac-base"; + reg = <0x002a 0x6>; + #nvmem-cell-cells = <1>; + }; + }; + }; + + partition@380000 { + label = "fip"; + reg = <0x380000 0x0200000>; + read-only; + }; + + partition@540000 { + label = "zloader"; + reg = <0x540000 0x0040000>; + read-only; + }; + + partition@580000 { + label = "ubi"; + reg = <0x580000 0x1da80000>; + }; +}; + +&gmac0 { + nvmem-cells = <&macaddr_factory_002a 0>; + nvmem-cell-names = "mac-address"; +}; + +&gmac1 { + nvmem-cells = <&macaddr_factory_0024 0>; + nvmem-cell-names = "mac-address"; +}; + +&wifi { + nvmem-cells = <&eeprom_factory>; + nvmem-cell-names = "eeprom"; +}; diff --git a/target/linux/mediatek/dts/mt7986a-zyxel-ex5700-telenor.dts b/target/linux/mediatek/dts/mt7986a-zyxel-ex5700-telenor.dts new file mode 100644 index 000000000..29961e528 --- /dev/null +++ b/target/linux/mediatek/dts/mt7986a-zyxel-ex5700-telenor.dts @@ -0,0 +1,375 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) + +/dts-v1/; +#include +#include +#include + +#include "mt7986a.dtsi" + +/ { + model = "ZyXEL EX5700 (Telenor)"; + compatible = "zyxel,ex5700-telenor", "mediatek,mt7986a"; + + aliases { + serial0 = &uart0; + ethernet0 = &gmac0; + led-boot = &led_status_green; + led-failsafe = &led_status_green; + led-running = &led_status_green; + led-upgrade = &led_status_amber; + }; + + chosen { + stdout-path = "serial0:115200n8"; + + // Stock U-Boot crashes unless /chosen/bootargs exists + bootargs = "earlycon=uart8250,mmio32,0x11002000 console=ttyS0,115200n8"; + }; + + memory { + reg = <0 0x40000000 0 0x40000000>; + }; + + reg_3p3v: regulator-3p3v { + compatible = "regulator-fixed"; + regulator-name = "fixed-3.3V"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + regulator-always-on; + }; + + reg_5v: regulator-5v { + compatible = "regulator-fixed"; + regulator-name = "fixed-5V"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-boot-on; + regulator-always-on; + }; + + + keys { + compatible = "gpio-keys"; + poll-interval = <20>; + + reset-button { + label = "reset"; + gpios = <&pio 9 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + + wps-button { + label = "wps"; + gpios = <&pio 10 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + leds { + compatible = "gpio-leds"; + + red1 { + label = "red:net"; + gpios = <&pio 23 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + green1 { + label = "green:net"; + gpios = <&pio 25 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + amber1 { + label = "amber:net"; + gpios = <&pio 29 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + white2 { + function = LED_FUNCTION_STATUS; + color = ; + gpios = <&pio 16 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + red2 { + function = LED_FUNCTION_STATUS; + color = ; + gpios = <&pio 17 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + led_status_green: green2 { + function = LED_FUNCTION_STATUS; + color = ; + gpios = <&pio 31 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + led_status_amber: amber2 { + function = LED_FUNCTION_STATUS; + color = ; + gpios = <&pio 18 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + }; + +}; + +ð { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <ð_pins>; + + gmac0: mac@0 { + compatible = "mediatek,eth-mac"; + reg = <0>; + phy-mode = "2500base-x"; + + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; + }; + + mac@1 { + compatible = "mediatek,eth-mac"; + reg = <1>; + label = "wan"; + phy-mode = "2500base-x"; + phy-handle = <&phy6>; + }; + + mdio: mdio-bus { + #address-cells = <1>; + #size-cells = <0>; + }; +}; + +&mdio { + reset-gpios = <&pio 6 GPIO_ACTIVE_LOW>; + reset-delay-us = <50000>; + reset-post-delay-us = <20000>; + + phy5: phy@5 { + compatible = "ethernet-phy-ieee802.3-c45"; + reg = <5>; + }; + + phy6: phy@6 { + compatible = "ethernet-phy-ieee802.3-c45"; + reg = <6>; + }; + + switch: switch@1f { + compatible = "mediatek,mt7531"; + reg = <31>; + reset-gpios = <&pio 5 GPIO_ACTIVE_HIGH>; + interrupt-controller; + #interrupt-cells = <1>; + interrupt-parent = <&pio>; + interrupts = <66 IRQ_TYPE_LEVEL_HIGH>; + }; +}; + +&switch { + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + label = "lan3"; + }; + + port@1 { + reg = <1>; + label = "lan2"; + }; + + port@2 { + reg = <2>; + label = "lan1"; + }; + + port@5 { + reg = <5>; + label = "lan4"; + phy-mode = "2500base-x"; + phy-handle = <&phy5>; + }; + + port@6 { + reg = <6>; + ethernet = <&gmac0>; + phy-mode = "2500base-x"; + + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; + }; + }; +}; + +&crypto { + status = "okay"; +}; + +&pcie { + pinctrl-names = "default"; + pinctrl-0 = <&pcie_pins>; + status = "okay"; + + pcie@0,0 { + reg = <0x0000 0 0 0 0>; + + wifi@0,0 { + compatible = "mediatek,mt76"; + reg = <0x0000 0 0 0 0>; + mediatek,mtd-eeprom = <&factory 0xa0000>; + }; + }; +}; + +&pcie_phy { + status = "okay"; +}; + +&watchdog { + status = "okay"; +}; + +&wifi { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&wf_5g_pins>; + + mediatek,mtd-eeprom = <&factory 0x0>; +}; + +&pio { + eth_pins: eth-pins { + mux { + function = "eth"; + groups = "switch_int", "mdc_mdio"; + }; + }; + + pcie_pins: pcie-pins { + mux { + function = "pcie"; + groups = "pcie_pereset"; // "pcie_clk" and "pcie_wake" is unused? + }; + }; + + spi_flash_pins: spi-flash-pins-33-to-38 { + mux { + function = "spi"; + groups = "spi0", "spi0_wp_hold"; + }; + conf-pu { + pins = "SPI2_CS", "SPI2_HOLD", "SPI2_WP"; + drive-strength = <8>; + mediatek,pull-up-adv = <0>; /* bias-disable */ + }; + conf-pd { + pins = "SPI2_CLK", "SPI2_MOSI", "SPI2_MISO"; + drive-strength = <8>; + mediatek,pull-down-adv = <0>; /* bias-disable */ + }; + }; + + wf_5g_pins: wf_5g-pins { + mux { + function = "wifi"; + groups = "wf_5g"; + }; + conf { + pins = "WF1_HB1", "WF1_HB2", "WF1_HB3", "WF1_HB4", + "WF1_HB0", "WF1_HB5", "WF1_HB6", "WF1_HB7", + "WF1_HB8", "WF1_TOP_CLK", "WF1_TOP_DATA"; + drive-strength = <4>; + }; + }; + +}; + +&spi0 { + pinctrl-names = "default"; + pinctrl-0 = <&spi_flash_pins>; + cs-gpios = <0>, <0>; + status = "okay"; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <20000000>; + }; + + flash@1 { + compatible = "spi-nand"; + reg = <1>; + + mediatek,nmbm; + mediatek,bmt-max-ratio = <1>; + mediatek,bmt-max-reserved-blocks = <64>; + + spi-max-frequency = <20000000>; + spi-tx-bus-width = <4>; + spi-rx-bus-width = <4>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "BL2"; + reg = <0x000000 0x100000>; + read-only; + }; + partition@100000 { + label = "u-boot-env"; + reg = <0x100000 0x80000>; + }; + factory: partition@180000 { + label = "Factory"; + reg = <0x180000 0x200000>; + read-only; + }; + partition@380000 { + label = "FIP"; + reg = <0x380000 0x200000>; + read-only; + }; + partition@580000 { + label = "ubi"; + reg = <0x580000 0x1da80000>; + }; + }; + }; +}; + +&ssusb { + vusb33-supply = <®_3p3v>; + vbus-supply = <®_5v>; + status = "okay"; +}; + +&trng { + status = "okay"; +}; + +&uart0 { + status = "okay"; +}; + +&usb_phy { + status = "okay"; +}; diff --git a/target/linux/mediatek/dts/mt7986b-mercusys-mr90x-v1.dts b/target/linux/mediatek/dts/mt7986b-mercusys-mr90x-v1.dts new file mode 100644 index 000000000..f0a995820 --- /dev/null +++ b/target/linux/mediatek/dts/mt7986b-mercusys-mr90x-v1.dts @@ -0,0 +1,286 @@ +// SPDX-License-Identifier: (GL-2.0 OR MIT) + +/dts-v1/; +#include +#include +#include + +#include "mt7986b.dtsi" + +/ { + compatible = "mercusys,mr90x-v1", "mediatek,mt7986b"; + model = "MERCUSYS MR90X v1"; + + aliases { + serial0 = &uart0; + + led-boot = &led_status_green; + led-failsafe = &led_status_green; + led-running = &led_status_green; + led-upgrade = &led_status_green; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + memory { + reg = <0 0x40000000 0 0x20000000>; + }; + + keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + gpios = <&pio 10 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + leds { + compatible = "gpio-leds"; + + led-0 { + color = ; + function = LED_FUNCTION_LAN; + function-enumerator = <2>; + gpios = <&pio 7 GPIO_ACTIVE_LOW>; + }; + + led-1 { + color = ; + function = LED_FUNCTION_LAN; + function-enumerator = <1>; + gpios = <&pio 9 GPIO_ACTIVE_LOW>; + }; + + led-2 { + color = ; + function = LED_FUNCTION_LAN; + function-enumerator = <0>; + gpios = <&pio 12 GPIO_ACTIVE_LOW>; + }; + + led-3 { + color = ; + function = LED_FUNCTION_WAN; + gpios = <&pio 13 GPIO_ACTIVE_LOW>; + }; + + led-4 { + color = ; + function = LED_FUNCTION_STATUS; + gpios = <&pio 16 GPIO_ACTIVE_HIGH>; + panic-indicator; + }; + + led_status_green: led-5 { + color = ; + function = LED_FUNCTION_STATUS; + gpios = <&pio 17 GPIO_ACTIVE_HIGH>; + }; + }; +}; + +&crypto { + status = "okay"; +}; + +ð { + status = "okay"; + + gmac0: mac@0 { + compatible = "mediatek,eth-mac"; + reg = <0>; + phy-mode = "2500base-x"; + + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; + }; + + gmac1: mac@1 { + compatible = "mediatek,eth-mac"; + reg = <1>; + phy-handle = <&phy6>; + phy-mode = "2500base-x"; + }; + + mdio: mdio-bus { + #address-cells = <1>; + #size-cells = <0>; + }; +}; + +&mdio { + #address-cells = <1>; + #size-cells = <0>; + + reset-gpios = <&pio 6 GPIO_ACTIVE_LOW>; + reset-delay-us = <1500000>; + reset-post-delay-us = <1000000>; + + /* WAN/LAN 2.5Gbps phy + MaxLinear GPY211C0VC (SLNW8) */ + phy6: phy@6 { + compatible = "ethernet-phy-ieee802.3-c45"; + reg = <6>; + }; + + switch: switch@1f { + compatible = "mediatek,mt7531"; + reg = <31>; + reset-gpios = <&pio 5 GPIO_ACTIVE_HIGH>; + }; +}; + +&switch { + ports { + #address-cells = <1>; + #size-cells = <0>; + + /* WAN/LAN 1Gbps port */ + port@0 { + reg = <0>; + label = "lan0"; + }; + + /* LAN1 port */ + port@1 { + reg = <1>; + label = "lan1"; + }; + + /* LAN2 port */ + port@2 { + reg = <2>; + label = "lan2"; + }; + + port@6 { + reg = <6>; + ethernet = <&gmac0>; + phy-mode = "2500base-x"; + + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; + }; + }; +}; + +&pio { + spi_flash_pins: spi-flash-pins-33-to-38 { + mux { + function = "spi"; + groups = "spi0", "spi0_wp_hold"; + }; + conf-pu { + pins = "SPI2_CS", "SPI2_HOLD", "SPI2_WP"; + drive-strength = <8>; + mediatek,pull-up-adv = <0>; /* bias-disable */ + }; + conf-pd { + pins = "SPI2_CLK", "SPI2_MOSI", "SPI2_MISO"; + drive-strength = <8>; + mediatek,pull-down-adv = <0>; /* bias-disable */ + }; + }; + + wf_2g_5g_pins: wf_2g_5g-pins { + mux { + function = "wifi"; + groups = "wf_2g", "wf_5g"; + }; + conf { + pins = "WF0_HB1", "WF0_HB2", "WF0_HB3", "WF0_HB4", + "WF0_HB0", "WF0_HB0_B", "WF0_HB5", "WF0_HB6", + "WF0_HB7", "WF0_HB8", "WF0_HB9", "WF0_HB10", + "WF0_TOP_CLK", "WF0_TOP_DATA", "WF1_HB1", + "WF1_HB2", "WF1_HB3", "WF1_HB4", "WF1_HB0", + "WF1_HB5", "WF1_HB6", "WF1_HB7", "WF1_HB8", + "WF1_TOP_CLK", "WF1_TOP_DATA"; + drive-strength = <4>; + }; + }; +}; + +&spi0 { + pinctrl-names = "default"; + pinctrl-0 = <&spi_flash_pins>; + status = "okay"; + + spi_nand_flash: flash@0 { + compatible = "spi-nand"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0>; + + spi-max-frequency = <20000000>; + spi-tx-bus-width = <4>; + spi-rx-bus-width = <4>; + + partitions: partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "boot"; + reg = <0x0 0x200000>; + read-only; + }; + + partition@200000 { + label = "u-boot-env"; + reg = <0x200000 0x100000>; + }; + + partition@300000 { + label = "ubi0"; + reg = <0x300000 0x3200000>; + }; + + partition@3500000 { + label = "ubi1"; + reg = <0x3500000 0x3200000>; + read-only; + }; + + partition@6700000 { + label = "userconfig"; + reg = <0x6700000 0x800000>; + read-only; + }; + + partition@6f00000 { + label = "tp_data"; + reg = <0x6f00000 0x400000>; + read-only; + }; + }; + }; +}; + +&trng { + status = "okay"; +}; + +&uart0 { + status = "okay"; +}; + +&watchdog { + status = "okay"; +}; + +&wifi { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&wf_2g_5g_pins>; +}; diff --git a/target/linux/mediatek/dts/mt7986b-netgear-wax220.dts b/target/linux/mediatek/dts/mt7986b-netgear-wax220.dts new file mode 100644 index 000000000..6e51d8847 --- /dev/null +++ b/target/linux/mediatek/dts/mt7986b-netgear-wax220.dts @@ -0,0 +1,293 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) + +/dts-v1/; +#include +#include +#include + +#include "mt7986b.dtsi" + +/ { + model = "Netgear WAX220"; + compatible = "netgear,wax220", "mediatek,mt7986b"; + + aliases { + serial0 = &uart0; + led-boot = &led_power_blue; + led-failsafe = &led_power_amber; + led-running = &led_power_green; + led-upgrade = &led_power_amber; + }; + + gpio-keys { + compatible = "gpio-keys"; + + reset { + gpios = <&pio 9 GPIO_ACTIVE_LOW>; + linux,code = ; + label = "reset"; + }; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + leds { + compatible = "gpio-leds"; + + wlan5g_green { + gpios = <&pio 12 GPIO_ACTIVE_LOW>; + label = "green:wlan5g"; + }; + + led_power_amber: power_amber { + gpios = <&pio 15 GPIO_ACTIVE_LOW>; + function = LED_FUNCTION_POWER; + color = ; + }; + + wlan2g_green { + gpios = <&pio 19 GPIO_ACTIVE_HIGH>; + label = "green:wlan2g"; + }; + + led_power_blue: power_blue { + gpios = <&pio 7 GPIO_ACTIVE_HIGH>; + function = LED_FUNCTION_POWER; + color = ; + }; + + led_power_green: power_green { + gpios = <&pio 10 GPIO_ACTIVE_LOW>; + function = LED_FUNCTION_POWER; + color = ; + }; + + wlan2g_blue { + gpios = <&pio 1 GPIO_ACTIVE_LOW>; + label = "blue:wlan2g"; + }; + + lan_green { + gpios = <&pio 22 GPIO_ACTIVE_HIGH>; + function = LED_FUNCTION_LAN; + color = ; + }; + + lan_amber { + gpios = <&pio 13 GPIO_ACTIVE_LOW>; + function = LED_FUNCTION_LAN; + color = ; + }; + + wlan5g_blue { + gpios = <&pio 2 GPIO_ACTIVE_LOW>; + label = "blue:wlan5g"; + }; + }; +}; + +&crypto { + status = "okay"; +}; + +ð { + status = "okay"; + + gmac1: mac@1 { + compatible = "mediatek,eth-mac"; + reg = <1>; + phy-handle = <&phy6>; + phy-mode = "2500base-x"; + }; + + mdio: mdio-bus { + #address-cells = <1>; + #size-cells = <0>; + }; +}; + +&mdio { + phy6: ethernet-phy@6 { + reg = <6>; + reset-assert-us = <100000>; + reset-deassert-us = <100000>; + reset-gpios = <&pio 6 GPIO_ACTIVE_LOW>; + interrupt-controller; + #interrupt-cells = <1>; + interrupt-parent = <&pio>; + interrupts = <46 IRQ_TYPE_LEVEL_HIGH>; + }; +}; + +&pio { + spi_flash_pins: spi-flash-pins-33-to-38 { + mux { + function = "spi"; + groups = "spi0", "spi0_wp_hold"; + }; + conf-pu { + pins = "SPI2_CS", "SPI2_HOLD", "SPI2_WP"; + drive-strength = <8>; + mediatek,pull-up-adv = <0>; /* bias-disable */ + }; + conf-pd { + pins = "SPI2_CLK", "SPI2_MOSI", "SPI2_MISO"; + drive-strength = <8>; + mediatek,pull-down-adv = <0>; /* bias-disable */ + }; + }; + + wf_2g_5g_pins: wf_2g_5g-pins { + mux { + function = "wifi"; + groups = "wf_2g", "wf_5g"; + }; + conf { + pins = "WF0_HB1", "WF0_HB2", "WF0_HB3", "WF0_HB4", + "WF0_HB0", "WF0_HB0_B", "WF0_HB5", "WF0_HB6", + "WF0_HB7", "WF0_HB8", "WF0_HB9", "WF0_HB10", + "WF0_TOP_CLK", "WF0_TOP_DATA", "WF1_HB1", + "WF1_HB2", "WF1_HB3", "WF1_HB4", "WF1_HB0", + "WF1_HB5", "WF1_HB6", "WF1_HB7", "WF1_HB8", + "WF1_TOP_CLK", "WF1_TOP_DATA"; + drive-strength = <4>; + }; + }; + + wf_dbdc_pins: wf-dbdc-pins { + mux { + function = "wifi"; + groups = "wf_dbdc"; + }; + conf { + pins = "WF0_HB1", "WF0_HB2", "WF0_HB3", "WF0_HB4", + "WF0_HB0", "WF0_HB0_B", "WF0_HB5", "WF0_HB6", + "WF0_HB7", "WF0_HB8", "WF0_HB9", "WF0_HB10", + "WF0_TOP_CLK", "WF0_TOP_DATA"; + drive-strength = <4>; + }; + }; +}; + +&spi0 { + pinctrl-names = "default"; + pinctrl-0 = <&spi_flash_pins>; + status = "okay"; + + spi_nand_flash: flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "spi-nand"; + reg = <0>; + + spi-max-frequency = <20000000>; + spi-tx-bus-width = <4>; + spi-rx-bus-width = <4>; + + mediatek,nmbm; + mediatek,bmt-max-ratio = <1>; + mediatek,bmt-max-reserved-blocks = <256>; + mediatek,bmt-remap-range = <0x0 0x580000>; + + partitions: partitions { + #address-cells = <0x1>; + #size-cells = <0x1>; + compatible = "fixed-partitions"; + + partition@0 { + label = "BL2"; + read-only; + reg = <0x0 0x100000>; + }; + + partition@100000 { + label = "u-boot-env"; + reg = <0x100000 0x80000>; + }; + + factory: partition@180000 { + label = "Factory"; + reg = <0x180000 0x200000>; + }; + + partition@380000 { + label = "FIP"; + reg = <0x380000 0x200000>; + }; + + partition@580000 { + label = "ubi"; + reg = <0x580000 0x5140000>; + }; + + partition@56c0000 { + label = "RAE"; + reg = <0x56c0000 0x400000>; + }; + + partition@5ac0000 { + label = "POT"; + reg = <0x5ac0000 0x100000>; + }; + + partition@5bc0000 { + label = "Language"; + reg = <0x5bc0000 0x400000>; + }; + + partition@5fc0000 { + label = "Traffic"; + reg = <0x5fc0000 0x200000>; + }; + + partition@61c0000 { + label = "Cert"; + reg = <0x61c0000 0x100000>; + }; + + partition@62c0000 { + label = "NTGRcryptK"; + reg = <0x62c0000 0x100000>; + }; + + partition@63c0000 { + label = "NTGRcryptD"; + reg = <0x63c0000 0x500000>; + }; + + partition@68c0000 { + label = "LOG"; + reg = <0x68c0000 0x100000>; + }; + + partition@69c0000 { + label = "User_data"; + reg = <0x69c0000 0x640000>; + }; + }; + }; + +}; + +&trng { + status = "okay"; +}; + +&uart0 { + status = "okay"; +}; + +&watchdog { + status = "okay"; +}; + +&wifi { + status = "okay"; + pinctrl-names = "default", "dbdc"; + pinctrl-0 = <&wf_2g_5g_pins>; + pinctrl-1 = <&wf_dbdc_pins>; + + mediatek,mtd-eeprom = <&factory 0x0>; +}; diff --git a/target/linux/mediatek/dts/mt7986b-tplink-re6000xd.dts b/target/linux/mediatek/dts/mt7986b-tplink-re6000xd.dts new file mode 100644 index 000000000..44a5e21e7 --- /dev/null +++ b/target/linux/mediatek/dts/mt7986b-tplink-re6000xd.dts @@ -0,0 +1,298 @@ +// SPDX-License-Identifier: (GL-2.0 OR MIT) + +/dts-v1/; +#include +#include +#include + +#include "mt7986b.dtsi" + +/ { + compatible = "tplink,re6000xd", "mediatek,mt7986b"; + model = "TP-Link RE6000XD"; + + aliases { + serial0 = &uart0; + + led-boot = &led_status_blue; + led-failsafe = &led_status_blue; + led-running = &led_status_blue; + led-upgrade = &led_status_blue; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + memory { + reg = <0 0x40000000 0 0x20000000>; + }; + + keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + gpios = <&pio 7 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + + wps { + label = "wps"; + gpios = <&pio 14 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + leds { + compatible = "gpio-leds"; + + led_status_blue: power { + gpios = <&pio 15 GPIO_ACTIVE_LOW>; + color = ; + function = LED_FUNCTION_STATUS; + panic-indicator; + function-enumerator = <0>; + }; + wlan_2g { + gpios = <&pio 11 GPIO_ACTIVE_HIGH>; + color = ; + function = LED_FUNCTION_WLAN_2GHZ; + linux,default-trigger = "phy0tpt"; + }; + wlan_5g { + gpios = <&pio 12 GPIO_ACTIVE_LOW>; + color = ; + function = LED_FUNCTION_WLAN_5GHZ; + linux,default-trigger = "phy1tpt"; + }; + signal_blue { + gpios = <&pio 9 GPIO_ACTIVE_LOW>; + color = ; + function = LED_FUNCTION_STATUS; + function-enumerator = <1>; + }; + signal_red { + gpios = <&pio 19 GPIO_ACTIVE_LOW>; + color = ; + function = LED_FUNCTION_STATUS; + function-enumerator = <2>; + }; + lan1 { + gpios = <&pio 16 GPIO_ACTIVE_HIGH>; + color = ; + function = LED_FUNCTION_LAN; + function-enumerator = <0>; + }; + lan2 { + gpios = <&pio 10 GPIO_ACTIVE_LOW>; + color = ; + function = LED_FUNCTION_LAN; + function-enumerator = <1>; + }; + lan3 { + gpios = <&pio 18 GPIO_ACTIVE_LOW>; + color = ; + function = LED_FUNCTION_LAN; + function-enumerator = <2>; + }; + }; +}; + +&crypto { + status = "okay"; +}; + +ð { + status = "okay"; + + gmac0: mac@0 { + compatible = "mediatek,eth-mac"; + reg = <0>; + phy-mode = "2500base-x"; + + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; + }; + + gmac1: mac@1 { + compatible = "mediatek,eth-mac"; + reg = <1>; + phy-handle = <&phy6>; + phy-mode = "2500base-x"; + }; + + mdio: mdio-bus { + #address-cells = <1>; + #size-cells = <0>; + }; +}; + +&mdio { + #address-cells = <1>; + #size-cells = <0>; + + reset-gpios = <&pio 6 GPIO_ACTIVE_LOW>; + reset-delay-us = <1500000>; + reset-post-delay-us = <1000000>; + + /* LAN3 2.5Gbps phy + MaxLinear GPY211C0VC (SLNW8) */ + phy6: phy@6 { + compatible = "ethernet-phy-ieee802.3-c45"; + reg = <6>; + }; + + switch: switch@1f { + compatible = "mediatek,mt7531"; + reg = <31>; + reset-gpios = <&pio 5 GPIO_ACTIVE_HIGH>; + }; +}; + +&switch { + ports { + #address-cells = <1>; + #size-cells = <0>; + /* reorder LAN1 and LAN2 port to match the port order of the case + LAN1 - LAN2 - LAN3 (top to bottom of the case, no silkscreen) + */ + /* LAN2 port */ + port@1 { + reg = <1>; + label = "lan2"; + }; + + /* LAN1 port */ + port@2 { + reg = <2>; + label = "lan1"; + }; + + port@6 { + reg = <6>; + ethernet = <&gmac0>; + phy-mode = "2500base-x"; + + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; + }; + }; +}; + +&pio { + spi_flash_pins: spi-flash-pins-33-to-38 { + mux { + function = "spi"; + groups = "spi0", "spi0_wp_hold"; + }; + conf-pu { + pins = "SPI2_CS", "SPI2_HOLD", "SPI2_WP"; + drive-strength = <8>; + mediatek,pull-up-adv = <0>; /* bias-disable */ + }; + conf-pd { + pins = "SPI2_CLK", "SPI2_MOSI", "SPI2_MISO"; + drive-strength = <8>; + mediatek,pull-down-adv = <0>; /* bias-disable */ + }; + }; + + wf_2g_5g_pins: wf_2g_5g-pins { + mux { + function = "wifi"; + groups = "wf_2g", "wf_5g"; + }; + conf { + pins = "WF0_HB1", "WF0_HB2", "WF0_HB3", "WF0_HB4", + "WF0_HB0", "WF0_HB0_B", "WF0_HB5", "WF0_HB6", + "WF0_HB7", "WF0_HB8", "WF0_HB9", "WF0_HB10", + "WF0_TOP_CLK", "WF0_TOP_DATA", "WF1_HB1", + "WF1_HB2", "WF1_HB3", "WF1_HB4", "WF1_HB0", + "WF1_HB5", "WF1_HB6", "WF1_HB7", "WF1_HB8", + "WF1_TOP_CLK", "WF1_TOP_DATA"; + drive-strength = <4>; + }; + }; +}; + +&spi0 { + pinctrl-names = "default"; + pinctrl-0 = <&spi_flash_pins>; + status = "okay"; + + spi_nand_flash: flash@0 { + compatible = "spi-nand"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0>; + + spi-max-frequency = <20000000>; + spi-tx-bus-width = <4>; + spi-rx-bus-width = <4>; + + partitions: partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "boot"; + reg = <0x0 0x200000>; + read-only; + }; + + partition@200000 { + label = "u-boot-env"; + reg = <0x200000 0x100000>; + }; + + partition@300000 { + label = "ubi0"; + reg = <0x300000 0x3200000>; + }; + + partition@3500000 { + label = "ubi1"; + reg = <0x3500000 0x3200000>; + read-only; + }; + + partition@6700000 { + label = "userconfig"; + reg = <0x6700000 0x800000>; + read-only; + }; + + partition@6f00000 { + label = "tp_data"; + reg = <0x6f00000 0x400000>; + read-only; + }; + }; + }; +}; + +&trng { + status = "okay"; +}; + +&uart0 { + status = "okay"; +}; + +&watchdog { + status = "okay"; +}; + +&wifi { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&wf_2g_5g_pins>; +}; diff --git a/target/linux/mediatek/dts/mt7988a-smartrg-SDG-8733.dts b/target/linux/mediatek/dts/mt7988a-smartrg-SDG-8733.dts new file mode 100644 index 000000000..c8c58271a --- /dev/null +++ b/target/linux/mediatek/dts/mt7988a-smartrg-SDG-8733.dts @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* + * Copyright (C) 2023 SmartRG Inc. + * Author: Chad Monroe + */ + +#include "mt7988a-smartrg-mt-stuart.dtsi" + +/ { + model = "SmartRG SDG-8733"; + compatible = "smartrg,sdg-8733", "mediatek,mt7988a"; +}; + +&gmac1 { + phy-connection-type = "usxgmii"; + phy = <&phy0>; +}; diff --git a/target/linux/mediatek/dts/mt7988a-smartrg-SDG-8734.dts b/target/linux/mediatek/dts/mt7988a-smartrg-SDG-8734.dts new file mode 100644 index 000000000..6eeb4993f --- /dev/null +++ b/target/linux/mediatek/dts/mt7988a-smartrg-SDG-8734.dts @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* + * Copyright (C) 2023 SmartRG Inc. + * Author: Chad Monroe + */ + +#include "mt7988a-smartrg-mt-stuart.dtsi" + +/ { + model = "SmartRG SDG-8734"; + compatible = "smartrg,sdg-8734", "mediatek,mt7988a"; + + gpio-leds { + compatible = "gpio-leds"; + + sfp_green { + color = ; + function = "sfp"; + gpios = <&pio 69 GPIO_ACTIVE_HIGH>; + }; + + sfp_red { + color = ; + function = "sfp"; + gpios = <&pio 70 GPIO_ACTIVE_HIGH>; + }; + }; + + i2c_sfp1: i2c-gpio-0 { + pinctrl-names = "default"; + pinctrl-0 = <&sfp_i2c_pins>; + + compatible = "i2c-gpio"; + sda-gpios = <&pio 27 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + scl-gpios = <&pio 22 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + i2c-gpio,delay-us = <2>; + #address-cells = <1>; + #size-cells = <0>; + }; + + sfp1: sfp1 { + compatible = "sff,sfp"; + i2c-bus = <&i2c_sfp1>; + los-gpios = <&pio 32 GPIO_ACTIVE_HIGH>; + mod-def0-gpios = <&pio 35 GPIO_ACTIVE_LOW>; + rate-select0-gpios = <&pio 34 GPIO_ACTIVE_HIGH>; + rate-select1-gpios = <&pio 33 GPIO_ACTIVE_HIGH>; + tx-disable-gpios = <&pio 36 GPIO_ACTIVE_HIGH>; + tx-fault-gpios = <&pio 37 GPIO_ACTIVE_HIGH>; + maximum-power-milliwatt = <4000>; + }; +}; + +&gmac1 { + sfp = <&sfp1>; + managed = "in-band-status"; +}; diff --git a/target/linux/mediatek/dts/mt7988a-smartrg-mt-stuart.dtsi b/target/linux/mediatek/dts/mt7988a-smartrg-mt-stuart.dtsi new file mode 100644 index 000000000..fac267abf --- /dev/null +++ b/target/linux/mediatek/dts/mt7988a-smartrg-mt-stuart.dtsi @@ -0,0 +1,682 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* + * Copyright (C) 2023 SmartRG Inc. + * Author: Chad Monroe + */ + +/dts-v1/; +#include "mt7988a.dtsi" +#include +#include +#include +#include +#include + +/ { + aliases { + serial0 = &uart0; + ethernet0 = &gmac0; + ethernet1 = &gmac1; + led-boot = &led_sys_green; + led-failsafe = &led_sys_blue; + led-running = &led_sys_white; + led-upgrade = &led_sys_red; + }; + + chosen { + stdout-path = &uart0; + bootargs = "console=ttyS0,115200n1 loglevel=8 pci=pcie_bus_perf root=PARTLABEL=rootfs"; + }; + + memory { + reg = <0x0 0x40000000 0x0 0x40000000>; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + + /delete-node/ramoops@42ff0000; + + bootdata@45000000 { + no-map; + reg = <0x0 0x45000000 0x0 0x00001000>; + }; + + ramoops_reserved: ramoops@45001000 { + no-map; + compatible = "ramoops"; + reg = <0x0 0x45001000 0x0 0x00140000>; + ftrace-size = <0x20000>; + record-size = <0x20000>; + console-size = <0x20000>; + pmsg-size = <0x80000>; + }; + }; + + reg_1p8v: regulator-1p8v { + compatible = "regulator-fixed"; + regulator-name = "fixed-1.8V"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-boot-on; + regulator-always-on; + }; + + reg_3p3v: regulator-3p3v { + compatible = "regulator-fixed"; + regulator-name = "fixed-3.3V"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + regulator-always-on; + }; + + gpio-keys { + compatible = "gpio-keys"; + pinctrl-names = "default"; + pinctrl-0 = <&button_pins>; + + factory { + label = "reset"; + linux,code = ; + gpios = <&pio 13 GPIO_ACTIVE_LOW>; + }; + + wps { + label = "sync"; + linux,code = ; + gpios = <&pio 14 GPIO_ACTIVE_LOW>; + }; + }; + + gpio-export { + compatible = "gpio-export"; + + bluetooth_reset { + gpio-export,name = "bt_reset"; + gpio-export,direction_may_change; + gpios = <&pio 20 GPIO_ACTIVE_HIGH>; + }; + + bluetooth_txrx_ctl { + gpio-export,name = "bt_txrx_ctl"; + gpio-export,direction_may_change; + gpios = <&pio 74 GPIO_ACTIVE_HIGH>; + }; + + gps_enable { + gpio-export,name = "gps_enable"; + gpio-export,output = <1>; + gpios = <&pio 9 GPIO_ACTIVE_LOW>; + }; + + slic_interrupt { + gpio-export,name = "slic_interrupt"; + gpio-export,direction_may_change; + gpios = <&pio 54 GPIO_ACTIVE_HIGH>; + }; + + slic_reset { + gpio-export,name = "slic_reset"; + gpio-export,output = <0>; + gpios = <&pio 72 GPIO_ACTIVE_HIGH>; + }; + + usb_enable { + gpio-export,name = "usb_enable"; + gpio-export,output = <1>; + gpios = <&pio 63 GPIO_ACTIVE_HIGH>; + }; + }; +}; + +&cpu0 { + proc-supply = <&rt5190_buck3>; +}; + +&cpu1 { + proc-supply = <&rt5190_buck3>; +}; + +&cpu2 { + proc-supply = <&rt5190_buck3>; +}; + +&cpu3 { + proc-supply = <&rt5190_buck3>; +}; + +&cci { + proc-supply = <&rt5190_buck3>; +}; + +&cpu_thermal { + /delete-node/cooling-maps; + /delete-node/trips; + + trips { + cpu_trip_crit: crit { + temperature = <125000>; + hysteresis = <2000>; + type = "critical"; + }; + + cpu_trip_hot: hot { + temperature = <120000>; + hysteresis = <2000>; + type = "hot"; + }; + + cpu_trip_active_high: active-high { + temperature = <110000>; + hysteresis = <2000>; + type = "active"; + }; + + cpu_trip_active_med: active-med { + temperature = <80000>; + hysteresis = <2000>; + type = "active"; + }; + + cpu_trip_active_low: active-low { + temperature = <60000>; + hysteresis = <2000>; + type = "active"; + }; + + cpu_trip_active_silent: active-silent { + temperature = <40000>; + hysteresis = <2000>; + type = "active"; + }; + }; + + cooling-maps { + cpu-active-high { + /* active: set fan to cooling level 3 */ + cooling-device = <&fan 3 3>; + trip = <&cpu_trip_active_high>; + }; + + cpu-active-med { + /* active: set fan to cooling level 2 */ + cooling-device = <&fan 2 2>; + trip = <&cpu_trip_active_med>; + }; + + cpu-active-low { + /* active: set fan to cooling level 1 */ + cooling-device = <&fan 1 1>; + trip = <&cpu_trip_active_low>; + }; + + cpu-active-silent { + /* active: set fan to cooling level 0 */ + cooling-device = <&fan 0 0>; + trip = <&cpu_trip_active_silent>; + }; + }; +}; + +ð { + pinctrl-0 = <&mdio0_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + +&fan { + pwms = <&pwm 0 40000 0>; + + /** + * set fan speed + * + * 0 = off + * 61 = 24% duty cycle + * 77 = 30% duty cycle + * 102 = 40% duty cycle + * 128 - 50% duty cycle + * 255 = 100% duty cycle + */ + cooling-levels = <61 77 102 128>; + + interrupt-parent = <&pio>; + interrupts = <21 IRQ_TYPE_EDGE_FALLING>; + pulses-per-revolution = <2>; + + status = "okay"; +}; + +&gmac0 { + status = "okay"; +}; + +&gmac1 { + label = "wan"; + status = "okay"; + phy-mode = "usxgmii"; +}; + +&gmac2 { + label = "lan1"; + status = "okay"; + phy-mode = "usxgmii"; + phy-connection-type = "usxgmii"; + phy = <&phy8>; +}; + +&gsw_phy0 { + status = "disabled"; +}; + +&gsw_phy1 { + pinctrl-names = "gbe-led"; + pinctrl-0 = <&gbe1_led0_pins>, <&gbe1_led1_pins>; +}; + +&gsw_phy1_led0 { + status = "okay"; + color = ; +}; + +&gsw_phy1_led1 { + status = "okay"; + color = ; +}; + +&gsw_phy2 { + pinctrl-names = "gbe-led"; + pinctrl-0 = <&gbe2_led0_pins>, <&gbe2_led1_pins>; +}; + +&gsw_phy2_led0 { + status = "okay"; + color = ; +}; + +&gsw_phy2_led1 { + status = "okay"; + color = ; +}; + +&gsw_phy3 { + pinctrl-names = "gbe-led"; + pinctrl-0 = <&gbe3_led0_pins>, <&gbe3_led1_pins>; +}; + +&gsw_phy3_led0 { + status = "okay"; + color = ; +}; + +&gsw_phy3_led1 { + status = "okay"; + color = ; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins>; + status = "okay"; + + rt5190a_64: rt5190a@64 { + compatible = "richtek,rt5190a"; + reg = <0x64>; + /*interrupts-extended = <&gpio26 0 IRQ_TYPE_LEVEL_LOW>;*/ + vin2-supply = <&rt5190_buck1>; + vin3-supply = <&rt5190_buck1>; + vin4-supply = <&rt5190_buck1>; + + regulators { + rt5190_buck1: buck1 { + regulator-name = "rt5190a-buck1"; + regulator-min-microvolt = <5090000>; + regulator-max-microvolt = <5090000>; + regulator-allowed-modes = + ; + regulator-boot-on; + regulator-always-on; + }; + buck2 { + regulator-name = "vcore"; + regulator-min-microvolt = <600000>; + regulator-max-microvolt = <1400000>; + regulator-boot-on; + regulator-always-on; + }; + rt5190_buck3: buck3 { + regulator-name = "vproc"; + regulator-min-microvolt = <600000>; + regulator-max-microvolt = <1400000>; + regulator-boot-on; + }; + buck4 { + regulator-name = "rt5190a-buck4"; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <850000>; + regulator-allowed-modes = + ; + regulator-boot-on; + regulator-always-on; + }; + ldo { + regulator-name = "rt5190a-ldo"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-boot-on; + regulator-always-on; + }; + }; + }; +}; + +&i2c1 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_pins>; + status = "okay"; + + system-leds { + compatible = "srg,sysled"; + reg = <0x30>; + + led_sys_red: system_red { + label = "red"; + reg = <1>; + }; + + led_sys_green: system_green { + label = "green"; + reg = <2>; + }; + + led_sys_blue: system_blue { + label = "blue"; + reg = <3>; + }; + + led_sys_white: system_white { + label = "white"; + reg = <4>; + }; + }; +}; + +&mdio_bus { + phy0: ethernet-phy@0 { + /* AQR113C */ + compatible = "ethernet-phy-ieee802.3-c45"; + reg = <0>; + + reset-gpios = <&pio 62 GPIO_ACTIVE_LOW>; + reset-assert-us = <100000>; + reset-deassert-us = <1000000>; + + leds { + #address-cells = <1>; + #size-cells = <0>; + + led@0 { + reg = <0>; + function = LED_FUNCTION_WAN; + color = ; + }; + + led@1 { + reg = <1>; + function = LED_FUNCTION_WAN; + color = ; + }; + + led@2 { + reg = <2>; + function = LED_FUNCTION_WAN; + color = ; + active-low; + }; + }; + }; + + phy8: ethernet-phy@8 { + /* AQR113C */ + compatible = "ethernet-phy-ieee802.3-c45"; + reg = <8>; + + reset-gpios = <&pio 71 GPIO_ACTIVE_LOW>; + reset-assert-us = <100000>; + reset-deassert-us = <1000000>; + + leds { + #address-cells = <1>; + #size-cells = <0>; + + led@0 { + reg = <0>; + function = LED_FUNCTION_LAN; + color = ; + }; + + led@1 { + reg = <1>; + function = LED_FUNCTION_LAN; + color = ; + }; + + led@2 { + reg = <2>; + function = LED_FUNCTION_LAN; + color = ; + active-low; + }; + }; + }; +}; + +&mmc0 { + pinctrl-names = "default", "state_uhs"; + pinctrl-0 = <&mmc0_pins_emmc_51>; + pinctrl-1 = <&mmc0_pins_emmc_51>; + bus-width = <8>; + max-frequency = <200000000>; + cap-mmc-highspeed; + mmc-hs200-1_8v; + vmmc-supply = <®_3p3v>; + vqmmc-supply = <®_1p8v>; + non-removable; + no-sd; + no-sdio; + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + + card@0 { + #address-cells = <0>; + #size-cells = <0>; + compatible = "mmc-card"; + reg = <0>; + + block { + compatible = "block-device"; + + partitions { + block-partition-factory { + partname = "factory"; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + eeprom_factory_0: eeprom@0 { + reg = <0x0 0x1e00>; + }; + }; + }; + }; + }; + }; +}; + +&pcie0 { + pinctrl-names = "default"; + pinctrl-0 = <&pcie0_1_pins>; + reset-gpios = <&pio 7 GPIO_ACTIVE_LOW>; + status = "okay"; + + pcie@0,0 { + reg = <0x0000 0 0 0 0>; + + mt7996@0,0 { + reg = <0x0000 0 0 0 0>; + nvmem-cells = <&eeprom_factory_0>; + nvmem-cell-names = "eeprom"; + ieee80211-freq-limit = <2400000 2500000>, <5170000 5835000>, <5945000 7125000>; + }; + }; +}; + +&pcie1 { + pinctrl-names = "default"; + pinctrl-0 = <&pcie1_pins>; + status = "okay"; +}; + +&pcie2 { + status = "disabled"; +}; + +&pcie3 { + status = "disabled"; +}; + +&pio { + button_pins: button-pins { + pins = "GPIO_RESET", "GPIO_WPS"; + mediatek,pull-down-adv = <0>; /* bias-disable */ + }; + + pcie0_1_pins: pcie0-pins-g1 { + mux { + function = "pcie"; + groups = "pcie_2l_0_pereset", "pcie_clk_req_n0_0"; + }; + }; + + pwm_pins: pwm-pins { + mux { + function = "pwm"; + groups = "pwm0", "pwm1"; + }; + }; + + sfp_i2c_pins: sfp-i2c-pins { + conf-scl { + pins = "LED_A"; + drive-strength = <8>; + mediatek,pull-up-adv = <1>; + }; + conf-sda { + pins = "LED_E"; + drive-strength = <8>; + mediatek,pull-up-adv = <0>; + }; + }; + + uart1_pins: uart1-pins { + mux { + function = "uart"; + groups = "uart1_2"; + }; + }; + + uart2_pins: uart2-pins { + mux { + function = "uart"; + groups = "uart2"; + }; + }; +}; + +&pwm { + pinctrl-names = "default"; + pinctrl-0 = <&pwm_pins>; + status = "okay"; +}; + +&spi0 { + pinctrl-names = "default"; + pinctrl-0 = <&spi0_flash_pins>; + status = "disabled"; + + spi_nand: spi_nand@0 { + compatible = "spi-nand"; + reg = <0>; + spi-max-frequency = <52000000>; + spi-tx-buswidth = <4>; + spi-rx-buswidth = <4>; + }; + +}; + +&ssusb0 { + status = "okay"; +}; + +&ssusb1 { + status = "okay"; +}; + +&switch { + status = "okay"; + + ports { + port@0 { + status = "disabled"; + }; + + port@1 { + label = "lan2"; + }; + + port@2 { + label = "lan3"; + }; + + port@3 { + label = "lan4"; + }; + }; +}; + +&tphy { + status = "okay"; +}; + +&uart0 { + status = "okay"; +}; + +&uart1 { + pinctrl-names = "default"; + pinctrl-0 = <&uart1_pins>; + status = "okay"; + + /* Airoha AG3352 GPS */ +}; + +&uart2 { + pinctrl-names = "default"; + pinctrl-0 = <&uart2_pins>; + status = "okay"; + + /* DA14531MOD Bluetooth */ +}; + +&watchdog { + status = "okay"; +}; + +&xphy { + status = "okay"; +}; diff --git a/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7981.dtsi b/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7981.dtsi deleted file mode 100644 index 2b7131dd1..000000000 --- a/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7981.dtsi +++ /dev/null @@ -1,801 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0 OR MIT) -/* - * Copyright (c) 2020 MediaTek Inc. - * Author: Sam.Shih - * Author: Jianhui Zhao - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/ { - compatible = "mediatek,mt7981"; - interrupt-parent = <&gic>; - #address-cells = <2>; - #size-cells = <2>; - - cpus { - #address-cells = <1>; - #size-cells = <0>; - - cpu@0 { - device_type = "cpu"; - compatible = "arm,cortex-a53"; - enable-method = "psci"; - reg = <0x0>; - }; - - cpu@1 { - device_type = "cpu"; - compatible = "arm,cortex-a53"; - enable-method = "psci"; - reg = <0x1>; - }; - }; - - pwm: pwm@10048000 { - compatible = "mediatek,mt7981-pwm"; - reg = <0 0x10048000 0 0x1000>; - #pwm-cells = <2>; - clocks = <&infracfg CLK_INFRA_PWM_STA>, - <&infracfg CLK_INFRA_PWM_HCK>, - <&infracfg CLK_INFRA_PWM1_CK>, - <&infracfg CLK_INFRA_PWM2_CK>, - <&infracfg CLK_INFRA_PWM3_CK>; - clock-names = "top", "main", "pwm1", "pwm2", "pwm3"; - }; - - fan: pwm-fan { - compatible = "pwm-fan"; - /* cooling level (0, 1, 2, 3) : (0% duty, 50% duty, 75% duty, 100% duty) */ - cooling-levels = <0 128 192 255>; - #cooling-cells = <2>; - status = "disabled"; - }; - - thermal-zones { - cpu_thermal: cpu-thermal { - polling-delay-passive = <1000>; - polling-delay = <1000>; - thermal-sensors = <&thermal 0>; - trips { - cpu_trip_crit: crit { - temperature = <125000>; - hysteresis = <2000>; - type = "critical"; - }; - - cpu_trip_hot: hot { - temperature = <120000>; - hysteresis = <2000>; - type = "hot"; - }; - - cpu_trip_active_high: active-high { - temperature = <115000>; - hysteresis = <2000>; - type = "active"; - }; - - cpu_trip_active_med: active-med { - temperature = <85000>; - hysteresis = <2000>; - type = "active"; - }; - - cpu_trip_active_low: active-low { - temperature = <60000>; - hysteresis = <2000>; - type = "active"; - }; - }; - - cooling-maps { - cpu-active-high { - /* active: set fan to cooling level 3 */ - cooling-device = <&fan 3 3>; - trip = <&cpu_trip_active_high>; - }; - - cpu-active-med { - /* active: set fan to cooling level 2 */ - cooling-device = <&fan 2 2>; - trip = <&cpu_trip_active_med>; - }; - - cpu-active-low { - /* passive: set fan to cooling level 1 */ - cooling-device = <&fan 1 1>; - trip = <&cpu_trip_active_low>; - }; - }; - }; - }; - - thermal: thermal@1100c800 { - #thermal-sensor-cells = <1>; - compatible = "mediatek,mt7981-thermal", "mediatek,mt7986-thermal"; - reg = <0 0x1100c800 0 0x800>; - interrupts = ; - clocks = <&infracfg CLK_INFRA_THERM_CK>, - <&infracfg CLK_INFRA_ADC_26M_CK>; - clock-names = "therm", "auxadc"; - mediatek,auxadc = <&auxadc>; - mediatek,apmixedsys = <&apmixedsys>; - nvmem-cells = <&thermal_calibration>; - nvmem-cell-names = "calibration-data"; - }; - - auxadc: adc@1100d000 { - compatible = "mediatek,mt7981-auxadc", - "mediatek,mt7986-auxadc", - "mediatek,mt7622-auxadc"; - reg = <0 0x1100d000 0 0x1000>; - clocks = <&infracfg CLK_INFRA_ADC_26M_CK>, - <&infracfg CLK_INFRA_ADC_FRC_CK>; - clock-names = "main", "32k"; - #io-channel-cells = <1>; - }; - - wdma: wdma@15104800 { - compatible = "mediatek,wed-wdma"; - reg = <0 0x15104800 0 0x400>, - <0 0x15104c00 0 0x400>; - }; - - ap2woccif: ap2woccif@151a5000 { - compatible = "mediatek,ap2woccif"; - reg = <0 0x151a5000 0 0x1000>, - <0 0x151ad000 0 0x1000>; - interrupt-parent = <&gic>; - interrupts = , - ; - }; - - reserved-memory { - #address-cells = <2>; - #size-cells = <2>; - ranges; - - /* 192 KiB reserved for ARM Trusted Firmware (BL31) */ - secmon_reserved: secmon@43000000 { - reg = <0 0x43000000 0 0x30000>; - no-map; - }; - - wmcpu_emi: wmcpu-reserved@47c80000 { - reg = <0 0x47c80000 0 0x100000>; - no-map; - }; - - wo_emi0: wo-emi@47d80000 { - reg = <0 0x47d80000 0 0x40000>; - no-map; - }; - - wo_data: wo-data@47dc0000 { - reg = <0 0x47dc0000 0 0x240000>; - no-map; - }; - }; - - psci { - compatible = "arm,psci-0.2"; - method = "smc"; - }; - - trng { - compatible = "mediatek,mt7981-rng"; - }; - - clk40m: oscillator@0 { - compatible = "fixed-clock"; - #clock-cells = <0>; - clock-frequency = <40000000>; - clock-output-names = "clkxtal"; - }; - - infracfg: infracfg@10001000 { - compatible = "mediatek,mt7981-infracfg", "syscon"; - reg = <0 0x10001000 0 0x1000>; - #clock-cells = <1>; - }; - - topckgen: topckgen@1001B000 { - compatible = "mediatek,mt7981-topckgen", "syscon"; - reg = <0 0x1001B000 0 0x1000>; - #clock-cells = <1>; - }; - - apmixedsys: apmixedsys@1001E000 { - compatible = "mediatek,mt7981-apmixedsys", "mediatek,mt7986-apmixedsys", "syscon"; - reg = <0 0x1001E000 0 0x1000>; - #clock-cells = <1>; - }; - - timer { - compatible = "arm,armv8-timer"; - interrupt-parent = <&gic>; - clock-frequency = <13000000>; - interrupts = , - , - , - ; - - }; - - watchdog: watchdog@1001c000 { - compatible = "mediatek,mt7986-wdt", - "mediatek,mt6589-wdt"; - reg = <0 0x1001c000 0 0x1000>; - interrupts = ; - #reset-cells = <1>; - status = "disabled"; - }; - - gic: interrupt-controller@c000000 { - compatible = "arm,gic-v3"; - #interrupt-cells = <3>; - interrupt-parent = <&gic>; - interrupt-controller; - reg = <0 0x0c000000 0 0x40000>, /* GICD */ - <0 0x0c080000 0 0x200000>; /* GICR */ - - interrupts = ; - }; - - uart0: serial@11002000 { - compatible = "mediatek,mt6577-uart"; - reg = <0 0x11002000 0 0x400>; - interrupts = ; - clocks = <&infracfg CLK_INFRA_UART0_SEL>, - <&infracfg CLK_INFRA_UART0_CK>; - clock-names = "baud", "bus"; - assigned-clocks = <&topckgen CLK_TOP_UART_SEL>, - <&infracfg CLK_INFRA_UART0_SEL>; - assigned-clock-parents = <&topckgen CLK_TOP_CB_CKSQ_40M>, - <&topckgen CLK_TOP_UART_SEL>; - pinctrl-0 = <&uart0_pins>; - pinctrl-names = "default"; - status = "disabled"; - }; - - uart1: serial@11003000 { - compatible = "mediatek,mt6577-uart"; - reg = <0 0x11003000 0 0x400>; - interrupts = ; - clocks = <&infracfg CLK_INFRA_UART1_SEL>, - <&infracfg CLK_INFRA_UART1_CK>; - clock-names = "baud", "bus"; - assigned-clocks = <&topckgen CLK_TOP_UART_SEL>, - <&infracfg CLK_INFRA_UART1_SEL>; - assigned-clock-parents = <&topckgen CLK_TOP_CB_CKSQ_40M>, - <&topckgen CLK_TOP_UART_SEL>; - status = "disabled"; - }; - - uart2: serial@11004000 { - compatible = "mediatek,mt6577-uart"; - reg = <0 0x11004000 0 0x400>; - interrupts = ; - clocks = <&infracfg CLK_INFRA_UART2_SEL>, - <&infracfg CLK_INFRA_UART2_CK>; - clock-names = "baud", "bus"; - assigned-clocks = <&topckgen CLK_TOP_UART_SEL>, - <&infracfg CLK_INFRA_UART2_SEL>; - assigned-clock-parents = <&topckgen CLK_TOP_CB_CKSQ_40M>, - <&topckgen CLK_TOP_UART_SEL>; - status = "disabled"; - }; - - i2c0: i2c@11007000 { - compatible = "mediatek,mt7981-i2c"; - reg = <0 0x11007000 0 0x1000>, - <0 0x10217080 0 0x80>; - interrupts = ; - clock-div = <1>; - clocks = <&infracfg CLK_INFRA_I2C0_CK>, - <&infracfg CLK_INFRA_AP_DMA_CK>, - <&infracfg CLK_INFRA_I2C_MCK_CK>, - <&infracfg CLK_INFRA_I2C_PCK_CK>; - clock-names = "main", "dma", "arb", "pmic"; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; - }; - - pcie: pcie@11280000 { - compatible = "mediatek,mt7981-pcie", - "mediatek,mt7986-pcie"; - device_type = "pci"; - reg = <0 0x11280000 0 0x4000>; - reg-names = "pcie-mac"; - #address-cells = <3>; - #size-cells = <2>; - interrupts = ; - bus-range = <0x00 0xff>; - ranges = <0x82000000 0 0x20000000 - 0x0 0x20000000 0 0x10000000>; - status = "disabled"; - - clocks = <&infracfg CLK_INFRA_IPCIE_CK>, - <&infracfg CLK_INFRA_IPCIE_PIPE_CK>, - <&infracfg CLK_INFRA_IPCIER_CK>, - <&infracfg CLK_INFRA_IPCIEB_CK>; - - phys = <&u3port0 PHY_TYPE_PCIE>; - phy-names = "pcie-phy"; - - #interrupt-cells = <1>; - interrupt-map-mask = <0 0 0 7>; - interrupt-map = <0 0 0 1 &pcie_intc 0>, - <0 0 0 2 &pcie_intc 1>, - <0 0 0 3 &pcie_intc 2>, - <0 0 0 4 &pcie_intc 3>; - pcie_intc: interrupt-controller { - interrupt-controller; - #address-cells = <0>; - #interrupt-cells = <1>; - }; - }; - - crypto: crypto@10320000 { - compatible = "inside-secure,safexcel-eip97"; - reg = <0 0x10320000 0 0x40000>; - interrupts = , - , - , - ; - interrupt-names = "ring0", "ring1", "ring2", "ring3"; - clocks = <&topckgen CLK_TOP_EIP97B>; - clock-names = "top_eip97_ck"; - assigned-clocks = <&topckgen CLK_TOP_EIP97B_SEL>; - assigned-clock-parents = <&topckgen CLK_TOP_CB_NET1_D5>; - }; - - pio: pinctrl@11d00000 { - compatible = "mediatek,mt7981-pinctrl"; - reg = <0 0x11d00000 0 0x1000>, - <0 0x11c00000 0 0x1000>, - <0 0x11c10000 0 0x1000>, - <0 0x11d20000 0 0x1000>, - <0 0x11e00000 0 0x1000>, - <0 0x11e20000 0 0x1000>, - <0 0x11f00000 0 0x1000>, - <0 0x11f10000 0 0x1000>, - <0 0x1000b000 0 0x1000>; - reg-names = "gpio", "iocfg_rt", "iocfg_rm", - "iocfg_rb", "iocfg_lb", "iocfg_bl", - "iocfg_tm", "iocfg_tl", "eint"; - gpio-controller; - #gpio-cells = <2>; - gpio-ranges = <&pio 0 0 56>; - interrupt-controller; - interrupts = ; - interrupt-parent = <&gic>; - #interrupt-cells = <2>; - - mdio_pins: mdc-mdio-pins { - mux { - function = "eth"; - groups = "smi_mdc_mdio"; - }; - }; - - uart0_pins: uart0-pins { - mux { - function = "uart"; - groups = "uart0"; - }; - }; - - wifi_dbdc_pins: wifi-dbdc-pins { - mux { - function = "eth"; - groups = "wf0_mode1"; - }; - conf { - pins = "WF_HB1", "WF_HB2", "WF_HB3", "WF_HB4", - "WF_HB0", "WF_HB0_B", "WF_HB5", "WF_HB6", - "WF_HB7", "WF_HB8", "WF_HB9", "WF_HB10", - "WF_TOP_CLK", "WF_TOP_DATA", "WF_XO_REQ", - "WF_CBA_RESETB", "WF_DIG_RESETB"; - drive-strength = <4>; - }; - }; - - gbe_led0_pins: gbe-led0-pins { - mux { - function = "led"; - groups = "gbe_led0"; - }; - }; - - gbe_led1_pins: gbe-led1-pins { - mux { - function = "led"; - groups = "gbe_led1"; - }; - }; - }; - - ethsys: syscon@15000000 { - #address-cells = <1>; - #size-cells = <1>; - compatible = "mediatek,mt7981-ethsys", - "mediatek,mt7986-ethsys", - "syscon"; - reg = <0 0x15000000 0 0x1000>; - #clock-cells = <1>; - #reset-cells = <1>; - }; - - wed: wed@15010000 { - compatible = "mediatek,mt7981-wed", - "mediatek,mt7986-wed", - "syscon"; - reg = <0 0x15010000 0 0x1000>; - interrupt-parent = <&gic>; - interrupts = ; - memory-region = <&wo_emi0>, <&wo_data>; - memory-region-names = "wo-emi", "wo-data"; - mediatek,wo-ccif = <&wo_ccif0>; - mediatek,wo-ilm = <&wo_ilm0>; - mediatek,wo-dlm = <&wo_dlm0>; - mediatek,wo-cpuboot = <&wo_cpuboot>; - }; - - eth: ethernet@15100000 { - compatible = "mediatek,mt7981-eth"; - reg = <0 0x15100000 0 0x80000>; - interrupts = , - , - , - ; - clocks = <ðsys CLK_ETH_FE_EN>, - <ðsys CLK_ETH_GP2_EN>, - <ðsys CLK_ETH_GP1_EN>, - <ðsys CLK_ETH_WOCPU0_EN>, - <&sgmiisys0 CLK_SGM0_TX_EN>, - <&sgmiisys0 CLK_SGM0_RX_EN>, - <&sgmiisys0 CLK_SGM0_CK0_EN>, - <&sgmiisys0 CLK_SGM0_CDR_CK0_EN>, - <&sgmiisys1 CLK_SGM1_TX_EN>, - <&sgmiisys1 CLK_SGM1_RX_EN>, - <&sgmiisys1 CLK_SGM1_CK1_EN>, - <&sgmiisys1 CLK_SGM1_CDR_CK1_EN>, - <&topckgen CLK_TOP_SGM_REG>, - <&topckgen CLK_TOP_NETSYS_SEL>, - <&topckgen CLK_TOP_NETSYS_500M_SEL>; - clock-names = "fe", "gp2", "gp1", "wocpu0", - "sgmii_tx250m", "sgmii_rx250m", - "sgmii_cdr_ref", "sgmii_cdr_fb", - "sgmii2_tx250m", "sgmii2_rx250m", - "sgmii2_cdr_ref", "sgmii2_cdr_fb", - "sgmii_ck", "netsys0", "netsys1"; - assigned-clocks = <&topckgen CLK_TOP_NETSYS_2X_SEL>, - <&topckgen CLK_TOP_SGM_325M_SEL>; - assigned-clock-parents = <&topckgen CLK_TOP_CB_NET2_800M>, - <&topckgen CLK_TOP_CB_SGM_325M>; - mediatek,ethsys = <ðsys>; - mediatek,sgmiisys = <&sgmiisys0>, <&sgmiisys1>; - mediatek,infracfg = <&topmisc>; - mediatek,wed = <&wed>; - #reset-cells = <1>; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; - - mdio_bus: mdio-bus { - #address-cells = <1>; - #size-cells = <0>; - - int_gbe_phy: ethernet-phy@0 { - reg = <0>; - compatible = "ethernet-phy-ieee802.3-c22"; - phy-mode = "gmii"; - phy-is-integrated; - nvmem-cells = <&phy_calibration>; - nvmem-cell-names = "phy-cal-data"; - - leds { - #address-cells = <1>; - #size-cells = <0>; - - int_gbe_phy_led0: int-gbe-phy-led0@0 { - reg = <0>; - function = LED_FUNCTION_LAN; - status = "disabled"; - }; - - int_gbe_phy_led1: int-gbe-phy-led1@1 { - reg = <1>; - function = LED_FUNCTION_LAN; - status = "disabled"; - }; - }; - }; - }; - }; - - wo_dlm0: syscon@151e8000 { - compatible = "mediatek,mt7986-wo-dlm", "syscon"; - reg = <0 0x151e8000 0 0x2000>; - }; - - wo_ilm0: syscon@151e0000 { - compatible = "mediatek,mt7986-wo-ilm", "syscon"; - reg = <0 0x151e0000 0 0x8000>; - }; - - wo_cpuboot: syscon@15194000 { - compatible = "mediatek,mt7986-wo-cpuboot", "syscon"; - reg = <0 0x15194000 0 0x1000>; - }; - - wo_ccif0: syscon@151a5000 { - compatible = "mediatek,mt7986-wo-ccif", "syscon"; - reg = <0 0x151a5000 0 0x1000>; - interrupt-parent = <&gic>; - interrupts = ; - }; - - sgmiisys0: syscon@10060000 { - compatible = "mediatek,mt7981-sgmiisys_0", "mediatek,mt7986-sgmiisys_0", "syscon"; - reg = <0 0x10060000 0 0x1000>; - mediatek,pnswap; - #clock-cells = <1>; - }; - - sgmiisys1: syscon@10070000 { - compatible = "mediatek,mt7981-sgmiisys_1", "mediatek,mt7986-sgmiisys_1", "syscon"; - reg = <0 0x10070000 0 0x1000>; - #clock-cells = <1>; - }; - - topmisc: topmisc@11d10000 { - compatible = "mediatek,mt7981-topmisc", "syscon"; - reg = <0 0x11d10000 0 0x10000>; - #clock-cells = <1>; - }; - - snand: snfi@11005000 { - compatible = "mediatek,mt7986-snand"; - reg = <0 0x11005000 0 0x1000>, <0 0x11006000 0 0x1000>; - reg-names = "nfi", "ecc"; - interrupts = ; - clocks = <&infracfg CLK_INFRA_SPINFI1_CK>, - <&infracfg CLK_INFRA_NFI1_CK>, - <&infracfg CLK_INFRA_NFI_HCK_CK>; - clock-names = "pad_clk", "nfi_clk", "nfi_hclk"; - assigned-clocks = <&topckgen CLK_TOP_SPINFI_SEL>, - <&topckgen CLK_TOP_NFI1X_SEL>; - assigned-clock-parents = <&topckgen CLK_TOP_CB_M_D8>, - <&topckgen CLK_TOP_CB_M_D8>; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; - }; - - mmc0: mmc@11230000 { - compatible = "mediatek,mt7986-mmc", - "mediatek,mt7981-mmc"; - reg = <0 0x11230000 0 0x1000>, <0 0x11c20000 0 0x1000>; - interrupts = ; - clocks = <&infracfg CLK_INFRA_MSDC_CK>, - <&infracfg CLK_INFRA_MSDC_HCK_CK>, - <&infracfg CLK_INFRA_MSDC_66M_CK>, - <&infracfg CLK_INFRA_MSDC_133M_CK>; - assigned-clocks = <&topckgen CLK_TOP_EMMC_208M_SEL>, - <&topckgen CLK_TOP_EMMC_400M_SEL>; - assigned-clock-parents = <&topckgen CLK_TOP_CB_M_D2>, - <&topckgen CLK_TOP_CB_NET2_D2>; - clock-names = "source", "hclk", "axi_cg", "ahb_cg"; - status = "disabled"; - }; - - wed_pcie: wed_pcie@10003000 { - compatible = "mediatek,wed_pcie"; - reg = <0 0x10003000 0 0x10>; - }; - - spi0: spi@1100a000 { - compatible = "mediatek,mt7986-spi-ipm", "mediatek,spi-ipm"; - #address-cells = <1>; - #size-cells = <0>; - reg = <0 0x1100a000 0 0x100>; - interrupts = ; - clocks = <&topckgen CLK_TOP_CB_M_D2>, - <&topckgen CLK_TOP_SPI_SEL>, - <&infracfg CLK_INFRA_SPI0_CK>, - <&infracfg CLK_INFRA_SPI0_HCK_CK>; - - clock-names = "parent-clk", "sel-clk", "spi-clk", "hclk"; - status = "disabled"; - }; - - spi1: spi@1100b000 { - compatible = "mediatek,mt7986-spi-ipm", "mediatek,spi-ipm"; - #address-cells = <1>; - #size-cells = <0>; - reg = <0 0x1100b000 0 0x100>; - interrupts = ; - clocks = <&topckgen CLK_TOP_CB_M_D2>, - <&topckgen CLK_TOP_SPIM_MST_SEL>, - <&infracfg CLK_INFRA_SPI1_CK>, - <&infracfg CLK_INFRA_SPI1_HCK_CK>; - clock-names = "parent-clk", "sel-clk", "spi-clk", "hclk"; - status = "disabled"; - }; - - spi2: spi@11009000 { - compatible = "mediatek,mt7986-spi-ipm", "mediatek,spi-ipm"; - #address-cells = <1>; - #size-cells = <0>; - reg = <0 0x11009000 0 0x100>; - interrupts = ; - clocks = <&topckgen CLK_TOP_CB_M_D2>, - <&topckgen CLK_TOP_SPI_SEL>, - <&infracfg CLK_INFRA_SPI2_CK>, - <&infracfg CLK_INFRA_SPI2_HCK_CK>; - clock-names = "parent-clk", "sel-clk", "spi-clk", "hclk"; - status = "disabled"; - }; - - consys: consys@10000000 { - compatible = "mediatek,mt7981-consys"; - reg = <0 0x10000000 0 0x8600000>; - memory-region = <&wmcpu_emi>; - }; - - xhci: usb@11200000 { - compatible = "mediatek,mt7986-xhci", - "mediatek,mtk-xhci"; - reg = <0 0x11200000 0 0x2e00>, - <0 0x11203e00 0 0x0100>; - reg-names = "mac", "ippc"; - interrupts = ; - clocks = <&infracfg CLK_INFRA_IUSB_SYS_CK>, - <&infracfg CLK_INFRA_IUSB_CK>, - <&infracfg CLK_INFRA_IUSB_133_CK>, - <&infracfg CLK_INFRA_IUSB_66M_CK>, - <&topckgen CLK_TOP_U2U3_XHCI_SEL>; - clock-names = "sys_ck", - "ref_ck", - "mcu_ck", - "dma_ck", - "xhci_ck"; - phys = <&u2port0 PHY_TYPE_USB2>, - <&u3port0 PHY_TYPE_USB3>; - vusb33-supply = <®_3p3v>; - status = "disabled"; - }; - - usb_phy: usb-phy@11e10000 { - compatible = "mediatek,mt7981", - "mediatek,generic-tphy-v2"; - #address-cells = <1>; - #size-cells = <1>; - ranges = <0 0 0x11e10000 0x1700>; - status = "disabled"; - - u2port0: usb-phy@0 { - reg = <0x0 0x700>; - clocks = <&topckgen CLK_TOP_USB_FRMCNT_SEL>; - clock-names = "ref"; - #phy-cells = <1>; - }; - - u3port0: usb-phy@700 { - reg = <0x700 0x900>; - clocks = <&topckgen CLK_TOP_USB3_PHY_SEL>; - clock-names = "ref"; - #phy-cells = <1>; - mediatek,syscon-type = <&topmisc 0x218 0>; - status = "okay"; - }; - }; - - reg_3p3v: regulator-3p3v { - compatible = "regulator-fixed"; - regulator-name = "fixed-3.3V"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - regulator-boot-on; - regulator-always-on; - }; - - efuse: efuse@11f20000 { - compatible = "mediatek,mt7981-efuse", - "mediatek,efuse"; - reg = <0 0x11f20000 0 0x1000>; - #address-cells = <1>; - #size-cells = <1>; - status = "okay"; - - thermal_calibration: thermal-calib@274 { - reg = <0x274 0xc>; - }; - - phy_calibration: phy-calib@8dc { - reg = <0x8dc 0x10>; - }; - - comb_rx_imp_p0: usb3-rx-imp@8c8 { - reg = <0x8c8 1>; - bits = <0 5>; - }; - - comb_tx_imp_p0: usb3-tx-imp@8c8 { - reg = <0x8c8 2>; - bits = <5 5>; - }; - - comb_intr_p0: usb3-intr@8c9 { - reg = <0x8c9 1>; - bits = <2 6>; - }; - }; - - afe: audio-controller@11210000 { - compatible = "mediatek,mt79xx-audio"; - reg = <0 0x11210000 0 0x9000>; - interrupts = ; - clocks = <&infracfg CLK_INFRA_AUD_BUS_CK>, - <&infracfg CLK_INFRA_AUD_26M_CK>, - <&infracfg CLK_INFRA_AUD_L_CK>, - <&infracfg CLK_INFRA_AUD_AUD_CK>, - <&infracfg CLK_INFRA_AUD_EG2_CK>, - <&topckgen CLK_TOP_AUD_SEL>; - clock-names = "aud_bus_ck", - "aud_26m_ck", - "aud_l_ck", - "aud_aud_ck", - "aud_eg2_ck", - "aud_sel"; - assigned-clocks = <&topckgen CLK_TOP_AUD_SEL>, - <&topckgen CLK_TOP_A1SYS_SEL>, - <&topckgen CLK_TOP_AUD_L_SEL>, - <&topckgen CLK_TOP_A_TUNER_SEL>; - assigned-clock-parents = <&topckgen CLK_TOP_CB_APLL2_196M>, - <&topckgen CLK_TOP_APLL2_D4>, - <&topckgen CLK_TOP_CB_APLL2_196M>, - <&topckgen CLK_TOP_APLL2_D4>; - status = "disabled"; - }; - - ice: ice_debug { - compatible = "mediatek,mt7981-ice_debug", - "mediatek,mt2701-ice_debug"; - clocks = <&infracfg CLK_INFRA_DBG_CK>; - clock-names = "ice_dbg"; - }; - - wifi: wifi@18000000 { - compatible = "mediatek,mt7981-wmac"; - resets = <&watchdog MT7986_TOPRGU_CONSYS_SW_RST>; - reset-names = "consys"; - pinctrl-0 = <&wifi_dbdc_pins>; - pinctrl-names = "dbdc"; - clocks = <&topckgen CLK_TOP_NETSYS_MCU_SEL>, - <&topckgen CLK_TOP_AP2CNN_HOST_SEL>; - clock-names = "mcu", "ap2conn"; - reg = <0 0x18000000 0 0x1000000>, - <0 0x10003000 0 0x1000>, - <0 0x11d10000 0 0x1000>; - interrupts = , - , - , - ; - memory-region = <&wmcpu_emi>; - status = "disabled"; - }; -}; diff --git a/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-emmc.dtso b/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-emmc.dtso deleted file mode 100644 index 779dc6782..000000000 --- a/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-emmc.dtso +++ /dev/null @@ -1,29 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0 OR MIT) -/* - * Copyright (C) 2021 MediaTek Inc. - * Author: Sam.Shih - */ - -/dts-v1/; -/plugin/; - -/ { - compatible = "bananapi,bpi-r3", "mediatek,mt7986a"; - - fragment@0 { - target-path = "/soc/mmc@11230000"; - __overlay__ { - bus-width = <8>; - max-frequency = <200000000>; - cap-mmc-highspeed; - mmc-hs200-1_8v; - mmc-hs400-1_8v; - hs400-ds-delay = <0x14014>; - non-removable; - no-sd; - no-sdio; - status = "okay"; - }; - }; -}; - diff --git a/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-nand.dtso b/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-nand.dtso deleted file mode 100644 index 0846d88f6..000000000 --- a/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-nand.dtso +++ /dev/null @@ -1,55 +0,0 @@ -/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */ -/* - * Authors: Daniel Golle - * Frank Wunderlich - */ - -/dts-v1/; -/plugin/; - -/ { - compatible = "bananapi,bpi-r3", "mediatek,mt7986a"; - - fragment@0 { - target-path = "/soc/spi@1100a000"; - __overlay__ { - #address-cells = <1>; - #size-cells = <0>; - spi_nand: spi_nand@0 { - compatible = "spi-nand"; - reg = <0>; - spi-max-frequency = <10000000>; - spi-tx-bus-width = <4>; - spi-rx-bus-width = <4>; - - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - partition@0 { - label = "bl2"; - reg = <0x0 0x80000>; - read-only; - }; - - partition@80000 { - label = "reserved"; - reg = <0x80000 0x300000>; - }; - - partition@380000 { - label = "fip"; - reg = <0x380000 0x200000>; - read-only; - }; - - partition@580000 { - label = "ubi"; - reg = <0x580000 0x7a80000>; - }; - }; - }; - }; - }; -}; diff --git a/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-nor.dtso b/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-nor.dtso deleted file mode 100644 index e48881be4..000000000 --- a/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-nor.dtso +++ /dev/null @@ -1,63 +0,0 @@ -/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */ -/* - * Authors: Daniel Golle - * Frank Wunderlich - */ - -/dts-v1/; -/plugin/; - -/ { - compatible = "bananapi,bpi-r3", "mediatek,mt7986a"; - - fragment@0 { - target-path = "/soc/spi@1100a000"; - __overlay__ { - #address-cells = <1>; - #size-cells = <0>; - flash@0 { - compatible = "jedec,spi-nor"; - reg = <0>; - spi-max-frequency = <10000000>; - - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - partition@0 { - label = "bl2"; - reg = <0x0 0x40000>; - read-only; - }; - - partition@40000 { - label = "u-boot-env"; - reg = <0x40000 0x40000>; - }; - - partition@80000 { - label = "reserved2"; - reg = <0x80000 0x80000>; - }; - - partition@100000 { - label = "fip"; - reg = <0x100000 0x80000>; - read-only; - }; - - partition@180000 { - label = "recovery"; - reg = <0x180000 0xa80000>; - }; - - partition@c00000 { - label = "fit"; - reg = <0xc00000 0x1400000>; - }; - }; - }; - }; - }; -}; diff --git a/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-sd.dtso b/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-sd.dtso deleted file mode 100644 index f623bce07..000000000 --- a/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-sd.dtso +++ /dev/null @@ -1,23 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0 OR MIT) -/* - * Copyright (C) 2021 MediaTek Inc. - * Author: Sam.Shih - */ - -/dts-v1/; -/plugin/; - -/ { - compatible = "bananapi,bpi-r3", "mediatek,mt7986a"; - - fragment@0 { - target-path = "/soc/mmc@11230000"; - __overlay__ { - bus-width = <4>; - max-frequency = <52000000>; - cap-sd-highspeed; - status = "okay"; - }; - }; -}; - diff --git a/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts b/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts deleted file mode 100644 index 1d3c575b7..000000000 --- a/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts +++ /dev/null @@ -1,501 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0 OR MIT) -/* - * Copyright (C) 2021 MediaTek Inc. - * Authors: Sam.Shih - * Frank Wunderlich - * Daniel Golle - */ - -/dts-v1/; -#include -#include -#include -#include - -#include "mt7986a.dtsi" - -/ { - model = "Bananapi BPI-R3"; - chassis-type = "embedded"; - compatible = "bananapi,bpi-r3", "mediatek,mt7986a"; - - aliases { - serial0 = &uart0; - ethernet0 = &gmac0; - ethernet1 = &gmac1; - }; - - chosen { - stdout-path = "serial0:115200n8"; - }; - - dcin: regulator-12vd { - compatible = "regulator-fixed"; - regulator-name = "12vd"; - regulator-min-microvolt = <12000000>; - regulator-max-microvolt = <12000000>; - regulator-boot-on; - regulator-always-on; - }; - - fan: pwm-fan { - compatible = "pwm-fan"; - #cooling-cells = <2>; - /* cooling level (0, 1, 2) - pwm inverted */ - cooling-levels = <255 96 0>; - pwms = <&pwm 0 10000 0>; - status = "okay"; - }; - - gpio-keys { - compatible = "gpio-keys"; - - reset-key { - label = "reset"; - linux,code = ; - gpios = <&pio 9 GPIO_ACTIVE_LOW>; - }; - - wps-key { - label = "wps"; - linux,code = ; - gpios = <&pio 10 GPIO_ACTIVE_LOW>; - }; - }; - - /* i2c of the left SFP cage (wan) */ - i2c_sfp1: i2c-gpio-0 { - compatible = "i2c-gpio"; - sda-gpios = <&pio 16 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; - scl-gpios = <&pio 17 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; - i2c-gpio,delay-us = <2>; - #address-cells = <1>; - #size-cells = <0>; - }; - - /* i2c of the right SFP cage (lan) */ - i2c_sfp2: i2c-gpio-1 { - compatible = "i2c-gpio"; - sda-gpios = <&pio 18 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; - scl-gpios = <&pio 19 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; - i2c-gpio,delay-us = <2>; - #address-cells = <1>; - #size-cells = <0>; - }; - - leds { - compatible = "gpio-leds"; - - green_led: led-0 { - color = ; - function = LED_FUNCTION_POWER; - gpios = <&pio 69 GPIO_ACTIVE_HIGH>; - default-state = "on"; - }; - - blue_led: led-1 { - color = ; - function = LED_FUNCTION_STATUS; - gpios = <&pio 86 GPIO_ACTIVE_HIGH>; - default-state = "off"; - }; - }; - - reg_1p8v: regulator-1p8v { - compatible = "regulator-fixed"; - regulator-name = "1.8vd"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - regulator-boot-on; - regulator-always-on; - vin-supply = <&dcin>; - }; - - reg_3p3v: regulator-3p3v { - compatible = "regulator-fixed"; - regulator-name = "3.3vd"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - regulator-boot-on; - regulator-always-on; - vin-supply = <&dcin>; - }; - - /* left SFP cage (wan) */ - sfp1: sfp-1 { - compatible = "sff,sfp"; - i2c-bus = <&i2c_sfp1>; - los-gpios = <&pio 46 GPIO_ACTIVE_HIGH>; - mod-def0-gpios = <&pio 49 GPIO_ACTIVE_LOW>; - tx-disable-gpios = <&pio 20 GPIO_ACTIVE_HIGH>; - tx-fault-gpios = <&pio 7 GPIO_ACTIVE_HIGH>; - maximum-power-milliwatt = <3000>; - }; - - /* right SFP cage (lan) */ - sfp2: sfp-2 { - compatible = "sff,sfp"; - i2c-bus = <&i2c_sfp2>; - los-gpios = <&pio 31 GPIO_ACTIVE_HIGH>; - mod-def0-gpios = <&pio 47 GPIO_ACTIVE_LOW>; - tx-disable-gpios = <&pio 15 GPIO_ACTIVE_HIGH>; - tx-fault-gpios = <&pio 48 GPIO_ACTIVE_HIGH>; - maximum-power-milliwatt = <3000>; - }; -}; - -&cpu_thermal { - cooling-maps { - cpu-active-high { - /* active: set fan to cooling level 2 */ - cooling-device = <&fan 2 2>; - trip = <&cpu_trip_active_high>; - }; - - cpu-active-med { - /* active: set fan to cooling level 1 */ - cooling-device = <&fan 1 1>; - trip = <&cpu_trip_active_med>; - }; - - cpu-active-low { - /* active: set fan to cooling level 0 */ - cooling-device = <&fan 0 0>; - trip = <&cpu_trip_active_low>; - }; - }; -}; - -&crypto { - status = "okay"; -}; - -ð { - status = "okay"; - - gmac0: mac@0 { - compatible = "mediatek,eth-mac"; - reg = <0>; - phy-mode = "2500base-x"; - - fixed-link { - speed = <2500>; - full-duplex; - pause; - }; - }; - - gmac1: mac@1 { - compatible = "mediatek,eth-mac"; - reg = <1>; - phy-mode = "2500base-x"; - sfp = <&sfp1>; - managed = "in-band-status"; - }; - - mdio: mdio-bus { - #address-cells = <1>; - #size-cells = <0>; - }; -}; - -&mdio { - switch: switch@31 { - compatible = "mediatek,mt7531"; - reg = <31>; - interrupt-controller; - #interrupt-cells = <1>; - interrupt-parent = <&pio>; - interrupts = <66 IRQ_TYPE_LEVEL_HIGH>; - reset-gpios = <&pio 5 GPIO_ACTIVE_HIGH>; - }; -}; - -&mmc0 { - pinctrl-names = "default", "state_uhs"; - pinctrl-0 = <&mmc0_pins_default>; - pinctrl-1 = <&mmc0_pins_uhs>; - vmmc-supply = <®_3p3v>; - vqmmc-supply = <®_1p8v>; -}; - -&i2c0 { - pinctrl-names = "default"; - pinctrl-0 = <&i2c_pins>; - status = "okay"; -}; - -&pcie { - pinctrl-names = "default"; - pinctrl-0 = <&pcie_pins>; - status = "okay"; -}; - -&pcie_phy { - status = "okay"; -}; - -&pio { - i2c_pins: i2c-pins { - mux { - function = "i2c"; - groups = "i2c"; - }; - }; - - mmc0_pins_default: mmc0-pins { - mux { - function = "emmc"; - groups = "emmc_51"; - }; - conf-cmd-dat { - pins = "EMMC_DATA_0", "EMMC_DATA_1", "EMMC_DATA_2", - "EMMC_DATA_3", "EMMC_DATA_4", "EMMC_DATA_5", - "EMMC_DATA_6", "EMMC_DATA_7", "EMMC_CMD"; - input-enable; - drive-strength = <4>; - bias-pull-up = ; /* pull-up 10K */ - }; - conf-clk { - pins = "EMMC_CK"; - drive-strength = <6>; - bias-pull-down = ; /* pull-down 50K */ - }; - conf-ds { - pins = "EMMC_DSL"; - bias-pull-down = ; /* pull-down 50K */ - }; - conf-rst { - pins = "EMMC_RSTB"; - drive-strength = <4>; - bias-pull-up = ; /* pull-up 10K */ - }; - }; - - mmc0_pins_uhs: mmc0-uhs-pins { - mux { - function = "emmc"; - groups = "emmc_51"; - }; - conf-cmd-dat { - pins = "EMMC_DATA_0", "EMMC_DATA_1", "EMMC_DATA_2", - "EMMC_DATA_3", "EMMC_DATA_4", "EMMC_DATA_5", - "EMMC_DATA_6", "EMMC_DATA_7", "EMMC_CMD"; - input-enable; - drive-strength = <4>; - bias-pull-up = ; /* pull-up 10K */ - }; - conf-clk { - pins = "EMMC_CK"; - drive-strength = <6>; - bias-pull-down = ; /* pull-down 50K */ - }; - conf-ds { - pins = "EMMC_DSL"; - bias-pull-down = ; /* pull-down 50K */ - }; - conf-rst { - pins = "EMMC_RSTB"; - drive-strength = <4>; - bias-pull-up = ; /* pull-up 10K */ - }; - }; - - pcie_pins: pcie-pins { - mux { - function = "pcie"; - groups = "pcie_clk", "pcie_pereset"; - }; - }; - - pwm_pins: pwm-pins { - mux { - function = "pwm"; - groups = "pwm0", "pwm1_0"; - }; - }; - - spi_flash_pins: spi-flash-pins { - mux { - function = "spi"; - groups = "spi0", "spi0_wp_hold"; - }; - }; - - spic_pins: spic-pins { - mux { - function = "spi"; - groups = "spi1_0"; - }; - }; - - uart1_pins: uart1-pins { - mux { - function = "uart"; - groups = "uart1_rx_tx"; - }; - }; - - uart2_pins: uart2-pins { - mux { - function = "uart"; - groups = "uart2_0_rx_tx"; - }; - }; - - wf_2g_5g_pins: wf-2g-5g-pins { - mux { - function = "wifi"; - groups = "wf_2g", "wf_5g"; - }; - conf { - pins = "WF0_HB1", "WF0_HB2", "WF0_HB3", "WF0_HB4", - "WF0_HB0", "WF0_HB0_B", "WF0_HB5", "WF0_HB6", - "WF0_HB7", "WF0_HB8", "WF0_HB9", "WF0_HB10", - "WF0_TOP_CLK", "WF0_TOP_DATA", "WF1_HB1", - "WF1_HB2", "WF1_HB3", "WF1_HB4", "WF1_HB0", - "WF1_HB5", "WF1_HB6", "WF1_HB7", "WF1_HB8", - "WF1_TOP_CLK", "WF1_TOP_DATA"; - drive-strength = <4>; - }; - }; - - wf_dbdc_pins: wf-dbdc-pins { - mux { - function = "wifi"; - groups = "wf_dbdc"; - }; - conf { - pins = "WF0_HB1", "WF0_HB2", "WF0_HB3", "WF0_HB4", - "WF0_HB0", "WF0_HB0_B", "WF0_HB5", "WF0_HB6", - "WF0_HB7", "WF0_HB8", "WF0_HB9", "WF0_HB10", - "WF0_TOP_CLK", "WF0_TOP_DATA", "WF1_HB1", - "WF1_HB2", "WF1_HB3", "WF1_HB4", "WF1_HB0", - "WF1_HB5", "WF1_HB6", "WF1_HB7", "WF1_HB8", - "WF1_TOP_CLK", "WF1_TOP_DATA"; - drive-strength = <4>; - }; - }; - - wf_led_pins: wf-led-pins { - mux { - function = "led"; - groups = "wifi_led"; - }; - }; -}; - -&pwm { - pinctrl-names = "default"; - pinctrl-0 = <&pwm_pins>; - status = "okay"; -}; - -&spi0 { - pinctrl-names = "default"; - pinctrl-0 = <&spi_flash_pins>; - status = "okay"; -}; - -&spi1 { - pinctrl-names = "default"; - pinctrl-0 = <&spic_pins>; - status = "okay"; -}; - -&ssusb { - status = "okay"; -}; - -&switch { - ports { - #address-cells = <1>; - #size-cells = <0>; - - port@0 { - reg = <0>; - label = "wan"; - }; - - port@1 { - reg = <1>; - label = "lan0"; - }; - - port@2 { - reg = <2>; - label = "lan1"; - }; - - port@3 { - reg = <3>; - label = "lan2"; - }; - - port@4 { - reg = <4>; - label = "lan3"; - }; - - port5: port@5 { - reg = <5>; - label = "lan4"; - phy-mode = "2500base-x"; - sfp = <&sfp2>; - managed = "in-band-status"; - }; - - port@6 { - reg = <6>; - label = "cpu"; - ethernet = <&gmac0>; - phy-mode = "2500base-x"; - - fixed-link { - speed = <2500>; - full-duplex; - pause; - }; - }; - }; -}; - -&trng { - status = "okay"; -}; - -&uart0 { - status = "okay"; -}; - -&uart1 { - pinctrl-names = "default"; - pinctrl-0 = <&uart1_pins>; - status = "okay"; -}; - -&uart2 { - pinctrl-names = "default"; - pinctrl-0 = <&uart2_pins>; - status = "okay"; -}; - -&usb_phy { - status = "okay"; -}; - -&watchdog { - status = "okay"; -}; - -&wifi { - status = "okay"; - pinctrl-names = "default", "dbdc"; - pinctrl-0 = <&wf_2g_5g_pins>, <&wf_led_pins>; - pinctrl-1 = <&wf_dbdc_pins>, <&wf_led_pins>; - - led { - led-active-low; - }; -}; - diff --git a/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7986a-rfb-spim-nand.dts b/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7986a-rfb-spim-nand.dts deleted file mode 100644 index ce007099d..000000000 --- a/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7986a-rfb-spim-nand.dts +++ /dev/null @@ -1,52 +0,0 @@ -/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */ - -#include "mt7986a-rfb.dtsi" - -/ { - compatible = "mediatek,mt7986a-rfb-snand"; -}; - -&spi0 { - status = "okay"; - - spi_nand: spi_nand@0 { - #address-cells = <1>; - #size-cells = <1>; - compatible = "spi-nand"; - reg = <1>; - spi-max-frequency = <10000000>; - spi-tx-bus-width = <4>; - spi-rx-bus-width = <4>; - - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - partition@0 { - label = "BL2"; - reg = <0x00000 0x0100000>; - read-only; - }; - partition@100000 { - label = "u-boot-env"; - reg = <0x0100000 0x0080000>; - }; - factory: partition@180000 { - label = "Factory"; - reg = <0x180000 0x0200000>; - }; - partition@380000 { - label = "FIP"; - reg = <0x380000 0x0200000>; - }; - partition@580000 { - label = "ubi"; - reg = <0x580000 0x4000000>; - }; - }; - }; -}; - -&wifi { - mediatek,mtd-eeprom = <&factory 0>; -}; diff --git a/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7986a-rfb-spim-nor.dts b/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7986a-rfb-spim-nor.dts deleted file mode 100644 index ea148315f..000000000 --- a/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7986a-rfb-spim-nor.dts +++ /dev/null @@ -1,51 +0,0 @@ -/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */ - -#include "mt7986a-rfb.dtsi" - -/ { - compatible = "mediatek,mt7986a-rfb-snor"; -}; - -&spi0 { - status = "okay"; - - spi_nor: spi_nor@0 { - #address-cells = <1>; - #size-cells = <1>; - compatible = "jedec,spi-nor"; - reg = <0>; - spi-max-frequency = <52000000>; - spi-tx-bus-width = <4>; - spi-rx-bus-width = <4>; - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - partition@00000 { - label = "BL2"; - reg = <0x00000 0x0040000>; - }; - partition@40000 { - label = "u-boot-env"; - reg = <0x40000 0x0010000>; - }; - factory: partition@50000 { - label = "Factory"; - reg = <0x50000 0x00B0000>; - }; - partition@100000 { - label = "FIP"; - reg = <0x100000 0x0080000>; - }; - partition@180000 { - label = "firmware"; - reg = <0x180000 0xE00000>; - }; - }; - }; -}; - -&wifi { - mediatek,mtd-eeprom = <&factory 0>; -}; diff --git a/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7986a-rfb.dtsi b/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7986a-rfb.dtsi deleted file mode 100644 index b3482f72c..000000000 --- a/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7986a-rfb.dtsi +++ /dev/null @@ -1,390 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0 OR MIT) -/* - * Copyright (C) 2021 MediaTek Inc. - * Author: Sam.Shih - */ - -/dts-v1/; -#include "mt7986a.dtsi" - -/ { - model = "MediaTek MT7986a RFB"; - compatible = "mediatek,mt7986a-rfb"; - - aliases { - serial0 = &uart0; - }; - - chosen { - stdout-path = "serial0:115200n8"; - }; - - memory { - reg = <0 0x40000000 0 0x40000000>; - }; - - reg_1p8v: regulator-1p8v { - compatible = "regulator-fixed"; - regulator-name = "fixed-1.8V"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - regulator-boot-on; - regulator-always-on; - }; - - reg_3p3v: regulator-3p3v { - compatible = "regulator-fixed"; - regulator-name = "fixed-3.3V"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - regulator-boot-on; - regulator-always-on; - }; - - reg_5v: regulator-5v { - compatible = "regulator-fixed"; - regulator-name = "fixed-5V"; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; - regulator-boot-on; - regulator-always-on; - }; -}; - -ð { - status = "okay"; - - gmac0: mac@0 { - compatible = "mediatek,eth-mac"; - reg = <0>; - phy-mode = "2500base-x"; - - fixed-link { - speed = <2500>; - full-duplex; - pause; - }; - }; - - gmac1: mac@1 { - compatible = "mediatek,eth-mac"; - reg = <1>; - phy-mode = "2500base-x"; - }; - - mdio: mdio-bus { - #address-cells = <1>; - #size-cells = <0>; - }; -}; - -&wifi { - status = "okay"; - pinctrl-names = "default", "dbdc"; - pinctrl-0 = <&wf_2g_5g_pins>; - pinctrl-1 = <&wf_dbdc_pins>; -}; - -&mdio { - phy5: phy@5 { - compatible = "ethernet-phy-id67c9.de0a"; - reg = <5>; - - reset-gpios = <&pio 6 1>; - reset-deassert-us = <20000>; - }; - - phy6: phy@6 { - compatible = "ethernet-phy-id67c9.de0a"; - reg = <6>; - }; - - switch: switch@0 { - compatible = "mediatek,mt7531"; - reg = <31>; - reset-gpios = <&pio 5 0>; - }; -}; - -&crypto { - status = "okay"; -}; - -&mmc0 { - pinctrl-names = "default", "state_uhs"; - pinctrl-0 = <&mmc0_pins_default>; - pinctrl-1 = <&mmc0_pins_uhs>; - bus-width = <8>; - max-frequency = <200000000>; - cap-mmc-highspeed; - mmc-hs200-1_8v; - mmc-hs400-1_8v; - hs400-ds-delay = <0x14014>; - vmmc-supply = <®_3p3v>; - vqmmc-supply = <®_1p8v>; - non-removable; - no-sd; - no-sdio; - status = "okay"; -}; - -&pcie { - pinctrl-names = "default"; - pinctrl-0 = <&pcie_pins>; - status = "okay"; -}; - -&pcie_phy { - status = "okay"; -}; - -&pio { - mmc0_pins_default: mmc0-pins { - mux { - function = "emmc"; - groups = "emmc_51"; - }; - conf-cmd-dat { - pins = "EMMC_DATA_0", "EMMC_DATA_1", "EMMC_DATA_2", - "EMMC_DATA_3", "EMMC_DATA_4", "EMMC_DATA_5", - "EMMC_DATA_6", "EMMC_DATA_7", "EMMC_CMD"; - input-enable; - drive-strength = <4>; - mediatek,pull-up-adv = <1>; /* pull-up 10K */ - }; - conf-clk { - pins = "EMMC_CK"; - drive-strength = <6>; - mediatek,pull-down-adv = <2>; /* pull-down 50K */ - }; - conf-ds { - pins = "EMMC_DSL"; - mediatek,pull-down-adv = <2>; /* pull-down 50K */ - }; - conf-rst { - pins = "EMMC_RSTB"; - drive-strength = <4>; - mediatek,pull-up-adv = <1>; /* pull-up 10K */ - }; - }; - - mmc0_pins_uhs: mmc0-uhs-pins { - mux { - function = "emmc"; - groups = "emmc_51"; - }; - conf-cmd-dat { - pins = "EMMC_DATA_0", "EMMC_DATA_1", "EMMC_DATA_2", - "EMMC_DATA_3", "EMMC_DATA_4", "EMMC_DATA_5", - "EMMC_DATA_6", "EMMC_DATA_7", "EMMC_CMD"; - input-enable; - drive-strength = <4>; - mediatek,pull-up-adv = <1>; /* pull-up 10K */ - }; - conf-clk { - pins = "EMMC_CK"; - drive-strength = <6>; - mediatek,pull-down-adv = <2>; /* pull-down 50K */ - }; - conf-ds { - pins = "EMMC_DSL"; - mediatek,pull-down-adv = <2>; /* pull-down 50K */ - }; - conf-rst { - pins = "EMMC_RSTB"; - drive-strength = <4>; - mediatek,pull-up-adv = <1>; /* pull-up 10K */ - }; - }; - - pcie_pins: pcie-pins { - mux { - function = "pcie"; - groups = "pcie_clk", "pcie_wake", "pcie_pereset"; - }; - }; - - spic_pins_g2: spic-pins-29-to-32 { - mux { - function = "spi"; - groups = "spi1_2"; - }; - }; - - spi_flash_pins: spi-flash-pins-33-to-38 { - mux { - function = "spi"; - groups = "spi0", "spi0_wp_hold"; - }; - conf-pu { - pins = "SPI2_CS", "SPI2_HOLD", "SPI2_WP"; - drive-strength = <8>; - mediatek,pull-up-adv = <0>; /* bias-disable */ - }; - conf-pd { - pins = "SPI2_CLK", "SPI2_MOSI", "SPI2_MISO"; - drive-strength = <8>; - mediatek,pull-down-adv = <0>; /* bias-disable */ - }; - }; - - uart1_pins: uart1-pins { - mux { - function = "uart"; - groups = "uart1"; - }; - }; - - uart2_pins: uart2-pins { - mux { - function = "uart"; - groups = "uart2"; - }; - }; - - wf_2g_5g_pins: wf_2g_5g-pins { - mux { - function = "wifi"; - groups = "wf_2g", "wf_5g"; - }; - conf { - pins = "WF0_HB1", "WF0_HB2", "WF0_HB3", "WF0_HB4", - "WF0_HB0", "WF0_HB0_B", "WF0_HB5", "WF0_HB6", - "WF0_HB7", "WF0_HB8", "WF0_HB9", "WF0_HB10", - "WF0_TOP_CLK", "WF0_TOP_DATA", "WF1_HB1", - "WF1_HB2", "WF1_HB3", "WF1_HB4", "WF1_HB0", - "WF1_HB5", "WF1_HB6", "WF1_HB7", "WF1_HB8", - "WF1_TOP_CLK", "WF1_TOP_DATA"; - drive-strength = <4>; - }; - }; - - wf_dbdc_pins: wf_dbdc-pins { - mux { - function = "wifi"; - groups = "wf_dbdc"; - }; - conf { - pins = "WF0_HB1", "WF0_HB2", "WF0_HB3", "WF0_HB4", - "WF0_HB0", "WF0_HB0_B", "WF0_HB5", "WF0_HB6", - "WF0_HB7", "WF0_HB8", "WF0_HB9", "WF0_HB10", - "WF0_TOP_CLK", "WF0_TOP_DATA", "WF1_HB1", - "WF1_HB2", "WF1_HB3", "WF1_HB4", "WF1_HB0", - "WF1_HB5", "WF1_HB6", "WF1_HB7", "WF1_HB8", - "WF1_TOP_CLK", "WF1_TOP_DATA"; - drive-strength = <4>; - }; - }; -}; - -&spi0 { - pinctrl-names = "default"; - pinctrl-0 = <&spi_flash_pins>; - cs-gpios = <0>, <0>; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; -}; - -&spi1 { - pinctrl-names = "default"; - pinctrl-0 = <&spic_pins_g2>; - status = "okay"; - - proslic_spi: proslic_spi@0 { - compatible = "silabs,proslic_spi"; - reg = <0>; - spi-max-frequency = <10000000>; - spi-cpha = <1>; - spi-cpol = <1>; - channel_count = <1>; - debug_level = <4>; /* 1 = TRC, 2 = DBG, 4 = ERR */ - reset_gpio = <&pio 7 0>; - ig,enable-spi = <1>; /* 1: Enable, 0: Disable */ - }; -}; - -&gmac1 { - phy-mode = "2500base-x"; - phy-connection-type = "2500base-x"; - phy-handle = <&phy6>; -}; - -&switch { - ports { - #address-cells = <1>; - #size-cells = <0>; - - port@0 { - reg = <0>; - label = "lan1"; - }; - - port@1 { - reg = <1>; - label = "lan2"; - }; - - port@2 { - reg = <2>; - label = "lan3"; - }; - - port@3 { - reg = <3>; - label = "lan4"; - }; - - port@4 { - reg = <4>; - label = "wan"; - }; - - port@5 { - reg = <5>; - label = "lan6"; - - phy-mode = "2500base-x"; - phy-handle = <&phy5>; - }; - - port@6 { - reg = <6>; - label = "cpu"; - ethernet = <&gmac0>; - phy-mode = "2500base-x"; - - fixed-link { - speed = <2500>; - full-duplex; - pause; - }; - }; - }; -}; - -&ssusb { - vusb33-supply = <®_3p3v>; - vbus-supply = <®_5v>; - status = "okay"; -}; - -&uart0 { - status = "okay"; -}; - -&uart1 { - pinctrl-names = "default"; - pinctrl-0 = <&uart1_pins>; - status = "okay"; -}; - -&uart2 { - pinctrl-names = "default"; - pinctrl-0 = <&uart2_pins>; - status = "okay"; -}; - -&usb_phy { - status = "okay"; -}; diff --git a/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7986a.dtsi b/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7986a.dtsi deleted file mode 100644 index 64f2cf375..000000000 --- a/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7986a.dtsi +++ /dev/null @@ -1,645 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0 OR MIT) -/* - * Copyright (C) 2021 MediaTek Inc. - * Author: Sam.Shih - */ - -#include -#include -#include -#include -#include - -/ { - compatible = "mediatek,mt7986a"; - interrupt-parent = <&gic>; - #address-cells = <2>; - #size-cells = <2>; - - clk40m: oscillator-40m { - compatible = "fixed-clock"; - clock-frequency = <40000000>; - #clock-cells = <0>; - clock-output-names = "clkxtal"; - }; - - cpus { - #address-cells = <1>; - #size-cells = <0>; - cpu0: cpu@0 { - device_type = "cpu"; - compatible = "arm,cortex-a53"; - enable-method = "psci"; - reg = <0x0>; - #cooling-cells = <2>; - }; - - cpu1: cpu@1 { - device_type = "cpu"; - compatible = "arm,cortex-a53"; - enable-method = "psci"; - reg = <0x1>; - #cooling-cells = <2>; - }; - - cpu2: cpu@2 { - device_type = "cpu"; - compatible = "arm,cortex-a53"; - enable-method = "psci"; - reg = <0x2>; - #cooling-cells = <2>; - }; - - cpu3: cpu@3 { - device_type = "cpu"; - enable-method = "psci"; - compatible = "arm,cortex-a53"; - reg = <0x3>; - #cooling-cells = <2>; - }; - }; - - psci { - compatible = "arm,psci-0.2"; - method = "smc"; - }; - - reserved-memory { - #address-cells = <2>; - #size-cells = <2>; - ranges; - /* 192 KiB reserved for ARM Trusted Firmware (BL31) */ - secmon_reserved: secmon@43000000 { - reg = <0 0x43000000 0 0x30000>; - no-map; - }; - - wmcpu_emi: wmcpu-reserved@4fc00000 { - no-map; - reg = <0 0x4fc00000 0 0x00100000>; - }; - - wo_emi0: wo-emi@4fd00000 { - reg = <0 0x4fd00000 0 0x40000>; - no-map; - }; - - wo_emi1: wo-emi@4fd40000 { - reg = <0 0x4fd40000 0 0x40000>; - no-map; - }; - - wo_ilm0: wo-ilm@151e0000 { - reg = <0 0x151e0000 0 0x8000>; - no-map; - }; - - wo_ilm1: wo-ilm@151f0000 { - reg = <0 0x151f0000 0 0x8000>; - no-map; - }; - - wo_data: wo-data@4fd80000 { - reg = <0 0x4fd80000 0 0x240000>; - no-map; - }; - - wo_dlm0: wo-dlm@151e8000 { - reg = <0 0x151e8000 0 0x2000>; - no-map; - }; - - wo_dlm1: wo-dlm@151f8000 { - reg = <0 0x151f8000 0 0x2000>; - no-map; - }; - - wo_boot: wo-boot@15194000 { - reg = <0 0x15194000 0 0x1000>; - no-map; - }; - - }; - - timer { - compatible = "arm,armv8-timer"; - interrupt-parent = <&gic>; - interrupts = , - , - , - ; - }; - - soc { - #address-cells = <2>; - #size-cells = <2>; - compatible = "simple-bus"; - ranges; - - gic: interrupt-controller@c000000 { - compatible = "arm,gic-v3"; - #interrupt-cells = <3>; - interrupt-parent = <&gic>; - interrupt-controller; - reg = <0 0x0c000000 0 0x10000>, /* GICD */ - <0 0x0c080000 0 0x80000>, /* GICR */ - <0 0x0c400000 0 0x2000>, /* GICC */ - <0 0x0c410000 0 0x1000>, /* GICH */ - <0 0x0c420000 0 0x2000>; /* GICV */ - interrupts = ; - }; - - infracfg: infracfg@10001000 { - compatible = "mediatek,mt7986-infracfg", "syscon"; - reg = <0 0x10001000 0 0x1000>; - #clock-cells = <1>; - }; - - wed_pcie: wed-pcie@10003000 { - compatible = "mediatek,mt7986-wed-pcie", - "syscon"; - reg = <0 0x10003000 0 0x10>; - }; - - topckgen: topckgen@1001b000 { - compatible = "mediatek,mt7986-topckgen", "syscon"; - reg = <0 0x1001B000 0 0x1000>; - #clock-cells = <1>; - }; - - watchdog: watchdog@1001c000 { - compatible = "mediatek,mt7986-wdt"; - reg = <0 0x1001c000 0 0x1000>; - interrupts = ; - #reset-cells = <1>; - status = "disabled"; - }; - - apmixedsys: apmixedsys@1001e000 { - compatible = "mediatek,mt7986-apmixedsys"; - reg = <0 0x1001E000 0 0x1000>; - #clock-cells = <1>; - }; - - pio: pinctrl@1001f000 { - compatible = "mediatek,mt7986a-pinctrl"; - reg = <0 0x1001f000 0 0x1000>, - <0 0x11c30000 0 0x1000>, - <0 0x11c40000 0 0x1000>, - <0 0x11e20000 0 0x1000>, - <0 0x11e30000 0 0x1000>, - <0 0x11f00000 0 0x1000>, - <0 0x11f10000 0 0x1000>, - <0 0x1000b000 0 0x1000>; - reg-names = "gpio", "iocfg_rt", "iocfg_rb", "iocfg_lt", - "iocfg_lb", "iocfg_tr", "iocfg_tl", "eint"; - gpio-controller; - #gpio-cells = <2>; - gpio-ranges = <&pio 0 0 100>; - interrupt-controller; - interrupts = ; - interrupt-parent = <&gic>; - #interrupt-cells = <2>; - }; - - sgmiisys0: syscon@10060000 { - compatible = "mediatek,mt7986-sgmiisys_0", - "syscon"; - reg = <0 0x10060000 0 0x1000>; - #clock-cells = <1>; - }; - - sgmiisys1: syscon@10070000 { - compatible = "mediatek,mt7986-sgmiisys_1", - "syscon"; - reg = <0 0x10070000 0 0x1000>; - #clock-cells = <1>; - }; - - trng: rng@1020f000 { - compatible = "mediatek,mt7986-rng", - "mediatek,mt7623-rng"; - reg = <0 0x1020f000 0 0x100>; - clocks = <&infracfg CLK_INFRA_TRNG_CK>; - clock-names = "rng"; - status = "disabled"; - }; - - crypto: crypto@10320000 { - compatible = "inside-secure,safexcel-eip97"; - reg = <0 0x10320000 0 0x40000>; - interrupts = , - , - , - ; - interrupt-names = "ring0", "ring1", "ring2", "ring3"; - clocks = <&infracfg CLK_INFRA_EIP97_CK>; - clock-names = "infra_eip97_ck"; - assigned-clocks = <&topckgen CLK_TOP_EIP_B_SEL>; - assigned-clock-parents = <&apmixedsys CLK_APMIXED_NET2PLL>; - status = "disabled"; - }; - - pwm: pwm@10048000 { - compatible = "mediatek,mt7986-pwm"; - reg = <0 0x10048000 0 0x1000>; - #clock-cells = <1>; - #pwm-cells = <2>; - interrupts = ; - clocks = <&topckgen CLK_TOP_PWM_SEL>, - <&infracfg CLK_INFRA_PWM_STA>, - <&infracfg CLK_INFRA_PWM1_CK>, - <&infracfg CLK_INFRA_PWM2_CK>; - clock-names = "top", "main", "pwm1", "pwm2"; - status = "disabled"; - }; - - uart0: serial@11002000 { - compatible = "mediatek,mt7986-uart", - "mediatek,mt6577-uart"; - reg = <0 0x11002000 0 0x400>; - interrupts = ; - clocks = <&infracfg CLK_INFRA_UART0_SEL>, - <&infracfg CLK_INFRA_UART0_CK>; - clock-names = "baud", "bus"; - assigned-clocks = <&topckgen CLK_TOP_UART_SEL>, - <&infracfg CLK_INFRA_UART0_SEL>; - assigned-clock-parents = <&topckgen CLK_TOP_XTAL>, - <&topckgen CLK_TOP_UART_SEL>; - status = "disabled"; - }; - - uart1: serial@11003000 { - compatible = "mediatek,mt7986-uart", - "mediatek,mt6577-uart"; - reg = <0 0x11003000 0 0x400>; - interrupts = ; - clocks = <&infracfg CLK_INFRA_UART1_SEL>, - <&infracfg CLK_INFRA_UART1_CK>; - clock-names = "baud", "bus"; - assigned-clocks = <&infracfg CLK_INFRA_UART1_SEL>; - assigned-clock-parents = <&topckgen CLK_TOP_F26M_SEL>; - status = "disabled"; - }; - - uart2: serial@11004000 { - compatible = "mediatek,mt7986-uart", - "mediatek,mt6577-uart"; - reg = <0 0x11004000 0 0x400>; - interrupts = ; - clocks = <&infracfg CLK_INFRA_UART2_SEL>, - <&infracfg CLK_INFRA_UART2_CK>; - clock-names = "baud", "bus"; - assigned-clocks = <&infracfg CLK_INFRA_UART2_SEL>; - assigned-clock-parents = <&topckgen CLK_TOP_F26M_SEL>; - status = "disabled"; - }; - - i2c0: i2c@11008000 { - compatible = "mediatek,mt7986-i2c"; - reg = <0 0x11008000 0 0x90>, - <0 0x10217080 0 0x80>; - interrupts = ; - clock-div = <5>; - clocks = <&infracfg CLK_INFRA_I2C0_CK>, - <&infracfg CLK_INFRA_AP_DMA_CK>; - clock-names = "main", "dma"; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; - }; - - spi0: spi@1100a000 { - compatible = "mediatek,mt7986-spi-ipm", "mediatek,spi-ipm"; - #address-cells = <1>; - #size-cells = <0>; - reg = <0 0x1100a000 0 0x100>; - interrupts = ; - clocks = <&topckgen CLK_TOP_MPLL_D2>, - <&topckgen CLK_TOP_SPI_SEL>, - <&infracfg CLK_INFRA_SPI0_CK>, - <&infracfg CLK_INFRA_SPI0_HCK_CK>; - clock-names = "parent-clk", "sel-clk", "spi-clk", "hclk"; - status = "disabled"; - }; - - spi1: spi@1100b000 { - compatible = "mediatek,mt7986-spi-ipm", "mediatek,spi-ipm"; - #address-cells = <1>; - #size-cells = <0>; - reg = <0 0x1100b000 0 0x100>; - interrupts = ; - clocks = <&topckgen CLK_TOP_MPLL_D2>, - <&topckgen CLK_TOP_SPIM_MST_SEL>, - <&infracfg CLK_INFRA_SPI1_CK>, - <&infracfg CLK_INFRA_SPI1_HCK_CK>; - clock-names = "parent-clk", "sel-clk", "spi-clk", "hclk"; - status = "disabled"; - }; - - auxadc: adc@1100d000 { - compatible = "mediatek,mt7986-auxadc"; - reg = <0 0x1100d000 0 0x1000>; - clocks = <&infracfg CLK_INFRA_ADC_26M_CK>; - clock-names = "main"; - #io-channel-cells = <1>; - status = "disabled"; - }; - - ssusb: usb@11200000 { - compatible = "mediatek,mt7986-xhci", - "mediatek,mtk-xhci"; - reg = <0 0x11200000 0 0x2e00>, - <0 0x11203e00 0 0x0100>; - reg-names = "mac", "ippc"; - interrupts = ; - clocks = <&infracfg CLK_INFRA_IUSB_SYS_CK>, - <&infracfg CLK_INFRA_IUSB_CK>, - <&infracfg CLK_INFRA_IUSB_133_CK>, - <&infracfg CLK_INFRA_IUSB_66M_CK>, - <&topckgen CLK_TOP_U2U3_XHCI_SEL>; - clock-names = "sys_ck", - "ref_ck", - "mcu_ck", - "dma_ck", - "xhci_ck"; - phys = <&u2port0 PHY_TYPE_USB2>, - <&u3port0 PHY_TYPE_USB3>, - <&u2port1 PHY_TYPE_USB2>; - status = "disabled"; - }; - - mmc0: mmc@11230000 { - compatible = "mediatek,mt7986-mmc"; - reg = <0 0x11230000 0 0x1000>, - <0 0x11c20000 0 0x1000>; - interrupts = ; - clocks = <&topckgen CLK_TOP_EMMC_416M_SEL>, - <&infracfg CLK_INFRA_MSDC_HCK_CK>, - <&infracfg CLK_INFRA_MSDC_CK>, - <&infracfg CLK_INFRA_MSDC_133M_CK>, - <&infracfg CLK_INFRA_MSDC_66M_CK>; - clock-names = "source", "hclk", "source_cg", "bus_clk", - "sys_cg"; - status = "disabled"; - }; - - thermal: thermal@1100c800 { - #thermal-sensor-cells = <1>; - compatible = "mediatek,mt7986-thermal"; - reg = <0 0x1100c800 0 0x800>; - interrupts = ; - clocks = <&infracfg CLK_INFRA_THERM_CK>, - <&infracfg CLK_INFRA_ADC_26M_CK>, - <&infracfg CLK_INFRA_ADC_FRC_CK>; - clock-names = "therm", "auxadc", "adc_32k"; - mediatek,auxadc = <&auxadc>; - mediatek,apmixedsys = <&apmixedsys>; - nvmem-cells = <&thermal_calibration>; - nvmem-cell-names = "calibration-data"; - }; - - pcie: pcie@11280000 { - compatible = "mediatek,mt7986-pcie", - "mediatek,mt8192-pcie"; - device_type = "pci"; - #address-cells = <3>; - #size-cells = <2>; - reg = <0x00 0x11280000 0x00 0x4000>; - reg-names = "pcie-mac"; - interrupts = ; - bus-range = <0x00 0xff>; - ranges = <0x82000000 0x00 0x20000000 0x00 - 0x20000000 0x00 0x10000000>; - clocks = <&infracfg CLK_INFRA_IPCIE_PIPE_CK>, - <&infracfg CLK_INFRA_IPCIE_CK>, - <&infracfg CLK_INFRA_IPCIER_CK>, - <&infracfg CLK_INFRA_IPCIEB_CK>; - clock-names = "pl_250m", "tl_26m", "peri_26m", "top_133m"; - status = "disabled"; - - phys = <&pcie_port PHY_TYPE_PCIE>; - phy-names = "pcie-phy"; - - #interrupt-cells = <1>; - interrupt-map-mask = <0 0 0 0x7>; - interrupt-map = <0 0 0 1 &pcie_intc 0>, - <0 0 0 2 &pcie_intc 1>, - <0 0 0 3 &pcie_intc 2>, - <0 0 0 4 &pcie_intc 3>; - pcie_intc: interrupt-controller { - #address-cells = <0>; - #interrupt-cells = <1>; - interrupt-controller; - }; - }; - - pcie_phy: t-phy@11c00000 { - compatible = "mediatek,mt7986-tphy", - "mediatek,generic-tphy-v2"; - #address-cells = <2>; - #size-cells = <2>; - ranges; - status = "disabled"; - - pcie_port: pcie-phy@11c00000 { - reg = <0 0x11c00000 0 0x20000>; - clocks = <&clk40m>; - clock-names = "ref"; - #phy-cells = <1>; - }; - }; - - efuse: efuse@11d00000 { - compatible = "mediatek,mt7986-efuse", "mediatek,efuse"; - reg = <0 0x11d00000 0 0x1000>; - #address-cells = <1>; - #size-cells = <1>; - - thermal_calibration: calib@274 { - reg = <0x274 0xc>; - }; - }; - - usb_phy: t-phy@11e10000 { - compatible = "mediatek,mt7986-tphy", - "mediatek,generic-tphy-v2"; - #address-cells = <1>; - #size-cells = <1>; - ranges = <0 0 0x11e10000 0x1700>; - status = "disabled"; - - u2port0: usb-phy@0 { - reg = <0x0 0x700>; - clocks = <&topckgen CLK_TOP_DA_U2_REFSEL>, - <&topckgen CLK_TOP_DA_U2_CK_1P_SEL>; - clock-names = "ref", "da_ref"; - #phy-cells = <1>; - }; - - u3port0: usb-phy@700 { - reg = <0x700 0x900>; - clocks = <&topckgen CLK_TOP_USB3_PHY_SEL>; - clock-names = "ref"; - #phy-cells = <1>; - }; - - u2port1: usb-phy@1000 { - reg = <0x1000 0x700>; - clocks = <&topckgen CLK_TOP_DA_U2_REFSEL>, - <&topckgen CLK_TOP_DA_U2_CK_1P_SEL>; - clock-names = "ref", "da_ref"; - #phy-cells = <1>; - }; - }; - - ethsys: syscon@15000000 { - #address-cells = <1>; - #size-cells = <1>; - compatible = "mediatek,mt7986-ethsys", - "syscon"; - reg = <0 0x15000000 0 0x1000>; - #clock-cells = <1>; - #reset-cells = <1>; - }; - - wed0: wed@15010000 { - compatible = "mediatek,mt7986-wed", - "syscon"; - reg = <0 0x15010000 0 0x1000>; - interrupt-parent = <&gic>; - interrupts = ; - memory-region = <&wo_emi0>, <&wo_ilm0>, <&wo_dlm0>, - <&wo_data>, <&wo_boot>; - memory-region-names = "wo-emi", "wo-ilm", "wo-dlm", - "wo-data", "wo-boot"; - mediatek,wo-ccif = <&wo_ccif0>; - }; - - wed1: wed@15011000 { - compatible = "mediatek,mt7986-wed", - "syscon"; - reg = <0 0x15011000 0 0x1000>; - interrupt-parent = <&gic>; - interrupts = ; - memory-region = <&wo_emi1>, <&wo_ilm1>, <&wo_dlm1>, - <&wo_data>, <&wo_boot>; - memory-region-names = "wo-emi", "wo-ilm", "wo-dlm", - "wo-data", "wo-boot"; - mediatek,wo-ccif = <&wo_ccif1>; - }; - - wo_ccif0: syscon@151a5000 { - compatible = "mediatek,mt7986-wo-ccif", "syscon"; - reg = <0 0x151a5000 0 0x1000>; - interrupt-parent = <&gic>; - interrupts = ; - }; - - wo_ccif1: syscon@151ad000 { - compatible = "mediatek,mt7986-wo-ccif", "syscon"; - reg = <0 0x151ad000 0 0x1000>; - interrupt-parent = <&gic>; - interrupts = ; - }; - - eth: ethernet@15100000 { - compatible = "mediatek,mt7986-eth"; - reg = <0 0x15100000 0 0x80000>; - interrupts = , - , - , - ; - clocks = <ðsys CLK_ETH_FE_EN>, - <ðsys CLK_ETH_GP2_EN>, - <ðsys CLK_ETH_GP1_EN>, - <ðsys CLK_ETH_WOCPU1_EN>, - <ðsys CLK_ETH_WOCPU0_EN>, - <&sgmiisys0 CLK_SGMII0_TX250M_EN>, - <&sgmiisys0 CLK_SGMII0_RX250M_EN>, - <&sgmiisys0 CLK_SGMII0_CDR_REF>, - <&sgmiisys0 CLK_SGMII0_CDR_FB>, - <&sgmiisys1 CLK_SGMII1_TX250M_EN>, - <&sgmiisys1 CLK_SGMII1_RX250M_EN>, - <&sgmiisys1 CLK_SGMII1_CDR_REF>, - <&sgmiisys1 CLK_SGMII1_CDR_FB>, - <&topckgen CLK_TOP_NETSYS_SEL>, - <&topckgen CLK_TOP_NETSYS_500M_SEL>; - clock-names = "fe", "gp2", "gp1", "wocpu1", "wocpu0", - "sgmii_tx250m", "sgmii_rx250m", - "sgmii_cdr_ref", "sgmii_cdr_fb", - "sgmii2_tx250m", "sgmii2_rx250m", - "sgmii2_cdr_ref", "sgmii2_cdr_fb", - "netsys0", "netsys1"; - assigned-clocks = <&topckgen CLK_TOP_NETSYS_2X_SEL>, - <&topckgen CLK_TOP_SGM_325M_SEL>; - assigned-clock-parents = <&apmixedsys CLK_APMIXED_NET2PLL>, - <&apmixedsys CLK_APMIXED_SGMPLL>; - mediatek,ethsys = <ðsys>; - mediatek,sgmiisys = <&sgmiisys0>, <&sgmiisys1>; - mediatek,wed-pcie = <&wed_pcie>; - mediatek,wed = <&wed0>, <&wed1>; - #reset-cells = <1>; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; - }; - - wifi: wifi@18000000 { - compatible = "mediatek,mt7986-wmac"; - resets = <&watchdog MT7986_TOPRGU_CONSYS_SW_RST>; - reset-names = "consys"; - clocks = <&topckgen CLK_TOP_CONN_MCUSYS_SEL>, - <&topckgen CLK_TOP_AP2CNN_HOST_SEL>; - clock-names = "mcu", "ap2conn"; - reg = <0 0x18000000 0 0x1000000>, - <0 0x10003000 0 0x1000>, - <0 0x11d10000 0 0x1000>; - interrupts = , - , - , - ; - memory-region = <&wmcpu_emi>; - }; - }; - - thermal-zones { - cpu_thermal: cpu-thermal { - polling-delay-passive = <1000>; - polling-delay = <1000>; - thermal-sensors = <&thermal 0>; - - trips { - cpu_trip_crit: crit { - temperature = <125000>; - hysteresis = <2000>; - type = "critical"; - }; - - cpu_trip_hot: hot { - temperature = <120000>; - hysteresis = <2000>; - type = "hot"; - }; - - cpu_trip_active_high: active-high { - temperature = <115000>; - hysteresis = <2000>; - type = "active"; - }; - - cpu_trip_active_med: active-med { - temperature = <85000>; - hysteresis = <2000>; - type = "active"; - }; - - cpu_trip_active_low: active-low { - temperature = <60000>; - hysteresis = <2000>; - type = "active"; - }; - }; - }; - }; -}; diff --git a/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7986b-rfb.dts b/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7986b-rfb.dts deleted file mode 100644 index a845c796d..000000000 --- a/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7986b-rfb.dts +++ /dev/null @@ -1,195 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0 OR MIT) -/* - * Copyright (C) 2021 MediaTek Inc. - * Author: Sam.Shih - */ - -/dts-v1/; -#include "mt7986b.dtsi" - -/ { - model = "MediaTek MT7986b RFB"; - compatible = "mediatek,mt7986b-rfb"; - - aliases { - serial0 = &uart0; - }; - - chosen { - stdout-path = "serial0:115200n8"; - }; - - memory { - reg = <0 0x40000000 0 0x40000000>; - }; - - reg_3p3v: regulator-3p3v { - compatible = "regulator-fixed"; - regulator-name = "fixed-3.3V"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - regulator-boot-on; - regulator-always-on; - }; - - reg_5v: regulator-5v { - compatible = "regulator-fixed"; - regulator-name = "fixed-5V"; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; - regulator-boot-on; - regulator-always-on; - }; -}; - -&ssusb { - vusb33-supply = <®_3p3v>; - vbus-supply = <®_5v>; - status = "okay"; -}; - -&uart0 { - status = "okay"; -}; - -&usb_phy { - status = "okay"; -}; - -&wifi { - status = "okay"; - pinctrl-names = "default", "dbdc"; - pinctrl-0 = <&wf_2g_5g_pins>; - pinctrl-1 = <&wf_dbdc_pins>; -}; - -ð { - status = "okay"; - - gmac0: mac@0 { - compatible = "mediatek,eth-mac"; - reg = <0>; - phy-mode = "2500base-x"; - - fixed-link { - speed = <2500>; - full-duplex; - pause; - }; - }; - - gmac1: mac@1 { - compatible = "mediatek,eth-mac"; - reg = <1>; - phy-mode = "2500base-x"; - - fixed-link { - speed = <2500>; - full-duplex; - pause; - }; - }; - - mdio: mdio-bus { - #address-cells = <1>; - #size-cells = <0>; - - phy5: phy@5 { - compatible = "ethernet-phy-id67c9.de0a"; - reg = <5>; - reset-gpios = <&pio 6 1>; - reset-deassert-us = <20000>; - phy-mode = "2500base-x"; - }; - - phy6: phy@6 { - compatible = "ethernet-phy-id67c9.de0a"; - reg = <6>; - phy-mode = "2500base-x"; - }; - - switch@0 { - compatible = "mediatek,mt7531"; - reg = <31>; - reset-gpios = <&pio 5 0>; - - ports { - #address-cells = <1>; - #size-cells = <0>; - - port@0 { - reg = <0>; - label = "lan0"; - }; - - port@1 { - reg = <1>; - label = "lan1"; - }; - - port@2 { - reg = <2>; - label = "lan2"; - }; - - port@3 { - reg = <3>; - label = "lan3"; - }; - - port@6 { - reg = <6>; - label = "cpu"; - ethernet = <&gmac0>; - phy-mode = "2500base-x"; - - fixed-link { - speed = <2500>; - full-duplex; - pause; - }; - }; - }; - }; - }; -}; - -&crypto { - status = "okay"; -}; - -&pio { - wf_2g_5g_pins: wf_2g_5g-pins { - mux { - function = "wifi"; - groups = "wf_2g", "wf_5g"; - }; - conf { - pins = "WF0_HB1", "WF0_HB2", "WF0_HB3", "WF0_HB4", - "WF0_HB0", "WF0_HB0_B", "WF0_HB5", "WF0_HB6", - "WF0_HB7", "WF0_HB8", "WF0_HB9", "WF0_HB10", - "WF0_TOP_CLK", "WF0_TOP_DATA", "WF1_HB1", - "WF1_HB2", "WF1_HB3", "WF1_HB4", "WF1_HB0", - "WF1_HB5", "WF1_HB6", "WF1_HB7", "WF1_HB8", - "WF1_TOP_CLK", "WF1_TOP_DATA"; - drive-strength = <4>; - }; - }; - - wf_dbdc_pins: wf_dbdc-pins { - mux { - function = "wifi"; - groups = "wf_dbdc"; - }; - conf { - pins = "WF0_HB1", "WF0_HB2", "WF0_HB3", "WF0_HB4", - "WF0_HB0", "WF0_HB0_B", "WF0_HB5", "WF0_HB6", - "WF0_HB7", "WF0_HB8", "WF0_HB9", "WF0_HB10", - "WF0_TOP_CLK", "WF0_TOP_DATA", "WF1_HB1", - "WF1_HB2", "WF1_HB3", "WF1_HB4", "WF1_HB0", - "WF1_HB5", "WF1_HB6", "WF1_HB7", "WF1_HB8", - "WF1_TOP_CLK", "WF1_TOP_DATA"; - drive-strength = <4>; - }; - }; -}; diff --git a/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7986b.dtsi b/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7986b.dtsi deleted file mode 100644 index db5189664..000000000 --- a/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7986b.dtsi +++ /dev/null @@ -1,15 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0 OR MIT) -/* - * Copyright (C) 2021 MediaTek Inc. - * Author: Sam.Shih - */ - -#include "mt7986a.dtsi" -/ { - compatible = "mediatek,mt7986b"; -}; - -&pio { - compatible = "mediatek,mt7986b-pinctrl"; - gpio-ranges = <&pio 0 0 41>, <&pio 66 66 35>; -}; diff --git a/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7988a-rfb-emmc.dtso b/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7988a-rfb-emmc.dtso deleted file mode 100644 index 3f8ac2ae3..000000000 --- a/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7988a-rfb-emmc.dtso +++ /dev/null @@ -1,33 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0 OR MIT) -/* - * Copyright (C) 2021 MediaTek Inc. - * Author: Frank Wunderlich - */ - -/dts-v1/; -/plugin/; - -/ { - compatible = "mediatek,mt7988a-rfb", "mediatek,mt7988a"; - - fragment@0 { - target = <&mmc0>; - __overlay__ { - pinctrl-names = "default", "state_uhs"; - pinctrl-0 = <&mmc0_pins_emmc_51>; - pinctrl-1 = <&mmc0_pins_emmc_51>; - bus-width = <8>; - max-frequency = <200000000>; - cap-mmc-highspeed; - mmc-hs200-1_8v; - mmc-hs400-1_8v; - hs400-ds-delay = <0x12814>; - vqmmc-supply = <®_1p8v>; - vmmc-supply = <®_3p3v>; - non-removable; - no-sd; - no-sdio; - status = "okay"; - }; - }; -}; diff --git a/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth1-aqr.dtso b/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth1-aqr.dtso deleted file mode 100644 index d21a61ad1..000000000 --- a/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth1-aqr.dtso +++ /dev/null @@ -1,41 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0 OR MIT) -/* - * Copyright (C) 2022 MediaTek Inc. - * Author: Sam.Shih - */ - -/dts-v1/; -/plugin/; - -#include - -/ { - compatible = "mediatek,mt7988a-rfb", "mediatek,mt7988a"; - - fragment@0 { - target = <&mdio_bus>; - __overlay__ { - #address-cells = <1>; - #size-cells = <0>; - - /* external Aquantia AQR113C */ - phy0: ethernet-phy@0 { - reg = <0>; - compatible = "ethernet-phy-ieee802.3-c45"; - reset-gpios = <&pio 72 GPIO_ACTIVE_LOW>; - reset-assert-us = <100000>; - reset-deassert-us = <221000>; - }; - }; - }; - - fragment@1 { - target = <&gmac1>; - __overlay__ { - phy-mode = "usxgmii"; - phy-connection-type = "usxgmii"; - phy = <&phy0>; - status = "okay"; - }; - }; -}; diff --git a/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth1-i2p5g-phy.dtso b/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth1-i2p5g-phy.dtso deleted file mode 100644 index 86ab7566d..000000000 --- a/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth1-i2p5g-phy.dtso +++ /dev/null @@ -1,30 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0 OR MIT) -/* - * Copyright (C) 2022 MediaTek Inc. - * Author: Sam.Shih - */ - -/dts-v1/; -/plugin/; - -/ { - compatible = "mediatek,mt7988a-rfb", "mediatek,mt7988a"; - - fragment@0 { - target = <&gmac1>; - __overlay__ { - phy-mode = "internal"; - phy-connection-type = "internal"; - phy = <&int_2p5g_phy>; - status = "okay"; - }; - }; - - fragment@1 { - target = <&int_2p5g_phy>; - __overlay__ { - pinctrl-names = "i2p5gbe-led"; - pinctrl-0 = <&i2p5gbe_led0_pins>; - }; - }; -}; diff --git a/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth1-mxl.dtso b/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth1-mxl.dtso deleted file mode 100644 index 34a23bbd7..000000000 --- a/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth1-mxl.dtso +++ /dev/null @@ -1,39 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0 OR MIT) -/* - * Copyright (C) 2022 MediaTek Inc. - * Author: Sam.Shih - */ - -/dts-v1/; -/plugin/; - -#include - -/ { - compatible = "mediatek,mt7988a-rfb", "mediatek,mt7988a"; - - fragment@0 { - target = <&mdio_bus>; - __overlay__ { - #address-cells = <1>; - #size-cells = <0>; - - /* external Maxlinear GPY211C */ - phy13: ethernet-phy@13 { - reg = <13>; - compatible = "ethernet-phy-ieee802.3-c45"; - phy-mode = "2500base-x"; - }; - }; - }; - - fragment@1 { - target = <&gmac1>; - __overlay__ { - phy-mode = "2500base-x"; - phy-connection-type = "2500base-x"; - phy = <&phy13>; - status = "okay"; - }; - }; -}; diff --git a/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth1-sfp.dtso b/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth1-sfp.dtso deleted file mode 100644 index ba40a119c..000000000 --- a/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth1-sfp.dtso +++ /dev/null @@ -1,47 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0 OR MIT) -/* - * Copyright (C) 2022 MediaTek Inc. - * Author: Sam.Shih - */ - -/dts-v1/; -/plugin/; - -#include - -/ { - compatible = "mediatek,mt7988a-rfb", "mediatek,mt7988a"; - - fragment@0 { - target = <&i2c2>; - __overlay__ { - pinctrl-names = "default"; - pinctrl-0 = <&i2c2_0_pins>; - status = "okay"; - }; - }; - - fragment@1 { - target-path = "/"; - __overlay__ { - sfp_esp1: sfp@1 { - compatible = "sff,sfp"; - i2c-bus = <&i2c2>; - mod-def0-gpios = <&pio 82 GPIO_ACTIVE_LOW>; - los-gpios = <&pio 81 GPIO_ACTIVE_HIGH>; - tx-disable-gpios = <&pio 36 GPIO_ACTIVE_HIGH>; - maximum-power-milliwatt = <3000>; - }; - }; - }; - - fragment@2 { - target = <&gmac1>; - __overlay__ { - phy-mode = "10gbase-r"; - managed = "in-band-status"; - sfp = <&sfp_esp1>; - status = "okay"; - }; - }; -}; diff --git a/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth2-aqr.dtso b/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth2-aqr.dtso deleted file mode 100644 index 140391fc4..000000000 --- a/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth2-aqr.dtso +++ /dev/null @@ -1,41 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0 OR MIT) -/* - * Copyright (C) 2022 MediaTek Inc. - * Author: Sam.Shih - */ - -/dts-v1/; -/plugin/; - -#include - -/ { - compatible = "mediatek,mt7988a-rfb", "mediatek,mt7988a"; - - fragment@0 { - target = <&mdio_bus>; - __overlay__ { - #address-cells = <1>; - #size-cells = <0>; - - /* external Aquantia AQR113C */ - phy8: ethernet-phy@8 { - reg = <8>; - compatible = "ethernet-phy-ieee802.3-c45"; - reset-gpios = <&pio 71 GPIO_ACTIVE_LOW>; - reset-assert-us = <100000>; - reset-deassert-us = <221000>; - }; - }; - }; - - fragment@1 { - target = <&gmac2>; - __overlay__ { - phy-mode = "usxgmii"; - phy-connection-type = "usxgmii"; - phy = <&phy8>; - status = "okay"; - }; - }; -}; diff --git a/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth2-mxl.dtso b/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth2-mxl.dtso deleted file mode 100644 index 19e0b2799..000000000 --- a/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth2-mxl.dtso +++ /dev/null @@ -1,39 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0 OR MIT) -/* - * Copyright (C) 2022 MediaTek Inc. - * Author: Sam.Shih - */ - -/dts-v1/; -/plugin/; - -#include - -/ { - compatible = "mediatek,mt7988a-rfb", "mediatek,mt7988a"; - - fragment@0 { - target = <&mdio_bus>; - __overlay__ { - #address-cells = <1>; - #size-cells = <0>; - - /* external Maxlinear GPY211C */ - phy5: ethernet-phy@5 { - reg = <5>; - compatible = "ethernet-phy-ieee802.3-c45"; - phy-mode = "2500base-x"; - }; - }; - }; - - fragment@1 { - target = <&gmac2>; - __overlay__ { - phy-mode = "2500base-x"; - phy-connection-type = "2500base-x"; - phy = <&phy5>; - status = "okay"; - }; - }; -}; diff --git a/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth2-sfp.dtso b/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth2-sfp.dtso deleted file mode 100644 index b9aabd272..000000000 --- a/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth2-sfp.dtso +++ /dev/null @@ -1,47 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0 OR MIT) -/* - * Copyright (C) 2022 MediaTek Inc. - * Author: Sam.Shih - */ - -/dts-v1/; -/plugin/; - -#include - -/ { - compatible = "mediatek,mt7988a-rfb", "mediatek,mt7988a"; - - fragment@0 { - target = <&i2c1>; - __overlay__ { - pinctrl-names = "default"; - pinctrl-0 = <&i2c1_sfp_pins>; - status = "okay"; - }; - }; - - fragment@1 { - target-path = "/"; - __overlay__ { - sfp_esp0: sfp@0 { - compatible = "sff,sfp"; - i2c-bus = <&i2c1>; - mod-def0-gpios = <&pio 35 GPIO_ACTIVE_LOW>; - los-gpios = <&pio 33 GPIO_ACTIVE_HIGH>; - tx-disable-gpios = <&pio 29 GPIO_ACTIVE_HIGH>; - maximum-power-milliwatt = <3000>; - }; - }; - }; - - fragment@2 { - target = <&gmac2>; - __overlay__ { - phy-mode = "10gbase-r"; - managed = "in-band-status"; - sfp = <&sfp_esp0>; - status = "okay"; - }; - }; -}; diff --git a/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7988a-rfb-sd.dtso b/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7988a-rfb-sd.dtso deleted file mode 100644 index 04472cc12..000000000 --- a/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7988a-rfb-sd.dtso +++ /dev/null @@ -1,31 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0 OR MIT) -/* - * Copyright (C) 2023 MediaTek Inc. - * Author: Frank Wunderlich - */ - -/dts-v1/; -/plugin/; - -#include - -/ { - compatible = "mediatek,mt7988a-rfb", "mediatek,mt7988a"; - - fragment@1 { - target-path = <&mmc0>; - __overlay__ { - pinctrl-names = "default", "state_uhs"; - pinctrl-0 = <&mmc0_pins_sdcard>; - pinctrl-1 = <&mmc0_pins_sdcard>; - cd-gpios = <&pio 69 GPIO_ACTIVE_LOW>; - bus-width = <4>; - max-frequency = <52000000>; - cap-sd-highspeed; - vmmc-supply = <®_3p3v>; - vqmmc-supply = <®_3p3v>; - no-mmc; - status = "okay"; - }; - }; -}; diff --git a/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7988a-rfb-snfi-nand.dtso b/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7988a-rfb-snfi-nand.dtso deleted file mode 100644 index 618016517..000000000 --- a/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7988a-rfb-snfi-nand.dtso +++ /dev/null @@ -1,69 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0 OR MIT) -/* - * Copyright (C) 2022 MediaTek Inc. - * Author: Sam.Shih - */ - -/dts-v1/; -/plugin/; - -/ { - compatible = "mediatek,mt7988a-rfb", "mediatek,mt7988a"; - - fragment@0 { - target = <&snand>; - __overlay__ { - status = "okay"; - - flash@0 { - compatible = "spi-nand"; - reg = <0>; - spi-max-frequency = <52000000>; - spi-tx-buswidth = <4>; - spi-rx-buswidth = <4>; - mediatek,nmbm; - mediatek,bmt-max-ratio = <1>; - mediatek,bmt-max-reserved-blocks = <64>; - - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - partition@0 { - label = "BL2"; - reg = <0x00000 0x0100000>; - read-only; - }; - - partition@100000 { - label = "u-boot-env"; - reg = <0x0100000 0x0080000>; - }; - - partition@180000 { - label = "Factory"; - reg = <0x180000 0x0400000>; - }; - - partition@580000 { - label = "FIP"; - reg = <0x580000 0x0200000>; - }; - - partition@780000 { - label = "ubi"; - reg = <0x780000 0x7080000>; - }; - }; - }; - }; - }; - - fragment@1 { - target = <&bch>; - __overlay__ { - status = "okay"; - }; - }; -}; diff --git a/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7988a-rfb-spim-nand.dtso b/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7988a-rfb-spim-nand.dtso deleted file mode 100644 index e63436fa5..000000000 --- a/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7988a-rfb-spim-nand.dtso +++ /dev/null @@ -1,64 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0 OR MIT) -/* - * Copyright (C) 2022 MediaTek Inc. - * Author: Sam.Shih - */ - -/dts-v1/; -/plugin/; - -/ { - compatible = "mediatek,mt7988a-rfb", "mediatek,mt7988a"; - - fragment@0 { - target = <&spi0>; - __overlay__ { - pinctrl-names = "default"; - pinctrl-0 = <&spi0_flash_pins>; - status = "okay"; - - flash@0 { - compatible = "spi-nand"; - reg = <0>; - spi-max-frequency = <52000000>; - spi-tx-buswidth = <4>; - spi-rx-buswidth = <4>; - mediatek,nmbm; - mediatek,bmt-max-ratio = <1>; - mediatek,bmt-max-reserved-blocks = <64>; - - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - partition@0 { - label = "BL2"; - reg = <0x00000 0x0100000>; - read-only; - }; - - partition@100000 { - label = "u-boot-env"; - reg = <0x0100000 0x0080000>; - }; - - partition@180000 { - label = "Factory"; - reg = <0x180000 0x0400000>; - }; - - partition@580000 { - label = "FIP"; - reg = <0x580000 0x0200000>; - }; - - partition@780000 { - label = "ubi"; - reg = <0x780000 0x7080000>; - }; - }; - }; - }; - }; -}; diff --git a/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7988a-rfb-spim-nor.dtso b/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7988a-rfb-spim-nor.dtso deleted file mode 100644 index 33bd57b3f..000000000 --- a/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7988a-rfb-spim-nor.dtso +++ /dev/null @@ -1,59 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0 OR MIT) -/* - * Copyright (C) 2022 MediaTek Inc. - * Author: Sam.Shih - */ - -/dts-v1/; -/plugin/; - -/ { - compatible = "mediatek,mt7988a-rfb", "mediatek,mt7988a"; - - fragment@0 { - target = <&spi2>; - __overlay__ { - pinctrl-names = "default"; - pinctrl-0 = <&spi2_flash_pins>; - status = "okay"; - - flash@0 { - #address-cells = <1>; - #size-cells = <1>; - compatible = "jedec,spi-nor"; - spi-cal-enable; - spi-cal-mode = "read-data"; - spi-cal-datalen = <7>; - spi-cal-data = /bits/ 8 < - 0x53 0x46 0x5F 0x42 0x4F 0x4F 0x54>; /* SF_BOOT */ - spi-cal-addrlen = <1>; - spi-cal-addr = /bits/ 32 <0x0>; - reg = <0>; - spi-max-frequency = <52000000>; - spi-tx-bus-width = <4>; - spi-rx-bus-width = <4>; - - partition@00000 { - label = "BL2"; - reg = <0x00000 0x0040000>; - }; - partition@40000 { - label = "u-boot-env"; - reg = <0x40000 0x0010000>; - }; - partition@50000 { - label = "Factory"; - reg = <0x50000 0x0200000>; - }; - partition@250000 { - label = "FIP"; - reg = <0x250000 0x0080000>; - }; - partition@2D0000 { - label = "firmware"; - reg = <0x2D0000 0x1D30000>; - }; - }; - }; - }; -}; diff --git a/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7988a-rfb.dts b/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7988a-rfb.dts deleted file mode 100644 index 11dbf9830..000000000 --- a/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7988a-rfb.dts +++ /dev/null @@ -1,200 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0 OR MIT) -/* - * Copyright (C) 2022 MediaTek Inc. - * Author: Sam.Shih - */ - -/dts-v1/; -#include "mt7988a.dtsi" -#include -#include -#include - -/ { - model = "MediaTek MT7988A Reference Board"; - compatible = "mediatek,mt7988a-rfb", - "mediatek,mt7988"; - - chosen { - bootargs = "console=ttyS0,115200n1 loglevel=8 \ - earlycon=uart8250,mmio32,0x11000000 \ - pci=pcie_bus_perf"; - }; - - memory { - reg = <0 0x40000000 0 0x40000000>; - }; -}; - -ð { - pinctrl-0 = <&mdio0_pins>; - pinctrl-names = "default"; -}; - -&gmac0 { - status = "okay"; -}; - -&cpu0 { - proc-supply = <&rt5190_buck3>; -}; - -&cpu1 { - proc-supply = <&rt5190_buck3>; -}; - -&cpu2 { - proc-supply = <&rt5190_buck3>; -}; - -&cpu3 { - proc-supply = <&rt5190_buck3>; -}; - -&cci { - proc-supply = <&rt5190_buck3>; -}; - -ð { - status = "okay"; -}; - -&switch { - status = "okay"; -}; - -&gsw_phy0 { - pinctrl-names = "gbe-led"; - pinctrl-0 = <&gbe0_led0_pins>; -}; - -&gsw_phy0_led0 { - status = "okay"; - color = ; -}; - -&gsw_phy1 { - pinctrl-names = "gbe-led"; - pinctrl-0 = <&gbe1_led0_pins>; -}; - -&gsw_phy1_led0 { - status = "okay"; - color = ; -}; - -&gsw_phy2 { - pinctrl-names = "gbe-led"; - pinctrl-0 = <&gbe2_led0_pins>; -}; - -&gsw_phy2_led0 { - status = "okay"; - color = ; -}; - -&gsw_phy3 { - pinctrl-names = "gbe-led"; - pinctrl-0 = <&gbe3_led0_pins>; -}; - -&gsw_phy3_led0 { - status = "okay"; - color = ; -}; - -&i2c0 { - pinctrl-names = "default"; - pinctrl-0 = <&i2c0_pins>; - status = "okay"; - - rt5190a_64: rt5190a@64 { - compatible = "richtek,rt5190a"; - reg = <0x64>; - /*interrupts-extended = <&gpio26 0 IRQ_TYPE_LEVEL_LOW>;*/ - vin2-supply = <&rt5190_buck1>; - vin3-supply = <&rt5190_buck1>; - vin4-supply = <&rt5190_buck1>; - - regulators { - rt5190_buck1: buck1 { - regulator-name = "rt5190a-buck1"; - regulator-min-microvolt = <5090000>; - regulator-max-microvolt = <5090000>; - regulator-allowed-modes = - ; - regulator-boot-on; - regulator-always-on; - }; - buck2 { - regulator-name = "vcore"; - regulator-min-microvolt = <600000>; - regulator-max-microvolt = <1400000>; - regulator-boot-on; - regulator-always-on; - }; - rt5190_buck3: buck3 { - regulator-name = "vproc"; - regulator-min-microvolt = <600000>; - regulator-max-microvolt = <1400000>; - regulator-boot-on; - }; - buck4 { - regulator-name = "rt5190a-buck4"; - regulator-min-microvolt = <850000>; - regulator-max-microvolt = <850000>; - regulator-allowed-modes = - ; - regulator-boot-on; - regulator-always-on; - }; - ldo { - regulator-name = "rt5190a-ldo"; - regulator-min-microvolt = <1200000>; - regulator-max-microvolt = <1200000>; - regulator-boot-on; - regulator-always-on; - }; - }; - }; -}; - -&pcie0 { - status = "okay"; -}; - -&pcie1 { - status = "okay"; -}; - -&pcie2 { - status = "disabled"; -}; - -&pcie3 { - status = "okay"; -}; - -&ssusb0 { - status = "okay"; -}; - -&ssusb1 { - status = "okay"; -}; - -&tphy { - status = "okay"; -}; - -&uart0 { - status = "okay"; -}; - -&watchdog { - status = "okay"; -}; - -&xphy { - status = "okay"; -}; diff --git a/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7988a.dtsi b/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7988a.dtsi deleted file mode 100644 index 7fed1e138..000000000 --- a/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7988a.dtsi +++ /dev/null @@ -1,1441 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0 OR MIT) -/* - * Copyright (C) 2023 MediaTek Inc. - * Author: Sam.Shih - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -/ { - compatible = "mediatek,mt7988"; - interrupt-parent = <&gic>; - #address-cells = <2>; - #size-cells = <2>; - - clk40m: oscillator@0 { - compatible = "fixed-clock"; - clock-frequency = <40000000>; - #clock-cells = <0>; - clock-output-names = "clkxtal"; - }; - - cpus { - #address-cells = <1>; - #size-cells = <0>; - cpu0: cpu@0 { - device_type = "cpu"; - compatible = "arm,cortex-a73"; - enable-method = "psci"; - reg = <0x0>; - clocks = <&mcusys CLK_MCU_ARM_DIV_SEL>, - <&topckgen CLK_TOP_XTAL>; - clock-names = "cpu", "intermediate"; - operating-points-v2 = <&cluster0_opp>; - mediatek,cci = <&cci>; - }; - - cpu1: cpu@1 { - device_type = "cpu"; - compatible = "arm,cortex-a73"; - enable-method = "psci"; - reg = <0x1>; - clocks = <&mcusys CLK_MCU_ARM_DIV_SEL>, - <&topckgen CLK_TOP_XTAL>; - clock-names = "cpu", "intermediate"; - operating-points-v2 = <&cluster0_opp>; - mediatek,cci = <&cci>; - }; - - cpu2: cpu@2 { - device_type = "cpu"; - compatible = "arm,cortex-a73"; - enable-method = "psci"; - reg = <0x2>; - clocks = <&mcusys CLK_MCU_ARM_DIV_SEL>, - <&topckgen CLK_TOP_XTAL>; - clock-names = "cpu", "intermediate"; - operating-points-v2 = <&cluster0_opp>; - mediatek,cci = <&cci>; - }; - - cpu3: cpu@3 { - device_type = "cpu"; - compatible = "arm,cortex-a73"; - enable-method = "psci"; - reg = <0x3>; - clocks = <&mcusys CLK_MCU_ARM_DIV_SEL>, - <&topckgen CLK_TOP_XTAL>; - clock-names = "cpu", "intermediate"; - operating-points-v2 = <&cluster0_opp>; - mediatek,cci = <&cci>; - }; - - cluster0_opp: opp_table0 { - compatible = "operating-points-v2"; - opp-shared; - opp00 { - opp-hz = /bits/ 64 <800000000>; - opp-microvolt = <850000>; - }; - opp01 { - opp-hz = /bits/ 64 <1100000000>; - opp-microvolt = <850000>; - }; - opp02 { - opp-hz = /bits/ 64 <1500000000>; - opp-microvolt = <850000>; - }; - opp03 { - opp-hz = /bits/ 64 <1800000000>; - opp-microvolt = <900000>; - }; - }; - }; - - cci: cci { - compatible = "mediatek,mt7988-cci", - "mediatek,mt8183-cci"; - clocks = <&mcusys CLK_MCU_BUS_DIV_SEL>, - <&topckgen CLK_TOP_XTAL>; - clock-names = "cci", "intermediate"; - operating-points-v2 = <&cci_opp>; - }; - - cci_opp: opp_table_cci { - compatible = "operating-points-v2"; - opp-shared; - opp00 { - opp-hz = /bits/ 64 <480000000>; - opp-microvolt = <850000>; - }; - opp01 { - opp-hz = /bits/ 64 <660000000>; - opp-microvolt = <850000>; - }; - opp02 { - opp-hz = /bits/ 64 <900000000>; - opp-microvolt = <850000>; - }; - opp03 { - opp-hz = /bits/ 64 <1080000000>; - opp-microvolt = <900000>; - }; - }; - - pmu { - compatible = "arm,cortex-a73-pmu"; - interrupt-parent = <&gic>; - interrupt = ; - }; - - psci { - compatible = "arm,psci-0.2"; - method = "smc"; - }; - - reserved-memory { - #address-cells = <2>; - #size-cells = <2>; - ranges; - - /* 320 KiB reserved for ARM Trusted Firmware (BL31 and BL32) */ - secmon_reserved: secmon@43000000 { - reg = <0 0x43000000 0 0x50000>; - no-map; - }; - }; - - thermal-zones { - cpu_thermal: cpu-thermal { - polling-delay-passive = <1000>; - polling-delay = <1000>; - thermal-sensors = <&lvts 0>; - trips { - cpu_trip_crit: crit { - temperature = <125000>; - hysteresis = <2000>; - type = "critical"; - }; - - cpu_trip_hot: hot { - temperature = <120000>; - hysteresis = <2000>; - type = "hot"; - }; - - cpu_trip_active_high: active-high { - temperature = <115000>; - hysteresis = <2000>; - type = "active"; - }; - - cpu_trip_active_med: active-med { - temperature = <85000>; - hysteresis = <2000>; - type = "active"; - }; - - cpu_trip_active_low: active-low { - temperature = <40000>; - hysteresis = <2000>; - type = "active"; - }; - }; - - cooling-maps { - cpu-active-high { - /* active: set fan to cooling level 2 */ - cooling-device = <&fan 3 3>; - trip = <&cpu_trip_active_high>; - }; - - cpu-active-low { - /* active: set fan to cooling level 1 */ - cooling-device = <&fan 2 2>; - trip = <&cpu_trip_active_med>; - }; - - cpu-passive { - /* passive: set fan to cooling level 0 */ - cooling-device = <&fan 1 1>; - trip = <&cpu_trip_active_low>; - }; - }; - }; - }; - - timer { - compatible = "arm,armv8-timer"; - interrupt-parent = <&gic>; - interrupts = , - , - , - ; - }; - - reg_1p8v: regulator-1p8v { - compatible = "regulator-fixed"; - regulator-name = "fixed-1.8V"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - regulator-boot-on; - regulator-always-on; - }; - - reg_3p3v: regulator-3p3v { - compatible = "regulator-fixed"; - regulator-name = "fixed-3.3V"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - regulator-boot-on; - regulator-always-on; - }; - - soc { - #address-cells = <2>; - #size-cells = <2>; - compatible = "simple-bus"; - ranges; - - gic: interrupt-controller@c000000 { - compatible = "arm,gic-v3"; - #interrupt-cells = <3>; - interrupt-parent = <&gic>; - interrupt-controller; - reg = <0 0x0c000000 0 0x40000>, /* GICD */ - <0 0x0c080000 0 0x200000>, /* GICR */ - <0 0x0c400000 0 0x2000>, /* GICC */ - <0 0x0c410000 0 0x1000>, /* GICH */ - <0 0x0c420000 0 0x2000>; /* GICV */ - - interrupts = ; - }; - - phyfw: phy-firmware@f000000 { - compatible = "mediatek,2p5gphy-fw"; - reg = <0 0x0f000000 0 0x8000>, - <0 0x0f100000 0 0x20000>, - <0 0x0f0f0000 0 0x200>; - }; - - infracfg: infracfg@10001000 { - compatible = "mediatek,mt7988-infracfg", "syscon"; - reg = <0 0x10001000 0 0x1000>; - #clock-cells = <1>; - }; - - topckgen: topckgen@1001b000 { - compatible = "mediatek,mt7988-topckgen", "syscon"; - reg = <0 0x1001b000 0 0x1000>; - #clock-cells = <1>; - }; - - watchdog: watchdog@1001c000 { - compatible = "mediatek,mt7988-wdt", - "mediatek,mt6589-wdt", - "syscon"; - reg = <0 0x1001c000 0 0x1000>; - interrupts = ; - #reset-cells = <1>; - }; - - apmixedsys: apmixedsys@1001e000 { - compatible = "mediatek,mt7988-apmixedsys"; - reg = <0 0x1001e000 0 0x1000>; - #clock-cells = <1>; - }; - - pio: pinctrl@1001f000 { - compatible = "mediatek,mt7988-pinctrl", "syscon"; - reg = <0 0x1001f000 0 0x1000>, - <0 0x11c10000 0 0x1000>, - <0 0x11d00000 0 0x1000>, - <0 0x11d20000 0 0x1000>, - <0 0x11e00000 0 0x1000>, - <0 0x11f00000 0 0x1000>, - <0 0x1000b000 0 0x1000>; - reg-names = "gpio_base", "iocfg_tr_base", - "iocfg_br_base", "iocfg_rb_base", - "iocfg_lb_base", "iocfg_tl_base", "eint"; - gpio-controller; - #gpio-cells = <2>; - gpio-ranges = <&pio 0 0 84>; - interrupt-controller; - interrupts = ; - interrupt-parent = <&gic>; - #interrupt-cells = <2>; - - mdio0_pins: mdio0-pins { - mux { - function = "eth"; - groups = "mdc_mdio0"; - }; - - conf { - groups = "mdc_mdio0"; - drive-strength = ; - }; - }; - - i2c0_pins: i2c0-pins-g0 { - mux { - function = "i2c"; - groups = "i2c0_1"; - }; - }; - - i2c1_pins: i2c1-pins-g0 { - mux { - function = "i2c"; - groups = "i2c1_0"; - }; - }; - - i2c1_sfp_pins: i2c1-sfp-pins-g0 { - mux { - function = "i2c"; - groups = "i2c1_sfp"; - }; - }; - - i2c2_pins: i2c2-pins { - mux { - function = "i2c"; - groups = "i2c2"; - }; - }; - - i2c2_0_pins: i2c2-pins-g0 { - mux { - function = "i2c"; - groups = "i2c2_0"; - }; - }; - - i2c2_1_pins: i2c2-pins-g1 { - mux { - function = "i2c"; - groups = "i2c2_1"; - }; - }; - - gbe0_led0_pins: gbe0-led0-pins { - mux { - function = "led"; - groups = "gbe0_led0"; - }; - }; - - gbe1_led0_pins: gbe1-led0-pins { - mux { - function = "led"; - groups = "gbe1_led0"; - }; - }; - - gbe2_led0_pins: gbe2-led0-pins { - mux { - function = "led"; - groups = "gbe2_led0"; - }; - }; - - gbe3_led0_pins: gbe3-led0-pins { - mux { - function = "led"; - groups = "gbe3_led0"; - }; - }; - - gbe0_led1_pins: gbe0-led1-pins { - mux { - function = "led"; - groups = "gbe0_led1"; - }; - }; - - gbe1_led1_pins: gbe1-led1-pins { - mux { - function = "led"; - groups = "gbe1_led1"; - }; - }; - - gbe2_led1_pins: gbe2-led1-pins { - mux { - function = "led"; - groups = "gbe2_led1"; - }; - }; - - gbe3_led1_pins: gbe3-led1-pins { - mux { - function = "led"; - groups = "gbe3_led1"; - }; - }; - - i2p5gbe_led0_pins: 2p5gbe-led0-pins { - mux { - function = "led"; - groups = "2p5gbe_led0"; - }; - }; - - i2p5gbe_led1_pins: 2p5gbe-led1-pins { - mux { - function = "led"; - groups = "2p5gbe_led1"; - }; - }; - - mmc0_pins_emmc_45: mmc0-pins-emmc-45 { - mux { - function = "flash"; - groups = "emmc_45"; - }; - }; - - mmc0_pins_emmc_51: mmc0-pins-emmc-51 { - mux { - function = "flash"; - groups = "emmc_51"; - }; - }; - - mmc0_pins_sdcard: mmc0-pins-sdcard { - mux { - function = "flash"; - groups = "sdcard"; - }; - }; - - uart0_pins: uart0-pins { - mux { - function = "uart"; - groups = "uart0"; - }; - }; - - snfi_pins: snfi-pins { - mux { - function = "flash"; - groups = "snfi"; - }; - }; - - spi0_pins: spi0-pins { - mux { - function = "spi"; - groups = "spi0"; - }; - }; - - spi0_flash_pins: spi0-flash-pins { - mux { - function = "spi"; - groups = "spi0", "spi0_wp_hold"; - }; - }; - - spi1_pins: spi1-pins { - mux { - function = "spi"; - groups = "spi1"; - }; - }; - - spi2_pins: spi2-pins { - mux { - function = "spi"; - groups = "spi2"; - }; - }; - - spi2_flash_pins: spi2-flash-pins { - mux { - function = "spi"; - groups = "spi2", "spi2_wp_hold"; - }; - }; - - pcie0_pins: pcie0-pins { - mux { - function = "pcie"; - groups = "pcie_2l_0_pereset", "pcie_clk_req_n0_0", - "pcie_wake_n0_0"; - }; - }; - - pcie1_pins: pcie1-pins { - mux { - function = "pcie"; - groups = "pcie_2l_1_pereset", "pcie_clk_req_n1", - "pcie_wake_n1_0"; - }; - }; - - pcie2_pins: pcie2-pins { - mux { - function = "pcie"; - groups = "pcie_1l_0_pereset", "pcie_clk_req_n2_0", - "pcie_wake_n2_0"; - }; - }; - - pcie3_pins: pcie3-pins { - mux { - function = "pcie"; - groups = "pcie_1l_1_pereset", "pcie_clk_req_n3", - "pcie_wake_n3_0"; - }; - }; - }; - - sgmiisys0: syscon@10060000 { - compatible = "mediatek,mt7988-sgmiisys", - "mediatek,mt7988-sgmiisys_0", - "syscon"; - reg = <0 0x10060000 0 0x1000>; - #clock-cells = <1>; - }; - - sgmiisys1: syscon@10070000 { - compatible = "mediatek,mt7988-sgmiisys", - "mediatek,mt7988-sgmiisys_1", - "syscon"; - reg = <0 0x10070000 0 0x1000>; - #clock-cells = <1>; - }; - - usxgmiisys0: usxgmiisys@10080000 { - compatible = "mediatek,mt7988-usxgmiisys", - "mediatek,mt7988-usxgmiisys_0", - "syscon"; - reg = <0 0x10080000 0 0x1000>; - #clock-cells = <1>; - }; - - usxgmiisys1: usxgmiisys@10081000 { - compatible = "mediatek,mt7988-usxgmiisys", - "mediatek,mt7988-usxgmiisys_1", - "syscon"; - reg = <0 0x10081000 0 0x1000>; - #clock-cells = <1>; - }; - - xfi_pextp0: xfi-pextp@11f20000 { - compatible = "mediatek,mt7988-xfi-pextp", - "mediatek,mt7988-xfi-pextp_0", - "syscon"; - reg = <0 0x11f20000 0 0x10000>; - #clock-cells = <1>; - }; - - xfi_pextp1: xfi-pextp@11f30000 { - compatible = "mediatek,mt7988-xfi-pextp", - "mediatek,mt7988-xfi-pextp_1", - "syscon"; - reg = <0 0x11f30000 0 0x10000>; - #clock-cells = <1>; - }; - - xfi_pll: xfi-pll@11f40000 { - compatible = "mediatek,mt7988-xfi-pll", "syscon"; - reg = <0 0x11f40000 0 0x1000>; - #clock-cells = <1>; - }; - - mcusys: mcusys@100e0000 { - compatible = "mediatek,mt7988-mcusys", "syscon"; - reg = <0 0x100e0000 0 0x1000>; - #clock-cells = <1>; - }; - - uart0: serial@11000000 { - compatible = "mediatek,mt7986-uart", - "mediatek,mt6577-uart"; - reg = <0 0x11000000 0 0x100>; - interrupts = ; - /* - * 8250-mtk driver don't control "baud" clock since commit - * e32a83c70cf9 (kernel v5.7), but both "baud" and "bus" clocks - * still need to be passed to the driver to prevent probe fail - */ - clocks = <&topckgen CLK_TOP_UART_SEL>, - <&infracfg CLK_INFRA_52M_UART0_CK>; - clock-names = "baud", "bus"; - assigned-clocks = <&topckgen CLK_TOP_UART_SEL>, - <&infracfg CLK_INFRA_MUX_UART0_SEL>; - assigned-clock-parents = <&topckgen CLK_TOP_XTAL>, - <&topckgen CLK_TOP_UART_SEL>; - pinctrl-names = "default"; - pinctrl-0 = <&uart0_pins>; - status = "disabled"; - }; - - snand: spi@11001000 { - compatible = "mediatek,mt7986-snand"; - reg = <0 0x11001000 0 0x1000>; - interrupts = ; - clocks = <&infracfg CLK_INFRA_SPINFI>, - <&infracfg CLK_INFRA_NFI>; - clock-names = "pad_clk", "nfi_clk"; - assigned-clocks = <&topckgen CLK_TOP_SPINFI_SEL>, - <&topckgen CLK_TOP_NFI1X_SEL>; - assigned-clock-parents = <&topckgen CLK_TOP_MPLL_D8>, - <&topckgen CLK_TOP_MPLL_D8>; - nand-ecc-engine = <&bch>; - mediatek,quad-spi; - #address-cells = <1>; - #size-cells = <0>; - pinctrl-names = "default"; - pinctrl-0 = <&snfi_pins>; - status = "disabled"; - }; - - bch: ecc@11002000 { - compatible = "mediatek,mt7686-ecc"; - reg = <0 0x11002000 0 0x1000>; - interrupts = ; - clocks = <&topckgen CLK_TOP_NFI1X_SEL>; - clock-names = "nfiecc_clk"; - status = "disabled"; - }; - - i2c0: i2c@11003000 { - compatible = "mediatek,mt7988-i2c", - "mediatek,mt7981-i2c"; - reg = <0 0x11003000 0 0x1000>, - <0 0x10217080 0 0x80>; - interrupts = ; - clock-div = <1>; - clocks = <&infracfg CLK_INFRA_I2C_BCK>, - <&infracfg CLK_INFRA_66M_AP_DMA_BCK>; - clock-names = "main", "dma"; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; - }; - - i2c1: i2c@11004000 { - compatible = "mediatek,mt7988-i2c", - "mediatek,mt7981-i2c"; - reg = <0 0x11004000 0 0x1000>, - <0 0x10217100 0 0x80>; - interrupts = ; - clock-div = <1>; - clocks = <&infracfg CLK_INFRA_I2C_BCK>, - <&infracfg CLK_INFRA_66M_AP_DMA_BCK>; - clock-names = "main", "dma"; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; - }; - - i2c2: i2c@11005000 { - compatible = "mediatek,mt7988-i2c", - "mediatek,mt7981-i2c"; - reg = <0 0x11005000 0 0x1000>, - <0 0x10217180 0 0x80>; - interrupts = ; - clock-div = <1>; - clocks = <&infracfg CLK_INFRA_I2C_BCK>, - <&infracfg CLK_INFRA_66M_AP_DMA_BCK>; - clock-names = "main", "dma"; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; - }; - - spi0: spi@11007000 { - compatible = "mediatek,ipm-spi-quad", "mediatek,spi-ipm"; - reg = <0 0x11007000 0 0x100>; - interrupts = ; - clocks = <&topckgen CLK_TOP_MPLL_D2>, - <&topckgen CLK_TOP_SPI_SEL>, - <&infracfg CLK_INFRA_104M_SPI0>, - <&infracfg CLK_INFRA_66M_SPI0_HCK>; - clock-names = "parent-clk", "sel-clk", "spi-clk", - "spi-hclk"; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; - }; - - spi1: spi@11008000 { - compatible = "mediatek,ipm-spi-single", "mediatek,spi-ipm"; - reg = <0 0x11008000 0 0x100>; - interrupts = ; - clocks = <&topckgen CLK_TOP_MPLL_D2>, - <&topckgen CLK_TOP_SPI_SEL>, - <&infracfg CLK_INFRA_104M_SPI1>, - <&infracfg CLK_INFRA_66M_SPI1_HCK>; - clock-names = "parent-clk", "sel-clk", "spi-clk", - "spi-hclk"; - #address-cells = <1>; - #size-cells = <0>; - pinctrl-names = "default"; - pinctrl-0 = <&spi1_pins>; - status = "disabled"; - }; - - spi2: spi@11009000 { - compatible = "mediatek,ipm-spi-quad", "mediatek,spi-ipm"; - reg = <0 0x11009000 0 0x100>; - interrupts = ; - clocks = <&topckgen CLK_TOP_MPLL_D2>, - <&topckgen CLK_TOP_SPI_SEL>, - <&infracfg CLK_INFRA_104M_SPI2_BCK>, - <&infracfg CLK_INFRA_66M_SPI2_HCK>; - clock-names = "parent-clk", "sel-clk", "spi-clk", - "spi-hclk"; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; - }; - - pwm: pwm@10048000 { - compatible = "mediatek,mt7988-pwm"; - reg = <0 0x10048000 0 0x1000>; - #pwm-cells = <2>; - clocks = <&infracfg CLK_INFRA_66M_PWM_BCK>, - <&infracfg CLK_INFRA_66M_PWM_HCK>, - <&infracfg CLK_INFRA_66M_PWM_CK1>, - <&infracfg CLK_INFRA_66M_PWM_CK2>, - <&infracfg CLK_INFRA_66M_PWM_CK3>, - <&infracfg CLK_INFRA_66M_PWM_CK4>, - <&infracfg CLK_INFRA_66M_PWM_CK5>, - <&infracfg CLK_INFRA_66M_PWM_CK6>, - <&infracfg CLK_INFRA_66M_PWM_CK7>, - <&infracfg CLK_INFRA_66M_PWM_CK8>; - clock-names = "top", "main", "pwm1", "pwm2", "pwm3", - "pwm4","pwm5","pwm6","pwm7","pwm8"; - status = "disabled"; - }; - - fan: pwm-fan { - compatible = "pwm-fan"; - /* cooling level (0, 1, 2) : (0% duty, 50% duty, 100% duty) */ - cooling-levels = <0 128 255>; - #cooling-cells = <2>; - #thermal-sensor-cells = <1>; - status = "disabled"; - }; - - lvts: lvts@1100a000 { - compatible = "mediatek,mt7988-lvts"; - #thermal-sensor-cells = <1>; - reg = <0 0x1100a000 0 0x1000>; - clocks = <&infracfg CLK_INFRA_26M_THERM_SYSTEM>; - clock-names = "lvts_clk"; - nvmem-cells = <&lvts_calibration>; - nvmem-cell-names = "e_data1"; - }; - - crypto: crypto@15600000 { - compatible = "inside-secure,safexcel-eip197b"; - reg = <0 0x15600000 0 0x180000>; - interrupts = , - , - , - ; - interrupt-names = "ring0", "ring1", "ring2", "ring3"; - status = "okay"; - }; - - afe: audio-controller@11210000 { - compatible = "mediatek,mt79xx-audio"; - reg = <0 0x11210000 0 0x9000>; - interrupts = ; - clocks = <&infracfg CLK_INFRA_66M_AUD_SLV_BCK>, - <&infracfg CLK_INFRA_AUD_26M>, - <&infracfg CLK_INFRA_AUD_L>, - <&infracfg CLK_INFRA_AUD_AUD>, - <&infracfg CLK_INFRA_AUD_EG2>, - <&topckgen CLK_TOP_AUD_SEL>, - <&topckgen CLK_TOP_AUD_I2S_M>; - clock-names = "aud_bus_ck", - "aud_26m_ck", - "aud_l_ck", - "aud_aud_ck", - "aud_eg2_ck", - "aud_sel", - "aud_i2s_m"; - assigned-clocks = <&topckgen CLK_TOP_AUD_SEL>, - <&topckgen CLK_TOP_A1SYS_SEL>, - <&topckgen CLK_TOP_AUD_L_SEL>, - <&topckgen CLK_TOP_A_TUNER_SEL>; - assigned-clock-parents = <&apmixedsys CLK_APMIXED_APLL2>, - <&topckgen CLK_TOP_APLL2_D4>, - <&apmixedsys CLK_APMIXED_APLL2>, - <&topckgen CLK_TOP_APLL2_D4>; - status = "disabled"; - }; - - pcie2: pcie@11280000 { - compatible = "mediatek,mt7988-pcie", - "mediatek,mt7986-pcie", - "mediatek,mt8192-pcie"; - device_type = "pci"; - #address-cells = <3>; - #size-cells = <2>; - reg = <0 0x11280000 0 0x2000>; - reg-names = "pcie-mac"; - linux,pci-domain = <3>; - interrupts = ; - bus-range = <0x00 0xff>; - ranges = <0x81000000 0x00 0x20000000 0x00 - 0x20000000 0x00 0x00200000>, - <0x82000000 0x00 0x20200000 0x00 - 0x20200000 0x00 0x07e00000>; - clocks = <&infracfg CLK_INFRA_PCIE_PIPE_P2>, - <&infracfg CLK_INFRA_PCIE_GFMUX_TL_P2>, - <&infracfg CLK_INFRA_PCIE_PERI_26M_CK_P2>, - <&infracfg CLK_INFRA_133M_PCIE_CK_P2>; - clock-names = "pl_250m", "tl_26m", "peri_26m", - "top_133m"; - pinctrl-names = "default"; - pinctrl-0 = <&pcie2_pins>; - status = "disabled"; - - phys = <&xphyu3port0 PHY_TYPE_PCIE>; - phy-names = "pcie-phy"; - - #interrupt-cells = <1>; - interrupt-map-mask = <0 0 0 0x7>; - interrupt-map = <0 0 0 1 &pcie_intc2 0>, - <0 0 0 2 &pcie_intc2 1>, - <0 0 0 3 &pcie_intc2 2>, - <0 0 0 4 &pcie_intc2 3>; - pcie_intc2: interrupt-controller { - #address-cells = <0>; - #interrupt-cells = <1>; - interrupt-controller; - }; - }; - - pcie3: pcie@11290000 { - compatible = "mediatek,mt7988-pcie", - "mediatek,mt7986-pcie", - "mediatek,mt8192-pcie"; - device_type = "pci"; - #address-cells = <3>; - #size-cells = <2>; - reg = <0 0x11290000 0 0x2000>; - reg-names = "pcie-mac"; - linux,pci-domain = <2>; - interrupts = ; - bus-range = <0x00 0xff>; - ranges = <0x81000000 0x00 0x28000000 0x00 - 0x28000000 0x00 0x00200000>, - <0x82000000 0x00 0x28200000 0x00 - 0x28200000 0x00 0x07e00000>; - clocks = <&infracfg CLK_INFRA_PCIE_PIPE_P3>, - <&infracfg CLK_INFRA_PCIE_GFMUX_TL_P3>, - <&infracfg CLK_INFRA_PCIE_PERI_26M_CK_P3>, - <&infracfg CLK_INFRA_133M_PCIE_CK_P3>; - clock-names = "pl_250m", "tl_26m", "peri_26m", - "top_133m"; - pinctrl-names = "default"; - pinctrl-0 = <&pcie3_pins>; - status = "disabled"; - - #interrupt-cells = <1>; - interrupt-map-mask = <0 0 0 0x7>; - interrupt-map = <0 0 0 1 &pcie_intc3 0>, - <0 0 0 2 &pcie_intc3 1>, - <0 0 0 3 &pcie_intc3 2>, - <0 0 0 4 &pcie_intc3 3>; - pcie_intc3: interrupt-controller { - #address-cells = <0>; - #interrupt-cells = <1>; - interrupt-controller; - }; - }; - - pcie0: pcie@11300000 { - compatible = "mediatek,mt7988-pcie", - "mediatek,mt7986-pcie", - "mediatek,mt8192-pcie"; - device_type = "pci"; - #address-cells = <3>; - #size-cells = <2>; - reg = <0 0x11300000 0 0x2000>; - reg-names = "pcie-mac"; - linux,pci-domain = <0>; - interrupts = ; - bus-range = <0x00 0xff>; - ranges = <0x81000000 0x00 0x30000000 0x00 - 0x30000000 0x00 0x00200000>, - <0x82000000 0x00 0x30200000 0x00 - 0x30200000 0x00 0x07e00000>; - clocks = <&infracfg CLK_INFRA_PCIE_PIPE_P0>, - <&infracfg CLK_INFRA_PCIE_GFMUX_TL_P0>, - <&infracfg CLK_INFRA_PCIE_PERI_26M_CK_P0>, - <&infracfg CLK_INFRA_133M_PCIE_CK_P0>; - clock-names = "pl_250m", "tl_26m", "peri_26m", - "top_133m"; - pinctrl-names = "default"; - pinctrl-0 = <&pcie0_pins>; - status = "disabled"; - - #interrupt-cells = <1>; - interrupt-map-mask = <0 0 0 0x7>; - interrupt-map = <0 0 0 1 &pcie_intc0 0>, - <0 0 0 2 &pcie_intc0 1>, - <0 0 0 3 &pcie_intc0 2>, - <0 0 0 4 &pcie_intc0 3>; - pcie_intc0: interrupt-controller { - #address-cells = <0>; - #interrupt-cells = <1>; - interrupt-controller; - }; - }; - - pcie1: pcie@11310000 { - compatible = "mediatek,mt7988-pcie", - "mediatek,mt7986-pcie", - "mediatek,mt8192-pcie"; - device_type = "pci"; - #address-cells = <3>; - #size-cells = <2>; - reg = <0 0x11310000 0 0x2000>; - reg-names = "pcie-mac"; - linux,pci-domain = <1>; - interrupts = ; - bus-range = <0x00 0xff>; - ranges = <0x81000000 0x00 0x38000000 0x00 - 0x38000000 0x00 0x00200000>, - <0x82000000 0x00 0x38200000 0x00 - 0x38200000 0x00 0x07e00000>; - clocks = <&infracfg CLK_INFRA_PCIE_PIPE_P1>, - <&infracfg CLK_INFRA_PCIE_GFMUX_TL_P1>, - <&infracfg CLK_INFRA_PCIE_PERI_26M_CK_P1>, - <&infracfg CLK_INFRA_133M_PCIE_CK_P1>; - clock-names = "pl_250m", "tl_26m", "peri_26m", - "top_133m"; - pinctrl-names = "default"; - pinctrl-0 = <&pcie1_pins>; - status = "disabled"; - - #interrupt-cells = <1>; - interrupt-map-mask = <0 0 0 0x7>; - interrupt-map = <0 0 0 1 &pcie_intc1 0>, - <0 0 0 2 &pcie_intc1 1>, - <0 0 0 3 &pcie_intc1 2>, - <0 0 0 4 &pcie_intc1 3>; - pcie_intc1: interrupt-controller { - #address-cells = <0>; - #interrupt-cells = <1>; - interrupt-controller; - }; - }; - - ssusb0: usb@11190000 { - compatible = "mediatek,mt7988-xhci", - "mediatek,mtk-xhci"; - reg = <0 0x11190000 0 0x2e00>, - <0 0x11193e00 0 0x0100>; - reg-names = "mac", "ippc"; - interrupts = ; - phys = <&xphyu2port0 PHY_TYPE_USB2>, - <&xphyu3port0 PHY_TYPE_USB3>; - clocks = <&infracfg CLK_INFRA_USB_SYS>, - <&infracfg CLK_INFRA_USB_XHCI>, - <&infracfg CLK_INFRA_USB_REF>, - <&infracfg CLK_INFRA_66M_USB_HCK>, - <&infracfg CLK_INFRA_133M_USB_HCK>; - clock-names = "sys_ck", - "xhci_ck", - "ref_ck", - "mcu_ck", - "dma_ck"; - #address-cells = <2>; - #size-cells = <2>; - mediatek,p0_speed_fixup; - status = "disabled"; - }; - - ssusb1: usb@11200000 { - compatible = "mediatek,mt7988-xhci", - "mediatek,mtk-xhci"; - reg = <0 0x11200000 0 0x2e00>, - <0 0x11203e00 0 0x0100>; - reg-names = "mac", "ippc"; - interrupts = ; - phys = <&tphyu2port0 PHY_TYPE_USB2>, - <&tphyu3port0 PHY_TYPE_USB3>; - clocks = <&infracfg CLK_INFRA_USB_SYS_CK_P1>, - <&infracfg CLK_INFRA_USB_XHCI_CK_P1>, - <&infracfg CLK_INFRA_USB_CK_P1>, - <&infracfg CLK_INFRA_66M_USB_HCK_CK_P1>, - <&infracfg CLK_INFRA_133M_USB_HCK_CK_P1>; - clock-names = "sys_ck", - "xhci_ck", - "ref_ck", - "mcu_ck", - "dma_ck"; - #address-cells = <2>; - #size-cells = <2>; - status = "disabled"; - }; - - mmc0: mmc@11230000 { - compatible = "mediatek,mt7986-mmc", - "mediatek,mt7981-mmc"; - reg = <0 0x11230000 0 0x1000>, - <0 0x11D60000 0 0x1000>; - interrupts = ; - clocks = <&infracfg CLK_INFRA_MSDC400>, - <&infracfg CLK_INFRA_MSDC2_HCK>, - <&infracfg CLK_INFRA_66M_MSDC_0_HCK>, - <&infracfg CLK_INFRA_133M_MSDC_0_HCK>; - assigned-clocks = <&topckgen CLK_TOP_EMMC_250M_SEL>, - <&topckgen CLK_TOP_EMMC_400M_SEL>; - assigned-clock-parents = <&topckgen CLK_TOP_NET1PLL_D5_D2>, - <&apmixedsys CLK_APMIXED_MSDCPLL>; - clock-names = "source", - "hclk", - "axi_cg", - "ahb_cg"; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; - }; - - tphy: tphy@11c50000 { - compatible = "mediatek,mt7988", - "mediatek,generic-tphy-v2"; - #address-cells = <2>; - #size-cells = <2>; - ranges; - status = "disabled"; - tphyu2port0: usb-phy@11c50000 { - reg = <0 0x11c50000 0 0x700>; - clocks = <&infracfg CLK_INFRA_USB_UTMI_CK_P1>; - clock-names = "ref"; - #phy-cells = <1>; - }; - tphyu3port0: usb-phy@11c50700 { - reg = <0 0x11c50700 0 0x900>; - clocks = <&infracfg CLK_INFRA_USB_PIPE_CK_P1>; - clock-names = "ref"; - #phy-cells = <1>; - mediatek,usb3-pll-ssc-delta; - mediatek,usb3-pll-ssc-delta1; - }; - }; - - topmisc: topmisc@11d10000 { - compatible = "mediatek,mt7988-topmisc", "syscon", - "mediatek,mt7988-power-controller"; - reg = <0 0x11d10000 0 0x10000>; - #clock-cells = <1>; - #power-domain-cells = <1>; - #address-cells = <1>; - #size-cells = <0>; - }; - - xphy: xphy@11e10000 { - compatible = "mediatek,mt7988", - "mediatek,xsphy"; - #address-cells = <2>; - #size-cells = <2>; - ranges; - status = "disabled"; - - xphyu2port0: usb-phy@11e10000 { - reg = <0 0x11e10000 0 0x400>; - clocks = <&infracfg CLK_INFRA_USB_UTMI>; - clock-names = "ref"; - #phy-cells = <1>; - }; - - xphyu3port0: usb-phy@11e13000 { - reg = <0 0x11e13400 0 0x500>; - clocks = <&infracfg CLK_INFRA_USB_PIPE>; - clock-names = "ref"; - #phy-cells = <1>; - mediatek,syscon-type = <&topmisc 0x218 0>; - }; - }; - - efuse: efuse@11f50000 { - compatible = "mediatek,efuse"; - reg = <0 0x11f50000 0 0x1000>; - #address-cells = <1>; - #size-cells = <1>; - - lvts_calibration: calib@918 { - reg = <0x918 0x28>; - }; - phy_calibration_p0: calib@940 { - reg = <0x940 0x10>; - }; - phy_calibration_p1: calib@954 { - reg = <0x954 0x10>; - }; - phy_calibration_p2: calib@968 { - reg = <0x968 0x10>; - }; - phy_calibration_p3: calib@97c { - reg = <0x97c 0x10>; - }; - cpufreq_calibration: calib@278 { - reg = <0x278 0x1>; - }; - }; - - ethsys: syscon@15000000 { - #address-cells = <1>; - #size-cells = <1>; - compatible = "mediatek,mt7988-ethsys", "syscon"; - reg = <0 0x15000000 0 0x1000>; - #clock-cells = <1>; - #reset-cells = <1>; - }; - - switch: switch@15020000 { - #address-cells = <1>; - #size-cells = <1>; - compatible = "mediatek,mt7988-switch"; - reg = <0 0x15020000 0 0x8000>; - interrupt-controller; - #interrupt-cells = <1>; - interrupt-parent = <&gic>; - interrupts = ; - resets = <ðrst 0>; - - ports { - #address-cells = <1>; - #size-cells = <0>; - - port@0 { - reg = <0>; - label = "lan0"; - phy-mode = "internal"; - phy-handle = <&gsw_phy0>; - }; - - port@1 { - reg = <1>; - label = "lan1"; - phy-mode = "internal"; - phy-handle = <&gsw_phy1>; - }; - - port@2 { - reg = <2>; - label = "lan2"; - phy-mode = "internal"; - phy-handle = <&gsw_phy2>; - }; - - port@3 { - reg = <3>; - label = "lan3"; - phy-mode = "internal"; - phy-handle = <&gsw_phy3>; - }; - - port@6 { - reg = <6>; - ethernet = <&gmac0>; - phy-mode = "internal"; - - fixed-link { - speed = <10000>; - full-duplex; - pause; - }; - }; - }; - - mdio { - #address-cells = <1>; - #size-cells = <0>; - mediatek,pio = <&pio>; - - gsw_phy0: ethernet-phy@0 { - compatible = "ethernet-phy-ieee802.3-c22"; - reg = <0>; - phy-mode = "internal"; - nvmem-cells = <&phy_calibration_p0>; - nvmem-cell-names = "phy-cal-data"; - - leds { - #address-cells = <1>; - #size-cells = <0>; - - gsw_phy0_led0: gsw-phy0-led0@0 { - reg = <0>; - function = LED_FUNCTION_LAN; - status = "disabled"; - }; - - gsw_phy0_led1: gsw-phy0-led1@1 { - reg = <1>; - function = LED_FUNCTION_LAN; - status = "disabled"; - }; - }; - }; - - gsw_phy1: ethernet-phy@1 { - compatible = "ethernet-phy-ieee802.3-c22"; - reg = <1>; - phy-mode = "internal"; - nvmem-cells = <&phy_calibration_p1>; - nvmem-cell-names = "phy-cal-data"; - - leds { - #address-cells = <1>; - #size-cells = <0>; - - gsw_phy1_led0: gsw-phy1-led0@0 { - reg = <0>; - function = LED_FUNCTION_LAN; - status = "disabled"; - }; - - gsw_phy1_led1: gsw-phy1-led1@1 { - reg = <1>; - function = LED_FUNCTION_LAN; - status = "disabled"; - }; - }; - }; - - gsw_phy2: ethernet-phy@2 { - compatible = "ethernet-phy-ieee802.3-c22"; - reg = <2>; - phy-mode = "internal"; - nvmem-cells = <&phy_calibration_p2>; - nvmem-cell-names = "phy-cal-data"; - - leds { - #address-cells = <1>; - #size-cells = <0>; - - gsw_phy2_led0: gsw-phy2-led0@0 { - reg = <0>; - function = LED_FUNCTION_LAN; - status = "disabled"; - }; - - gsw_phy2_led1: gsw-phy2-led1@1 { - reg = <1>; - function = LED_FUNCTION_LAN; - status = "disabled"; - }; - }; - }; - - gsw_phy3: ethernet-phy@3 { - compatible = "ethernet-phy-ieee802.3-c22"; - reg = <3>; - phy-mode = "internal"; - nvmem-cells = <&phy_calibration_p3>; - nvmem-cell-names = "phy-cal-data"; - - leds { - #address-cells = <1>; - #size-cells = <0>; - - gsw_phy3_led0: gsw-phy3-led0@0 { - reg = <0>; - function = LED_FUNCTION_LAN; - status = "disabled"; - }; - - gsw_phy3_led1: gsw-phy3-led1@1 { - reg = <1>; - function = LED_FUNCTION_LAN; - status = "disabled"; - }; - }; - }; - }; - }; - - ethwarp: syscon@15031000 { - compatible = "mediatek,mt7988-ethwarp", "syscon", "simple-mfd"; - reg = <0 0x15031000 0 0x1000>; - #clock-cells = <1>; - - ethrst: reset-controller { - compatible = "ti,syscon-reset"; - #reset-cells = <1>; - ti,reset-bits = < - 0x8 9 0x8 9 0 0 (ASSERT_SET | DEASSERT_CLEAR | STATUS_NONE) - >; - }; - }; - - eth: ethernet@15100000 { - compatible = "mediatek,mt7988-eth"; - reg = <0 0x15100000 0 0x80000>, - <0 0x15400000 0 0x380000>; - interrupts = , - , - , - ; - clocks = <ðsys CLK_ETHDMA_XGP1_EN>, - <ðsys CLK_ETHDMA_XGP2_EN>, - <ðsys CLK_ETHDMA_XGP3_EN>, - <ðsys CLK_ETHDMA_FE_EN>, - <ðsys CLK_ETHDMA_GP2_EN>, - <ðsys CLK_ETHDMA_GP1_EN>, - <ðsys CLK_ETHDMA_GP3_EN>, - <ðsys CLK_ETHDMA_ESW_EN>, - <ðsys CLK_ETHDMA_CRYPT0_EN>, - <&sgmiisys0 CLK_SGM0_TX_EN>, - <&sgmiisys0 CLK_SGM0_RX_EN>, - <&sgmiisys1 CLK_SGM1_TX_EN>, - <&sgmiisys1 CLK_SGM1_RX_EN>, - <ðwarp CLK_ETHWARP_WOCPU2_EN>, - <ðwarp CLK_ETHWARP_WOCPU1_EN>, - <ðwarp CLK_ETHWARP_WOCPU0_EN>, - <&topckgen CLK_TOP_USXGMII_SBUS_0_SEL>, - <&topckgen CLK_TOP_USXGMII_SBUS_1_SEL>, - <&topckgen CLK_TOP_SGM_0_SEL>, - <&topckgen CLK_TOP_SGM_1_SEL>, - <&topckgen CLK_TOP_XFI_PHY_0_XTAL_SEL>, - <&topckgen CLK_TOP_XFI_PHY_1_XTAL_SEL>, - <&topckgen CLK_TOP_ETH_GMII_SEL>, - <&topckgen CLK_TOP_ETH_REFCK_50M_SEL>, - <&topckgen CLK_TOP_ETH_SYS_200M_SEL>, - <&topckgen CLK_TOP_ETH_SYS_SEL>, - <&topckgen CLK_TOP_ETH_XGMII_SEL>, - <&topckgen CLK_TOP_ETH_MII_SEL>, - <&topckgen CLK_TOP_NETSYS_SEL>, - <&topckgen CLK_TOP_NETSYS_500M_SEL>, - <&topckgen CLK_TOP_NETSYS_PAO_2X_SEL>, - <&topckgen CLK_TOP_NETSYS_SYNC_250M_SEL>, - <&topckgen CLK_TOP_NETSYS_PPEFB_250M_SEL>, - <&topckgen CLK_TOP_NETSYS_WARP_SEL>; - clock-names = "xgp1", "xgp2", "xgp3", "fe", "gp2", "gp1", - "gp3", "esw", "crypto", "sgmii_tx250m", - "sgmii_rx250m", "sgmii2_tx250m", "sgmii2_rx250m", - "ethwarp_wocpu2", "ethwarp_wocpu1", - "ethwarp_wocpu0", "top_usxgmii0_sel", - "top_usxgmii1_sel", "top_sgm0_sel", - "top_sgm1_sel", "top_xfi_phy0_xtal_sel", - "top_xfi_phy1_xtal_sel", "top_eth_gmii_sel", - "top_eth_refck_50m_sel", "top_eth_sys_200m_sel", - "top_eth_sys_sel", "top_eth_xgmii_sel", - "top_eth_mii_sel", "top_netsys_sel", - "top_netsys_500m_sel", "top_netsys_pao_2x_sel", - "top_netsys_sync_250m_sel", - "top_netsys_ppefb_250m_sel", - "top_netsys_warp_sel"; - assigned-clocks = <&topckgen CLK_TOP_NETSYS_2X_SEL>, - <&topckgen CLK_TOP_NETSYS_GSW_SEL>, - <&topckgen CLK_TOP_USXGMII_SBUS_0_SEL>, - <&topckgen CLK_TOP_USXGMII_SBUS_1_SEL>, - <&topckgen CLK_TOP_SGM_0_SEL>, - <&topckgen CLK_TOP_SGM_1_SEL>; - assigned-clock-parents = <&apmixedsys CLK_APMIXED_NET2PLL>, - <&topckgen CLK_TOP_NET1PLL_D4>, - <&topckgen CLK_TOP_NET1PLL_D8_D4>, - <&topckgen CLK_TOP_NET1PLL_D8_D4>, - <&apmixedsys CLK_APMIXED_SGMPLL>, - <&apmixedsys CLK_APMIXED_SGMPLL>; - mediatek,ethsys = <ðsys>; - mediatek,sgmiisys = <&sgmiisys0>, <&sgmiisys1>; - mediatek,usxgmiisys = <&usxgmiisys0>, <&usxgmiisys1>; - mediatek,xfi-pextp = <&xfi_pextp0>, <&xfi_pextp1>; - mediatek,xfi-pll = <&xfi_pll>; - mediatek,infracfg = <&topmisc>; - mediatek,toprgu = <&watchdog>; - #reset-cells = <1>; - #address-cells = <1>; - #size-cells = <0>; - - gmac0: mac@0 { - compatible = "mediatek,eth-mac"; - reg = <0>; - phy-mode = "internal"; - status = "disabled"; - - fixed-link { - speed = <10000>; - full-duplex; - pause; - }; - }; - - gmac1: mac@1 { - compatible = "mediatek,eth-mac"; - reg = <1>; - status = "disabled"; - }; - - gmac2: mac@2 { - compatible = "mediatek,eth-mac"; - reg = <2>; - status = "disabled"; - }; - - mdio_bus: mdio-bus { - #address-cells = <1>; - #size-cells = <0>; - - /* internal 2.5G PHY */ - int_2p5g_phy: ethernet-phy@15 { - reg = <15>; - compatible = "ethernet-phy-ieee802.3-c45"; - phy-mode = "internal"; - }; - }; - }; - }; -}; diff --git a/target/linux/mediatek/files-5.15/drivers/clk/mediatek/clk-mt7981-apmixed.c b/target/linux/mediatek/files-5.15/drivers/clk/mediatek/clk-mt7981-apmixed.c deleted file mode 100644 index 1647021de..000000000 --- a/target/linux/mediatek/files-5.15/drivers/clk/mediatek/clk-mt7981-apmixed.c +++ /dev/null @@ -1,102 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (c) 2021 MediaTek Inc. - * Author: Sam Shih - * Author: Wenzhen Yu - * Author: Jianhui Zhao - * Author: Daniel Golle - */ - -#include -#include -#include -#include -#include -#include "clk-mtk.h" -#include "clk-gate.h" -#include "clk-mux.h" - -#include -#include - -#define MT7981_PLL_FMAX (2500UL * MHZ) -#define CON0_MT7981_RST_BAR BIT(27) - -#define PLL_xtal(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \ - _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, _pcw_shift, \ - _div_table, _parent_name) \ - { \ - .id = _id, .name = _name, .reg = _reg, .pwr_reg = _pwr_reg, \ - .en_mask = _en_mask, .flags = _flags, \ - .rst_bar_mask = CON0_MT7981_RST_BAR, .fmax = MT7981_PLL_FMAX, \ - .pcwbits = _pcwbits, .pd_reg = _pd_reg, .pd_shift = _pd_shift, \ - .tuner_reg = _tuner_reg, .pcw_reg = _pcw_reg, \ - .pcw_shift = _pcw_shift, .div_table = _div_table, \ - .parent_name = _parent_name, \ - } - -#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, _pd_reg, \ - _pd_shift, _tuner_reg, _pcw_reg, _pcw_shift) \ - PLL_xtal(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \ - _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, _pcw_shift, NULL, \ - "clkxtal") - -static const struct mtk_pll_data plls[] = { - PLL(CLK_APMIXED_ARMPLL, "armpll", 0x0200, 0x020C, 0x00000001, PLL_AO, - 32, 0x0200, 4, 0, 0x0204, 0), - PLL(CLK_APMIXED_NET2PLL, "net2pll", 0x0210, 0x021C, 0x00000001, 0, 32, - 0x0210, 4, 0, 0x0214, 0), - PLL(CLK_APMIXED_MMPLL, "mmpll", 0x0220, 0x022C, 0x00000001, 0, 32, - 0x0220, 4, 0, 0x0224, 0), - PLL(CLK_APMIXED_SGMPLL, "sgmpll", 0x0230, 0x023C, 0x00000001, 0, 32, - 0x0230, 4, 0, 0x0234, 0), - PLL(CLK_APMIXED_WEDMCUPLL, "wedmcupll", 0x0240, 0x024C, 0x00000001, 0, 32, - 0x0240, 4, 0, 0x0244, 0), - PLL(CLK_APMIXED_NET1PLL, "net1pll", 0x0250, 0x025C, 0x00000001, 0, 32, - 0x0250, 4, 0, 0x0254, 0), - PLL(CLK_APMIXED_MPLL, "mpll", 0x0260, 0x0270, 0x00000001, 0, 32, - 0x0260, 4, 0, 0x0264, 0), - PLL(CLK_APMIXED_APLL2, "apll2", 0x0278, 0x0288, 0x00000001, 0, 32, - 0x0278, 4, 0, 0x027C, 0), -}; - -static const struct of_device_id of_match_clk_mt7981_apmixed[] = { - { .compatible = "mediatek,mt7981-apmixedsys", }, - {} -}; - -static int clk_mt7981_apmixed_probe(struct platform_device *pdev) -{ - struct clk_onecell_data *clk_data; - struct device_node *node = pdev->dev.of_node; - int r; - - clk_data = mtk_alloc_clk_data(ARRAY_SIZE(plls)); - if (!clk_data) - return -ENOMEM; - - mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data); - - clk_prepare_enable(clk_data->clks[CLK_APMIXED_ARMPLL]); - - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); - if (r) { - pr_err("%s(): could not register clock provider: %d\n", - __func__, r); - goto free_apmixed_data; - } - return r; - -free_apmixed_data: - mtk_free_clk_data(clk_data); - return r; -} - -static struct platform_driver clk_mt7981_apmixed_drv = { - .probe = clk_mt7981_apmixed_probe, - .driver = { - .name = "clk-mt7981-apmixed", - .of_match_table = of_match_clk_mt7981_apmixed, - }, -}; -builtin_platform_driver(clk_mt7981_apmixed_drv); diff --git a/target/linux/mediatek/files-5.15/drivers/clk/mediatek/clk-mt7981-eth.c b/target/linux/mediatek/files-5.15/drivers/clk/mediatek/clk-mt7981-eth.c deleted file mode 100644 index 4aba657aa..000000000 --- a/target/linux/mediatek/files-5.15/drivers/clk/mediatek/clk-mt7981-eth.c +++ /dev/null @@ -1,139 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (c) 2021 MediaTek Inc. - * Author: Sam Shih - * Author: Wenzhen Yu - * Author: Jianhui Zhao - * Author: Daniel Golle - */ - -#include -#include -#include -#include -#include - -#include "clk-mtk.h" -#include "clk-gate.h" - -#include - -static const struct mtk_gate_regs sgmii0_cg_regs = { - .set_ofs = 0xE4, - .clr_ofs = 0xE4, - .sta_ofs = 0xE4, -}; - -#define GATE_SGMII0(_id, _name, _parent, _shift) { \ - .id = _id, \ - .name = _name, \ - .parent_name = _parent, \ - .regs = &sgmii0_cg_regs, \ - .shift = _shift, \ - .ops = &mtk_clk_gate_ops_no_setclr_inv, \ - } - -static const struct mtk_gate sgmii0_clks[] __initconst = { - GATE_SGMII0(CLK_SGM0_TX_EN, "sgm0_tx_en", "usb_tx250m", 2), - GATE_SGMII0(CLK_SGM0_RX_EN, "sgm0_rx_en", "usb_eq_rx250m", 3), - GATE_SGMII0(CLK_SGM0_CK0_EN, "sgm0_ck0_en", "usb_ln0", 4), - GATE_SGMII0(CLK_SGM0_CDR_CK0_EN, "sgm0_cdr_ck0_en", "usb_cdr", 5), -}; - -static const struct mtk_gate_regs sgmii1_cg_regs = { - .set_ofs = 0xE4, - .clr_ofs = 0xE4, - .sta_ofs = 0xE4, -}; - -#define GATE_SGMII1(_id, _name, _parent, _shift) { \ - .id = _id, \ - .name = _name, \ - .parent_name = _parent, \ - .regs = &sgmii1_cg_regs, \ - .shift = _shift, \ - .ops = &mtk_clk_gate_ops_no_setclr_inv, \ - } - -static const struct mtk_gate sgmii1_clks[] __initconst = { - GATE_SGMII1(CLK_SGM1_TX_EN, "sgm1_tx_en", "usb_tx250m", 2), - GATE_SGMII1(CLK_SGM1_RX_EN, "sgm1_rx_en", "usb_eq_rx250m", 3), - GATE_SGMII1(CLK_SGM1_CK1_EN, "sgm1_ck1_en", "usb_ln0", 4), - GATE_SGMII1(CLK_SGM1_CDR_CK1_EN, "sgm1_cdr_ck1_en", "usb_cdr", 5), -}; - -static const struct mtk_gate_regs eth_cg_regs = { - .set_ofs = 0x30, - .clr_ofs = 0x30, - .sta_ofs = 0x30, -}; - -#define GATE_ETH(_id, _name, _parent, _shift) { \ - .id = _id, \ - .name = _name, \ - .parent_name = _parent, \ - .regs = ð_cg_regs, \ - .shift = _shift, \ - .ops = &mtk_clk_gate_ops_no_setclr_inv, \ - } - -static const struct mtk_gate eth_clks[] __initconst = { - GATE_ETH(CLK_ETH_FE_EN, "eth_fe_en", "netsys_2x", 6), - GATE_ETH(CLK_ETH_GP2_EN, "eth_gp2_en", "sgm_325m", 7), - GATE_ETH(CLK_ETH_GP1_EN, "eth_gp1_en", "sgm_325m", 8), - GATE_ETH(CLK_ETH_WOCPU0_EN, "eth_wocpu0_en", "netsys_wed_mcu", 15), -}; - -static void __init mtk_sgmiisys_0_init(struct device_node *node) -{ - struct clk_onecell_data *clk_data; - int r; - - clk_data = mtk_alloc_clk_data(ARRAY_SIZE(sgmii0_clks)); - - mtk_clk_register_gates(node, sgmii0_clks, ARRAY_SIZE(sgmii0_clks), - clk_data); - - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); - if (r) - pr_err("%s(): could not register clock provider: %d\n", - __func__, r); -} -CLK_OF_DECLARE(mtk_sgmiisys_0, "mediatek,mt7981-sgmiisys_0", - mtk_sgmiisys_0_init); - -static void __init mtk_sgmiisys_1_init(struct device_node *node) -{ - struct clk_onecell_data *clk_data; - int r; - - clk_data = mtk_alloc_clk_data(ARRAY_SIZE(sgmii1_clks)); - - mtk_clk_register_gates(node, sgmii1_clks, ARRAY_SIZE(sgmii1_clks), - clk_data); - - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); - - if (r) - pr_err("%s(): could not register clock provider: %d\n", - __func__, r); -} -CLK_OF_DECLARE(mtk_sgmiisys_1, "mediatek,mt7981-sgmiisys_1", - mtk_sgmiisys_1_init); - -static void __init mtk_ethsys_init(struct device_node *node) -{ - struct clk_onecell_data *clk_data; - int r; - - clk_data = mtk_alloc_clk_data(ARRAY_SIZE(eth_clks)); - - mtk_clk_register_gates(node, eth_clks, ARRAY_SIZE(eth_clks), clk_data); - - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); - - if (r) - pr_err("%s(): could not register clock provider: %d\n", - __func__, r); -} -CLK_OF_DECLARE(mtk_ethsys, "mediatek,mt7981-ethsys", mtk_ethsys_init); diff --git a/target/linux/mediatek/files-5.15/drivers/clk/mediatek/clk-mt7981-infracfg.c b/target/linux/mediatek/files-5.15/drivers/clk/mediatek/clk-mt7981-infracfg.c deleted file mode 100644 index 8416829e3..000000000 --- a/target/linux/mediatek/files-5.15/drivers/clk/mediatek/clk-mt7981-infracfg.c +++ /dev/null @@ -1,235 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (c) 2021 MediaTek Inc. - * Author: Sam Shih - * Author: Wenzhen Yu - * Author: Jianhui Zhao - * Author: Daniel Golle - */ - -#include -#include -#include -#include -#include -#include "clk-mtk.h" -#include "clk-gate.h" -#include "clk-mux.h" - -#include -#include - -static DEFINE_SPINLOCK(mt7981_clk_lock); - -static const struct mtk_fixed_factor infra_divs[] = { - FACTOR(CLK_INFRA_66M_MCK, "infra_66m_mck", "sysaxi_sel", 1, 2), -}; - -static const char *const infra_uart_parent[] __initconst = { "csw_f26m_sel", - "uart_sel" }; - -static const char *const infra_spi0_parents[] __initconst = { "i2c_sel", - "spi_sel" }; - -static const char *const infra_spi1_parents[] __initconst = { "i2c_sel", - "spim_mst_sel" }; - -static const char *const infra_pwm1_parents[] __initconst = { "pwm_sel" }; - -static const char *const infra_pwm_bsel_parents[] __initconst = { - "cb_rtc_32p7k", "csw_f26m_sel", "infra_66m_mck", "pwm_sel" -}; - -static const char *const infra_pcie_parents[] __initconst = { - "cb_rtc_32p7k", "csw_f26m_sel", "cb_cksq_40m", "pextp_tl_ck_sel" -}; - -static const struct mtk_mux infra_muxes[] = { - /* MODULE_CLK_SEL_0 */ - MUX_GATE_CLR_SET_UPD(CLK_INFRA_UART0_SEL, "infra_uart0_sel", - infra_uart_parent, 0x0018, 0x0010, 0x0014, 0, 1, - -1, -1, -1), - MUX_GATE_CLR_SET_UPD(CLK_INFRA_UART1_SEL, "infra_uart1_sel", - infra_uart_parent, 0x0018, 0x0010, 0x0014, 1, 1, - -1, -1, -1), - MUX_GATE_CLR_SET_UPD(CLK_INFRA_UART2_SEL, "infra_uart2_sel", - infra_uart_parent, 0x0018, 0x0010, 0x0014, 2, 1, - -1, -1, -1), - MUX_GATE_CLR_SET_UPD(CLK_INFRA_SPI0_SEL, "infra_spi0_sel", - infra_spi0_parents, 0x0018, 0x0010, 0x0014, 4, 1, - -1, -1, -1), - MUX_GATE_CLR_SET_UPD(CLK_INFRA_SPI1_SEL, "infra_spi1_sel", - infra_spi1_parents, 0x0018, 0x0010, 0x0014, 5, 1, - -1, -1, -1), - MUX_GATE_CLR_SET_UPD(CLK_INFRA_SPI2_SEL, "infra_spi2_sel", - infra_spi0_parents, 0x0018, 0x0010, 0x0014, 6, 1, - -1, -1, -1), - MUX_GATE_CLR_SET_UPD(CLK_INFRA_PWM1_SEL, "infra_pwm1_sel", - infra_pwm1_parents, 0x0018, 0x0010, 0x0014, 9, 1, - -1, -1, -1), - MUX_GATE_CLR_SET_UPD(CLK_INFRA_PWM2_SEL, "infra_pwm2_sel", - infra_pwm1_parents, 0x0018, 0x0010, 0x0014, 11, 1, - -1, -1, -1), - MUX_GATE_CLR_SET_UPD(CLK_INFRA_PWM3_SEL, "infra_pwm3_sel", - infra_pwm1_parents, 0x0018, 0x0010, 0x0014, 15, 1, - -1, -1, -1), - MUX_GATE_CLR_SET_UPD(CLK_INFRA_PWM_BSEL, "infra_pwm_bsel", - infra_pwm_bsel_parents, 0x0018, 0x0010, 0x0014, 13, - 2, -1, -1, -1), - /* MODULE_CLK_SEL_1 */ - MUX_GATE_CLR_SET_UPD(CLK_INFRA_PCIE_SEL, "infra_pcie_sel", - infra_pcie_parents, 0x0028, 0x0020, 0x0024, 0, 2, - -1, -1, -1), -}; - -static const struct mtk_gate_regs infra0_cg_regs = { - .set_ofs = 0x40, - .clr_ofs = 0x44, - .sta_ofs = 0x48, -}; - -static const struct mtk_gate_regs infra1_cg_regs = { - .set_ofs = 0x50, - .clr_ofs = 0x54, - .sta_ofs = 0x58, -}; - -static const struct mtk_gate_regs infra2_cg_regs = { - .set_ofs = 0x60, - .clr_ofs = 0x64, - .sta_ofs = 0x68, -}; - -#define GATE_INFRA0(_id, _name, _parent, _shift) \ - { \ - .id = _id, .name = _name, .parent_name = _parent, \ - .regs = &infra0_cg_regs, .shift = _shift, \ - .ops = &mtk_clk_gate_ops_setclr, \ - } - -#define GATE_INFRA1(_id, _name, _parent, _shift) \ - { \ - .id = _id, .name = _name, .parent_name = _parent, \ - .regs = &infra1_cg_regs, .shift = _shift, \ - .ops = &mtk_clk_gate_ops_setclr, \ - } - -#define GATE_INFRA2(_id, _name, _parent, _shift) \ - { \ - .id = _id, .name = _name, .parent_name = _parent, \ - .regs = &infra2_cg_regs, .shift = _shift, \ - .ops = &mtk_clk_gate_ops_setclr, \ - } - -static const struct mtk_gate infra_clks[] = { - /* INFRA0 */ - GATE_INFRA0(CLK_INFRA_GPT_STA, "infra_gpt_sta", "infra_66m_mck", 0), - GATE_INFRA0(CLK_INFRA_PWM_HCK, "infra_pwm_hck", "infra_66m_mck", 1), - GATE_INFRA0(CLK_INFRA_PWM_STA, "infra_pwm_sta", "infra_pwm_bsel", 2), - GATE_INFRA0(CLK_INFRA_PWM1_CK, "infra_pwm1", "infra_pwm1_sel", 3), - GATE_INFRA0(CLK_INFRA_PWM2_CK, "infra_pwm2", "infra_pwm2_sel", 4), - GATE_INFRA0(CLK_INFRA_CQ_DMA_CK, "infra_cq_dma", "sysaxi", 6), - - GATE_INFRA0(CLK_INFRA_AUD_BUS_CK, "infra_aud_bus", "sysaxi", 8), - GATE_INFRA0(CLK_INFRA_AUD_26M_CK, "infra_aud_26m", "csw_f26m_sel", 9), - GATE_INFRA0(CLK_INFRA_AUD_L_CK, "infra_aud_l", "aud_l", 10), - GATE_INFRA0(CLK_INFRA_AUD_AUD_CK, "infra_aud_aud", "a1sys", 11), - GATE_INFRA0(CLK_INFRA_AUD_EG2_CK, "infra_aud_eg2", "a_tuner", 13), - GATE_INFRA0(CLK_INFRA_DRAMC_26M_CK, "infra_dramc_26m", "csw_f26m_sel", - 14), - GATE_INFRA0(CLK_INFRA_DBG_CK, "infra_dbg", "infra_66m_mck", 15), - GATE_INFRA0(CLK_INFRA_AP_DMA_CK, "infra_ap_dma", "infra_66m_mck", 16), - GATE_INFRA0(CLK_INFRA_SEJ_CK, "infra_sej", "infra_66m_mck", 24), - GATE_INFRA0(CLK_INFRA_SEJ_13M_CK, "infra_sej_13m", "csw_f26m_sel", 25), - GATE_INFRA0(CLK_INFRA_PWM3_CK, "infra_pwm3", "infra_pwm3_sel", 27), - /* INFRA1 */ - GATE_INFRA1(CLK_INFRA_THERM_CK, "infra_therm", "csw_f26m_sel", 0), - GATE_INFRA1(CLK_INFRA_I2C0_CK, "infra_i2c0", "i2c_bck", 1), - GATE_INFRA1(CLK_INFRA_UART0_CK, "infra_uart0", "infra_uart0_sel", 2), - GATE_INFRA1(CLK_INFRA_UART1_CK, "infra_uart1", "infra_uart1_sel", 3), - GATE_INFRA1(CLK_INFRA_UART2_CK, "infra_uart2", "infra_uart2_sel", 4), - GATE_INFRA1(CLK_INFRA_SPI2_CK, "infra_spi2", "infra_spi2_sel", 6), - GATE_INFRA1(CLK_INFRA_SPI2_HCK_CK, "infra_spi2_hck", "infra_66m_mck", 7), - GATE_INFRA1(CLK_INFRA_NFI1_CK, "infra_nfi1", "nfi1x", 8), - GATE_INFRA1(CLK_INFRA_SPINFI1_CK, "infra_spinfi1", "spinfi_bck", 9), - GATE_INFRA1(CLK_INFRA_NFI_HCK_CK, "infra_nfi_hck", "infra_66m_mck", 10), - GATE_INFRA1(CLK_INFRA_SPI0_CK, "infra_spi0", "infra_spi0_sel", 11), - GATE_INFRA1(CLK_INFRA_SPI1_CK, "infra_spi1", "infra_spi1_sel", 12), - GATE_INFRA1(CLK_INFRA_SPI0_HCK_CK, "infra_spi0_hck", "infra_66m_mck", - 13), - GATE_INFRA1(CLK_INFRA_SPI1_HCK_CK, "infra_spi1_hck", "infra_66m_mck", - 14), - GATE_INFRA1(CLK_INFRA_FRTC_CK, "infra_frtc", "cb_rtc_32k", 15), - GATE_INFRA1(CLK_INFRA_MSDC_CK, "infra_msdc", "emmc_400m", 16), - GATE_INFRA1(CLK_INFRA_MSDC_HCK_CK, "infra_msdc_hck", "emmc_208m", 17), - GATE_INFRA1(CLK_INFRA_MSDC_133M_CK, "infra_msdc_133m", "sysaxi", 18), - GATE_INFRA1(CLK_INFRA_MSDC_66M_CK, "infra_msdc_66m", "sysaxi", 19), - GATE_INFRA1(CLK_INFRA_ADC_26M_CK, "infra_adc_26m", "infra_adc_frc", 20), - GATE_INFRA1(CLK_INFRA_ADC_FRC_CK, "infra_adc_frc", "csw_f26m", 21), - GATE_INFRA1(CLK_INFRA_FBIST2FPC_CK, "infra_fbist2fpc", "nfi1x", 23), - GATE_INFRA1(CLK_INFRA_I2C_MCK_CK, "infra_i2c_mck", "sysaxi", 25), - GATE_INFRA1(CLK_INFRA_I2C_PCK_CK, "infra_i2c_pck", "infra_66m_mck", 26), - /* INFRA2 */ - GATE_INFRA2(CLK_INFRA_IUSB_133_CK, "infra_iusb_133", "sysaxi", 0), - GATE_INFRA2(CLK_INFRA_IUSB_66M_CK, "infra_iusb_66m", "sysaxi", 1), - GATE_INFRA2(CLK_INFRA_IUSB_SYS_CK, "infra_iusb_sys", "u2u3_sys", 2), - GATE_INFRA2(CLK_INFRA_IUSB_CK, "infra_iusb", "u2u3_ref", 3), - GATE_INFRA2(CLK_INFRA_IPCIE_CK, "infra_ipcie", "pextp_tl", 12), - GATE_INFRA2(CLK_INFRA_IPCIE_PIPE_CK, "infra_ipcie_pipe", "cb_cksq_40m", - 13), - GATE_INFRA2(CLK_INFRA_IPCIER_CK, "infra_ipcier", "csw_f26m", 14), - GATE_INFRA2(CLK_INFRA_IPCIEB_CK, "infra_ipcieb", "sysaxi", 15), -}; - -static int clk_mt7981_infracfg_probe(struct platform_device *pdev) -{ - struct clk_onecell_data *clk_data; - struct device_node *node = pdev->dev.of_node; - int r; - void __iomem *base; - int nr = ARRAY_SIZE(infra_divs) + ARRAY_SIZE(infra_muxes) + - ARRAY_SIZE(infra_clks); - - base = of_iomap(node, 0); - if (!base) { - pr_err("%s(): ioremap failed\n", __func__); - return -ENOMEM; - } - - clk_data = mtk_alloc_clk_data(nr); - - if (!clk_data) - return -ENOMEM; - - mtk_clk_register_factors(infra_divs, ARRAY_SIZE(infra_divs), clk_data); - mtk_clk_register_muxes(infra_muxes, ARRAY_SIZE(infra_muxes), node, - &mt7981_clk_lock, clk_data); - mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks), - clk_data); - - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); - if (r) { - pr_err("%s(): could not register clock provider: %d\n", - __func__, r); - goto free_infracfg_data; - } - return r; - -free_infracfg_data: - mtk_free_clk_data(clk_data); - return r; -} - -static const struct of_device_id of_match_clk_mt7981_infracfg[] = { - { .compatible = "mediatek,mt7981-infracfg", }, - {} -}; - -static struct platform_driver clk_mt7981_infracfg_drv = { - .probe = clk_mt7981_infracfg_probe, - .driver = { - .name = "clk-mt7981-infracfg", - .of_match_table = of_match_clk_mt7981_infracfg, - }, -}; -builtin_platform_driver(clk_mt7981_infracfg_drv); diff --git a/target/linux/mediatek/files-5.15/drivers/clk/mediatek/clk-mt7981-topckgen.c b/target/linux/mediatek/files-5.15/drivers/clk/mediatek/clk-mt7981-topckgen.c deleted file mode 100644 index ce6dc1867..000000000 --- a/target/linux/mediatek/files-5.15/drivers/clk/mediatek/clk-mt7981-topckgen.c +++ /dev/null @@ -1,450 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (c) 2021 MediaTek Inc. - * Author: Sam Shih - * Author: Wenzhen Yu - * Author: Jianhui Zhao - */ - - -#include -#include -#include -#include -#include -#include "clk-mtk.h" -#include "clk-gate.h" -#include "clk-mux.h" - -#include -#include - -static DEFINE_SPINLOCK(mt7981_clk_lock); - -static const struct mtk_fixed_factor top_divs[] = { - FACTOR(CLK_TOP_CB_CKSQ_40M, "cb_cksq_40m", "clkxtal", 1, 1), - FACTOR(CLK_TOP_CB_M_416M, "cb_m_416m", "mpll", 1, 1), - FACTOR(CLK_TOP_CB_M_D2, "cb_m_d2", "mpll", 1, 2), - FACTOR(CLK_TOP_CB_M_D3, "cb_m_d3", "mpll", 1, 3), - FACTOR(CLK_TOP_M_D3_D2, "m_d3_d2", "mpll", 1, 2), - FACTOR(CLK_TOP_CB_M_D4, "cb_m_d4", "mpll", 1, 4), - FACTOR(CLK_TOP_CB_M_D8, "cb_m_d8", "mpll", 1, 8), - FACTOR(CLK_TOP_M_D8_D2, "m_d8_d2", "mpll", 1, 16), - FACTOR(CLK_TOP_CB_MM_720M, "cb_mm_720m", "mmpll", 1, 1), - FACTOR(CLK_TOP_CB_MM_D2, "cb_mm_d2", "mmpll", 1, 2), - FACTOR(CLK_TOP_CB_MM_D3, "cb_mm_d3", "mmpll", 1, 3), - FACTOR(CLK_TOP_CB_MM_D3_D5, "cb_mm_d3_d5", "mmpll", 1, 15), - FACTOR(CLK_TOP_CB_MM_D4, "cb_mm_d4", "mmpll", 1, 4), - FACTOR(CLK_TOP_CB_MM_D6, "cb_mm_d6", "mmpll", 1, 6), - FACTOR(CLK_TOP_MM_D6_D2, "mm_d6_d2", "mmpll", 1, 12), - FACTOR(CLK_TOP_CB_MM_D8, "cb_mm_d8", "mmpll", 1, 8), - FACTOR(CLK_TOP_CB_APLL2_196M, "cb_apll2_196m", "apll2", 1, 1), - FACTOR(CLK_TOP_APLL2_D2, "apll2_d2", "apll2", 1, 2), - FACTOR(CLK_TOP_APLL2_D4, "apll2_d4", "apll2", 1, 4), - FACTOR(CLK_TOP_NET1_2500M, "net1_2500m", "net1pll", 1, 1), - FACTOR(CLK_TOP_CB_NET1_D4, "cb_net1_d4", "net1pll", 1, 4), - FACTOR(CLK_TOP_CB_NET1_D5, "cb_net1_d5", "net1pll", 1, 5), - FACTOR(CLK_TOP_NET1_D5_D2, "net1_d5_d2", "net1pll", 1, 10), - FACTOR(CLK_TOP_NET1_D5_D4, "net1_d5_d4", "net1pll", 1, 20), - FACTOR(CLK_TOP_CB_NET1_D8, "cb_net1_d8", "net1pll", 1, 8), - FACTOR(CLK_TOP_NET1_D8_D2, "net1_d8_d2", "net1pll", 1, 16), - FACTOR(CLK_TOP_NET1_D8_D4, "net1_d8_d4", "net1pll", 1, 32), - FACTOR(CLK_TOP_CB_NET2_800M, "cb_net2_800m", "net2pll", 1, 1), - FACTOR(CLK_TOP_CB_NET2_D2, "cb_net2_d2", "net2pll", 1, 2), - FACTOR(CLK_TOP_CB_NET2_D4, "cb_net2_d4", "net2pll", 1, 4), - FACTOR(CLK_TOP_NET2_D4_D2, "net2_d4_d2", "net2pll", 1, 8), - FACTOR(CLK_TOP_NET2_D4_D4, "net2_d4_d4", "net2pll", 1, 16), - FACTOR(CLK_TOP_CB_NET2_D6, "cb_net2_d6", "net2pll", 1, 6), - FACTOR(CLK_TOP_CB_WEDMCU_208M, "cb_wedmcu_208m", "wedmcupll", 1, 1), - FACTOR(CLK_TOP_CB_SGM_325M, "cb_sgm_325m", "sgmpll", 1, 1), - FACTOR(CLK_TOP_CKSQ_40M_D2, "cksq_40m_d2", "cb_cksq_40m", 1, 2), - FACTOR(CLK_TOP_CB_RTC_32K, "cb_rtc_32k", "cb_cksq_40m", 1, 1250), - FACTOR(CLK_TOP_CB_RTC_32P7K, "cb_rtc_32p7k", "cb_cksq_40m", 1, 1220), - FACTOR(CLK_TOP_USB_TX250M, "usb_tx250m", "cb_cksq_40m", 1, 1), - FACTOR(CLK_TOP_FAUD, "faud", "aud_sel", 1, 1), - FACTOR(CLK_TOP_NFI1X, "nfi1x", "nfi1x_sel", 1, 1), - FACTOR(CLK_TOP_USB_EQ_RX250M, "usb_eq_rx250m", "cb_cksq_40m", 1, 1), - FACTOR(CLK_TOP_USB_CDR_CK, "usb_cdr", "cb_cksq_40m", 1, 1), - FACTOR(CLK_TOP_USB_LN0_CK, "usb_ln0", "cb_cksq_40m", 1, 1), - FACTOR(CLK_TOP_SPINFI_BCK, "spinfi_bck", "spinfi_sel", 1, 1), - FACTOR(CLK_TOP_SPI, "spi", "spi_sel", 1, 1), - FACTOR(CLK_TOP_SPIM_MST, "spim_mst", "spim_mst_sel", 1, 1), - FACTOR(CLK_TOP_UART_BCK, "uart_bck", "uart_sel", 1, 1), - FACTOR(CLK_TOP_PWM_BCK, "pwm_bck", "pwm_sel", 1, 1), - FACTOR(CLK_TOP_I2C_BCK, "i2c_bck", "i2c_sel", 1, 1), - FACTOR(CLK_TOP_PEXTP_TL, "pextp_tl", "pextp_tl_ck_sel", 1, 1), - FACTOR(CLK_TOP_EMMC_208M, "emmc_208m", "emmc_208m_sel", 1, 1), - FACTOR(CLK_TOP_EMMC_400M, "emmc_400m", "emmc_400m_sel", 1, 1), - FACTOR(CLK_TOP_DRAMC_REF, "dramc_ref", "dramc_sel", 1, 1), - FACTOR(CLK_TOP_DRAMC_MD32, "dramc_md32", "dramc_md32_sel", 1, 1), - FACTOR(CLK_TOP_SYSAXI, "sysaxi", "sysaxi_sel", 1, 1), - FACTOR(CLK_TOP_SYSAPB, "sysapb", "sysapb_sel", 1, 1), - FACTOR(CLK_TOP_ARM_DB_MAIN, "arm_db_main", "arm_db_main_sel", 1, 1), - FACTOR(CLK_TOP_AP2CNN_HOST, "ap2cnn_host", "ap2cnn_host_sel", 1, 1), - FACTOR(CLK_TOP_NETSYS, "netsys", "netsys_sel", 1, 1), - FACTOR(CLK_TOP_NETSYS_500M, "netsys_500m", "netsys_500m_sel", 1, 1), - FACTOR(CLK_TOP_NETSYS_WED_MCU, "netsys_wed_mcu", "netsys_mcu_sel", 1, 1), - FACTOR(CLK_TOP_NETSYS_2X, "netsys_2x", "netsys_2x_sel", 1, 1), - FACTOR(CLK_TOP_SGM_325M, "sgm_325m", "sgm_325m_sel", 1, 1), - FACTOR(CLK_TOP_SGM_REG, "sgm_reg", "sgm_reg_sel", 1, 1), - FACTOR(CLK_TOP_F26M, "csw_f26m", "csw_f26m_sel", 1, 1), - FACTOR(CLK_TOP_EIP97B, "eip97b", "eip97b_sel", 1, 1), - FACTOR(CLK_TOP_USB3_PHY, "usb3_phy", "usb3_phy_sel", 1, 1), - FACTOR(CLK_TOP_AUD, "aud", "faud", 1, 1), - FACTOR(CLK_TOP_A1SYS, "a1sys", "a1sys_sel", 1, 1), - FACTOR(CLK_TOP_AUD_L, "aud_l", "aud_l_sel", 1, 1), - FACTOR(CLK_TOP_A_TUNER, "a_tuner", "a_tuner_sel", 1, 1), - FACTOR(CLK_TOP_U2U3_REF, "u2u3_ref", "u2u3_sel", 1, 1), - FACTOR(CLK_TOP_U2U3_SYS, "u2u3_sys", "u2u3_sys_sel", 1, 1), - FACTOR(CLK_TOP_U2U3_XHCI, "u2u3_xhci", "u2u3_xhci_sel", 1, 1), - FACTOR(CLK_TOP_USB_FRMCNT, "usb_frmcnt", "usb_frmcnt_sel", 1, 1), -}; - -static const char * const nfi1x_parents[] __initconst = { - "cb_cksq_40m", - "cb_mm_d4", - "net1_d8_d2", - "cb_net2_d6", - "cb_m_d4", - "cb_mm_d8", - "net1_d8_d4", - "cb_m_d8" -}; - -static const char * const spinfi_parents[] __initconst = { - "cksq_40m_d2", - "cb_cksq_40m", - "net1_d5_d4", - "cb_m_d4", - "cb_mm_d8", - "net1_d8_d4", - "mm_d6_d2", - "cb_m_d8" -}; - -static const char * const spi_parents[] __initconst = { - "cb_cksq_40m", - "cb_m_d2", - "cb_mm_d4", - "net1_d8_d2", - "cb_net2_d6", - "net1_d5_d4", - "cb_m_d4", - "net1_d8_d4" -}; - -static const char * const uart_parents[] __initconst = { - "cb_cksq_40m", - "cb_m_d8", - "m_d8_d2" -}; - -static const char * const pwm_parents[] __initconst = { - "cb_cksq_40m", - "net1_d8_d2", - "net1_d5_d4", - "cb_m_d4", - "m_d8_d2", - "cb_rtc_32k" -}; - -static const char * const i2c_parents[] __initconst = { - "cb_cksq_40m", - "net1_d5_d4", - "cb_m_d4", - "net1_d8_d4" -}; - -static const char * const pextp_tl_ck_parents[] __initconst = { - "cb_cksq_40m", - "net1_d5_d4", - "cb_m_d4", - "cb_rtc_32k" -}; - -static const char * const emmc_208m_parents[] __initconst = { - "cb_cksq_40m", - "cb_m_d2", - "cb_net2_d4", - "cb_apll2_196m", - "cb_mm_d4", - "net1_d8_d2", - "cb_mm_d6" -}; - -static const char * const emmc_400m_parents[] __initconst = { - "cb_cksq_40m", - "cb_net2_d2", - "cb_mm_d2", - "cb_net2_d2" -}; - -static const char * const csw_f26m_parents[] __initconst = { - "cksq_40m_d2", - "m_d8_d2" -}; - -static const char * const dramc_md32_parents[] __initconst = { - "cb_cksq_40m", - "cb_m_d2", - "cb_wedmcu_208m" -}; - -static const char * const sysaxi_parents[] __initconst = { - "cb_cksq_40m", - "net1_d8_d2" -}; - -static const char * const sysapb_parents[] __initconst = { - "cb_cksq_40m", - "m_d3_d2" -}; - -static const char * const arm_db_main_parents[] __initconst = { - "cb_cksq_40m", - "cb_net2_d6" -}; - -static const char * const ap2cnn_host_parents[] __initconst = { - "cb_cksq_40m", - "net1_d8_d4" -}; - -static const char * const netsys_parents[] __initconst = { - "cb_cksq_40m", - "cb_mm_d2" -}; - -static const char * const netsys_500m_parents[] __initconst = { - "cb_cksq_40m", - "cb_net1_d5" -}; - -static const char * const netsys_mcu_parents[] __initconst = { - "cb_cksq_40m", - "cb_mm_720m", - "cb_net1_d4", - "cb_net1_d5", - "cb_m_416m" -}; - -static const char * const netsys_2x_parents[] __initconst = { - "cb_cksq_40m", - "cb_net2_800m", - "cb_mm_720m" -}; - -static const char * const sgm_325m_parents[] __initconst = { - "cb_cksq_40m", - "cb_sgm_325m" -}; - -static const char * const sgm_reg_parents[] __initconst = { - "cb_cksq_40m", - "cb_net2_d4" -}; - -static const char * const eip97b_parents[] __initconst = { - "cb_cksq_40m", - "cb_net1_d5", - "cb_m_416m", - "cb_mm_d2", - "net1_d5_d2" -}; - -static const char * const aud_parents[] __initconst = { - "cb_cksq_40m", - "cb_apll2_196m" -}; - -static const char * const a1sys_parents[] __initconst = { - "cb_cksq_40m", - "apll2_d4" -}; - -static const char * const aud_l_parents[] __initconst = { - "cb_cksq_40m", - "cb_apll2_196m", - "m_d8_d2" -}; - -static const char * const a_tuner_parents[] __initconst = { - "cb_cksq_40m", - "apll2_d4", - "m_d8_d2" -}; - -static const char * const u2u3_parents[] __initconst = { - "cb_cksq_40m", - "m_d8_d2" -}; - -static const char * const u2u3_sys_parents[] __initconst = { - "cb_cksq_40m", - "net1_d5_d4" -}; - -static const char * const usb_frmcnt_parents[] __initconst = { - "cb_cksq_40m", - "cb_mm_d3_d5" -}; - -static const struct mtk_mux top_muxes[] = { - /* CLK_CFG_0 */ - MUX_GATE_CLR_SET_UPD(CLK_TOP_NFI1X_SEL, "nfi1x_sel", nfi1x_parents, - 0x000, 0x004, 0x008, 0, 3, 7, 0x1C0, 0), - MUX_GATE_CLR_SET_UPD(CLK_TOP_SPINFI_SEL, "spinfi_sel", spinfi_parents, - 0x000, 0x004, 0x008, 8, 3, 15, 0x1C0, 1), - MUX_GATE_CLR_SET_UPD(CLK_TOP_SPI_SEL, "spi_sel", spi_parents, - 0x000, 0x004, 0x008, 16, 3, 23, 0x1C0, 2), - MUX_GATE_CLR_SET_UPD(CLK_TOP_SPIM_MST_SEL, "spim_mst_sel", spi_parents, - 0x000, 0x004, 0x008, 24, 3, 31, 0x1C0, 3), - /* CLK_CFG_1 */ - MUX_GATE_CLR_SET_UPD(CLK_TOP_UART_SEL, "uart_sel", uart_parents, - 0x010, 0x014, 0x018, 0, 2, 7, 0x1C0, 4), - MUX_GATE_CLR_SET_UPD(CLK_TOP_PWM_SEL, "pwm_sel", pwm_parents, - 0x010, 0x014, 0x018, 8, 3, 15, 0x1C0, 5), - MUX_GATE_CLR_SET_UPD(CLK_TOP_I2C_SEL, "i2c_sel", i2c_parents, - 0x010, 0x014, 0x018, 16, 2, 23, 0x1C0, 6), - MUX_GATE_CLR_SET_UPD(CLK_TOP_PEXTP_TL_SEL, "pextp_tl_ck_sel", - pextp_tl_ck_parents, 0x010, 0x014, 0x018, 24, 2, 31, - 0x1C0, 7), - /* CLK_CFG_2 */ - MUX_GATE_CLR_SET_UPD(CLK_TOP_EMMC_208M_SEL, "emmc_208m_sel", - emmc_208m_parents, 0x020, 0x024, 0x028, 0, 3, 7, - 0x1C0, 8), - MUX_GATE_CLR_SET_UPD(CLK_TOP_EMMC_400M_SEL, "emmc_400m_sel", - emmc_400m_parents, 0x020, 0x024, 0x028, 8, 2, 15, - 0x1C0, 9), - MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_F26M_SEL, "csw_f26m_sel", - csw_f26m_parents, 0x020, 0x024, 0x028, 16, 1, 23, - 0x1C0, 10, - CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), - MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_DRAMC_SEL, "dramc_sel", - csw_f26m_parents, 0x020, 0x024, 0x028, 24, 1, - 31, 0x1C0, 11, - CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), - /* CLK_CFG_3 */ - MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_DRAMC_MD32_SEL, "dramc_md32_sel", - dramc_md32_parents, 0x030, 0x034, 0x038, 0, 2, - 7, 0x1C0, 12, - CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), - MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SYSAXI_SEL, "sysaxi_sel", - sysaxi_parents, 0x030, 0x034, 0x038, 8, 1, 15, - 0x1C0, 13, - CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), - MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SYSAPB_SEL, "sysapb_sel", - sysapb_parents, 0x030, 0x034, 0x038, 16, 1, - 23, 0x1C0, 14, - CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), - MUX_GATE_CLR_SET_UPD(CLK_TOP_ARM_DB_MAIN_SEL, "arm_db_main_sel", - arm_db_main_parents, 0x030, 0x034, 0x038, 24, 1, 31, - 0x1C0, 15), - /* CLK_CFG_4 */ - MUX_GATE_CLR_SET_UPD(CLK_TOP_AP2CNN_HOST_SEL, "ap2cnn_host_sel", - ap2cnn_host_parents, 0x040, 0x044, 0x048, 0, 1, 7, - 0x1C0, 16), - MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_SEL, "netsys_sel", netsys_parents, - 0x040, 0x044, 0x048, 8, 1, 15, 0x1C0, 17), - MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_500M_SEL, "netsys_500m_sel", - netsys_500m_parents, 0x040, 0x044, 0x048, 16, 1, 23, - 0x1C0, 18), - MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_MCU_SEL, "netsys_mcu_sel", - netsys_mcu_parents, 0x040, 0x044, 0x048, 24, 3, 31, - 0x1C0, 19), - /* CLK_CFG_5 */ - MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_2X_SEL, "netsys_2x_sel", - netsys_2x_parents, 0x050, 0x054, 0x058, 0, 2, 7, - 0x1C0, 20), - MUX_GATE_CLR_SET_UPD(CLK_TOP_SGM_325M_SEL, "sgm_325m_sel", - sgm_325m_parents, 0x050, 0x054, 0x058, 8, 1, 15, - 0x1C0, 21), - MUX_GATE_CLR_SET_UPD(CLK_TOP_SGM_REG_SEL, "sgm_reg_sel", sgm_reg_parents, - 0x050, 0x054, 0x058, 16, 1, 23, 0x1C0, 22), - MUX_GATE_CLR_SET_UPD(CLK_TOP_EIP97B_SEL, "eip97b_sel", eip97b_parents, - 0x050, 0x054, 0x058, 24, 3, 31, 0x1C0, 23), - /* CLK_CFG_6 */ - MUX_GATE_CLR_SET_UPD(CLK_TOP_USB3_PHY_SEL, "usb3_phy_sel", - csw_f26m_parents, 0x060, 0x064, 0x068, 0, 1, - 7, 0x1C0, 24), - MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_SEL, "aud_sel", aud_parents, 0x060, - 0x064, 0x068, 8, 1, 15, 0x1C0, 25), - MUX_GATE_CLR_SET_UPD(CLK_TOP_A1SYS_SEL, "a1sys_sel", a1sys_parents, - 0x060, 0x064, 0x068, 16, 1, 23, 0x1C0, 26), - MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_L_SEL, "aud_l_sel", aud_l_parents, - 0x060, 0x064, 0x068, 24, 2, 31, 0x1C0, 27), - /* CLK_CFG_7 */ - MUX_GATE_CLR_SET_UPD(CLK_TOP_A_TUNER_SEL, "a_tuner_sel", - a_tuner_parents, 0x070, 0x074, 0x078, 0, 2, 7, - 0x1C0, 28), - MUX_GATE_CLR_SET_UPD(CLK_TOP_U2U3_SEL, "u2u3_sel", u2u3_parents, 0x070, - 0x074, 0x078, 8, 1, 15, 0x1C0, 29), - MUX_GATE_CLR_SET_UPD(CLK_TOP_U2U3_SYS_SEL, "u2u3_sys_sel", - u2u3_sys_parents, 0x070, 0x074, 0x078, 16, 1, 23, - 0x1C0, 30), - MUX_GATE_CLR_SET_UPD(CLK_TOP_U2U3_XHCI_SEL, "u2u3_xhci_sel", - u2u3_sys_parents, 0x070, 0x074, 0x078, 24, 1, 31, - 0x1C4, 0), - /* CLK_CFG_8 */ - MUX_GATE_CLR_SET_UPD(CLK_TOP_USB_FRMCNT_SEL, "usb_frmcnt_sel", - usb_frmcnt_parents, 0x080, 0x084, 0x088, 0, 1, 7, - 0x1C4, 1), -}; - -static struct mtk_composite top_aud_divs[] = { - DIV_GATE(CLK_TOP_AUD_I2S_M, "aud_i2s_m", "aud", - 0x0420, 0, 0x0420, 8, 8), -}; - -static int clk_mt7981_topckgen_probe(struct platform_device *pdev) -{ - struct clk_onecell_data *clk_data; - struct device_node *node = pdev->dev.of_node; - int r; - void __iomem *base; - int nr = ARRAY_SIZE(top_divs) + ARRAY_SIZE(top_muxes) + - ARRAY_SIZE(top_aud_divs); - - base = of_iomap(node, 0); - if (!base) { - pr_err("%s(): ioremap failed\n", __func__); - return -ENOMEM; - } - - clk_data = mtk_alloc_clk_data(nr); - if (!clk_data) - return -ENOMEM; - - mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), clk_data); - mtk_clk_register_muxes(top_muxes, ARRAY_SIZE(top_muxes), node, - &mt7981_clk_lock, clk_data); - mtk_clk_register_composites(top_aud_divs, ARRAY_SIZE(top_aud_divs), base, - &mt7981_clk_lock, clk_data); - - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); - - if (r) { - pr_err("%s(): could not register clock provider: %d\n", - __func__, r); - goto free_topckgen_data; - } - return r; - -free_topckgen_data: - mtk_free_clk_data(clk_data); - return r; -} - -static const struct of_device_id of_match_clk_mt7981_topckgen[] = { - { .compatible = "mediatek,mt7981-topckgen", }, - {} -}; - -static struct platform_driver clk_mt7981_topckgen_drv = { - .probe = clk_mt7981_topckgen_probe, - .driver = { - .name = "clk-mt7981-topckgen", - .of_match_table = of_match_clk_mt7981_topckgen, - }, -}; -builtin_platform_driver(clk_mt7981_topckgen_drv); diff --git a/target/linux/mediatek/files-5.15/drivers/clk/mediatek/clk-mt7986-apmixed.c b/target/linux/mediatek/files-5.15/drivers/clk/mediatek/clk-mt7986-apmixed.c deleted file mode 100644 index 76c8ebdea..000000000 --- a/target/linux/mediatek/files-5.15/drivers/clk/mediatek/clk-mt7986-apmixed.c +++ /dev/null @@ -1,100 +0,0 @@ -// SPDX-License-Identifier: GPL-1.0 -/* - * Copyright (c) 2021 MediaTek Inc. - * Author: Sam Shih - * Author: Wenzhen Yu - */ - -#include -#include -#include -#include -#include -#include "clk-mtk.h" -#include "clk-gate.h" -#include "clk-mux.h" - -#include -#include - -#define MT7986_PLL_FMAX (2500UL * MHZ) -#define CON0_MT7986_RST_BAR BIT(27) - -#define PLL_xtal(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \ - _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, _pcw_shift, \ - _div_table, _parent_name) \ - { \ - .id = _id, .name = _name, .reg = _reg, .pwr_reg = _pwr_reg, \ - .en_mask = _en_mask, .flags = _flags, \ - .rst_bar_mask = CON0_MT7986_RST_BAR, .fmax = MT7986_PLL_FMAX, \ - .pcwbits = _pcwbits, .pd_reg = _pd_reg, .pd_shift = _pd_shift, \ - .tuner_reg = _tuner_reg, .pcw_reg = _pcw_reg, \ - .pcw_shift = _pcw_shift, .div_table = _div_table, \ - .parent_name = _parent_name, \ - } - -#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, _pd_reg, \ - _pd_shift, _tuner_reg, _pcw_reg, _pcw_shift) \ - PLL_xtal(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \ - _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, _pcw_shift, NULL, \ - "clkxtal") - -static const struct mtk_pll_data plls[] = { - PLL(CLK_APMIXED_ARMPLL, "armpll", 0x0200, 0x020C, 0x00000001, 0, 32, - 0x0200, 4, 0, 0x0204, 0), - PLL(CLK_APMIXED_NET2PLL, "net2pll", 0x0210, 0x021C, 0x00000001, 0, 32, - 0x0210, 4, 0, 0x0214, 0), - PLL(CLK_APMIXED_MMPLL, "mmpll", 0x0220, 0x022C, 0x00000001, 0, 32, - 0x0220, 4, 0, 0x0224, 0), - PLL(CLK_APMIXED_SGMPLL, "sgmpll", 0x0230, 0x023c, 0x00000001, 0, 32, - 0x0230, 4, 0, 0x0234, 0), - PLL(CLK_APMIXED_WEDMCUPLL, "wedmcupll", 0x0240, 0x024c, 0x00000001, 0, - 32, 0x0240, 4, 0, 0x0244, 0), - PLL(CLK_APMIXED_NET1PLL, "net1pll", 0x0250, 0x025c, 0x00000001, 0, 32, - 0x0250, 4, 0, 0x0254, 0), - PLL(CLK_APMIXED_MPLL, "mpll", 0x0260, 0x0270, 0x00000001, 0, 32, 0x0260, - 4, 0, 0x0264, 0), - PLL(CLK_APMIXED_APLL2, "apll2", 0x0278, 0x0288, 0x00000001, 0, 32, - 0x0278, 4, 0, 0x027c, 0), -}; - -static const struct of_device_id of_match_clk_mt7986_apmixed[] = { - { .compatible = "mediatek,mt7986-apmixedsys", }, - {} -}; - -static int clk_mt7986_apmixed_probe(struct platform_device *pdev) -{ - struct clk_onecell_data *clk_data; - struct device_node *node = pdev->dev.of_node; - int r; - - clk_data = mtk_alloc_clk_data(ARRAY_SIZE(plls)); - if (!clk_data) - return -ENOMEM; - - mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data); - - clk_prepare_enable(clk_data->clks[CLK_APMIXED_ARMPLL]); - - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); - if (r) { - pr_err("%s(): could not register clock provider: %d\n", - __func__, r); - goto free_apmixed_data; - } - return r; - -free_apmixed_data: - mtk_free_clk_data(clk_data); - return r; -} - -static struct platform_driver clk_mt7986_apmixed_drv = { - .probe = clk_mt7986_apmixed_probe, - .driver = { - .name = "clk-mt7986-apmixed", - .of_match_table = of_match_clk_mt7986_apmixed, - }, -}; -builtin_platform_driver(clk_mt7986_apmixed_drv); diff --git a/target/linux/mediatek/files-5.15/drivers/clk/mediatek/clk-mt7986-eth.c b/target/linux/mediatek/files-5.15/drivers/clk/mediatek/clk-mt7986-eth.c deleted file mode 100644 index ed2e7b200..000000000 --- a/target/linux/mediatek/files-5.15/drivers/clk/mediatek/clk-mt7986-eth.c +++ /dev/null @@ -1,132 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (c) 2021 MediaTek Inc. - * Author: Sam Shih - * Author: Wenzhen Yu - */ - -#include -#include -#include -#include -#include - -#include "clk-mtk.h" -#include "clk-gate.h" - -#include - -static const struct mtk_gate_regs sgmii0_cg_regs = { - .set_ofs = 0xe4, - .clr_ofs = 0xe4, - .sta_ofs = 0xe4, -}; - -#define GATE_SGMII0(_id, _name, _parent, _shift) \ - { \ - .id = _id, .name = _name, .parent_name = _parent, \ - .regs = &sgmii0_cg_regs, .shift = _shift, \ - .ops = &mtk_clk_gate_ops_no_setclr_inv, \ - } - -static const struct mtk_gate sgmii0_clks[] __initconst = { - GATE_SGMII0(CLK_SGMII0_TX250M_EN, "sgmii0_tx250m_en", "top_xtal", 2), - GATE_SGMII0(CLK_SGMII0_RX250M_EN, "sgmii0_rx250m_en", "top_xtal", 3), - GATE_SGMII0(CLK_SGMII0_CDR_REF, "sgmii0_cdr_ref", "top_xtal", 4), - GATE_SGMII0(CLK_SGMII0_CDR_FB, "sgmii0_cdr_fb", "top_xtal", 5), -}; - -static const struct mtk_gate_regs sgmii1_cg_regs = { - .set_ofs = 0xe4, - .clr_ofs = 0xe4, - .sta_ofs = 0xe4, -}; - -#define GATE_SGMII1(_id, _name, _parent, _shift) \ - { \ - .id = _id, .name = _name, .parent_name = _parent, \ - .regs = &sgmii1_cg_regs, .shift = _shift, \ - .ops = &mtk_clk_gate_ops_no_setclr_inv, \ - } - -static const struct mtk_gate sgmii1_clks[] __initconst = { - GATE_SGMII1(CLK_SGMII1_TX250M_EN, "sgmii1_tx250m_en", "top_xtal", 2), - GATE_SGMII1(CLK_SGMII1_RX250M_EN, "sgmii1_rx250m_en", "top_xtal", 3), - GATE_SGMII1(CLK_SGMII1_CDR_REF, "sgmii1_cdr_ref", "top_xtal", 4), - GATE_SGMII1(CLK_SGMII1_CDR_FB, "sgmii1_cdr_fb", "top_xtal", 5), -}; - -static const struct mtk_gate_regs eth_cg_regs = { - .set_ofs = 0x30, - .clr_ofs = 0x30, - .sta_ofs = 0x30, -}; - -#define GATE_ETH(_id, _name, _parent, _shift) \ - { \ - .id = _id, .name = _name, .parent_name = _parent, \ - .regs = ð_cg_regs, .shift = _shift, \ - .ops = &mtk_clk_gate_ops_no_setclr_inv, \ - } - -static const struct mtk_gate eth_clks[] __initconst = { - GATE_ETH(CLK_ETH_FE_EN, "eth_fe_en", "netsys_2x_sel", 6), - GATE_ETH(CLK_ETH_GP2_EN, "eth_gp2_en", "sgm_325m_sel", 7), - GATE_ETH(CLK_ETH_GP1_EN, "eth_gp1_en", "sgm_325m_sel", 8), - GATE_ETH(CLK_ETH_WOCPU1_EN, "eth_wocpu1_en", "netsys_mcu_sel", 14), - GATE_ETH(CLK_ETH_WOCPU0_EN, "eth_wocpu0_en", "netsys_mcu_sel", 15), -}; - -static void __init mtk_sgmiisys_0_init(struct device_node *node) -{ - struct clk_onecell_data *clk_data; - int r; - - clk_data = mtk_alloc_clk_data(ARRAY_SIZE(sgmii0_clks)); - - mtk_clk_register_gates(node, sgmii0_clks, ARRAY_SIZE(sgmii0_clks), - clk_data); - - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); - if (r) - pr_err("%s(): could not register clock provider: %d\n", - __func__, r); -} -CLK_OF_DECLARE(mtk_sgmiisys_0, "mediatek,mt7986-sgmiisys_0", - mtk_sgmiisys_0_init); - -static void __init mtk_sgmiisys_1_init(struct device_node *node) -{ - struct clk_onecell_data *clk_data; - int r; - - clk_data = mtk_alloc_clk_data(ARRAY_SIZE(sgmii1_clks)); - - mtk_clk_register_gates(node, sgmii1_clks, ARRAY_SIZE(sgmii1_clks), - clk_data); - - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); - - if (r) - pr_err("%s(): could not register clock provider: %d\n", - __func__, r); -} -CLK_OF_DECLARE(mtk_sgmiisys_1, "mediatek,mt7986-sgmiisys_1", - mtk_sgmiisys_1_init); - -static void __init mtk_ethsys_init(struct device_node *node) -{ - struct clk_onecell_data *clk_data; - int r; - - clk_data = mtk_alloc_clk_data(ARRAY_SIZE(eth_clks)); - - mtk_clk_register_gates(node, eth_clks, ARRAY_SIZE(eth_clks), clk_data); - - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); - - if (r) - pr_err("%s(): could not register clock provider: %d\n", - __func__, r); -} -CLK_OF_DECLARE(mtk_ethsys, "mediatek,mt7986-ethsys", mtk_ethsys_init); diff --git a/target/linux/mediatek/files-5.15/drivers/clk/mediatek/clk-mt7986-infracfg.c b/target/linux/mediatek/files-5.15/drivers/clk/mediatek/clk-mt7986-infracfg.c deleted file mode 100644 index 82279dfcf..000000000 --- a/target/linux/mediatek/files-5.15/drivers/clk/mediatek/clk-mt7986-infracfg.c +++ /dev/null @@ -1,224 +0,0 @@ -// SPDX-License-Identifier: GPL-1.0 -/* - * Copyright (c) 2021 MediaTek Inc. - * Author: Sam Shih - * Author: Wenzhen Yu - */ - -#include -#include -#include -#include -#include -#include "clk-mtk.h" -#include "clk-gate.h" -#include "clk-mux.h" - -#include -#include - -static DEFINE_SPINLOCK(mt7986_clk_lock); - -static const struct mtk_fixed_factor infra_divs[] = { - FACTOR(CLK_INFRA_SYSAXI_D2, "infra_sysaxi_d2", "sysaxi_sel", 1, 2), -}; - -static const char *const infra_uart_parent[] __initconst = { "csw_f26m_sel", - "uart_sel" }; - -static const char *const infra_spi_parents[] __initconst = { "i2c_sel", - "spi_sel" }; - -static const char *const infra_pwm_bsel_parents[] __initconst = { - "top_rtc_32p7k", "csw_f26m_sel", "infra_sysaxi_d2", "pwm_sel" -}; - -static const char *const infra_pcie_parents[] __initconst = { - "top_rtc_32p7k", "csw_f26m_sel", "top_xtal", "pextp_tl_ck_sel" -}; - -static const struct mtk_mux infra_muxes[] = { - /* MODULE_CLK_SEL_0 */ - MUX_GATE_CLR_SET_UPD(CLK_INFRA_UART0_SEL, "infra_uart0_sel", - infra_uart_parent, 0x0018, 0x0010, 0x0014, 0, 1, - -1, -1, -1), - MUX_GATE_CLR_SET_UPD(CLK_INFRA_UART1_SEL, "infra_uart1_sel", - infra_uart_parent, 0x0018, 0x0010, 0x0014, 1, 1, - -1, -1, -1), - MUX_GATE_CLR_SET_UPD(CLK_INFRA_UART2_SEL, "infra_uart2_sel", - infra_uart_parent, 0x0018, 0x0010, 0x0014, 2, 1, - -1, -1, -1), - MUX_GATE_CLR_SET_UPD(CLK_INFRA_SPI0_SEL, "infra_spi0_sel", - infra_spi_parents, 0x0018, 0x0010, 0x0014, 4, 1, - -1, -1, -1), - MUX_GATE_CLR_SET_UPD(CLK_INFRA_SPI1_SEL, "infra_spi1_sel", - infra_spi_parents, 0x0018, 0x0010, 0x0014, 5, 1, - -1, -1, -1), - MUX_GATE_CLR_SET_UPD(CLK_INFRA_PWM1_SEL, "infra_pwm1_sel", - infra_pwm_bsel_parents, 0x0018, 0x0010, 0x0014, 9, - 2, -1, -1, -1), - MUX_GATE_CLR_SET_UPD(CLK_INFRA_PWM2_SEL, "infra_pwm2_sel", - infra_pwm_bsel_parents, 0x0018, 0x0010, 0x0014, 11, - 2, -1, -1, -1), - MUX_GATE_CLR_SET_UPD(CLK_INFRA_PWM_BSEL, "infra_pwm_bsel", - infra_pwm_bsel_parents, 0x0018, 0x0010, 0x0014, 13, - 2, -1, -1, -1), - /* MODULE_CLK_SEL_1 */ - MUX_GATE_CLR_SET_UPD(CLK_INFRA_PCIE_SEL, "infra_pcie_sel", - infra_pcie_parents, 0x0028, 0x0020, 0x0024, 0, 2, - -1, -1, -1), -}; - -static const struct mtk_gate_regs infra0_cg_regs = { - .set_ofs = 0x40, - .clr_ofs = 0x44, - .sta_ofs = 0x48, -}; - -static const struct mtk_gate_regs infra1_cg_regs = { - .set_ofs = 0x50, - .clr_ofs = 0x54, - .sta_ofs = 0x58, -}; - -static const struct mtk_gate_regs infra2_cg_regs = { - .set_ofs = 0x60, - .clr_ofs = 0x64, - .sta_ofs = 0x68, -}; - -#define GATE_INFRA0(_id, _name, _parent, _shift) \ - { \ - .id = _id, .name = _name, .parent_name = _parent, \ - .regs = &infra0_cg_regs, .shift = _shift, \ - .ops = &mtk_clk_gate_ops_setclr, \ - } - -#define GATE_INFRA1(_id, _name, _parent, _shift) \ - { \ - .id = _id, .name = _name, .parent_name = _parent, \ - .regs = &infra1_cg_regs, .shift = _shift, \ - .ops = &mtk_clk_gate_ops_setclr, \ - } - -#define GATE_INFRA2(_id, _name, _parent, _shift) \ - { \ - .id = _id, .name = _name, .parent_name = _parent, \ - .regs = &infra2_cg_regs, .shift = _shift, \ - .ops = &mtk_clk_gate_ops_setclr, \ - } - -static const struct mtk_gate infra_clks[] = { - /* INFRA0 */ - GATE_INFRA0(CLK_INFRA_GPT_STA, "infra_gpt_sta", "infra_sysaxi_d2", 0), - GATE_INFRA0(CLK_INFRA_PWM_HCK, "infra_pwm_hck", "infra_sysaxi_d2", 1), - GATE_INFRA0(CLK_INFRA_PWM_STA, "infra_pwm_sta", "infra_pwm_bsel", 2), - GATE_INFRA0(CLK_INFRA_PWM1_CK, "infra_pwm1", "infra_pwm1_sel", 3), - GATE_INFRA0(CLK_INFRA_PWM2_CK, "infra_pwm2", "infra_pwm2_sel", 4), - GATE_INFRA0(CLK_INFRA_CQ_DMA_CK, "infra_cq_dma", "sysaxi_sel", 6), - GATE_INFRA0(CLK_INFRA_EIP97_CK, "infra_eip97", "eip_b_sel", 7), - GATE_INFRA0(CLK_INFRA_AUD_BUS_CK, "infra_aud_bus", "sysaxi_sel", 8), - GATE_INFRA0(CLK_INFRA_AUD_26M_CK, "infra_aud_26m", "csw_f26m_sel", 9), - GATE_INFRA0(CLK_INFRA_AUD_L_CK, "infra_aud_l", "aud_l_sel", 10), - GATE_INFRA0(CLK_INFRA_AUD_AUD_CK, "infra_aud_aud", "a1sys_sel", 11), - GATE_INFRA0(CLK_INFRA_AUD_EG2_CK, "infra_aud_eg2", "a_tuner_sel", 13), - GATE_INFRA0(CLK_INFRA_DRAMC_26M_CK, "infra_dramc_26m", "csw_f26m_sel", - 14), - GATE_INFRA0(CLK_INFRA_DBG_CK, "infra_dbg", "infra_sysaxi_d2", 15), - GATE_INFRA0(CLK_INFRA_AP_DMA_CK, "infra_ap_dma", "infra_sysaxi_d2", 16), - GATE_INFRA0(CLK_INFRA_SEJ_CK, "infra_sej", "infra_sysaxi_d2", 24), - GATE_INFRA0(CLK_INFRA_SEJ_13M_CK, "infra_sej_13m", "csw_f26m_sel", 25), - GATE_INFRA0(CLK_INFRA_TRNG_CK, "infra_trng", "sysaxi_sel", 26), - /* INFRA1 */ - GATE_INFRA1(CLK_INFRA_THERM_CK, "infra_therm", "csw_f26m_sel", 0), - GATE_INFRA1(CLK_INFRA_I2C0_CK, "infra_i2c0", "i2c_sel", 1), - GATE_INFRA1(CLK_INFRA_UART0_CK, "infra_uart0", "infra_uart0_sel", 2), - GATE_INFRA1(CLK_INFRA_UART1_CK, "infra_uart1", "infra_uart1_sel", 3), - GATE_INFRA1(CLK_INFRA_UART2_CK, "infra_uart2", "infra_uart2_sel", 4), - GATE_INFRA1(CLK_INFRA_NFI1_CK, "infra_nfi1", "nfi1x_sel", 8), - GATE_INFRA1(CLK_INFRA_SPINFI1_CK, "infra_spinfi1", "spinfi_sel", 9), - GATE_INFRA1(CLK_INFRA_NFI_HCK_CK, "infra_nfi_hck", "infra_sysaxi_d2", - 10), - GATE_INFRA1(CLK_INFRA_SPI0_CK, "infra_spi0", "infra_spi0_sel", 11), - GATE_INFRA1(CLK_INFRA_SPI1_CK, "infra_spi1", "infra_spi1_sel", 12), - GATE_INFRA1(CLK_INFRA_SPI0_HCK_CK, "infra_spi0_hck", "infra_sysaxi_d2", - 13), - GATE_INFRA1(CLK_INFRA_SPI1_HCK_CK, "infra_spi1_hck", "infra_sysaxi_d2", - 14), - GATE_INFRA1(CLK_INFRA_FRTC_CK, "infra_frtc", "top_rtc_32k", 15), - GATE_INFRA1(CLK_INFRA_MSDC_CK, "infra_msdc", "emmc_416m_sel", 16), - GATE_INFRA1(CLK_INFRA_MSDC_HCK_CK, "infra_msdc_hck", "emmc_250m_sel", - 17), - GATE_INFRA1(CLK_INFRA_MSDC_133M_CK, "infra_msdc_133m", "sysaxi_sel", - 18), - GATE_INFRA1(CLK_INFRA_MSDC_66M_CK, "infra_msdc_66m", "infra_sysaxi_d2", - 19), - GATE_INFRA1(CLK_INFRA_ADC_26M_CK, "infra_adc_26m", "infra_adc_frc", 20), - GATE_INFRA1(CLK_INFRA_ADC_FRC_CK, "infra_adc_frc", "csw_f26m_sel", 21), - GATE_INFRA1(CLK_INFRA_FBIST2FPC_CK, "infra_fbist2fpc", "nfi1x_sel", 23), - /* INFRA2 */ - GATE_INFRA2(CLK_INFRA_IUSB_133_CK, "infra_iusb_133", "sysaxi_sel", 0), - GATE_INFRA2(CLK_INFRA_IUSB_66M_CK, "infra_iusb_66m", "infra_sysaxi_d2", - 1), - GATE_INFRA2(CLK_INFRA_IUSB_SYS_CK, "infra_iusb_sys", "u2u3_sys_sel", 2), - GATE_INFRA2(CLK_INFRA_IUSB_CK, "infra_iusb", "u2u3_sel", 3), - GATE_INFRA2(CLK_INFRA_IPCIE_CK, "infra_ipcie", "pextp_tl_ck_sel", 12), - GATE_INFRA2(CLK_INFRA_IPCIE_PIPE_CK, "infra_ipcie_pipe", "top_xtal", - 13), - GATE_INFRA2(CLK_INFRA_IPCIER_CK, "infra_ipcier", "csw_f26m_sel", 14), - GATE_INFRA2(CLK_INFRA_IPCIEB_CK, "infra_ipcieb", "sysaxi_sel", 15), -}; - -static int clk_mt7986_infracfg_probe(struct platform_device *pdev) -{ - struct clk_onecell_data *clk_data; - struct device_node *node = pdev->dev.of_node; - int r; - void __iomem *base; - int nr = ARRAY_SIZE(infra_divs) + ARRAY_SIZE(infra_muxes) + - ARRAY_SIZE(infra_clks); - - base = of_iomap(node, 0); - if (!base) { - pr_err("%s(): ioremap failed\n", __func__); - return -ENOMEM; - } - - clk_data = mtk_alloc_clk_data(nr); - - if (!clk_data) - return -ENOMEM; - - mtk_clk_register_factors(infra_divs, ARRAY_SIZE(infra_divs), clk_data); - mtk_clk_register_muxes(infra_muxes, ARRAY_SIZE(infra_muxes), node, - &mt7986_clk_lock, clk_data); - mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks), - clk_data); - - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); - if (r) { - pr_err("%s(): could not register clock provider: %d\n", - __func__, r); - goto free_infracfg_data; - } - return r; - -free_infracfg_data: - mtk_free_clk_data(clk_data); - return r; - -} - -static const struct of_device_id of_match_clk_mt7986_infracfg[] = { - { .compatible = "mediatek,mt7986-infracfg", }, - {} -}; - -static struct platform_driver clk_mt7986_infracfg_drv = { - .probe = clk_mt7986_infracfg_probe, - .driver = { - .name = "clk-mt7986-infracfg", - .of_match_table = of_match_clk_mt7986_infracfg, - }, -}; -builtin_platform_driver(clk_mt7986_infracfg_drv); diff --git a/target/linux/mediatek/files-5.15/drivers/clk/mediatek/clk-mt7986-topckgen.c b/target/linux/mediatek/files-5.15/drivers/clk/mediatek/clk-mt7986-topckgen.c deleted file mode 100644 index 8550e2be7..000000000 --- a/target/linux/mediatek/files-5.15/drivers/clk/mediatek/clk-mt7986-topckgen.c +++ /dev/null @@ -1,342 +0,0 @@ -// SPDX-License-Identifier: GPL-1.0 -/* - * Copyright (c) 2021 MediaTek Inc. - * Author: Sam Shih - * Author: Wenzhen Yu - */ - -#include -#include -#include -#include -#include -#include "clk-mtk.h" -#include "clk-gate.h" -#include "clk-mux.h" - -#include -#include - -static DEFINE_SPINLOCK(mt7986_clk_lock); - -static const struct mtk_fixed_clk top_fixed_clks[] = { - FIXED_CLK(CLK_TOP_XTAL, "top_xtal", "clkxtal", 40000000), - FIXED_CLK(CLK_TOP_JTAG, "top_jtag", "clkxtal", 50000000), -}; - -static const struct mtk_fixed_factor top_divs[] = { - /* XTAL */ - FACTOR(CLK_TOP_XTAL_D2, "top_xtal_d2", "top_xtal", 1, 2), - FACTOR(CLK_TOP_RTC_32K, "top_rtc_32k", "top_xtal", 1, 1250), - FACTOR(CLK_TOP_RTC_32P7K, "top_rtc_32p7k", "top_xtal", 1, 1220), - /* MPLL */ - FACTOR(CLK_TOP_MPLL_D2, "top_mpll_d2", "mpll", 1, 2), - FACTOR(CLK_TOP_MPLL_D4, "top_mpll_d4", "mpll", 1, 4), - FACTOR(CLK_TOP_MPLL_D8, "top_mpll_d8", "mpll", 1, 8), - FACTOR(CLK_TOP_MPLL_D8_D2, "top_mpll_d8_d2", "mpll", 1, 16), - FACTOR(CLK_TOP_MPLL_D3_D2, "top_mpll_d3_d2", "mpll", 1, 6), - /* MMPLL */ - FACTOR(CLK_TOP_MMPLL_D2, "top_mmpll_d2", "mmpll", 1, 2), - FACTOR(CLK_TOP_MMPLL_D4, "top_mmpll_d4", "mmpll", 1, 4), - FACTOR(CLK_TOP_MMPLL_D8, "top_mmpll_d8", "mmpll", 1, 8), - FACTOR(CLK_TOP_MMPLL_D8_D2, "top_mmpll_d8_d2", "mmpll", 1, 16), - FACTOR(CLK_TOP_MMPLL_D3_D8, "top_mmpll_d3_d8", "mmpll", 1, 24), - FACTOR(CLK_TOP_MMPLL_U2PHY, "top_mmpll_u2phy", "mmpll", 1, 30), - /* APLL2 */ - FACTOR(CLK_TOP_APLL2_D4, "top_apll2_d4", "apll2", 1, 4), - /* NET1PLL */ - FACTOR(CLK_TOP_NET1PLL_D4, "top_net1pll_d4", "net1pll", 1, 4), - FACTOR(CLK_TOP_NET1PLL_D5, "top_net1pll_d5", "net1pll", 1, 5), - FACTOR(CLK_TOP_NET1PLL_D5_D2, "top_net1pll_d5_d2", "net1pll", 1, 10), - FACTOR(CLK_TOP_NET1PLL_D5_D4, "top_net1pll_d5_d4", "net1pll", 1, 20), - FACTOR(CLK_TOP_NET1PLL_D8_D2, "top_net1pll_d8_d2", "net1pll", 1, 16), - FACTOR(CLK_TOP_NET1PLL_D8_D4, "top_net1pll_d8_d4", "net1pll", 1, 32), - /* NET2PLL */ - FACTOR(CLK_TOP_NET2PLL_D4, "top_net2pll_d4", "net2pll", 1, 4), - FACTOR(CLK_TOP_NET2PLL_D4_D2, "top_net2pll_d4_d2", "net2pll", 1, 8), - FACTOR(CLK_TOP_NET2PLL_D3_D2, "top_net2pll_d3_d2", "net2pll", 1, 2), - /* WEDMCUPLL */ - FACTOR(CLK_TOP_WEDMCUPLL_D5_D2, "top_wedmcupll_d5_d2", "wedmcupll", 1, - 10), -}; - -static const char *const nfi1x_parents[] __initconst = { "top_xtal", - "top_mmpll_d8", - "top_net1pll_d8_d2", - "top_net2pll_d3_d2", - "top_mpll_d4", - "top_mmpll_d8_d2", - "top_wedmcupll_d5_d2", - "top_mpll_d8" }; - -static const char *const spinfi_parents[] __initconst = { - "top_xtal_d2", "top_xtal", "top_net1pll_d5_d4", - "top_mpll_d4", "top_mmpll_d8_d2", "top_wedmcupll_d5_d2", - "top_mmpll_d3_d8", "top_mpll_d8" -}; - -static const char *const spi_parents[] __initconst = { - "top_xtal", "top_mpll_d2", "top_mmpll_d8", - "top_net1pll_d8_d2", "top_net2pll_d3_d2", "top_net1pll_d5_d4", - "top_mpll_d4", "top_wedmcupll_d5_d2" -}; - -static const char *const uart_parents[] __initconst = { "top_xtal", - "top_mpll_d8", - "top_mpll_d8_d2" }; - -static const char *const pwm_parents[] __initconst = { - "top_xtal", "top_net1pll_d8_d2", "top_net1pll_d5_d4", "top_mpll_d4" -}; - -static const char *const i2c_parents[] __initconst = { - "top_xtal", "top_net1pll_d5_d4", "top_mpll_d4", "top_net1pll_d8_d4" -}; - -static const char *const pextp_tl_ck_parents[] __initconst = { - "top_xtal", "top_net1pll_d5_d4", "top_net2pll_d4_d2", "top_rtc_32k" -}; - -static const char *const emmc_250m_parents[] __initconst = { - "top_xtal", "top_net1pll_d5_d2" -}; - -static const char *const emmc_416m_parents[] __initconst = { "top_xtal", - "mpll" }; - -static const char *const f_26m_adc_parents[] __initconst = { "top_xtal", - "top_mpll_d8_d2" }; - -static const char *const dramc_md32_parents[] __initconst = { "top_xtal", - "top_mpll_d2" }; - -static const char *const sysaxi_parents[] __initconst = { "top_xtal", - "top_net1pll_d8_d2", - "top_net2pll_d4" }; - -static const char *const sysapb_parents[] __initconst = { "top_xtal", - "top_mpll_d3_d2", - "top_net2pll_d4_d2" }; - -static const char *const arm_db_main_parents[] __initconst = { - "top_xtal", "top_net2pll_d3_d2" -}; - -static const char *const arm_db_jtsel_parents[] __initconst = { "top_jtag", - "top_xtal" }; - -static const char *const netsys_parents[] __initconst = { "top_xtal", - "top_mmpll_d4" }; - -static const char *const netsys_500m_parents[] __initconst = { - "top_xtal", "top_net1pll_d5" -}; - -static const char *const netsys_mcu_parents[] __initconst = { - "top_xtal", "wedmcupll", "top_mmpll_d2", "top_net1pll_d4", - "top_net1pll_d5" -}; - -static const char *const netsys_2x_parents[] __initconst = { - "top_xtal", "net2pll", "wedmcupll", "top_mmpll_d2" -}; - -static const char *const sgm_325m_parents[] __initconst = { "top_xtal", - "sgmpll" }; - -static const char *const sgm_reg_parents[] __initconst = { - "top_xtal", "top_net1pll_d8_d4" -}; - -static const char *const a1sys_parents[] __initconst = { "top_xtal", - "top_apll2_d4" }; - -static const char *const conn_mcusys_parents[] __initconst = { "top_xtal", - "top_mmpll_d2" }; - -static const char *const eip_b_parents[] __initconst = { "top_xtal", - "net2pll" }; - -static const char *const aud_l_parents[] __initconst = { "top_xtal", "apll2", - "top_mpll_d8_d2" }; - -static const char *const a_tuner_parents[] __initconst = { "top_xtal", - "top_apll2_d4", - "top_mpll_d8_d2" }; - -static const char *const u2u3_sys_parents[] __initconst = { - "top_xtal", "top_net1pll_d5_d4" -}; - -static const char *const da_u2_refsel_parents[] __initconst = { - "top_xtal", "top_mmpll_u2phy" -}; - -static const struct mtk_mux top_muxes[] = { - /* CLK_CFG_0 */ - MUX_GATE_CLR_SET_UPD(CLK_TOP_NFI1X_SEL, "nfi1x_sel", nfi1x_parents, - 0x000, 0x004, 0x008, 0, 3, 7, 0x1C0, 0), - MUX_GATE_CLR_SET_UPD(CLK_TOP_SPINFI_SEL, "spinfi_sel", spinfi_parents, - 0x000, 0x004, 0x008, 8, 3, 15, 0x1C0, 1), - MUX_GATE_CLR_SET_UPD(CLK_TOP_SPI_SEL, "spi_sel", spi_parents, 0x000, - 0x004, 0x008, 16, 3, 23, 0x1C0, 2), - MUX_GATE_CLR_SET_UPD(CLK_TOP_SPIM_MST_SEL, "spim_mst_sel", spi_parents, - 0x000, 0x004, 0x008, 24, 3, 31, 0x1C0, 3), - /* CLK_CFG_1 */ - MUX_GATE_CLR_SET_UPD(CLK_TOP_UART_SEL, "uart_sel", uart_parents, 0x010, - 0x014, 0x018, 0, 2, 7, 0x1C0, 4), - MUX_GATE_CLR_SET_UPD(CLK_TOP_PWM_SEL, "pwm_sel", pwm_parents, 0x010, - 0x014, 0x018, 8, 2, 15, 0x1C0, 5), - MUX_GATE_CLR_SET_UPD(CLK_TOP_I2C_SEL, "i2c_sel", i2c_parents, 0x010, - 0x014, 0x018, 16, 2, 23, 0x1C0, 6), - MUX_GATE_CLR_SET_UPD(CLK_TOP_PEXTP_TL_SEL, "pextp_tl_ck_sel", - pextp_tl_ck_parents, 0x010, 0x014, 0x018, 24, 2, - 31, 0x1C0, 7), - /* CLK_CFG_2 */ - MUX_GATE_CLR_SET_UPD(CLK_TOP_EMMC_250M_SEL, "emmc_250m_sel", - emmc_250m_parents, 0x020, 0x024, 0x028, 0, 1, 7, - 0x1C0, 8), - MUX_GATE_CLR_SET_UPD(CLK_TOP_EMMC_416M_SEL, "emmc_416m_sel", - emmc_416m_parents, 0x020, 0x024, 0x028, 8, 1, 15, - 0x1C0, 9), - MUX_GATE_CLR_SET_UPD(CLK_TOP_F_26M_ADC_SEL, "f_26m_adc_sel", - f_26m_adc_parents, 0x020, 0x024, 0x028, 16, 1, 23, - 0x1C0, 10), - MUX_GATE_CLR_SET_UPD(CLK_TOP_DRAMC_SEL, "dramc_sel", f_26m_adc_parents, - 0x020, 0x024, 0x028, 24, 1, 31, 0x1C0, 11), - /* CLK_CFG_3 */ - MUX_GATE_CLR_SET_UPD(CLK_TOP_DRAMC_MD32_SEL, "dramc_md32_sel", - dramc_md32_parents, 0x030, 0x034, 0x038, 0, 1, 7, - 0x1C0, 12), - MUX_GATE_CLR_SET_UPD(CLK_TOP_SYSAXI_SEL, "sysaxi_sel", sysaxi_parents, - 0x030, 0x034, 0x038, 8, 2, 15, 0x1C0, 13), - MUX_GATE_CLR_SET_UPD(CLK_TOP_SYSAPB_SEL, "sysapb_sel", sysapb_parents, - 0x030, 0x034, 0x038, 16, 2, 23, 0x1C0, 14), - MUX_GATE_CLR_SET_UPD(CLK_TOP_ARM_DB_MAIN_SEL, "arm_db_main_sel", - arm_db_main_parents, 0x030, 0x034, 0x038, 24, 1, - 31, 0x1C0, 15), - /* CLK_CFG_4 */ - MUX_GATE_CLR_SET_UPD(CLK_TOP_ARM_DB_JTSEL, "arm_db_jtsel", - arm_db_jtsel_parents, 0x040, 0x044, 0x048, 0, 1, 7, - 0x1C0, 16), - MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_SEL, "netsys_sel", netsys_parents, - 0x040, 0x044, 0x048, 8, 1, 15, 0x1C0, 17), - MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_500M_SEL, "netsys_500m_sel", - netsys_500m_parents, 0x040, 0x044, 0x048, 16, 1, - 23, 0x1C0, 18), - MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_MCU_SEL, "netsys_mcu_sel", - netsys_mcu_parents, 0x040, 0x044, 0x048, 24, 3, 31, - 0x1C0, 19), - /* CLK_CFG_5 */ - MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_2X_SEL, "netsys_2x_sel", - netsys_2x_parents, 0x050, 0x054, 0x058, 0, 2, 7, - 0x1C0, 20), - MUX_GATE_CLR_SET_UPD(CLK_TOP_SGM_325M_SEL, "sgm_325m_sel", - sgm_325m_parents, 0x050, 0x054, 0x058, 8, 1, 15, - 0x1C0, 21), - MUX_GATE_CLR_SET_UPD(CLK_TOP_SGM_REG_SEL, "sgm_reg_sel", - sgm_reg_parents, 0x050, 0x054, 0x058, 16, 1, 23, - 0x1C0, 22), - MUX_GATE_CLR_SET_UPD(CLK_TOP_A1SYS_SEL, "a1sys_sel", a1sys_parents, - 0x050, 0x054, 0x058, 24, 1, 31, 0x1C0, 23), - /* CLK_CFG_6 */ - MUX_GATE_CLR_SET_UPD(CLK_TOP_CONN_MCUSYS_SEL, "conn_mcusys_sel", - conn_mcusys_parents, 0x060, 0x064, 0x068, 0, 1, 7, - 0x1C0, 24), - MUX_GATE_CLR_SET_UPD(CLK_TOP_EIP_B_SEL, "eip_b_sel", eip_b_parents, - 0x060, 0x064, 0x068, 8, 1, 15, 0x1C0, 25), - MUX_GATE_CLR_SET_UPD(CLK_TOP_PCIE_PHY_SEL, "pcie_phy_sel", - f_26m_adc_parents, 0x060, 0x064, 0x068, 16, 1, 23, - 0x1C0, 26), - MUX_GATE_CLR_SET_UPD(CLK_TOP_USB3_PHY_SEL, "usb3_phy_sel", - f_26m_adc_parents, 0x060, 0x064, 0x068, 24, 1, 31, - 0x1C0, 27), - /* CLK_CFG_7 */ - MUX_GATE_CLR_SET_UPD(CLK_TOP_F26M_SEL, "csw_f26m_sel", - f_26m_adc_parents, 0x070, 0x074, 0x078, 0, 1, 7, - 0x1C0, 28), - MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_L_SEL, "aud_l_sel", aud_l_parents, - 0x070, 0x074, 0x078, 8, 2, 15, 0x1C0, 29), - MUX_GATE_CLR_SET_UPD(CLK_TOP_A_TUNER_SEL, "a_tuner_sel", - a_tuner_parents, 0x070, 0x074, 0x078, 16, 2, 23, - 0x1C0, 30), - MUX_GATE_CLR_SET_UPD(CLK_TOP_U2U3_SEL, "u2u3_sel", f_26m_adc_parents, - 0x070, 0x074, 0x078, 24, 1, 31, 0x1C4, 0), - /* CLK_CFG_8 */ - MUX_GATE_CLR_SET_UPD(CLK_TOP_U2U3_SYS_SEL, "u2u3_sys_sel", - u2u3_sys_parents, 0x080, 0x084, 0x088, 0, 1, 7, - 0x1C4, 1), - MUX_GATE_CLR_SET_UPD(CLK_TOP_U2U3_XHCI_SEL, "u2u3_xhci_sel", - u2u3_sys_parents, 0x080, 0x084, 0x088, 8, 1, 15, - 0x1C4, 2), - MUX_GATE_CLR_SET_UPD(CLK_TOP_DA_U2_REFSEL, "da_u2_refsel", - da_u2_refsel_parents, 0x080, 0x084, 0x088, 16, 1, - 23, 0x1C4, 3), - MUX_GATE_CLR_SET_UPD(CLK_TOP_DA_U2_CK_1P_SEL, "da_u2_ck_1p_sel", - da_u2_refsel_parents, 0x080, 0x084, 0x088, 24, 1, - 31, 0x1C4, 4), - /* CLK_CFG_9 */ - MUX_GATE_CLR_SET_UPD(CLK_TOP_AP2CNN_HOST_SEL, "ap2cnn_host_sel", - sgm_reg_parents, 0x090, 0x094, 0x098, 0, 1, 7, - 0x1C4, 5), -}; - -static int clk_mt7986_topckgen_probe(struct platform_device *pdev) -{ - struct clk_onecell_data *clk_data; - struct device_node *node = pdev->dev.of_node; - int r; - void __iomem *base; - int nr = ARRAY_SIZE(top_fixed_clks) + ARRAY_SIZE(top_divs) + - ARRAY_SIZE(top_muxes); - - base = of_iomap(node, 0); - if (!base) { - pr_err("%s(): ioremap failed\n", __func__); - return -ENOMEM; - } - - clk_data = mtk_alloc_clk_data(nr); - if (!clk_data) - return -ENOMEM; - - mtk_clk_register_fixed_clks(top_fixed_clks, ARRAY_SIZE(top_fixed_clks), - clk_data); - mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), clk_data); - mtk_clk_register_muxes(top_muxes, ARRAY_SIZE(top_muxes), node, - &mt7986_clk_lock, clk_data); - - clk_prepare_enable(clk_data->clks[CLK_TOP_SYSAXI_SEL]); - clk_prepare_enable(clk_data->clks[CLK_TOP_SYSAPB_SEL]); - clk_prepare_enable(clk_data->clks[CLK_TOP_DRAMC_SEL]); - clk_prepare_enable(clk_data->clks[CLK_TOP_DRAMC_MD32_SEL]); - clk_prepare_enable(clk_data->clks[CLK_TOP_F26M_SEL]); - clk_prepare_enable(clk_data->clks[CLK_TOP_SGM_REG_SEL]); - - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); - - if (r) { - pr_err("%s(): could not register clock provider: %d\n", - __func__, r); - goto free_topckgen_data; - } - return r; - -free_topckgen_data: - mtk_free_clk_data(clk_data); - return r; -} - -static const struct of_device_id of_match_clk_mt7986_topckgen[] = { - { .compatible = "mediatek,mt7986-topckgen", }, - {} -}; - -static struct platform_driver clk_mt7986_topckgen_drv = { - .probe = clk_mt7986_topckgen_probe, - .driver = { - .name = "clk-mt7986-topckgen", - .of_match_table = of_match_clk_mt7986_topckgen, - }, -}; -builtin_platform_driver(clk_mt7986_topckgen_drv); diff --git a/target/linux/mediatek/files-5.15/drivers/clk/mediatek/clk-mt7988-apmixed.c b/target/linux/mediatek/files-5.15/drivers/clk/mediatek/clk-mt7988-apmixed.c deleted file mode 100644 index 587b70767..000000000 --- a/target/linux/mediatek/files-5.15/drivers/clk/mediatek/clk-mt7988-apmixed.c +++ /dev/null @@ -1,113 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (c) 2023 MediaTek Inc. - * Author: Sam Shih - * Author: Xiufeng Li - */ - -#include -#include -#include -#include -#include -#include "clk-mtk.h" -#include "clk-gate.h" -#include "clk-mux.h" -#include - -#define MT7988_PLL_FMAX (2500UL * MHZ) -#define MT7988_PCW_CHG_SHIFT 2 - -#define PLL_xtal(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _rst_bar_mask, \ - _pcwbits, _pd_reg, _pd_shift, _tuner_reg, _tuner_en_reg, \ - _tuner_en_bit, _pcw_reg, _pcw_shift, _pcw_chg_reg, \ - _div_table) \ - { \ - .id = _id, .name = _name, .reg = _reg, .pwr_reg = _pwr_reg, \ - .en_mask = _en_mask, .flags = _flags, \ - .rst_bar_mask = BIT(_rst_bar_mask), .fmax = MT7988_PLL_FMAX, \ - .pcwbits = _pcwbits, .pd_reg = _pd_reg, \ - .pd_shift = _pd_shift, .tuner_reg = _tuner_reg, \ - .tuner_en_reg = _tuner_en_reg, .tuner_en_bit = _tuner_en_bit, \ - .pcw_reg = _pcw_reg, .pcw_shift = _pcw_shift, \ - .pcw_chg_reg = _pcw_chg_reg, \ - .pcw_chg_shift = MT7988_PCW_CHG_SHIFT, \ - .div_table = _div_table, .parent_name = "clkxtal", \ - } - -#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _rst_bar_mask, \ - _pcwbits, _pd_reg, _pd_shift, _tuner_reg, _tuner_en_reg, \ - _tuner_en_bit, _pcw_reg, _pcw_shift, _pcw_chg_reg) \ - PLL_xtal(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _rst_bar_mask, \ - _pcwbits, _pd_reg, _pd_shift, _tuner_reg, _tuner_en_reg, \ - _tuner_en_bit, _pcw_reg, _pcw_shift, _pcw_chg_reg, NULL) - -static const struct mtk_pll_data plls[] = { - PLL(CLK_APMIXED_NETSYSPLL, "netsyspll", 0x0104, 0x0110, 0x00000001, 0, - 0, 32, 0x0104, 4, 0, 0, 0, 0x0108, 0, 0x0104), - PLL(CLK_APMIXED_MPLL, "mpll", 0x0114, 0x0120, 0xff000001, HAVE_RST_BAR, - 23, 32, 0x0114, 4, 0, 0, 0, 0x0118, 0, 0x0114), - PLL(CLK_APMIXED_MMPLL, "mmpll", 0x0124, 0x0130, 0xff000001, - HAVE_RST_BAR, 23, 32, 0x0124, 4, 0, 0, 0, 0x0128, 0, 0x0124), - PLL(CLK_APMIXED_APLL2, "apll2", 0x0134, 0x0140, 0x00000001, 0, 0, 32, - 0x0134, 4, 0x0704, 0x0700, 1, 0x0138, 0, 0x0134), - PLL(CLK_APMIXED_NET1PLL, "net1pll", 0x0144, 0x0150, 0xff000001, - HAVE_RST_BAR, 23, 32, 0x0144, 4, 0, 0, 0, 0x0148, 0, 0x0144), - PLL(CLK_APMIXED_NET2PLL, "net2pll", 0x0154, 0x0160, 0xff000001, - (HAVE_RST_BAR | PLL_AO), 23, 32, 0x0154, 4, 0, 0, 0, 0x0158, 0, - 0x0154), - PLL(CLK_APMIXED_WEDMCUPLL, "wedmcupll", 0x0164, 0x0170, 0x00000001, 0, - 0, 32, 0x0164, 4, 0, 0, 0, 0x0168, 0, 0x0164), - PLL(CLK_APMIXED_SGMPLL, "sgmpll", 0x0174, 0x0180, 0x00000001, 0, 0, 32, - 0x0174, 4, 0, 0, 0, 0x0178, 0, 0x0174), - PLL(CLK_APMIXED_ARM_B, "arm_b", 0x0204, 0x0210, 0xff000001, - (HAVE_RST_BAR | PLL_AO), 23, 32, 0x0204, 4, 0, 0, 0, 0x0208, 0, - 0x0204), - PLL(CLK_APMIXED_CCIPLL2_B, "ccipll2_b", 0x0214, 0x0220, 0xff000001, - HAVE_RST_BAR, 23, 32, 0x0214, 4, 0, 0, 0, 0x0218, 0, 0x0214), - PLL(CLK_APMIXED_USXGMIIPLL, "usxgmiipll", 0x0304, 0x0310, 0xff000001, - HAVE_RST_BAR, 23, 32, 0x0304, 4, 0, 0, 0, 0x0308, 0, 0x0304), - PLL(CLK_APMIXED_MSDCPLL, "msdcpll", 0x0314, 0x0320, 0x00000001, 0, 0, - 32, 0x0314, 4, 0, 0, 0, 0x0318, 0, 0x0314), -}; - -static const struct of_device_id of_match_clk_mt7988_apmixed[] = { - { - .compatible = "mediatek,mt7988-apmixedsys", - }, - {} -}; - -static int clk_mt7988_apmixed_probe(struct platform_device *pdev) -{ - struct clk_onecell_data *clk_data; - struct device_node *node = pdev->dev.of_node; - int r; - - clk_data = mtk_alloc_clk_data(ARRAY_SIZE(plls)); - if (!clk_data) - return -ENOMEM; - - mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data); - - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); - if (r) { - pr_err("%s(): could not register clock provider: %d\n", - __func__, r); - goto free_apmixed_data; - } - return r; - -free_apmixed_data: - mtk_free_clk_data(clk_data); - return r; -} - -static struct platform_driver clk_mt7988_apmixed_drv = { - .probe = clk_mt7988_apmixed_probe, - .driver = { - .name = "clk-mt7988-apmixed", - .of_match_table = of_match_clk_mt7988_apmixed, - }, -}; -builtin_platform_driver(clk_mt7988_apmixed_drv); diff --git a/target/linux/mediatek/files-5.15/drivers/clk/mediatek/clk-mt7988-eth.c b/target/linux/mediatek/files-5.15/drivers/clk/mediatek/clk-mt7988-eth.c deleted file mode 100644 index 341d0f73f..000000000 --- a/target/linux/mediatek/files-5.15/drivers/clk/mediatek/clk-mt7988-eth.c +++ /dev/null @@ -1,299 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (c) 2023 MediaTek Inc. - * Author: Sam Shih - * Author: Xiufeng Li - */ - -#include -#include -#include -#include -#include -#include "clk-mtk.h" -#include "clk-gate.h" -#include - -static const struct mtk_gate_regs ethdma_cg_regs = { - .set_ofs = 0x30, - .clr_ofs = 0x30, - .sta_ofs = 0x30, -}; - -#define GATE_ETHDMA(_id, _name, _parent, _shift) \ - { \ - .id = _id, .name = _name, .parent_name = _parent, \ - .regs = ðdma_cg_regs, .shift = _shift, \ - .ops = &mtk_clk_gate_ops_no_setclr_inv, \ - } - -static const struct mtk_gate ethdma_clks[] = { - GATE_ETHDMA(CLK_ETHDMA_XGP1_EN, "ethdma_xgp1_en", "top_xtal", 0), - GATE_ETHDMA(CLK_ETHDMA_XGP2_EN, "ethdma_xgp2_en", "top_xtal", 1), - GATE_ETHDMA(CLK_ETHDMA_XGP3_EN, "ethdma_xgp3_en", "top_xtal", 2), - GATE_ETHDMA(CLK_ETHDMA_FE_EN, "ethdma_fe_en", "netsys_2x_sel", 6), - GATE_ETHDMA(CLK_ETHDMA_GP2_EN, "ethdma_gp2_en", "top_xtal", 7), - GATE_ETHDMA(CLK_ETHDMA_GP1_EN, "ethdma_gp1_en", "top_xtal", 8), - GATE_ETHDMA(CLK_ETHDMA_GP3_EN, "ethdma_gp3_en", "top_xtal", 10), - GATE_ETHDMA(CLK_ETHDMA_ESW_EN, "ethdma_esw_en", "netsys_gsw_sel", 16), - GATE_ETHDMA(CLK_ETHDMA_CRYPT0_EN, "ethdma_crypt0_en", "eip197_sel", - 29), -}; - -static int clk_mt7988_ethsys_probe(struct platform_device *pdev) -{ - struct clk_onecell_data *clk_data; - struct device_node *node = pdev->dev.of_node; - int r; - void __iomem *base; - - base = of_iomap(node, 0); - if (!base) { - pr_err("%s(): ioremap failed\n", __func__); - return -ENOMEM; - } - - clk_data = mtk_alloc_clk_data(ARRAY_SIZE(ethdma_clks)); - - if (!clk_data) - return -ENOMEM; - - mtk_clk_register_gates(node, ethdma_clks, ARRAY_SIZE(ethdma_clks), - clk_data); - - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); - if (r) { - pr_err("%s(): could not register clock provider: %d\n", - __func__, r); - goto free_data; - } - return r; - -free_data: - mtk_free_clk_data(clk_data); - return r; -} - -static const struct mtk_gate_regs sgmii0_cg_regs = { - .set_ofs = 0xe4, - .clr_ofs = 0xe4, - .sta_ofs = 0xe4, -}; - -#define GATE_SGMII0(_id, _name, _parent, _shift) \ - { \ - .id = _id, .name = _name, .parent_name = _parent, \ - .regs = &sgmii0_cg_regs, .shift = _shift, \ - .ops = &mtk_clk_gate_ops_no_setclr_inv, \ - } - -static const struct mtk_gate sgmii0_clks[] = { - GATE_SGMII0(CLK_SGM0_TX_EN, "sgm0_tx_en", "top_xtal", 2), - GATE_SGMII0(CLK_SGM0_RX_EN, "sgm0_rx_en", "top_xtal", 3), -}; - -static int clk_mt7988_sgmii0_probe(struct platform_device *pdev) -{ - struct clk_onecell_data *clk_data; - struct device_node *node = pdev->dev.of_node; - int r; - void __iomem *base; - - base = of_iomap(node, 0); - if (!base) { - pr_err("%s(): ioremap failed\n", __func__); - return -ENOMEM; - } - - clk_data = mtk_alloc_clk_data(ARRAY_SIZE(sgmii0_clks)); - - if (!clk_data) - return -ENOMEM; - - mtk_clk_register_gates(node, sgmii0_clks, ARRAY_SIZE(sgmii0_clks), - clk_data); - - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); - if (r) { - pr_err("%s(): could not register clock provider: %d\n", - __func__, r); - goto free_data; - } - return r; - -free_data: - mtk_free_clk_data(clk_data); - return r; -} - -static const struct mtk_gate_regs sgmii1_cg_regs = { - .set_ofs = 0xe4, - .clr_ofs = 0xe4, - .sta_ofs = 0xe4, -}; - -#define GATE_SGMII1(_id, _name, _parent, _shift) \ - { \ - .id = _id, .name = _name, .parent_name = _parent, \ - .regs = &sgmii1_cg_regs, .shift = _shift, \ - .ops = &mtk_clk_gate_ops_no_setclr_inv, \ - } - -static const struct mtk_gate sgmii1_clks[] = { - GATE_SGMII1(CLK_SGM1_TX_EN, "sgm1_tx_en", "top_xtal", 2), - GATE_SGMII1(CLK_SGM1_RX_EN, "sgm1_rx_en", "top_xtal", 3), -}; - -static int clk_mt7988_sgmii1_probe(struct platform_device *pdev) -{ - struct clk_onecell_data *clk_data; - struct device_node *node = pdev->dev.of_node; - int r; - void __iomem *base; - - base = of_iomap(node, 0); - if (!base) { - pr_err("%s(): ioremap failed\n", __func__); - return -ENOMEM; - } - - clk_data = mtk_alloc_clk_data(ARRAY_SIZE(sgmii1_clks)); - - if (!clk_data) - return -ENOMEM; - - mtk_clk_register_gates(node, sgmii1_clks, ARRAY_SIZE(sgmii1_clks), - clk_data); - - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); - if (r) { - pr_err("%s(): could not register clock provider: %d\n", - __func__, r); - goto free_data; - } - return r; - -free_data: - mtk_free_clk_data(clk_data); - return r; -} - -static const struct mtk_gate_regs ethwarp_cg_regs = { - .set_ofs = 0x14, - .clr_ofs = 0x14, - .sta_ofs = 0x14, -}; - -#define GATE_ETHWARP(_id, _name, _parent, _shift) \ - { \ - .id = _id, .name = _name, .parent_name = _parent, \ - .regs = ðwarp_cg_regs, .shift = _shift, \ - .ops = &mtk_clk_gate_ops_no_setclr_inv, \ - } - -static const struct mtk_gate ethwarp_clks[] = { - GATE_ETHWARP(CLK_ETHWARP_WOCPU2_EN, "ethwarp_wocpu2_en", - "netsys_mcu_sel", 13), - GATE_ETHWARP(CLK_ETHWARP_WOCPU1_EN, "ethwarp_wocpu1_en", - "netsys_mcu_sel", 14), - GATE_ETHWARP(CLK_ETHWARP_WOCPU0_EN, "ethwarp_wocpu0_en", - "netsys_mcu_sel", 15), -}; - -static int clk_mt7988_ethwarp_probe(struct platform_device *pdev) -{ - struct clk_onecell_data *clk_data; - struct device_node *node = pdev->dev.of_node; - int r; - void __iomem *base; - - base = of_iomap(node, 0); - if (!base) { - pr_err("%s(): ioremap failed\n", __func__); - return -ENOMEM; - } - - clk_data = mtk_alloc_clk_data(ARRAY_SIZE(ethwarp_clks)); - - if (!clk_data) - return -ENOMEM; - - mtk_clk_register_gates(node, ethwarp_clks, ARRAY_SIZE(ethwarp_clks), - clk_data); - - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); - if (r) { - pr_err("%s(): could not register clock provider: %d\n", - __func__, r); - goto free_data; - } - return r; - -free_data: - mtk_free_clk_data(clk_data); - return r; -} - -static const struct of_device_id of_match_clk_mt7988_ethsys[] = { - { - .compatible = "mediatek,mt7988-ethsys", - }, - {} -}; - -static struct platform_driver clk_mt7988_ethsys_drv = { - .probe = clk_mt7988_ethsys_probe, - .driver = { - .name = "clk-mt7988-ethsys", - .of_match_table = of_match_clk_mt7988_ethsys, - }, -}; -builtin_platform_driver(clk_mt7988_ethsys_drv); - -static const struct of_device_id of_match_clk_mt7988_sgmii0[] = { - { - .compatible = "mediatek,mt7988-sgmiisys_0", - }, - {} -}; - -static struct platform_driver clk_mt7988_sgmii0_drv = { - .probe = clk_mt7988_sgmii0_probe, - .driver = { - .name = "clk-mt7988-sgmiisys_0", - .of_match_table = of_match_clk_mt7988_sgmii0, - }, -}; -builtin_platform_driver(clk_mt7988_sgmii0_drv); - -static const struct of_device_id of_match_clk_mt7988_sgmii1[] = { - { - .compatible = "mediatek,mt7988-sgmiisys_1", - }, - {} -}; - -static struct platform_driver clk_mt7988_sgmii1_drv = { - .probe = clk_mt7988_sgmii1_probe, - .driver = { - .name = "clk-mt7988-sgmiisys_1", - .of_match_table = of_match_clk_mt7988_sgmii1, - }, -}; -builtin_platform_driver(clk_mt7988_sgmii1_drv); - -static const struct of_device_id of_match_clk_mt7988_ethwarp[] = { - { - .compatible = "mediatek,mt7988-ethwarp", - }, - {} -}; - -static struct platform_driver clk_mt7988_ethwarp_drv = { - .probe = clk_mt7988_ethwarp_probe, - .driver = { - .name = "clk-mt7988-ethwarp", - .of_match_table = of_match_clk_mt7988_ethwarp, - }, -}; -builtin_platform_driver(clk_mt7988_ethwarp_drv); \ No newline at end of file diff --git a/target/linux/mediatek/files-5.15/drivers/clk/mediatek/clk-mt7988-infracfg.c b/target/linux/mediatek/files-5.15/drivers/clk/mediatek/clk-mt7988-infracfg.c deleted file mode 100644 index bce8d5637..000000000 --- a/target/linux/mediatek/files-5.15/drivers/clk/mediatek/clk-mt7988-infracfg.c +++ /dev/null @@ -1,406 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (c) 2023 MediaTek Inc. - * Author: Sam Shih - * Author: Xiufeng Li - */ - -#include -#include -#include -#include -#include -#include "clk-mtk.h" -#include "clk-gate.h" -#include "clk-mux.h" -#include - -static DEFINE_SPINLOCK(mt7988_clk_lock); - -static const char *const infra_mux_uart0_parents[] __initconst = { - "csw_infra_f26m_sel", "uart_sel" -}; - -static const char *const infra_mux_uart1_parents[] __initconst = { - "csw_infra_f26m_sel", "uart_sel" -}; - -static const char *const infra_mux_uart2_parents[] __initconst = { - "csw_infra_f26m_sel", "uart_sel" -}; - -static const char *const infra_mux_spi0_parents[] __initconst = { "i2c_sel", - "spi_sel" }; - -static const char *const infra_mux_spi1_parents[] __initconst = { - "i2c_sel", "spim_mst_sel" -}; - -static const char *const infra_pwm_bck_parents[] __initconst = { - "top_rtc_32p7k", "csw_infra_f26m_sel", "sysaxi_sel", "pwm_sel" -}; - -static const char *const infra_pcie_gfmux_tl_ck_o_p0_parents[] __initconst = { - "top_rtc_32p7k", "csw_infra_f26m_sel", "csw_infra_f26m_sel", - "pextp_tl_sel" -}; - -static const char *const infra_pcie_gfmux_tl_ck_o_p1_parents[] __initconst = { - "top_rtc_32p7k", "csw_infra_f26m_sel", "csw_infra_f26m_sel", - "pextp_tl_p1_sel" -}; - -static const char *const infra_pcie_gfmux_tl_ck_o_p2_parents[] __initconst = { - "top_rtc_32p7k", "csw_infra_f26m_sel", "csw_infra_f26m_sel", - "pextp_tl_p2_sel" -}; - -static const char *const infra_pcie_gfmux_tl_ck_o_p3_parents[] __initconst = { - "top_rtc_32p7k", "csw_infra_f26m_sel", "csw_infra_f26m_sel", - "pextp_tl_p3_sel" -}; - -static const struct mtk_mux infra_muxes[] = { - /* MODULE_CLK_SEL_0 */ - MUX_GATE_CLR_SET_UPD(CLK_INFRA_MUX_UART0_SEL, "infra_mux_uart0_sel", - infra_mux_uart0_parents, 0x0018, 0x0010, 0x0014, - 0, 1, -1, -1, -1), - MUX_GATE_CLR_SET_UPD(CLK_INFRA_MUX_UART1_SEL, "infra_mux_uart1_sel", - infra_mux_uart1_parents, 0x0018, 0x0010, 0x0014, - 1, 1, -1, -1, -1), - MUX_GATE_CLR_SET_UPD(CLK_INFRA_MUX_UART2_SEL, "infra_mux_uart2_sel", - infra_mux_uart2_parents, 0x0018, 0x0010, 0x0014, - 2, 1, -1, -1, -1), - MUX_GATE_CLR_SET_UPD(CLK_INFRA_MUX_SPI0_SEL, "infra_mux_spi0_sel", - infra_mux_spi0_parents, 0x0018, 0x0010, 0x0014, 4, - 1, -1, -1, -1), - MUX_GATE_CLR_SET_UPD(CLK_INFRA_MUX_SPI1_SEL, "infra_mux_spi1_sel", - infra_mux_spi1_parents, 0x0018, 0x0010, 0x0014, 5, - 1, -1, -1, -1), - MUX_GATE_CLR_SET_UPD(CLK_INFRA_MUX_SPI2_SEL, "infra_mux_spi2_sel", - infra_mux_spi0_parents, 0x0018, 0x0010, 0x0014, 6, - 1, -1, -1, -1), - MUX_GATE_CLR_SET_UPD(CLK_INFRA_PWM_SEL, "infra_pwm_sel", - infra_pwm_bck_parents, 0x0018, 0x0010, 0x0014, 14, - 2, -1, -1, -1), - MUX_GATE_CLR_SET_UPD(CLK_INFRA_PWM_CK1_SEL, "infra_pwm_ck1_sel", - infra_pwm_bck_parents, 0x0018, 0x0010, 0x0014, 16, - 2, -1, -1, -1), - MUX_GATE_CLR_SET_UPD(CLK_INFRA_PWM_CK2_SEL, "infra_pwm_ck2_sel", - infra_pwm_bck_parents, 0x0018, 0x0010, 0x0014, 18, - 2, -1, -1, -1), - MUX_GATE_CLR_SET_UPD(CLK_INFRA_PWM_CK3_SEL, "infra_pwm_ck3_sel", - infra_pwm_bck_parents, 0x0018, 0x0010, 0x0014, 20, - 2, -1, -1, -1), - MUX_GATE_CLR_SET_UPD(CLK_INFRA_PWM_CK4_SEL, "infra_pwm_ck4_sel", - infra_pwm_bck_parents, 0x0018, 0x0010, 0x0014, 22, - 2, -1, -1, -1), - MUX_GATE_CLR_SET_UPD(CLK_INFRA_PWM_CK5_SEL, "infra_pwm_ck5_sel", - infra_pwm_bck_parents, 0x0018, 0x0010, 0x0014, 24, - 2, -1, -1, -1), - MUX_GATE_CLR_SET_UPD(CLK_INFRA_PWM_CK6_SEL, "infra_pwm_ck6_sel", - infra_pwm_bck_parents, 0x0018, 0x0010, 0x0014, 26, - 2, -1, -1, -1), - MUX_GATE_CLR_SET_UPD(CLK_INFRA_PWM_CK7_SEL, "infra_pwm_ck7_sel", - infra_pwm_bck_parents, 0x0018, 0x0010, 0x0014, 28, - 2, -1, -1, -1), - MUX_GATE_CLR_SET_UPD(CLK_INFRA_PWM_CK8_SEL, "infra_pwm_ck8_sel", - infra_pwm_bck_parents, 0x0018, 0x0010, 0x0014, 30, - 2, -1, -1, -1), - /* MODULE_CLK_SEL_1 */ - MUX_GATE_CLR_SET_UPD(CLK_INFRA_PCIE_GFMUX_TL_O_P0_SEL, - "infra_pcie_gfmux_tl_o_p0_sel", - infra_pcie_gfmux_tl_ck_o_p0_parents, 0x0028, - 0x0020, 0x0024, 0, 2, -1, -1, -1), - MUX_GATE_CLR_SET_UPD(CLK_INFRA_PCIE_GFMUX_TL_O_P1_SEL, - "infra_pcie_gfmux_tl_o_p1_sel", - infra_pcie_gfmux_tl_ck_o_p1_parents, 0x0028, - 0x0020, 0x0024, 2, 2, -1, -1, -1), - MUX_GATE_CLR_SET_UPD(CLK_INFRA_PCIE_GFMUX_TL_O_P2_SEL, - "infra_pcie_gfmux_tl_o_p2_sel", - infra_pcie_gfmux_tl_ck_o_p2_parents, 0x0028, - 0x0020, 0x0024, 4, 2, -1, -1, -1), - MUX_GATE_CLR_SET_UPD(CLK_INFRA_PCIE_GFMUX_TL_O_P3_SEL, - "infra_pcie_gfmux_tl_o_p3_sel", - infra_pcie_gfmux_tl_ck_o_p3_parents, 0x0028, - 0x0020, 0x0024, 6, 2, -1, -1, -1), -}; - -static const struct mtk_gate_regs infra0_cg_regs = { - .set_ofs = 0x10, - .clr_ofs = 0x14, - .sta_ofs = 0x18, -}; - -static const struct mtk_gate_regs infra1_cg_regs = { - .set_ofs = 0x40, - .clr_ofs = 0x44, - .sta_ofs = 0x48, -}; - -static const struct mtk_gate_regs infra2_cg_regs = { - .set_ofs = 0x50, - .clr_ofs = 0x54, - .sta_ofs = 0x58, -}; - -static const struct mtk_gate_regs infra3_cg_regs = { - .set_ofs = 0x60, - .clr_ofs = 0x64, - .sta_ofs = 0x68, -}; - -#define GATE_INFRA0_FLAGS(_id, _name, _parent, _shift, _flags) \ - { \ - .id = _id, .name = _name, .parent_name = _parent, \ - .regs = &infra0_cg_regs, .shift = _shift, \ - .ops = &mtk_clk_gate_ops_setclr, .flags = _flags, \ - } - -#define GATE_INFRA1_FLAGS(_id, _name, _parent, _shift, _flags) \ - { \ - .id = _id, .name = _name, .parent_name = _parent, \ - .regs = &infra1_cg_regs, .shift = _shift, \ - .ops = &mtk_clk_gate_ops_setclr, .flags = _flags, \ - } - -#define GATE_INFRA2_FLAGS(_id, _name, _parent, _shift, _flags) \ - { \ - .id = _id, .name = _name, .parent_name = _parent, \ - .regs = &infra2_cg_regs, .shift = _shift, \ - .ops = &mtk_clk_gate_ops_setclr, .flags = _flags, \ - } - -#define GATE_INFRA3_FLAGS(_id, _name, _parent, _shift, _flags) \ - { \ - .id = _id, .name = _name, .parent_name = _parent, \ - .regs = &infra3_cg_regs, .shift = _shift, \ - .ops = &mtk_clk_gate_ops_setclr, .flags = _flags, \ - } - -#define GATE_INFRA0(_id, _name, _parent, _shift) \ - GATE_INFRA0_FLAGS(_id, _name, _parent, _shift, 0) - -#define GATE_INFRA1(_id, _name, _parent, _shift) \ - GATE_INFRA1_FLAGS(_id, _name, _parent, _shift, 0) - -#define GATE_INFRA2(_id, _name, _parent, _shift) \ - GATE_INFRA2_FLAGS(_id, _name, _parent, _shift, 0) - -#define GATE_INFRA3(_id, _name, _parent, _shift) \ - GATE_INFRA3_FLAGS(_id, _name, _parent, _shift, 0) - -#define GATE_CRITICAL(_id, _name, _parent, _regs, _shift) { \ - .id = _id, .name = _name, .parent_name = _parent, \ - .regs = _regs, .shift = _shift, \ - .flags = CLK_IS_CRITICAL, \ - .ops = &mtk_clk_gate_ops_setclr, \ - } - -static const struct mtk_gate infra_clks[] = { - /* INFRA0 */ - GATE_INFRA0(CLK_INFRA_PCIE_PERI_26M_CK_P0, - "infra_pcie_peri_ck_26m_ck_p0", "csw_infra_f26m_sel", 7), - GATE_INFRA0(CLK_INFRA_PCIE_PERI_26M_CK_P1, - "infra_pcie_peri_ck_26m_ck_p1", "csw_infra_f26m_sel", 8), - GATE_INFRA0(CLK_INFRA_PCIE_PERI_26M_CK_P2, - "infra_pcie_peri_ck_26m_ck_p2", "csw_infra_f26m_sel", 9), - GATE_INFRA0(CLK_INFRA_PCIE_PERI_26M_CK_P3, - "infra_pcie_peri_ck_26m_ck_p3", "csw_infra_f26m_sel", 10), - /* INFRA1 */ - GATE_INFRA1(CLK_INFRA_66M_GPT_BCK, "infra_hf_66m_gpt_bck", - "sysaxi_sel", 0), - GATE_INFRA1(CLK_INFRA_66M_PWM_HCK, "infra_hf_66m_pwm_hck", - "sysaxi_sel", 1), - GATE_INFRA1(CLK_INFRA_66M_PWM_BCK, "infra_hf_66m_pwm_bck", - "infra_pwm_sel", 2), - GATE_INFRA1(CLK_INFRA_66M_PWM_CK1, "infra_hf_66m_pwm_ck1", - "infra_pwm_ck1_sel", 3), - GATE_INFRA1(CLK_INFRA_66M_PWM_CK2, "infra_hf_66m_pwm_ck2", - "infra_pwm_ck2_sel", 4), - GATE_INFRA1(CLK_INFRA_66M_PWM_CK3, "infra_hf_66m_pwm_ck3", - "infra_pwm_ck3_sel", 5), - GATE_INFRA1(CLK_INFRA_66M_PWM_CK4, "infra_hf_66m_pwm_ck4", - "infra_pwm_ck4_sel", 6), - GATE_INFRA1(CLK_INFRA_66M_PWM_CK5, "infra_hf_66m_pwm_ck5", - "infra_pwm_ck5_sel", 7), - GATE_INFRA1(CLK_INFRA_66M_PWM_CK6, "infra_hf_66m_pwm_ck6", - "infra_pwm_ck6_sel", 8), - GATE_INFRA1(CLK_INFRA_66M_PWM_CK7, "infra_hf_66m_pwm_ck7", - "infra_pwm_ck7_sel", 9), - GATE_INFRA1(CLK_INFRA_66M_PWM_CK8, "infra_hf_66m_pwm_ck8", - "infra_pwm_ck8_sel", 10), - GATE_INFRA1(CLK_INFRA_133M_CQDMA_BCK, "infra_hf_133m_cqdma_bck", - "sysaxi_sel", 12), - GATE_INFRA1(CLK_INFRA_66M_AUD_SLV_BCK, "infra_66m_aud_slv_bck", - "sysaxi_sel", 13), - GATE_INFRA1(CLK_INFRA_AUD_26M, "infra_f_faud_26m", - "csw_infra_f26m_sel", 14), - GATE_INFRA1(CLK_INFRA_AUD_L, "infra_f_faud_l", "aud_l_sel", 15), - GATE_INFRA1(CLK_INFRA_AUD_AUD, "infra_f_aud_aud", "a1sys_sel", 16), - GATE_INFRA1(CLK_INFRA_AUD_EG2, "infra_f_faud_eg2", "a_tuner_sel", 18), - GATE_INFRA1_FLAGS(CLK_INFRA_DRAMC_F26M, "infra_dramc_f26m", - "csw_infra_f26m_sel", 19, CLK_IS_CRITICAL), - // JTAG - GATE_INFRA1_FLAGS(CLK_INFRA_133M_DBG_ACKM, "infra_hf_133m_dbg_ackm", - "sysaxi_sel", 20, CLK_IS_CRITICAL), - GATE_INFRA1(CLK_INFRA_66M_AP_DMA_BCK, "infra_66m_ap_dma_bck", - "sysaxi_sel", 21), - GATE_INFRA1(CLK_INFRA_66M_SEJ_BCK, "infra_hf_66m_sej_bck", - "sysaxi_sel", 29), - GATE_INFRA1(CLK_INFRA_PRE_CK_SEJ_F13M, "infra_pre_ck_sej_f13m", - "csw_infra_f26m_sel", 30), - /* INFRA2 */ - GATE_INFRA2(CLK_INFRA_26M_THERM_SYSTEM, "infra_hf_26m_therm_system", - "csw_infra_f26m_sel", 0), - GATE_INFRA2(CLK_INFRA_I2C_BCK, "infra_i2c_bck", "i2c_sel", 1), - GATE_INFRA2(CLK_INFRA_52M_UART0_CK, "infra_f_52m_uart0", - "infra_mux_uart0_sel", 3), - GATE_INFRA2(CLK_INFRA_52M_UART1_CK, "infra_f_52m_uart1", - "infra_mux_uart1_sel", 4), - GATE_INFRA2(CLK_INFRA_52M_UART2_CK, "infra_f_52m_uart2", - "infra_mux_uart2_sel", 5), - GATE_INFRA2(CLK_INFRA_NFI, "infra_f_fnfi", "nfi1x_sel", 9), - GATE_INFRA2(CLK_INFRA_SPINFI, "infra_f_fspinfi", "spinfi_sel", 10), - GATE_INFRA2_FLAGS(CLK_INFRA_66M_NFI_HCK, "infra_hf_66m_nfi_hck", - "sysaxi_sel", 11, CLK_IS_CRITICAL), - GATE_INFRA2_FLAGS(CLK_INFRA_104M_SPI0, "infra_hf_104m_spi0", - "infra_mux_spi0_sel", 12, CLK_IS_CRITICAL), - GATE_INFRA2(CLK_INFRA_104M_SPI1, "infra_hf_104m_spi1", - "infra_mux_spi1_sel", 13), - GATE_INFRA2(CLK_INFRA_104M_SPI2_BCK, "infra_hf_104m_spi2_bck", - "infra_mux_spi2_sel", 14), - GATE_INFRA2_FLAGS(CLK_INFRA_66M_SPI0_HCK, "infra_hf_66m_spi0_hck", - "sysaxi_sel", 15, CLK_IS_CRITICAL), - GATE_INFRA2(CLK_INFRA_66M_SPI1_HCK, "infra_hf_66m_spi1_hck", - "sysaxi_sel", 16), - GATE_INFRA2(CLK_INFRA_66M_SPI2_HCK, "infra_hf_66m_spi2_hck", - "sysaxi_sel", 17), - GATE_INFRA2(CLK_INFRA_66M_FLASHIF_AXI, "infra_hf_66m_flashif_axi", - "sysaxi_sel", 18), - GATE_CRITICAL(CLK_INFRA_RTC, "infra_f_frtc", "top_rtc_32k", &infra2_cg_regs, 19), - GATE_INFRA2(CLK_INFRA_26M_ADC_BCK, "infra_f_26m_adc_bck", - "csw_infra_f26m_sel", 20), - GATE_INFRA2(CLK_INFRA_RC_ADC, "infra_f_frc_adc", "infra_f_26m_adc_bck", - 21), - GATE_INFRA2(CLK_INFRA_MSDC400, "infra_f_fmsdc400", "emmc_400m_sel", - 22), - GATE_INFRA2(CLK_INFRA_MSDC2_HCK, "infra_f_fmsdc2_hck", "emmc_250m_sel", - 23), - GATE_INFRA2(CLK_INFRA_133M_MSDC_0_HCK, "infra_hf_133m_msdc_0_hck", - "sysaxi_sel", 24), - GATE_INFRA2(CLK_INFRA_66M_MSDC_0_HCK, "infra_66m_msdc_0_hck", - "sysaxi_sel", 25), - GATE_INFRA2(CLK_INFRA_133M_CPUM_BCK, "infra_hf_133m_cpum_bck", - "sysaxi_sel", 26), - GATE_INFRA2(CLK_INFRA_BIST2FPC, "infra_hf_fbist2fpc", "nfi1x_sel", 27), - GATE_INFRA2(CLK_INFRA_I2C_X16W_MCK_CK_P1, - "infra_hf_i2c_x16w_mck_ck_p1", "sysaxi_sel", 29), - GATE_INFRA2(CLK_INFRA_I2C_X16W_PCK_CK_P1, - "infra_hf_i2c_x16w_pck_ck_p1", "sysaxi_sel", 31), - /* INFRA3 */ - GATE_INFRA3(CLK_INFRA_133M_USB_HCK, "infra_133m_usb_hck", "sysaxi_sel", - 0), - GATE_INFRA3(CLK_INFRA_133M_USB_HCK_CK_P1, "infra_133m_usb_hck_ck_p1", - "sysaxi_sel", 1), - GATE_INFRA3(CLK_INFRA_66M_USB_HCK, "infra_66m_usb_hck", "sysaxi_sel", - 2), - GATE_INFRA3(CLK_INFRA_66M_USB_HCK_CK_P1, "infra_66m_usb_hck_ck_p1", - "sysaxi_sel", 3), - GATE_INFRA3(CLK_INFRA_USB_SYS, "infra_usb_sys", "usb_sys_sel", 4), - GATE_INFRA3(CLK_INFRA_USB_SYS_CK_P1, "infra_usb_sys_ck_p1", - "usb_sys_p1_sel", 5), - GATE_INFRA3(CLK_INFRA_USB_REF, "infra_usb_ref", "top_xtal", 6), - GATE_INFRA3(CLK_INFRA_USB_CK_P1, "infra_usb_ck_p1", "top_xtal", 7), - GATE_INFRA3_FLAGS(CLK_INFRA_USB_FRMCNT, "infra_usb_frmcnt", - "usb_frmcnt_sel", 8, CLK_IS_CRITICAL), - GATE_INFRA3_FLAGS(CLK_INFRA_USB_FRMCNT_CK_P1, "infra_usb_frmcnt_ck_p1", - "usb_frmcnt_p1_sel", 9, CLK_IS_CRITICAL), - GATE_INFRA3(CLK_INFRA_USB_PIPE, "infra_usb_pipe", "sspxtp_sel", 10), - GATE_INFRA3(CLK_INFRA_USB_PIPE_CK_P1, "infra_usb_pipe_ck_p1", - "usb_phy_sel", 11), - GATE_INFRA3(CLK_INFRA_USB_UTMI, "infra_usb_utmi", "top_xtal", 12), - GATE_INFRA3(CLK_INFRA_USB_UTMI_CK_P1, "infra_usb_utmi_ck_p1", - "top_xtal", 13), - GATE_INFRA3(CLK_INFRA_USB_XHCI, "infra_usb_xhci", "usb_xhci_sel", 14), - GATE_INFRA3(CLK_INFRA_USB_XHCI_CK_P1, "infra_usb_xhci_ck_p1", - "usb_xhci_p1_sel", 15), - GATE_INFRA3(CLK_INFRA_PCIE_GFMUX_TL_P0, "infra_pcie_gfmux_tl_ck_p0", - "infra_pcie_gfmux_tl_o_p0_sel", 20), - GATE_INFRA3(CLK_INFRA_PCIE_GFMUX_TL_P1, "infra_pcie_gfmux_tl_ck_p1", - "infra_pcie_gfmux_tl_o_p1_sel", 21), - GATE_INFRA3(CLK_INFRA_PCIE_GFMUX_TL_P2, "infra_pcie_gfmux_tl_ck_p2", - "infra_pcie_gfmux_tl_o_p2_sel", 22), - GATE_INFRA3(CLK_INFRA_PCIE_GFMUX_TL_P3, "infra_pcie_gfmux_tl_ck_p3", - "infra_pcie_gfmux_tl_o_p3_sel", 23), - GATE_INFRA3(CLK_INFRA_PCIE_PIPE_P0, "infra_pcie_pipe_ck_p0", - "top_xtal", 24), - GATE_INFRA3(CLK_INFRA_PCIE_PIPE_P1, "infra_pcie_pipe_ck_p1", - "top_xtal", 25), - GATE_INFRA3(CLK_INFRA_PCIE_PIPE_P2, "infra_pcie_pipe_ck_p2", - "top_xtal", 26), - GATE_INFRA3(CLK_INFRA_PCIE_PIPE_P3, "infra_pcie_pipe_ck_p3", - "top_xtal", 27), - GATE_INFRA3(CLK_INFRA_133M_PCIE_CK_P0, "infra_133m_pcie_ck_p0", - "sysaxi_sel", 28), - GATE_INFRA3(CLK_INFRA_133M_PCIE_CK_P1, "infra_133m_pcie_ck_p1", - "sysaxi_sel", 29), - GATE_INFRA3(CLK_INFRA_133M_PCIE_CK_P2, "infra_133m_pcie_ck_p2", - "sysaxi_sel", 30), - GATE_INFRA3(CLK_INFRA_133M_PCIE_CK_P3, "infra_133m_pcie_ck_p3", - "sysaxi_sel", 31), -}; - -static int clk_mt7988_infracfg_probe(struct platform_device *pdev) -{ - struct clk_onecell_data *clk_data; - struct device_node *node = pdev->dev.of_node; - int r; - void __iomem *base; - int nr = ARRAY_SIZE(infra_muxes) + ARRAY_SIZE(infra_clks); - - base = of_iomap(node, 0); - if (!base) { - pr_err("%s(): ioremap failed\n", __func__); - return -ENOMEM; - } - - clk_data = mtk_alloc_clk_data(nr); - - if (!clk_data) - return -ENOMEM; - - mtk_clk_register_muxes(infra_muxes, ARRAY_SIZE(infra_muxes), node, - &mt7988_clk_lock, clk_data); - - mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks), - clk_data); - - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); - if (r) { - pr_err("%s(): could not register clock provider: %d\n", - __func__, r); - goto free_infracfg_data; - } - return r; - -free_infracfg_data: - mtk_free_clk_data(clk_data); - return r; -} - -static const struct of_device_id of_match_clk_mt7988_infracfg[] = { - { - .compatible = "mediatek,mt7988-infracfg", - }, - {} -}; - -static struct platform_driver clk_mt7988_infracfg_drv = { - .probe = clk_mt7988_infracfg_probe, - .driver = { - .name = "clk-mt7988-infracfg", - .of_match_table = of_match_clk_mt7988_infracfg, - }, -}; -builtin_platform_driver(clk_mt7988_infracfg_drv); diff --git a/target/linux/mediatek/files-5.15/drivers/clk/mediatek/clk-mt7988-topckgen.c b/target/linux/mediatek/files-5.15/drivers/clk/mediatek/clk-mt7988-topckgen.c deleted file mode 100644 index 917302b6d..000000000 --- a/target/linux/mediatek/files-5.15/drivers/clk/mediatek/clk-mt7988-topckgen.c +++ /dev/null @@ -1,522 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (c) 2023 MediaTek Inc. - * Author: Sam Shih - * Author: Xiufeng Li - */ - -#include -#include -#include -#include -#include -#include "clk-mtk.h" -#include "clk-gate.h" -#include "clk-mux.h" -#include - -static DEFINE_SPINLOCK(mt7988_clk_lock); - -static const struct mtk_fixed_clk top_fixed_clks[] = { - FIXED_CLK(CLK_TOP_XTAL, "top_xtal", "clkxtal", 40000000), -}; - -static const struct mtk_fixed_factor top_divs[] = { - FACTOR(CLK_TOP_XTAL_D2, "top_xtal_d2", "top_xtal", 1, 2), - FACTOR(CLK_TOP_RTC_32K, "top_rtc_32k", "top_xtal", 1, 1250), - FACTOR(CLK_TOP_RTC_32P7K, "top_rtc_32p7k", "top_xtal", 1, 1220), - FACTOR(CLK_TOP_MPLL_D2, "mpll_d2", "mpll", 1, 2), - FACTOR(CLK_TOP_MPLL_D3_D2, "mpll_d3_d2", "mpll", 1, 2), - FACTOR(CLK_TOP_MPLL_D4, "mpll_d4", "mpll", 1, 4), - FACTOR(CLK_TOP_MPLL_D8, "mpll_d8", "mpll", 1, 8), - FACTOR(CLK_TOP_MPLL_D8_D2, "mpll_d8_d2", "mpll", 1, 16), - FACTOR(CLK_TOP_MMPLL_D2, "mmpll_d2", "mmpll", 1, 2), - FACTOR(CLK_TOP_MMPLL_D3_D5, "mmpll_d3_d5", "mmpll", 1, 15), - FACTOR(CLK_TOP_MMPLL_D4, "mmpll_d4", "mmpll", 1, 4), - FACTOR(CLK_TOP_MMPLL_D6_D2, "mmpll_d6_d2", "mmpll", 1, 12), - FACTOR(CLK_TOP_MMPLL_D8, "mmpll_d8", "mmpll", 1, 8), - FACTOR(CLK_TOP_APLL2_D4, "apll2_d4", "apll2", 1, 4), - FACTOR(CLK_TOP_NET1PLL_D4, "net1pll_d4", "net1pll", 1, 4), - FACTOR(CLK_TOP_NET1PLL_D5, "net1pll_d5", "net1pll", 1, 5), - FACTOR(CLK_TOP_NET1PLL_D5_D2, "net1pll_d5_d2", "net1pll", 1, 10), - FACTOR(CLK_TOP_NET1PLL_D5_D4, "net1pll_d5_d4", "net1pll", 1, 20), - FACTOR(CLK_TOP_NET1PLL_D8, "net1pll_d8", "net1pll", 1, 8), - FACTOR(CLK_TOP_NET1PLL_D8_D2, "net1pll_d8_d2", "net1pll", 1, 16), - FACTOR(CLK_TOP_NET1PLL_D8_D4, "net1pll_d8_d4", "net1pll", 1, 32), - FACTOR(CLK_TOP_NET1PLL_D8_D8, "net1pll_d8_d8", "net1pll", 1, 64), - FACTOR(CLK_TOP_NET1PLL_D8_D16, "net1pll_d8_d16", "net1pll", 1, 128), - FACTOR(CLK_TOP_NET2PLL_D2, "net2pll_d2", "net2pll", 1, 2), - FACTOR(CLK_TOP_NET2PLL_D4, "net2pll_d4", "net2pll", 1, 4), - FACTOR(CLK_TOP_NET2PLL_D4_D4, "net2pll_d4_d4", "net2pll", 1, 16), - FACTOR(CLK_TOP_NET2PLL_D4_D8, "net2pll_d4_d8", "net2pll", 1, 32), - FACTOR(CLK_TOP_NET2PLL_D6, "net2pll_d6", "net2pll", 1, 6), - FACTOR(CLK_TOP_NET2PLL_D8, "net2pll_d8", "net2pll", 1, 8), -}; - -static const char *const netsys_parents[] = { "top_xtal", "net2pll_d2", - "mmpll_d2" }; - -static const char *const netsys_500m_parents[] = { "top_xtal", "net1pll_d5", - "net1pll_d5_d2" }; - -static const char *const netsys_2x_parents[] = { "top_xtal", "net2pll", - "mmpll" }; - -static const char *const netsys_gsw_parents[] = { "top_xtal", "net1pll_d4", - "net1pll_d5" }; - -static const char *const eth_gmii_parents[] = { "top_xtal", "net1pll_d5_d4" }; - -static const char *const netsys_mcu_parents[] = { "top_xtal", "net2pll", - "mmpll", "net1pll_d4", - "net1pll_d5", "mpll" }; - -static const char *const eip197_parents[] = { "top_xtal", "netsyspll", - "net2pll", "mmpll", - "net1pll_d4", "net1pll_d5" }; - -static const char *const axi_infra_parents[] = { "top_xtal", "net1pll_d8_d2" }; - -static const char *const uart_parents[] = { "top_xtal", "mpll_d8", - "mpll_d8_d2" }; - -static const char *const emmc_250m_parents[] = { "top_xtal", "net1pll_d5_d2", - "mmpll_d4" }; - -static const char *const emmc_400m_parents[] = { "top_xtal", "msdcpll", - "mmpll_d2", "mpll_d2", - "mmpll_d4", "net1pll_d8_d2" }; - -static const char *const spi_parents[] = { "top_xtal", "mpll_d2", - "mmpll_d4", "net1pll_d8_d2", - "net2pll_d6", "net1pll_d5_d4", - "mpll_d4", "net1pll_d8_d4" }; - -static const char *const nfi1x_parents[] = { "top_xtal", "mmpll_d4", - "net1pll_d8_d2", "net2pll_d6", - "mpll_d4", "mmpll_d8", - "net1pll_d8_d4", "mpll_d8" }; - -static const char *const spinfi_parents[] = { "top_xtal_d2", "top_xtal", - "net1pll_d5_d4", "mpll_d4", - "mmpll_d8", "net1pll_d8_d4", - "mmpll_d6_d2", "mpll_d8" }; - -static const char *const pwm_parents[] = { "top_xtal", "net1pll_d8_d2", - "net1pll_d5_d4", "mpll_d4", - "mpll_d8_d2", "top_rtc_32k" }; - -static const char *const i2c_parents[] = { "top_xtal", "net1pll_d5_d4", - "mpll_d4", "net1pll_d8_d4" }; - -static const char *const pcie_mbist_250m_parents[] = { "top_xtal", - "net1pll_d5_d2" }; - -static const char *const pextp_tl_ck_parents[] = { "top_xtal", "net2pll_d6", - "mmpll_d8", "mpll_d8_d2", - "top_rtc_32k" }; - -static const char *const usb_frmcnt_parents[] = { "top_xtal", "mmpll_d3_d5" }; - -static const char *const aud_parents[] = { "top_xtal", "apll2" }; - -static const char *const a1sys_parents[] = { "top_xtal", "apll2_d4" }; - -static const char *const aud_l_parents[] = { "top_xtal", "apll2", - "mpll_d8_d2" }; - -static const char *const sspxtp_parents[] = { "top_xtal_d2", "mpll_d8_d2" }; - -static const char *const usxgmii_sbus_0_parents[] = { "top_xtal", - "net1pll_d8_d4" }; - -static const char *const sgm_0_parents[] = { "top_xtal", "sgmpll" }; - -static const char *const sysapb_parents[] = { "top_xtal", "mpll_d3_d2" }; - -static const char *const eth_refck_50m_parents[] = { "top_xtal", - "net2pll_d4_d4" }; - -static const char *const eth_sys_200m_parents[] = { "top_xtal", "net2pll_d4" }; - -static const char *const eth_xgmii_parents[] = { "top_xtal_d2", - "net1pll_d8_d8", - "net1pll_d8_d16" }; - -static const char *const bus_tops_parents[] = { "top_xtal", "net1pll_d5", - "net2pll_d2" }; - -static const char *const npu_tops_parents[] = { "top_xtal", "net2pll" }; - -static const char *const dramc_md32_parents[] = { "top_xtal", "mpll_d2", - "wedmcupll" }; - -static const char *const da_xtp_glb_p0_parents[] = { "top_xtal", - "net2pll_d8" }; - -static const char *const mcusys_backup_625m_parents[] = { "top_xtal", - "net1pll_d4" }; - -static const char *const macsec_parents[] = { "top_xtal", "sgmpll", - "net1pll_d8" }; - -static const char *const netsys_tops_400m_parents[] = { "top_xtal", - "net2pll_d2" }; - -static const char *const eth_mii_parents[] = { "top_xtal_d2", - "net2pll_d4_d8" }; - -static const struct mtk_mux top_muxes[] = { - /* CLK_CFG_0 */ - MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_SEL, "netsys_sel", netsys_parents, - 0x000, 0x004, 0x008, 0, 2, 7, 0x1c0, 0), - MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_500M_SEL, "netsys_500m_sel", - netsys_500m_parents, 0x000, 0x004, 0x008, 8, 2, - 15, 0x1C0, 1), - MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_2X_SEL, "netsys_2x_sel", - netsys_2x_parents, 0x000, 0x004, 0x008, 16, 2, 23, - 0x1C0, 2), - MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_GSW_SEL, "netsys_gsw_sel", - netsys_gsw_parents, 0x000, 0x004, 0x008, 24, 2, - 31, 0x1C0, 3), - /* CLK_CFG_1 */ - MUX_GATE_CLR_SET_UPD(CLK_TOP_ETH_GMII_SEL, "eth_gmii_sel", - eth_gmii_parents, 0x010, 0x014, 0x018, 0, 1, 7, - 0x1C0, 4), - MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_MCU_SEL, "netsys_mcu_sel", - netsys_mcu_parents, 0x010, 0x014, 0x018, 8, 3, 15, - 0x1C0, 5), - MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_PAO_2X_SEL, "netsys_pao_2x_sel", - netsys_mcu_parents, 0x010, 0x014, 0x018, 16, 3, - 23, 0x1C0, 6), - MUX_GATE_CLR_SET_UPD(CLK_TOP_EIP197_SEL, "eip197_sel", eip197_parents, - 0x010, 0x014, 0x018, 24, 3, 31, 0x1c0, 7), - /* CLK_CFG_2 */ - MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_AXI_INFRA_SEL, "axi_infra_sel", - axi_infra_parents, 0x020, 0x024, 0x028, 0, - 1, 7, 0x1C0, 8, CLK_IS_CRITICAL), - MUX_GATE_CLR_SET_UPD(CLK_TOP_UART_SEL, "uart_sel", uart_parents, 0x020, - 0x024, 0x028, 8, 2, 15, 0x1c0, 9), - MUX_GATE_CLR_SET_UPD(CLK_TOP_EMMC_250M_SEL, "emmc_250m_sel", - emmc_250m_parents, 0x020, 0x024, 0x028, 16, 2, 23, - 0x1C0, 10), - MUX_GATE_CLR_SET_UPD(CLK_TOP_EMMC_400M_SEL, "emmc_400m_sel", - emmc_400m_parents, 0x020, 0x024, 0x028, 24, 3, 31, - 0x1C0, 11), - /* CLK_CFG_3 */ - MUX_GATE_CLR_SET_UPD(CLK_TOP_SPI_SEL, "spi_sel", spi_parents, 0x030, - 0x034, 0x038, 0, 3, 7, 0x1c0, 12), - MUX_GATE_CLR_SET_UPD(CLK_TOP_SPIM_MST_SEL, "spim_mst_sel", spi_parents, - 0x030, 0x034, 0x038, 8, 3, 15, 0x1c0, 13), - MUX_GATE_CLR_SET_UPD(CLK_TOP_NFI1X_SEL, "nfi1x_sel", nfi1x_parents, - 0x030, 0x034, 0x038, 16, 3, 23, 0x1c0, 14), - MUX_GATE_CLR_SET_UPD(CLK_TOP_SPINFI_SEL, "spinfi_sel", spinfi_parents, - 0x030, 0x034, 0x038, 24, 3, 31, 0x1c0, 15), - /* CLK_CFG_4 */ - MUX_GATE_CLR_SET_UPD(CLK_TOP_PWM_SEL, "pwm_sel", pwm_parents, 0x040, - 0x044, 0x048, 0, 3, 7, 0x1c0, 16), - MUX_GATE_CLR_SET_UPD(CLK_TOP_I2C_SEL, "i2c_sel", i2c_parents, 0x040, - 0x044, 0x048, 8, 2, 15, 0x1c0, 17), - MUX_GATE_CLR_SET_UPD(CLK_TOP_PCIE_MBIST_250M_SEL, - "pcie_mbist_250m_sel", pcie_mbist_250m_parents, - 0x040, 0x044, 0x048, 16, 1, 23, 0x1C0, 18), - MUX_GATE_CLR_SET_UPD(CLK_TOP_PEXTP_TL_SEL, "pextp_tl_sel", - pextp_tl_ck_parents, 0x040, 0x044, 0x048, 24, 3, - 31, 0x1C0, 19), - /* CLK_CFG_5 */ - MUX_GATE_CLR_SET_UPD(CLK_TOP_PEXTP_TL_P1_SEL, "pextp_tl_p1_sel", - pextp_tl_ck_parents, 0x050, 0x054, 0x058, 0, 3, 7, - 0x1C0, 20), - MUX_GATE_CLR_SET_UPD(CLK_TOP_PEXTP_TL_P2_SEL, "pextp_tl_p2_sel", - pextp_tl_ck_parents, 0x050, 0x054, 0x058, 8, 3, - 15, 0x1C0, 21), - MUX_GATE_CLR_SET_UPD(CLK_TOP_PEXTP_TL_P3_SEL, "pextp_tl_p3_sel", - pextp_tl_ck_parents, 0x050, 0x054, 0x058, 16, 3, - 23, 0x1C0, 22), - MUX_GATE_CLR_SET_UPD(CLK_TOP_USB_SYS_SEL, "usb_sys_sel", - eth_gmii_parents, 0x050, 0x054, 0x058, 24, 1, 31, - 0x1C0, 23), - /* CLK_CFG_6 */ - MUX_GATE_CLR_SET_UPD(CLK_TOP_USB_SYS_P1_SEL, "usb_sys_p1_sel", - eth_gmii_parents, 0x060, 0x064, 0x068, 0, 1, 7, - 0x1C0, 24), - MUX_GATE_CLR_SET_UPD(CLK_TOP_USB_XHCI_SEL, "usb_xhci_sel", - eth_gmii_parents, 0x060, 0x064, 0x068, 8, 1, 15, - 0x1C0, 25), - MUX_GATE_CLR_SET_UPD(CLK_TOP_USB_XHCI_P1_SEL, "usb_xhci_p1_sel", - eth_gmii_parents, 0x060, 0x064, 0x068, 16, 1, 23, - 0x1C0, 26), - MUX_GATE_CLR_SET_UPD(CLK_TOP_USB_FRMCNT_SEL, "usb_frmcnt_sel", - usb_frmcnt_parents, 0x060, 0x064, 0x068, 24, 1, - 31, 0x1C0, 27), - /* CLK_CFG_7 */ - MUX_GATE_CLR_SET_UPD(CLK_TOP_USB_FRMCNT_P1_SEL, "usb_frmcnt_p1_sel", - usb_frmcnt_parents, 0x070, 0x074, 0x078, 0, 1, 7, - 0x1C0, 28), - MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_SEL, "aud_sel", aud_parents, 0x070, - 0x074, 0x078, 8, 1, 15, 0x1c0, 29), - MUX_GATE_CLR_SET_UPD(CLK_TOP_A1SYS_SEL, "a1sys_sel", a1sys_parents, - 0x070, 0x074, 0x078, 16, 1, 23, 0x1c0, 30), - MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_L_SEL, "aud_l_sel", aud_l_parents, - 0x070, 0x074, 0x078, 24, 2, 31, 0x1c4, 0), - /* CLK_CFG_8 */ - MUX_GATE_CLR_SET_UPD(CLK_TOP_A_TUNER_SEL, "a_tuner_sel", a1sys_parents, - 0x080, 0x084, 0x088, 0, 1, 7, 0x1c4, 1), - MUX_GATE_CLR_SET_UPD(CLK_TOP_SSPXTP_SEL, "sspxtp_sel", sspxtp_parents, - 0x080, 0x084, 0x088, 8, 1, 15, 0x1c4, 2), - MUX_GATE_CLR_SET_UPD(CLK_TOP_USB_PHY_SEL, "usb_phy_sel", - sspxtp_parents, 0x080, 0x084, 0x088, 16, 1, 23, - 0x1c4, 3), - MUX_GATE_CLR_SET_UPD(CLK_TOP_USXGMII_SBUS_0_SEL, "usxgmii_sbus_0_sel", - usxgmii_sbus_0_parents, 0x080, 0x084, 0x088, 24, - 1, 31, 0x1C4, 4), - /* CLK_CFG_9 */ - MUX_GATE_CLR_SET_UPD(CLK_TOP_USXGMII_SBUS_1_SEL, "usxgmii_sbus_1_sel", - usxgmii_sbus_0_parents, 0x090, 0x094, 0x098, 0, 1, - 7, 0x1C4, 5), - MUX_GATE_CLR_SET_UPD(CLK_TOP_SGM_0_SEL, "sgm_0_sel", sgm_0_parents, - 0x090, 0x094, 0x098, 8, 1, 15, 0x1c4, 6), - MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SGM_SBUS_0_SEL, "sgm_sbus_0_sel", - usxgmii_sbus_0_parents, 0x090, 0x094, 0x098, - 16, 1, 23, 0x1C4, 7, CLK_IS_CRITICAL), - MUX_GATE_CLR_SET_UPD(CLK_TOP_SGM_1_SEL, "sgm_1_sel", sgm_0_parents, - 0x090, 0x094, 0x098, 24, 1, 31, 0x1c4, 8), - /* CLK_CFG_10 */ - MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SGM_SBUS_1_SEL, "sgm_sbus_1_sel", - usxgmii_sbus_0_parents, 0x0a0, 0x0a4, 0x0a8, - 0, 1, 7, 0x1C4, 9, CLK_IS_CRITICAL), - MUX_GATE_CLR_SET_UPD(CLK_TOP_XFI_PHY_0_XTAL_SEL, "xfi_phy_0_xtal_sel", - sspxtp_parents, 0x0a0, 0x0a4, 0x0a8, 8, 1, 15, - 0x1C4, 10), - MUX_GATE_CLR_SET_UPD(CLK_TOP_XFI_PHY_1_XTAL_SEL, "xfi_phy_1_xtal_sel", - sspxtp_parents, 0x0a0, 0x0a4, 0x0a8, 16, 1, 23, - 0x1C4, 11), - /* CLK_CFG_11 */ - MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SYSAXI_SEL, "sysaxi_sel", - axi_infra_parents, 0x0a0, 0x0a4, 0x0a8, 24, - 1, 31, 0x1C4, 12, CLK_IS_CRITICAL), - MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SYSAPB_SEL, "sysapb_sel", - sysapb_parents, 0x0b0, 0x0b4, 0x0b8, 0, 1, - 7, 0x1c4, 13, CLK_IS_CRITICAL), - MUX_GATE_CLR_SET_UPD(CLK_TOP_ETH_REFCK_50M_SEL, "eth_refck_50m_sel", - eth_refck_50m_parents, 0x0b0, 0x0b4, 0x0b8, 8, 1, - 15, 0x1C4, 14), - MUX_GATE_CLR_SET_UPD(CLK_TOP_ETH_SYS_200M_SEL, "eth_sys_200m_sel", - eth_sys_200m_parents, 0x0b0, 0x0b4, 0x0b8, 16, 1, - 23, 0x1C4, 15), - MUX_GATE_CLR_SET_UPD(CLK_TOP_ETH_SYS_SEL, "eth_sys_sel", - pcie_mbist_250m_parents, 0x0b0, 0x0b4, 0x0b8, 24, - 1, 31, 0x1C4, 16), - /* CLK_CFG_12 */ - MUX_GATE_CLR_SET_UPD(CLK_TOP_ETH_XGMII_SEL, "eth_xgmii_sel", - eth_xgmii_parents, 0x0c0, 0x0c4, 0x0c8, 0, 2, 7, - 0x1C4, 17), - MUX_GATE_CLR_SET_UPD(CLK_TOP_BUS_TOPS_SEL, "bus_tops_sel", - bus_tops_parents, 0x0c0, 0x0c4, 0x0c8, 8, 2, 15, - 0x1C4, 18), - MUX_GATE_CLR_SET_UPD(CLK_TOP_NPU_TOPS_SEL, "npu_tops_sel", - npu_tops_parents, 0x0c0, 0x0c4, 0x0c8, 16, 1, 23, - 0x1C4, 19), - MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_DRAMC_SEL, "dramc_sel", - sspxtp_parents, 0x0c0, 0x0c4, 0x0c8, 24, 1, - 31, 0x1C4, 20, CLK_IS_CRITICAL), - /* CLK_CFG_13 */ - MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_DRAMC_MD32_SEL, "dramc_md32_sel", - dramc_md32_parents, 0x0d0, 0x0d4, 0x0d8, 0, - 2, 7, 0x1C4, 21, CLK_IS_CRITICAL), - MUX_GATE_CLR_SET_UPD_FLAGS( - CLK_TOP_INFRA_F26M_SEL, "csw_infra_f26m_sel", sspxtp_parents, - 0x0d0, 0x0d4, 0x0d8, 8, 1, 15, 0x1C4, 22, CLK_IS_CRITICAL), - MUX_GATE_CLR_SET_UPD(CLK_TOP_PEXTP_P0_SEL, "pextp_p0_sel", - sspxtp_parents, 0x0d0, 0x0d4, 0x0d8, 16, 1, 23, - 0x1C4, 23), - MUX_GATE_CLR_SET_UPD(CLK_TOP_PEXTP_P1_SEL, "pextp_p1_sel", - sspxtp_parents, 0x0d0, 0x0d4, 0x0d8, 24, 1, 31, - 0x1C4, 24), - /* CLK_CFG_14 */ - MUX_GATE_CLR_SET_UPD(CLK_TOP_PEXTP_P2_SEL, "pextp_p2_sel", - sspxtp_parents, 0x0e0, 0x0e4, 0x0e8, 0, 1, 7, - 0x1C4, 25), - MUX_GATE_CLR_SET_UPD(CLK_TOP_PEXTP_P3_SEL, "pextp_p3_sel", - sspxtp_parents, 0x0e0, 0x0e4, 0x0e8, 8, 1, 15, - 0x1C4, 26), - MUX_GATE_CLR_SET_UPD(CLK_TOP_DA_XTP_GLB_P0_SEL, "da_xtp_glb_p0_sel", - da_xtp_glb_p0_parents, 0x0e0, 0x0e4, 0x0e8, 16, 1, - 23, 0x1C4, 27), - MUX_GATE_CLR_SET_UPD(CLK_TOP_DA_XTP_GLB_P1_SEL, "da_xtp_glb_p1_sel", - da_xtp_glb_p0_parents, 0x0e0, 0x0e4, 0x0e8, 24, 1, - 31, 0x1C4, 28), - /* CLK_CFG_15 */ - MUX_GATE_CLR_SET_UPD(CLK_TOP_DA_XTP_GLB_P2_SEL, "da_xtp_glb_p2_sel", - da_xtp_glb_p0_parents, 0x0f0, 0x0f4, 0x0f8, 0, 1, - 7, 0x1C4, 29), - MUX_GATE_CLR_SET_UPD(CLK_TOP_DA_XTP_GLB_P3_SEL, "da_xtp_glb_p3_sel", - da_xtp_glb_p0_parents, 0x0f0, 0x0f4, 0x0f8, 8, 1, - 15, 0x1C4, 30), - MUX_GATE_CLR_SET_UPD(CLK_TOP_CKM_SEL, "ckm_sel", sspxtp_parents, 0x0F0, - 0x0f4, 0x0f8, 16, 1, 23, 0x1c8, 0), - MUX_GATE_CLR_SET_UPD(CLK_TOP_DA_SEL, "da_sel", sspxtp_parents, 0x0f0, - 0x0f4, 0x0f8, 24, 1, 31, 0x1C8, 1), - /* CLK_CFG_16 */ - MUX_GATE_CLR_SET_UPD(CLK_TOP_PEXTP_SEL, "pextp_sel", sspxtp_parents, - 0x0100, 0x104, 0x108, 0, 1, 7, 0x1c8, 2), - MUX_GATE_CLR_SET_UPD(CLK_TOP_TOPS_P2_26M_SEL, "tops_p2_26m_sel", - sspxtp_parents, 0x0100, 0x104, 0x108, 8, 1, 15, - 0x1C8, 3), - MUX_GATE_CLR_SET_UPD(CLK_TOP_MCUSYS_BACKUP_625M_SEL, - "mcusys_backup_625m_sel", - mcusys_backup_625m_parents, 0x0100, 0x104, 0x108, - 16, 1, 23, 0x1C8, 4), - MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_SYNC_250M_SEL, - "netsys_sync_250m_sel", pcie_mbist_250m_parents, - 0x0100, 0x104, 0x108, 24, 1, 31, 0x1c8, 5), - /* CLK_CFG_17 */ - MUX_GATE_CLR_SET_UPD(CLK_TOP_MACSEC_SEL, "macsec_sel", macsec_parents, - 0x0110, 0x114, 0x118, 0, 2, 7, 0x1c8, 6), - MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_TOPS_400M_SEL, - "netsys_tops_400m_sel", netsys_tops_400m_parents, - 0x0110, 0x114, 0x118, 8, 1, 15, 0x1c8, 7), - MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_PPEFB_250M_SEL, - "netsys_ppefb_250m_sel", pcie_mbist_250m_parents, - 0x0110, 0x114, 0x118, 16, 1, 23, 0x1c8, 8), - MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_WARP_SEL, "netsys_warp_sel", - netsys_parents, 0x0110, 0x114, 0x118, 24, 2, 31, - 0x1C8, 9), - /* CLK_CFG_18 */ - MUX_GATE_CLR_SET_UPD(CLK_TOP_ETH_MII_SEL, "eth_mii_sel", - eth_mii_parents, 0x0120, 0x124, 0x128, 0, 1, 7, - 0x1c8, 10), - MUX_GATE_CLR_SET_UPD(CLK_TOP_NPU_SEL, "ck_npu_sel", netsys_2x_parents, - 0x0120, 0x124, 0x128, 8, 2, 15, 0x1c8, 11), -}; - -static const struct mtk_composite top_aud_divs[] = { - DIV_GATE(CLK_TOP_AUD_I2S_M, "aud_i2s_m", "aud_sel", 0x0420, 0, 0x0420, - 8, 8), -}; - -static int clk_mt7988_topckgen_probe(struct platform_device *pdev) -{ - struct clk_onecell_data *clk_data; - struct device_node *node = pdev->dev.of_node; - int r; - void __iomem *base; - int nr = ARRAY_SIZE(top_fixed_clks) + ARRAY_SIZE(top_divs) + - ARRAY_SIZE(top_muxes) + ARRAY_SIZE(top_aud_divs); - - base = of_iomap(node, 0); - if (!base) { - pr_err("%s(): ioremap failed\n", __func__); - return -ENOMEM; - } - - clk_data = mtk_alloc_clk_data(nr); - if (!clk_data) - return -ENOMEM; - - mtk_clk_register_fixed_clks(top_fixed_clks, ARRAY_SIZE(top_fixed_clks), - clk_data); - - mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), clk_data); - - mtk_clk_register_muxes(top_muxes, ARRAY_SIZE(top_muxes), node, - &mt7988_clk_lock, clk_data); - - mtk_clk_register_composites(top_aud_divs, ARRAY_SIZE(top_aud_divs), - base, &mt7988_clk_lock, clk_data); - - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); - - if (r) { - pr_err("%s(): could not register clock provider: %d\n", - __func__, r); - goto free_topckgen_data; - } - return r; - -free_topckgen_data: - mtk_free_clk_data(clk_data); - return r; -} - -static const char *const mcu_bus_div_parents[] = { "top_xtal", "ccipll2_b", - "net1pll_d4" }; - -static const char *const mcu_arm_div_parents[] = { "top_xtal", "arm_b", - "net1pll_d4" }; - -static struct mtk_composite mcu_muxes[] = { - /* bus_pll_divider_cfg */ - MUX_GATE_FLAGS(CLK_MCU_BUS_DIV_SEL, "mcu_bus_div_sel", - mcu_bus_div_parents, 0x7C0, 9, 2, -1, CLK_IS_CRITICAL), - /* mp2_pll_divider_cfg */ - MUX_GATE_FLAGS(CLK_MCU_ARM_DIV_SEL, "mcu_arm_div_sel", - mcu_arm_div_parents, 0x7A8, 9, 2, -1, CLK_IS_CRITICAL), -}; - -static int clk_mt7988_mcusys_probe(struct platform_device *pdev) -{ - struct clk_onecell_data *clk_data; - struct device_node *node = pdev->dev.of_node; - int r; - void __iomem *base; - int nr = ARRAY_SIZE(mcu_muxes); - - base = of_iomap(node, 0); - if (!base) { - pr_err("%s(): ioremap failed\n", __func__); - return -ENOMEM; - } - - clk_data = mtk_alloc_clk_data(nr); - if (!clk_data) - return -ENOMEM; - - mtk_clk_register_composites(mcu_muxes, ARRAY_SIZE(mcu_muxes), base, - &mt7988_clk_lock, clk_data); - - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); - - if (r) { - pr_err("%s(): could not register clock provider: %d\n", - __func__, r); - goto free_mcusys_data; - } - return r; - -free_mcusys_data: - mtk_free_clk_data(clk_data); - return r; -} - -static const struct of_device_id of_match_clk_mt7988_topckgen[] = { - { - .compatible = "mediatek,mt7988-topckgen", - }, - {} -}; - -static struct platform_driver clk_mt7988_topckgen_drv = { - .probe = clk_mt7988_topckgen_probe, - .driver = { - .name = "clk-mt7988-topckgen", - .of_match_table = of_match_clk_mt7988_topckgen, - }, -}; -builtin_platform_driver(clk_mt7988_topckgen_drv); - -static const struct of_device_id of_match_clk_mt7988_mcusys[] = { - { - .compatible = "mediatek,mt7988-mcusys", - }, - {} -}; - -static struct platform_driver clk_mt7988_mcusys_drv = { - .probe = clk_mt7988_mcusys_probe, - .driver = { - .name = "clk-mt7988-mcusys", - .of_match_table = of_match_clk_mt7988_mcusys, - }, -}; -builtin_platform_driver(clk_mt7988_mcusys_drv); \ No newline at end of file diff --git a/target/linux/mediatek/files-5.15/drivers/net/phy/mediatek-2p5ge.c b/target/linux/mediatek/files-5.15/drivers/net/phy/mediatek-2p5ge.c deleted file mode 100644 index c12e6b8eb..000000000 --- a/target/linux/mediatek/files-5.15/drivers/net/phy/mediatek-2p5ge.c +++ /dev/null @@ -1,262 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -#include -#include -#include -#include -#include -#include -#include -#include - -#define MEDAITEK_2P5GE_PHY_DMB_FW "mediatek/mediatek-2p5ge-phy-dmb.bin" -#define MEDIATEK_2P5GE_PHY_PMB_FW "mediatek/mediatek-2p5ge-phy-pmb.bin" - -#define MD32_EN_CFG 0x18 -#define MD32_EN BIT(0) - -#define BASE100T_STATUS_EXTEND 0x10 -#define BASE1000T_STATUS_EXTEND 0x11 -#define EXTEND_CTRL_AND_STATUS 0x16 - -#define PHY_AUX_CTRL_STATUS 0x1d -#define PHY_AUX_DPX_MASK GENMASK(5, 5) -#define PHY_AUX_SPEED_MASK GENMASK(4, 2) - -/* Registers on MDIO_MMD_VEND1 */ -#define MTK_PHY_LINK_STATUS_MISC 0xa2 -#define MTK_PHY_FDX_ENABLE BIT(5) - -/* Registers on MDIO_MMD_VEND2 */ -#define MTK_PHY_LED0_ON_CTRL 0x24 -#define MTK_PHY_LED0_ON_LINK1000 BIT(0) -#define MTK_PHY_LED0_ON_LINK100 BIT(1) -#define MTK_PHY_LED0_ON_LINK10 BIT(2) -#define MTK_PHY_LED0_ON_LINK2500 BIT(7) -#define MTK_PHY_LED0_POLARITY BIT(14) - -#define MTK_PHY_LED1_ON_CTRL 0x26 -#define MTK_PHY_LED1_ON_FDX BIT(4) -#define MTK_PHY_LED1_ON_HDX BIT(5) -#define MTK_PHY_LED1_POLARITY BIT(14) - -enum { - PHY_AUX_SPD_10 = 0, - PHY_AUX_SPD_100, - PHY_AUX_SPD_1000, - PHY_AUX_SPD_2500, -}; - -static int mt798x_2p5ge_phy_config_init(struct phy_device *phydev) -{ - int ret; - int i; - const struct firmware *fw; - struct device *dev = &phydev->mdio.dev; - struct device_node *np; - void __iomem *dmb_addr; - void __iomem *pmb_addr; - void __iomem *mcucsr_base; - u16 reg; - struct pinctrl *pinctrl; - - np = of_find_compatible_node(NULL, NULL, "mediatek,2p5gphy-fw"); - if (!np) - return -ENOENT; - - dmb_addr = of_iomap(np, 0); - if (!dmb_addr) - return -ENOMEM; - pmb_addr = of_iomap(np, 1); - if (!pmb_addr) - return -ENOMEM; - mcucsr_base = of_iomap(np, 2); - if (!mcucsr_base) - return -ENOMEM; - - ret = request_firmware(&fw, MEDAITEK_2P5GE_PHY_DMB_FW, dev); - if (ret) { - dev_err(dev, "failed to load firmware: %s, ret: %d\n", - MEDAITEK_2P5GE_PHY_DMB_FW, ret); - return ret; - } - for (i = 0; i < fw->size - 1; i += 4) - writel(*((uint32_t *)(fw->data + i)), dmb_addr + i); - release_firmware(fw); - - ret = request_firmware(&fw, MEDIATEK_2P5GE_PHY_PMB_FW, dev); - if (ret) { - dev_err(dev, "failed to load firmware: %s, ret: %d\n", - MEDIATEK_2P5GE_PHY_PMB_FW, ret); - return ret; - } - for (i = 0; i < fw->size - 1; i += 4) - writel(*((uint32_t *)(fw->data + i)), pmb_addr + i); - release_firmware(fw); - - reg = readw(mcucsr_base + MD32_EN_CFG); - writew(reg | MD32_EN, mcucsr_base + MD32_EN_CFG); - dev_dbg(dev, "Firmware loading/trigger ok.\n"); - - /* Setup LED */ - phy_clear_bits_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_LED0_ON_CTRL, - MTK_PHY_LED0_POLARITY); - - phy_set_bits_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_LED0_ON_CTRL, - MTK_PHY_LED0_ON_LINK10 | - MTK_PHY_LED0_ON_LINK100 | - MTK_PHY_LED0_ON_LINK1000 | - MTK_PHY_LED0_ON_LINK2500); - - phy_set_bits_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_LED1_ON_CTRL, - MTK_PHY_LED1_ON_FDX | MTK_PHY_LED1_ON_HDX); - - pinctrl = devm_pinctrl_get_select(&phydev->mdio.dev, "i2p5gbe-led"); - if (IS_ERR(pinctrl)) { - dev_err(&phydev->mdio.dev, "Fail to set LED pins!\n"); - return PTR_ERR(pinctrl); - } - - return 0; -} - -static int mt798x_2p5ge_phy_config_aneg(struct phy_device *phydev) -{ - bool changed = false; - u32 adv; - int ret; - - if (phydev->autoneg == AUTONEG_DISABLE) { - /* Configure half duplex with genphy_setup_forced, - * because genphy_c45_pma_setup_forced does not support. - */ - return phydev->duplex != DUPLEX_FULL - ? genphy_setup_forced(phydev) - : genphy_c45_pma_setup_forced(phydev); - } - - ret = genphy_c45_an_config_aneg(phydev); - if (ret < 0) - return ret; - if (ret > 0) - changed = true; - - adv = linkmode_adv_to_mii_ctrl1000_t(phydev->advertising); - ret = phy_modify_changed(phydev, MII_CTRL1000, - ADVERTISE_1000FULL | ADVERTISE_1000HALF, - adv); - if (ret < 0) - return ret; - if (ret > 0) - changed = true; - - return genphy_c45_check_and_restart_aneg(phydev, changed); -} - -static int mt798x_2p5ge_phy_get_features(struct phy_device *phydev) -{ - int ret; - - ret = genphy_read_abilities(phydev); - if (ret) - return ret; - - /* We don't support HDX at MAC layer on mt798x. - * So mask phy's HDX capabilities, too. - */ - linkmode_set_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT, - phydev->supported); - linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT, - phydev->supported); - linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, - phydev->supported); - linkmode_set_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, - phydev->supported); - linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, phydev->supported); - - return 0; -} - -static int mt798x_2p5ge_phy_read_status(struct phy_device *phydev) -{ - int ret; - - ret = genphy_update_link(phydev); - if (ret) - return ret; - - phydev->speed = SPEED_UNKNOWN; - phydev->duplex = DUPLEX_UNKNOWN; - phydev->pause = 0; - phydev->asym_pause = 0; - - if (!phydev->link) - return 0; - - if (phydev->autoneg == AUTONEG_ENABLE && phydev->autoneg_complete) { - ret = genphy_c45_read_lpa(phydev); - if (ret < 0) - return ret; - - /* Read the link partner's 1G advertisement */ - ret = phy_read(phydev, MII_STAT1000); - if (ret < 0) - return ret; - mii_stat1000_mod_linkmode_lpa_t(phydev->lp_advertising, ret); - } else if (phydev->autoneg == AUTONEG_DISABLE) { - linkmode_zero(phydev->lp_advertising); - } - - ret = phy_read(phydev, PHY_AUX_CTRL_STATUS); - if (ret < 0) - return ret; - - switch (FIELD_GET(PHY_AUX_SPEED_MASK, ret)) { - case PHY_AUX_SPD_10: - phydev->speed = SPEED_10; - break; - case PHY_AUX_SPD_100: - phydev->speed = SPEED_100; - break; - case PHY_AUX_SPD_1000: - phydev->speed = SPEED_1000; - break; - case PHY_AUX_SPD_2500: - phydev->speed = SPEED_2500; - phydev->duplex = DUPLEX_FULL; /* 2.5G must be FDX */ - break; - } - - ret = phy_read_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_LINK_STATUS_MISC); - if (ret < 0) - return ret; - - phydev->duplex = (ret & MTK_PHY_FDX_ENABLE) ? DUPLEX_FULL : DUPLEX_HALF; - - return 0; -} - -static struct phy_driver mtk_gephy_driver[] = { - { - PHY_ID_MATCH_EXACT(0x00339c11), - .name = "MediaTek MT798x 2.5GbE PHY", - .config_init = mt798x_2p5ge_phy_config_init, - .config_aneg = mt798x_2p5ge_phy_config_aneg, - .get_features = mt798x_2p5ge_phy_get_features, - .read_status = mt798x_2p5ge_phy_read_status, - }, -}; - -module_phy_driver(mtk_gephy_driver); - -static struct mdio_device_id __maybe_unused mtk_2p5ge_phy_tbl[] = { - { PHY_ID_MATCH_VENDOR(0x00339c00) }, - { } -}; - -MODULE_DESCRIPTION("MediaTek 2.5Gb Ethernet PHY driver"); -MODULE_AUTHOR("SkyLake Huang "); -MODULE_LICENSE("GPL"); - -MODULE_DEVICE_TABLE(mdio, mtk_2p5ge_phy_tbl); -MODULE_FIRMWARE(MEDAITEK_2P5GE_PHY_DMB_FW); -MODULE_FIRMWARE(MEDIATEK_2P5GE_PHY_PMB_FW); diff --git a/target/linux/mediatek/files-5.15/drivers/pinctrl/mediatek/pinctrl-mt7981.c b/target/linux/mediatek/files-5.15/drivers/pinctrl/mediatek/pinctrl-mt7981.c deleted file mode 100644 index 7c082dd20..000000000 --- a/target/linux/mediatek/files-5.15/drivers/pinctrl/mediatek/pinctrl-mt7981.c +++ /dev/null @@ -1,1041 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * The MT7981 driver based on Linux generic pinctrl binding. - * - * Copyright (C) 2020 MediaTek Inc. - * Author: Sam Shih - */ - -#include "pinctrl-moore.h" - -#define MT7981_PIN(_number, _name) \ - MTK_PIN(_number, _name, 0, _number, DRV_GRP4) - -#define PIN_FIELD_BASE(_s_pin, _e_pin, _i_base, _s_addr, _x_addrs, _s_bit, _x_bits) \ - PIN_FIELD_CALC(_s_pin, _e_pin, _i_base, _s_addr, _x_addrs, _s_bit, \ - _x_bits, 32, 0) - -#define PINS_FIELD_BASE(_s_pin, _e_pin, _i_base, _s_addr, _x_addrs, _s_bit, _x_bits) \ - PIN_FIELD_CALC(_s_pin, _e_pin, _i_base, _s_addr, _x_addrs, _s_bit, \ - _x_bits, 32, 1) - -static const struct mtk_pin_field_calc mt7981_pin_mode_range[] = { - PIN_FIELD(0, 56, 0x300, 0x10, 0, 4), -}; - -static const struct mtk_pin_field_calc mt7981_pin_dir_range[] = { - PIN_FIELD(0, 56, 0x0, 0x10, 0, 1), -}; - -static const struct mtk_pin_field_calc mt7981_pin_di_range[] = { - PIN_FIELD(0, 56, 0x200, 0x10, 0, 1), -}; - -static const struct mtk_pin_field_calc mt7981_pin_do_range[] = { - PIN_FIELD(0, 56, 0x100, 0x10, 0, 1), -}; - -static const struct mtk_pin_field_calc mt7981_pin_ies_range[] = { - PIN_FIELD_BASE(0, 0, 1, 0x10, 0x10, 1, 1), - PIN_FIELD_BASE(1, 1, 1, 0x10, 0x10, 0, 1), - PIN_FIELD_BASE(2, 2, 5, 0x20, 0x10, 6, 1), - PIN_FIELD_BASE(3, 3, 4, 0x20, 0x10, 6, 1), - PIN_FIELD_BASE(4, 4, 4, 0x20, 0x10, 2, 1), - PIN_FIELD_BASE(5, 5, 4, 0x20, 0x10, 1, 1), - PIN_FIELD_BASE(6, 6, 4, 0x20, 0x10, 3, 1), - PIN_FIELD_BASE(7, 7, 4, 0x20, 0x10, 0, 1), - PIN_FIELD_BASE(8, 8, 4, 0x20, 0x10, 4, 1), - - PIN_FIELD_BASE(9, 9, 5, 0x20, 0x10, 9, 1), - PIN_FIELD_BASE(10, 10, 5, 0x20, 0x10, 8, 1), - PIN_FIELD_BASE(11, 11, 5, 0x40, 0x10, 10, 1), - PIN_FIELD_BASE(12, 12, 5, 0x20, 0x10, 7, 1), - PIN_FIELD_BASE(13, 13, 5, 0x20, 0x10, 11, 1), - - PIN_FIELD_BASE(14, 14, 4, 0x20, 0x10, 8, 1), - - PIN_FIELD_BASE(15, 15, 2, 0x20, 0x10, 0, 1), - PIN_FIELD_BASE(16, 16, 2, 0x20, 0x10, 1, 1), - PIN_FIELD_BASE(17, 17, 2, 0x20, 0x10, 5, 1), - PIN_FIELD_BASE(18, 18, 2, 0x20, 0x10, 4, 1), - PIN_FIELD_BASE(19, 19, 2, 0x20, 0x10, 2, 1), - PIN_FIELD_BASE(20, 20, 2, 0x20, 0x10, 3, 1), - PIN_FIELD_BASE(21, 21, 2, 0x20, 0x10, 6, 1), - PIN_FIELD_BASE(22, 22, 2, 0x20, 0x10, 7, 1), - PIN_FIELD_BASE(23, 23, 2, 0x20, 0x10, 10, 1), - PIN_FIELD_BASE(24, 24, 2, 0x20, 0x10, 9, 1), - PIN_FIELD_BASE(25, 25, 2, 0x20, 0x10, 8, 1), - - PIN_FIELD_BASE(26, 26, 5, 0x20, 0x10, 0, 1), - PIN_FIELD_BASE(27, 27, 5, 0x20, 0x10, 4, 1), - PIN_FIELD_BASE(28, 28, 5, 0x20, 0x10, 3, 1), - PIN_FIELD_BASE(29, 29, 5, 0x20, 0x10, 1, 1), - PIN_FIELD_BASE(30, 30, 5, 0x20, 0x10, 2, 1), - PIN_FIELD_BASE(31, 31, 5, 0x20, 0x10, 5, 1), - - PIN_FIELD_BASE(32, 32, 1, 0x10, 0x10, 2, 1), - PIN_FIELD_BASE(33, 33, 1, 0x10, 0x10, 3, 1), - - PIN_FIELD_BASE(34, 34, 4, 0x20, 0x10, 5, 1), - PIN_FIELD_BASE(35, 35, 4, 0x20, 0x10, 7, 1), - - PIN_FIELD_BASE(36, 36, 3, 0x10, 0x10, 2, 1), - PIN_FIELD_BASE(37, 37, 3, 0x10, 0x10, 3, 1), - PIN_FIELD_BASE(38, 38, 3, 0x10, 0x10, 0, 1), - PIN_FIELD_BASE(39, 39, 3, 0x10, 0x10, 1, 1), - - PIN_FIELD_BASE(40, 40, 7, 0x30, 0x10, 1, 1), - PIN_FIELD_BASE(41, 41, 7, 0x30, 0x10, 0, 1), - PIN_FIELD_BASE(42, 42, 7, 0x30, 0x10, 9, 1), - PIN_FIELD_BASE(43, 43, 7, 0x30, 0x10, 7, 1), - PIN_FIELD_BASE(44, 44, 7, 0x30, 0x10, 8, 1), - PIN_FIELD_BASE(45, 45, 7, 0x30, 0x10, 3, 1), - PIN_FIELD_BASE(46, 46, 7, 0x30, 0x10, 4, 1), - PIN_FIELD_BASE(47, 47, 7, 0x30, 0x10, 5, 1), - PIN_FIELD_BASE(48, 48, 7, 0x30, 0x10, 6, 1), - PIN_FIELD_BASE(49, 49, 7, 0x30, 0x10, 2, 1), - - PIN_FIELD_BASE(50, 50, 6, 0x10, 0x10, 0, 1), - PIN_FIELD_BASE(51, 51, 6, 0x10, 0x10, 2, 1), - PIN_FIELD_BASE(52, 52, 6, 0x10, 0x10, 3, 1), - PIN_FIELD_BASE(53, 53, 6, 0x10, 0x10, 4, 1), - PIN_FIELD_BASE(54, 54, 6, 0x10, 0x10, 5, 1), - PIN_FIELD_BASE(55, 55, 6, 0x10, 0x10, 6, 1), - PIN_FIELD_BASE(56, 56, 6, 0x10, 0x10, 1, 1), -}; - -static const struct mtk_pin_field_calc mt7981_pin_smt_range[] = { - PIN_FIELD_BASE(0, 0, 1, 0x60, 0x10, 1, 1), - PIN_FIELD_BASE(1, 1, 1, 0x60, 0x10, 0, 1), - PIN_FIELD_BASE(2, 2, 5, 0x90, 0x10, 6, 1), - PIN_FIELD_BASE(3, 3, 4, 0x80, 0x10, 6, 1), - PIN_FIELD_BASE(4, 4, 4, 0x80, 0x10, 2, 1), - PIN_FIELD_BASE(5, 5, 4, 0x80, 0x10, 1, 1), - PIN_FIELD_BASE(6, 6, 4, 0x80, 0x10, 3, 1), - PIN_FIELD_BASE(7, 7, 4, 0x80, 0x10, 0, 1), - PIN_FIELD_BASE(8, 8, 4, 0x80, 0x10, 4, 1), - - PIN_FIELD_BASE(9, 9, 5, 0x90, 0x10, 9, 1), - PIN_FIELD_BASE(10, 10, 5, 0x90, 0x10, 8, 1), - PIN_FIELD_BASE(11, 11, 5, 0x90, 0x10, 10, 1), - PIN_FIELD_BASE(12, 12, 5, 0x90, 0x10, 7, 1), - PIN_FIELD_BASE(13, 13, 5, 0x90, 0x10, 11, 1), - - PIN_FIELD_BASE(14, 14, 4, 0x80, 0x10, 8, 1), - - PIN_FIELD_BASE(15, 15, 2, 0x90, 0x10, 0, 1), - PIN_FIELD_BASE(16, 16, 2, 0x90, 0x10, 1, 1), - PIN_FIELD_BASE(17, 17, 2, 0x90, 0x10, 5, 1), - PIN_FIELD_BASE(18, 18, 2, 0x90, 0x10, 4, 1), - PIN_FIELD_BASE(19, 19, 2, 0x90, 0x10, 2, 1), - PIN_FIELD_BASE(20, 20, 2, 0x90, 0x10, 3, 1), - PIN_FIELD_BASE(21, 21, 2, 0x90, 0x10, 6, 1), - PIN_FIELD_BASE(22, 22, 2, 0x90, 0x10, 7, 1), - PIN_FIELD_BASE(23, 23, 2, 0x90, 0x10, 10, 1), - PIN_FIELD_BASE(24, 24, 2, 0x90, 0x10, 9, 1), - PIN_FIELD_BASE(25, 25, 2, 0x90, 0x10, 8, 1), - - PIN_FIELD_BASE(26, 26, 5, 0x90, 0x10, 0, 1), - PIN_FIELD_BASE(27, 27, 5, 0x90, 0x10, 4, 1), - PIN_FIELD_BASE(28, 28, 5, 0x90, 0x10, 3, 1), - PIN_FIELD_BASE(29, 29, 5, 0x90, 0x10, 1, 1), - PIN_FIELD_BASE(30, 30, 5, 0x90, 0x10, 2, 1), - PIN_FIELD_BASE(31, 31, 5, 0x90, 0x10, 5, 1), - - PIN_FIELD_BASE(32, 32, 1, 0x60, 0x10, 2, 1), - PIN_FIELD_BASE(33, 33, 1, 0x60, 0x10, 3, 1), - - PIN_FIELD_BASE(34, 34, 4, 0x80, 0x10, 5, 1), - PIN_FIELD_BASE(35, 35, 4, 0x80, 0x10, 7, 1), - - PIN_FIELD_BASE(36, 36, 3, 0x60, 0x10, 2, 1), - PIN_FIELD_BASE(37, 37, 3, 0x60, 0x10, 3, 1), - PIN_FIELD_BASE(38, 38, 3, 0x60, 0x10, 0, 1), - PIN_FIELD_BASE(39, 39, 3, 0x60, 0x10, 1, 1), - - PIN_FIELD_BASE(40, 40, 7, 0x70, 0x10, 1, 1), - PIN_FIELD_BASE(41, 41, 7, 0x70, 0x10, 0, 1), - PIN_FIELD_BASE(42, 42, 7, 0x70, 0x10, 9, 1), - PIN_FIELD_BASE(43, 43, 7, 0x70, 0x10, 7, 1), - PIN_FIELD_BASE(44, 44, 7, 0x30, 0x10, 8, 1), - PIN_FIELD_BASE(45, 45, 7, 0x70, 0x10, 3, 1), - PIN_FIELD_BASE(46, 46, 7, 0x70, 0x10, 4, 1), - PIN_FIELD_BASE(47, 47, 7, 0x70, 0x10, 5, 1), - PIN_FIELD_BASE(48, 48, 7, 0x70, 0x10, 6, 1), - PIN_FIELD_BASE(49, 49, 7, 0x70, 0x10, 2, 1), - - PIN_FIELD_BASE(50, 50, 6, 0x50, 0x10, 0, 1), - PIN_FIELD_BASE(51, 51, 6, 0x50, 0x10, 2, 1), - PIN_FIELD_BASE(52, 52, 6, 0x50, 0x10, 3, 1), - PIN_FIELD_BASE(53, 53, 6, 0x50, 0x10, 4, 1), - PIN_FIELD_BASE(54, 54, 6, 0x50, 0x10, 5, 1), - PIN_FIELD_BASE(55, 55, 6, 0x50, 0x10, 6, 1), - PIN_FIELD_BASE(56, 56, 6, 0x50, 0x10, 1, 1), -}; - -static const struct mtk_pin_field_calc mt7981_pin_pu_range[] = { - PIN_FIELD_BASE(40, 40, 7, 0x50, 0x10, 1, 1), - PIN_FIELD_BASE(41, 41, 7, 0x50, 0x10, 0, 1), - PIN_FIELD_BASE(42, 42, 7, 0x50, 0x10, 9, 1), - PIN_FIELD_BASE(43, 43, 7, 0x50, 0x10, 7, 1), - PIN_FIELD_BASE(44, 44, 7, 0x50, 0x10, 8, 1), - PIN_FIELD_BASE(45, 45, 7, 0x50, 0x10, 3, 1), - PIN_FIELD_BASE(46, 46, 7, 0x50, 0x10, 4, 1), - PIN_FIELD_BASE(47, 47, 7, 0x50, 0x10, 5, 1), - PIN_FIELD_BASE(48, 48, 7, 0x50, 0x10, 6, 1), - PIN_FIELD_BASE(49, 49, 7, 0x50, 0x10, 2, 1), - - PIN_FIELD_BASE(50, 50, 6, 0x30, 0x10, 0, 1), - PIN_FIELD_BASE(51, 51, 6, 0x30, 0x10, 2, 1), - PIN_FIELD_BASE(52, 52, 6, 0x30, 0x10, 3, 1), - PIN_FIELD_BASE(53, 53, 6, 0x30, 0x10, 4, 1), - PIN_FIELD_BASE(54, 54, 6, 0x30, 0x10, 5, 1), - PIN_FIELD_BASE(55, 55, 6, 0x30, 0x10, 6, 1), - PIN_FIELD_BASE(56, 56, 6, 0x30, 0x10, 1, 1), -}; - -static const struct mtk_pin_field_calc mt7981_pin_pd_range[] = { - PIN_FIELD_BASE(40, 40, 7, 0x40, 0x10, 1, 1), - PIN_FIELD_BASE(41, 41, 7, 0x40, 0x10, 0, 1), - PIN_FIELD_BASE(42, 42, 7, 0x40, 0x10, 9, 1), - PIN_FIELD_BASE(43, 43, 7, 0x40, 0x10, 7, 1), - PIN_FIELD_BASE(44, 44, 7, 0x40, 0x10, 8, 1), - PIN_FIELD_BASE(45, 45, 7, 0x40, 0x10, 3, 1), - PIN_FIELD_BASE(46, 46, 7, 0x40, 0x10, 4, 1), - PIN_FIELD_BASE(47, 47, 7, 0x40, 0x10, 5, 1), - PIN_FIELD_BASE(48, 48, 7, 0x40, 0x10, 6, 1), - PIN_FIELD_BASE(49, 49, 7, 0x40, 0x10, 2, 1), - - PIN_FIELD_BASE(50, 50, 6, 0x20, 0x10, 0, 1), - PIN_FIELD_BASE(51, 51, 6, 0x20, 0x10, 2, 1), - PIN_FIELD_BASE(52, 52, 6, 0x20, 0x10, 3, 1), - PIN_FIELD_BASE(53, 53, 6, 0x20, 0x10, 4, 1), - PIN_FIELD_BASE(54, 54, 6, 0x20, 0x10, 5, 1), - PIN_FIELD_BASE(55, 55, 6, 0x20, 0x10, 6, 1), - PIN_FIELD_BASE(56, 56, 6, 0x20, 0x10, 1, 1), -}; - -static const struct mtk_pin_field_calc mt7981_pin_drv_range[] = { - PIN_FIELD_BASE(0, 0, 1, 0x00, 0x10, 3, 3), - PIN_FIELD_BASE(1, 1, 1, 0x00, 0x10, 0, 3), - - PIN_FIELD_BASE(2, 2, 5, 0x00, 0x10, 18, 3), - - PIN_FIELD_BASE(3, 3, 4, 0x00, 0x10, 18, 1), - PIN_FIELD_BASE(4, 4, 4, 0x00, 0x10, 6, 1), - PIN_FIELD_BASE(5, 5, 4, 0x00, 0x10, 3, 3), - PIN_FIELD_BASE(6, 6, 4, 0x00, 0x10, 9, 3), - PIN_FIELD_BASE(7, 7, 4, 0x00, 0x10, 0, 3), - PIN_FIELD_BASE(8, 8, 4, 0x00, 0x10, 12, 3), - - PIN_FIELD_BASE(9, 9, 5, 0x00, 0x10, 27, 3), - PIN_FIELD_BASE(10, 10, 5, 0x00, 0x10, 24, 3), - PIN_FIELD_BASE(11, 11, 5, 0x00, 0x10, 0, 3), - PIN_FIELD_BASE(12, 12, 5, 0x00, 0x10, 21, 3), - PIN_FIELD_BASE(13, 13, 5, 0x00, 0x10, 3, 3), - - PIN_FIELD_BASE(14, 14, 4, 0x00, 0x10, 27, 3), - - PIN_FIELD_BASE(15, 15, 2, 0x00, 0x10, 0, 3), - PIN_FIELD_BASE(16, 16, 2, 0x00, 0x10, 3, 3), - PIN_FIELD_BASE(17, 17, 2, 0x00, 0x10, 15, 3), - PIN_FIELD_BASE(18, 18, 2, 0x00, 0x10, 12, 3), - PIN_FIELD_BASE(19, 19, 2, 0x00, 0x10, 6, 3), - PIN_FIELD_BASE(20, 20, 2, 0x00, 0x10, 9, 3), - PIN_FIELD_BASE(21, 21, 2, 0x00, 0x10, 18, 3), - PIN_FIELD_BASE(22, 22, 2, 0x00, 0x10, 21, 3), - PIN_FIELD_BASE(23, 23, 2, 0x00, 0x10, 0, 3), - PIN_FIELD_BASE(24, 24, 2, 0x00, 0x10, 27, 3), - PIN_FIELD_BASE(25, 25, 2, 0x00, 0x10, 24, 3), - - PIN_FIELD_BASE(26, 26, 5, 0x00, 0x10, 0, 3), - PIN_FIELD_BASE(27, 27, 5, 0x00, 0x10, 12, 3), - PIN_FIELD_BASE(28, 28, 5, 0x00, 0x10, 9, 3), - PIN_FIELD_BASE(29, 29, 5, 0x00, 0x10, 3, 3), - PIN_FIELD_BASE(30, 30, 5, 0x00, 0x10, 6, 3), - PIN_FIELD_BASE(31, 31, 5, 0x00, 0x10, 15, 3), - - PIN_FIELD_BASE(32, 32, 1, 0x00, 0x10, 9, 3), - PIN_FIELD_BASE(33, 33, 1, 0x00, 0x10, 12, 3), - - PIN_FIELD_BASE(34, 34, 4, 0x00, 0x10, 15, 3), - PIN_FIELD_BASE(35, 35, 4, 0x00, 0x10, 21, 3), - - PIN_FIELD_BASE(36, 36, 3, 0x00, 0x10, 6, 3), - PIN_FIELD_BASE(37, 37, 3, 0x00, 0x10, 9, 3), - PIN_FIELD_BASE(38, 38, 3, 0x00, 0x10, 0, 3), - PIN_FIELD_BASE(39, 39, 3, 0x00, 0x10, 3, 3), - - PIN_FIELD_BASE(40, 40, 7, 0x00, 0x10, 3, 3), - PIN_FIELD_BASE(41, 41, 7, 0x00, 0x10, 0, 3), - PIN_FIELD_BASE(42, 42, 7, 0x00, 0x10, 27, 3), - PIN_FIELD_BASE(43, 43, 7, 0x00, 0x10, 21, 3), - PIN_FIELD_BASE(44, 44, 7, 0x00, 0x10, 24, 3), - PIN_FIELD_BASE(45, 45, 7, 0x00, 0x10, 9, 3), - PIN_FIELD_BASE(46, 46, 7, 0x00, 0x10, 12, 3), - PIN_FIELD_BASE(47, 47, 7, 0x00, 0x10, 15, 3), - PIN_FIELD_BASE(48, 48, 7, 0x00, 0x10, 18, 3), - PIN_FIELD_BASE(49, 49, 7, 0x00, 0x10, 6, 3), - - PIN_FIELD_BASE(50, 50, 6, 0x00, 0x10, 0, 3), - PIN_FIELD_BASE(51, 51, 6, 0x00, 0x10, 6, 3), - PIN_FIELD_BASE(52, 52, 6, 0x00, 0x10, 9, 3), - PIN_FIELD_BASE(53, 53, 6, 0x00, 0x10, 12, 3), - PIN_FIELD_BASE(54, 54, 6, 0x00, 0x10, 15, 3), - PIN_FIELD_BASE(55, 55, 6, 0x00, 0x10, 18, 3), - PIN_FIELD_BASE(56, 56, 6, 0x00, 0x10, 3, 3), -}; - -static const struct mtk_pin_field_calc mt7981_pin_pupd_range[] = { - PIN_FIELD_BASE(0, 0, 1, 0x20, 0x10, 1, 1), - PIN_FIELD_BASE(1, 1, 1, 0x20, 0x10, 0, 1), - PIN_FIELD_BASE(2, 2, 5, 0x30, 0x10, 6, 1), - PIN_FIELD_BASE(3, 3, 4, 0x30, 0x10, 6, 1), - PIN_FIELD_BASE(4, 4, 4, 0x30, 0x10, 2, 1), - PIN_FIELD_BASE(5, 5, 4, 0x30, 0x10, 1, 1), - PIN_FIELD_BASE(6, 6, 4, 0x30, 0x10, 3, 1), - PIN_FIELD_BASE(7, 7, 4, 0x30, 0x10, 0, 1), - PIN_FIELD_BASE(8, 8, 4, 0x30, 0x10, 4, 1), - - PIN_FIELD_BASE(9, 9, 5, 0x30, 0x10, 9, 1), - PIN_FIELD_BASE(10, 10, 5, 0x30, 0x10, 8, 1), - PIN_FIELD_BASE(11, 11, 5, 0x30, 0x10, 10, 1), - PIN_FIELD_BASE(12, 12, 5, 0x30, 0x10, 7, 1), - PIN_FIELD_BASE(13, 13, 5, 0x30, 0x10, 11, 1), - - PIN_FIELD_BASE(14, 14, 4, 0x30, 0x10, 8, 1), - - PIN_FIELD_BASE(15, 15, 2, 0x30, 0x10, 0, 1), - PIN_FIELD_BASE(16, 16, 2, 0x30, 0x10, 1, 1), - PIN_FIELD_BASE(17, 17, 2, 0x30, 0x10, 5, 1), - PIN_FIELD_BASE(18, 18, 2, 0x30, 0x10, 4, 1), - PIN_FIELD_BASE(19, 19, 2, 0x30, 0x10, 2, 1), - PIN_FIELD_BASE(20, 20, 2, 0x90, 0x10, 3, 1), - PIN_FIELD_BASE(21, 21, 2, 0x30, 0x10, 6, 1), - PIN_FIELD_BASE(22, 22, 2, 0x30, 0x10, 7, 1), - PIN_FIELD_BASE(23, 23, 2, 0x30, 0x10, 10, 1), - PIN_FIELD_BASE(24, 24, 2, 0x30, 0x10, 9, 1), - PIN_FIELD_BASE(25, 25, 2, 0x30, 0x10, 8, 1), - - PIN_FIELD_BASE(26, 26, 5, 0x30, 0x10, 0, 1), - PIN_FIELD_BASE(27, 27, 5, 0x30, 0x10, 4, 1), - PIN_FIELD_BASE(28, 28, 5, 0x30, 0x10, 3, 1), - PIN_FIELD_BASE(29, 29, 5, 0x30, 0x10, 1, 1), - PIN_FIELD_BASE(30, 30, 5, 0x30, 0x10, 2, 1), - PIN_FIELD_BASE(31, 31, 5, 0x30, 0x10, 5, 1), - - PIN_FIELD_BASE(32, 32, 1, 0x20, 0x10, 2, 1), - PIN_FIELD_BASE(33, 33, 1, 0x20, 0x10, 3, 1), - - PIN_FIELD_BASE(34, 34, 4, 0x30, 0x10, 5, 1), - PIN_FIELD_BASE(35, 35, 4, 0x30, 0x10, 7, 1), - - PIN_FIELD_BASE(36, 36, 3, 0x20, 0x10, 2, 1), - PIN_FIELD_BASE(37, 37, 3, 0x20, 0x10, 3, 1), - PIN_FIELD_BASE(38, 38, 3, 0x20, 0x10, 0, 1), - PIN_FIELD_BASE(39, 39, 3, 0x20, 0x10, 1, 1), -}; - -static const struct mtk_pin_field_calc mt7981_pin_r0_range[] = { - PIN_FIELD_BASE(0, 0, 1, 0x30, 0x10, 1, 1), - PIN_FIELD_BASE(1, 1, 1, 0x30, 0x10, 0, 1), - PIN_FIELD_BASE(2, 2, 5, 0x40, 0x10, 6, 1), - PIN_FIELD_BASE(3, 3, 4, 0x40, 0x10, 6, 1), - PIN_FIELD_BASE(4, 4, 4, 0x40, 0x10, 2, 1), - PIN_FIELD_BASE(5, 5, 4, 0x40, 0x10, 1, 1), - PIN_FIELD_BASE(6, 6, 4, 0x40, 0x10, 3, 1), - PIN_FIELD_BASE(7, 7, 4, 0x40, 0x10, 0, 1), - PIN_FIELD_BASE(8, 8, 4, 0x40, 0x10, 4, 1), - - PIN_FIELD_BASE(9, 9, 5, 0x40, 0x10, 9, 1), - PIN_FIELD_BASE(10, 10, 5, 0x40, 0x10, 8, 1), - PIN_FIELD_BASE(11, 11, 5, 0x40, 0x10, 10, 1), - PIN_FIELD_BASE(12, 12, 5, 0x40, 0x10, 7, 1), - PIN_FIELD_BASE(13, 13, 5, 0x40, 0x10, 11, 1), - - PIN_FIELD_BASE(14, 14, 4, 0x40, 0x10, 8, 1), - - PIN_FIELD_BASE(15, 15, 2, 0x40, 0x10, 0, 1), - PIN_FIELD_BASE(16, 16, 2, 0x40, 0x10, 1, 1), - PIN_FIELD_BASE(17, 17, 2, 0x40, 0x10, 5, 1), - PIN_FIELD_BASE(18, 18, 2, 0x40, 0x10, 4, 1), - PIN_FIELD_BASE(19, 19, 2, 0x40, 0x10, 2, 1), - PIN_FIELD_BASE(20, 20, 2, 0x40, 0x10, 3, 1), - PIN_FIELD_BASE(21, 21, 2, 0x40, 0x10, 6, 1), - PIN_FIELD_BASE(22, 22, 2, 0x40, 0x10, 7, 1), - PIN_FIELD_BASE(23, 23, 2, 0x40, 0x10, 10, 1), - PIN_FIELD_BASE(24, 24, 2, 0x40, 0x10, 9, 1), - PIN_FIELD_BASE(25, 25, 2, 0x40, 0x10, 8, 1), - - PIN_FIELD_BASE(26, 26, 5, 0x40, 0x10, 0, 1), - PIN_FIELD_BASE(27, 27, 5, 0x40, 0x10, 4, 1), - PIN_FIELD_BASE(28, 28, 5, 0x40, 0x10, 3, 1), - PIN_FIELD_BASE(29, 29, 5, 0x40, 0x10, 1, 1), - PIN_FIELD_BASE(30, 30, 5, 0x40, 0x10, 2, 1), - PIN_FIELD_BASE(31, 31, 5, 0x40, 0x10, 5, 1), - - PIN_FIELD_BASE(32, 32, 1, 0x30, 0x10, 2, 1), - PIN_FIELD_BASE(33, 33, 1, 0x30, 0x10, 3, 1), - - PIN_FIELD_BASE(34, 34, 4, 0x40, 0x10, 5, 1), - PIN_FIELD_BASE(35, 35, 4, 0x40, 0x10, 7, 1), - - PIN_FIELD_BASE(36, 36, 3, 0x30, 0x10, 2, 1), - PIN_FIELD_BASE(37, 37, 3, 0x30, 0x10, 3, 1), - PIN_FIELD_BASE(38, 38, 3, 0x30, 0x10, 0, 1), - PIN_FIELD_BASE(39, 39, 3, 0x30, 0x10, 1, 1), -}; - -static const struct mtk_pin_field_calc mt7981_pin_r1_range[] = { - PIN_FIELD_BASE(0, 0, 1, 0x40, 0x10, 1, 1), - PIN_FIELD_BASE(1, 1, 1, 0x40, 0x10, 0, 1), - PIN_FIELD_BASE(2, 2, 5, 0x50, 0x10, 6, 1), - PIN_FIELD_BASE(3, 3, 4, 0x50, 0x10, 6, 1), - PIN_FIELD_BASE(4, 4, 4, 0x50, 0x10, 2, 1), - PIN_FIELD_BASE(5, 5, 4, 0x50, 0x10, 1, 1), - PIN_FIELD_BASE(6, 6, 4, 0x50, 0x10, 3, 1), - PIN_FIELD_BASE(7, 7, 4, 0x50, 0x10, 0, 1), - PIN_FIELD_BASE(8, 8, 4, 0x50, 0x10, 4, 1), - - PIN_FIELD_BASE(9, 9, 5, 0x50, 0x10, 9, 1), - PIN_FIELD_BASE(10, 10, 5, 0x50, 0x10, 8, 1), - PIN_FIELD_BASE(11, 11, 5, 0x50, 0x10, 10, 1), - PIN_FIELD_BASE(12, 12, 5, 0x50, 0x10, 7, 1), - PIN_FIELD_BASE(13, 13, 5, 0x50, 0x10, 11, 1), - - PIN_FIELD_BASE(14, 14, 4, 0x50, 0x10, 8, 1), - - PIN_FIELD_BASE(15, 15, 2, 0x50, 0x10, 0, 1), - PIN_FIELD_BASE(16, 16, 2, 0x50, 0x10, 1, 1), - PIN_FIELD_BASE(17, 17, 2, 0x50, 0x10, 5, 1), - PIN_FIELD_BASE(18, 18, 2, 0x50, 0x10, 4, 1), - PIN_FIELD_BASE(19, 19, 2, 0x50, 0x10, 2, 1), - PIN_FIELD_BASE(20, 20, 2, 0x50, 0x10, 3, 1), - PIN_FIELD_BASE(21, 21, 2, 0x50, 0x10, 6, 1), - PIN_FIELD_BASE(22, 22, 2, 0x50, 0x10, 7, 1), - PIN_FIELD_BASE(23, 23, 2, 0x50, 0x10, 10, 1), - PIN_FIELD_BASE(24, 24, 2, 0x50, 0x10, 9, 1), - PIN_FIELD_BASE(25, 25, 2, 0x50, 0x10, 8, 1), - - PIN_FIELD_BASE(26, 26, 5, 0x50, 0x10, 0, 1), - PIN_FIELD_BASE(27, 27, 5, 0x50, 0x10, 4, 1), - PIN_FIELD_BASE(28, 28, 5, 0x50, 0x10, 3, 1), - PIN_FIELD_BASE(29, 29, 5, 0x50, 0x10, 1, 1), - PIN_FIELD_BASE(30, 30, 5, 0x50, 0x10, 2, 1), - PIN_FIELD_BASE(31, 31, 5, 0x50, 0x10, 5, 1), - - PIN_FIELD_BASE(32, 32, 1, 0x40, 0x10, 2, 1), - PIN_FIELD_BASE(33, 33, 1, 0x40, 0x10, 3, 1), - - PIN_FIELD_BASE(34, 34, 4, 0x50, 0x10, 5, 1), - PIN_FIELD_BASE(35, 35, 4, 0x50, 0x10, 7, 1), - - PIN_FIELD_BASE(36, 36, 3, 0x40, 0x10, 2, 1), - PIN_FIELD_BASE(37, 37, 3, 0x40, 0x10, 3, 1), - PIN_FIELD_BASE(38, 38, 3, 0x40, 0x10, 0, 1), - PIN_FIELD_BASE(39, 39, 3, 0x40, 0x10, 1, 1), -}; - -static const unsigned int mt7981_pull_type[] = { - MTK_PULL_PUPD_R1R0_TYPE,/*0*/ MTK_PULL_PUPD_R1R0_TYPE,/*1*/ - MTK_PULL_PUPD_R1R0_TYPE,/*2*/ MTK_PULL_PUPD_R1R0_TYPE,/*3*/ - MTK_PULL_PUPD_R1R0_TYPE,/*4*/ MTK_PULL_PUPD_R1R0_TYPE,/*5*/ - MTK_PULL_PUPD_R1R0_TYPE,/*6*/ MTK_PULL_PUPD_R1R0_TYPE,/*7*/ - MTK_PULL_PUPD_R1R0_TYPE,/*8*/ MTK_PULL_PUPD_R1R0_TYPE,/*9*/ - MTK_PULL_PUPD_R1R0_TYPE,/*10*/ MTK_PULL_PUPD_R1R0_TYPE,/*11*/ - MTK_PULL_PUPD_R1R0_TYPE,/*12*/ MTK_PULL_PUPD_R1R0_TYPE,/*13*/ - MTK_PULL_PUPD_R1R0_TYPE,/*14*/ MTK_PULL_PUPD_R1R0_TYPE,/*15*/ - MTK_PULL_PUPD_R1R0_TYPE,/*16*/ MTK_PULL_PUPD_R1R0_TYPE,/*17*/ - MTK_PULL_PUPD_R1R0_TYPE,/*18*/ MTK_PULL_PUPD_R1R0_TYPE,/*19*/ - MTK_PULL_PUPD_R1R0_TYPE,/*20*/ MTK_PULL_PUPD_R1R0_TYPE,/*21*/ - MTK_PULL_PUPD_R1R0_TYPE,/*22*/ MTK_PULL_PUPD_R1R0_TYPE,/*23*/ - MTK_PULL_PUPD_R1R0_TYPE,/*24*/ MTK_PULL_PUPD_R1R0_TYPE,/*25*/ - MTK_PULL_PUPD_R1R0_TYPE,/*26*/ MTK_PULL_PUPD_R1R0_TYPE,/*27*/ - MTK_PULL_PUPD_R1R0_TYPE,/*28*/ MTK_PULL_PUPD_R1R0_TYPE,/*29*/ - MTK_PULL_PUPD_R1R0_TYPE,/*30*/ MTK_PULL_PUPD_R1R0_TYPE,/*31*/ - MTK_PULL_PUPD_R1R0_TYPE,/*32*/ MTK_PULL_PUPD_R1R0_TYPE,/*33*/ - MTK_PULL_PUPD_R1R0_TYPE,/*34*/ MTK_PULL_PUPD_R1R0_TYPE,/*35*/ - MTK_PULL_PUPD_R1R0_TYPE,/*36*/ MTK_PULL_PUPD_R1R0_TYPE,/*37*/ - MTK_PULL_PUPD_R1R0_TYPE,/*38*/ MTK_PULL_PUPD_R1R0_TYPE,/*39*/ - MTK_PULL_PU_PD_TYPE,/*40*/ MTK_PULL_PU_PD_TYPE,/*41*/ - MTK_PULL_PU_PD_TYPE,/*42*/ MTK_PULL_PU_PD_TYPE,/*43*/ - MTK_PULL_PU_PD_TYPE,/*44*/ MTK_PULL_PU_PD_TYPE,/*45*/ - MTK_PULL_PU_PD_TYPE,/*46*/ MTK_PULL_PU_PD_TYPE,/*47*/ - MTK_PULL_PU_PD_TYPE,/*48*/ MTK_PULL_PU_PD_TYPE,/*49*/ - MTK_PULL_PU_PD_TYPE,/*50*/ MTK_PULL_PU_PD_TYPE,/*51*/ - MTK_PULL_PU_PD_TYPE,/*52*/ MTK_PULL_PU_PD_TYPE,/*53*/ - MTK_PULL_PU_PD_TYPE,/*54*/ MTK_PULL_PU_PD_TYPE,/*55*/ - MTK_PULL_PU_PD_TYPE,/*56*/ -}; - -static const struct mtk_pin_reg_calc mt7981_reg_cals[] = { - [PINCTRL_PIN_REG_MODE] = MTK_RANGE(mt7981_pin_mode_range), - [PINCTRL_PIN_REG_DIR] = MTK_RANGE(mt7981_pin_dir_range), - [PINCTRL_PIN_REG_DI] = MTK_RANGE(mt7981_pin_di_range), - [PINCTRL_PIN_REG_DO] = MTK_RANGE(mt7981_pin_do_range), - [PINCTRL_PIN_REG_SMT] = MTK_RANGE(mt7981_pin_smt_range), - [PINCTRL_PIN_REG_IES] = MTK_RANGE(mt7981_pin_ies_range), - [PINCTRL_PIN_REG_PU] = MTK_RANGE(mt7981_pin_pu_range), - [PINCTRL_PIN_REG_PD] = MTK_RANGE(mt7981_pin_pd_range), - [PINCTRL_PIN_REG_DRV] = MTK_RANGE(mt7981_pin_drv_range), - [PINCTRL_PIN_REG_PUPD] = MTK_RANGE(mt7981_pin_pupd_range), - [PINCTRL_PIN_REG_R0] = MTK_RANGE(mt7981_pin_r0_range), - [PINCTRL_PIN_REG_R1] = MTK_RANGE(mt7981_pin_r1_range), -}; - -static const struct mtk_pin_desc mt7981_pins[] = { - MT7981_PIN(0, "GPIO_WPS"), - MT7981_PIN(1, "GPIO_RESET"), - MT7981_PIN(2, "SYS_WATCHDOG"), - MT7981_PIN(3, "PCIE_PERESET_N"), - MT7981_PIN(4, "JTAG_JTDO"), - MT7981_PIN(5, "JTAG_JTDI"), - MT7981_PIN(6, "JTAG_JTMS"), - MT7981_PIN(7, "JTAG_JTCLK"), - MT7981_PIN(8, "JTAG_JTRST_N"), - MT7981_PIN(9, "WO_JTAG_JTDO"), - MT7981_PIN(10, "WO_JTAG_JTDI"), - MT7981_PIN(11, "WO_JTAG_JTMS"), - MT7981_PIN(12, "WO_JTAG_JTCLK"), - MT7981_PIN(13, "WO_JTAG_JTRST_N"), - MT7981_PIN(14, "USB_VBUS"), - MT7981_PIN(15, "PWM0"), - MT7981_PIN(16, "SPI0_CLK"), - MT7981_PIN(17, "SPI0_MOSI"), - MT7981_PIN(18, "SPI0_MISO"), - MT7981_PIN(19, "SPI0_CS"), - MT7981_PIN(20, "SPI0_HOLD"), - MT7981_PIN(21, "SPI0_WP"), - MT7981_PIN(22, "SPI1_CLK"), - MT7981_PIN(23, "SPI1_MOSI"), - MT7981_PIN(24, "SPI1_MISO"), - MT7981_PIN(25, "SPI1_CS"), - MT7981_PIN(26, "SPI2_CLK"), - MT7981_PIN(27, "SPI2_MOSI"), - MT7981_PIN(28, "SPI2_MISO"), - MT7981_PIN(29, "SPI2_CS"), - MT7981_PIN(30, "SPI2_HOLD"), - MT7981_PIN(31, "SPI2_WP"), - MT7981_PIN(32, "UART0_RXD"), - MT7981_PIN(33, "UART0_TXD"), - MT7981_PIN(34, "PCIE_CLK_REQ"), - MT7981_PIN(35, "PCIE_WAKE_N"), - MT7981_PIN(36, "SMI_MDC"), - MT7981_PIN(37, "SMI_MDIO"), - MT7981_PIN(38, "GBE_INT"), - MT7981_PIN(39, "GBE_RESET"), - MT7981_PIN(40, "WF_DIG_RESETB"), - MT7981_PIN(41, "WF_CBA_RESETB"), - MT7981_PIN(42, "WF_XO_REQ"), - MT7981_PIN(43, "WF_TOP_CLK"), - MT7981_PIN(44, "WF_TOP_DATA"), - MT7981_PIN(45, "WF_HB1"), - MT7981_PIN(46, "WF_HB2"), - MT7981_PIN(47, "WF_HB3"), - MT7981_PIN(48, "WF_HB4"), - MT7981_PIN(49, "WF_HB0"), - MT7981_PIN(50, "WF_HB0_B"), - MT7981_PIN(51, "WF_HB5"), - MT7981_PIN(52, "WF_HB6"), - MT7981_PIN(53, "WF_HB7"), - MT7981_PIN(54, "WF_HB8"), - MT7981_PIN(55, "WF_HB9"), - MT7981_PIN(56, "WF_HB10"), -}; - -/* List all groups consisting of these pins dedicated to the enablement of - * certain hardware block and the corresponding mode for all of the pins. - * The hardware probably has multiple combinations of these pinouts. - */ - -/* WA_AICE */ -static int mt7981_wa_aice1_pins[] = { 0, 1, }; -static int mt7981_wa_aice1_funcs[] = { 2, 2, }; - -static int mt7981_wa_aice2_pins[] = { 0, 1, }; -static int mt7981_wa_aice2_funcs[] = { 3, 3, }; - -static int mt7981_wa_aice3_pins[] = { 28, 29, }; -static int mt7981_wa_aice3_funcs[] = { 3, 3, }; - -static int mt7981_wm_aice1_pins[] = { 9, 10, }; -static int mt7981_wm_aice1_funcs[] = { 2, 2, }; - -static int mt7981_wm_aice2_pins[] = { 30, 31, }; -static int mt7981_wm_aice2_funcs[] = { 5, 5, }; - -/* WM_UART */ -static int mt7981_wm_uart_0_pins[] = { 0, 1, }; -static int mt7981_wm_uart_0_funcs[] = { 5, 5, }; - -static int mt7981_wm_uart_1_pins[] = { 20, 21, }; -static int mt7981_wm_uart_1_funcs[] = { 4, 4, }; - -static int mt7981_wm_uart_2_pins[] = { 30, 31, }; -static int mt7981_wm_uart_2_funcs[] = { 3, 3, }; - -/* DFD */ -static int mt7981_dfd_pins[] = { 0, 1, 4, 5, }; -static int mt7981_dfd_funcs[] = { 5, 5, 6, 6, }; - -/* SYS_WATCHDOG */ -static int mt7981_watchdog_pins[] = { 2, }; -static int mt7981_watchdog_funcs[] = { 1, }; - -static int mt7981_watchdog1_pins[] = { 13, }; -static int mt7981_watchdog1_funcs[] = { 5, }; - -/* PCIE_PERESET_N */ -static int mt7981_pcie_pereset_pins[] = { 3, }; -static int mt7981_pcie_pereset_funcs[] = { 1, }; - -/* JTAG */ -static int mt7981_jtag_pins[] = { 4, 5, 6, 7, 8, }; -static int mt7981_jtag_funcs[] = { 1, 1, 1, 1, 1, }; - -/* WM_JTAG */ -static int mt7981_wm_jtag_0_pins[] = { 4, 5, 6, 7, 8, }; -static int mt7981_wm_jtag_0_funcs[] = { 2, 2, 2, 2, 2, }; - -static int mt7981_wm_jtag_1_pins[] = { 20, 21, 22, 23, 24, }; -static int mt7981_wm_jtag_1_funcs[] = { 5, 5, 5, 5, 5, }; - -/* WO0_JTAG */ -static int mt7981_wo0_jtag_0_pins[] = { 9, 10, 11, 12, 13, }; -static int mt7981_wo0_jtag_0_funcs[] = { 1, 1, 1, 1, 1, }; - -static int mt7981_wo0_jtag_1_pins[] = { 25, 26, 27, 28, 29, }; -static int mt7981_wo0_jtag_1_funcs[] = { 5, 5, 5, 5, 5, }; - -/* UART2 */ -static int mt7981_uart2_0_pins[] = { 4, 5, 6, 7, }; -static int mt7981_uart2_0_funcs[] = { 3, 3, 3, 3, }; - -static int mt7981_uart2_0_tx_rx_pins[] = { 4, 5, }; -static int mt7981_uart2_0_tx_rx_funcs[] = { 3, 3, }; - -/* GBE_LED0 */ -static int mt7981_gbe_led0_pins[] = { 8, }; -static int mt7981_gbe_led0_funcs[] = { 3, }; - -/* PTA_EXT */ -static int mt7981_pta_ext_0_pins[] = { 4, 5, 6, }; -static int mt7981_pta_ext_0_funcs[] = { 4, 4, 4, }; - -static int mt7981_pta_ext_1_pins[] = { 22, 23, 24, }; -static int mt7981_pta_ext_1_funcs[] = { 4, 4, 4, }; - -/* PWM2 */ -static int mt7981_pwm2_pins[] = { 7, }; -static int mt7981_pwm2_funcs[] = { 4, }; - -/* NET_WO0_UART_TXD */ -static int mt7981_net_wo0_uart_txd_0_pins[] = { 8, }; -static int mt7981_net_wo0_uart_txd_0_funcs[] = { 4, }; - -static int mt7981_net_wo0_uart_txd_1_pins[] = { 14, }; -static int mt7981_net_wo0_uart_txd_1_funcs[] = { 3, }; - -static int mt7981_net_wo0_uart_txd_2_pins[] = { 15, }; -static int mt7981_net_wo0_uart_txd_2_funcs[] = { 4, }; - -/* SPI1 */ -static int mt7981_spi1_0_pins[] = { 4, 5, 6, 7, }; -static int mt7981_spi1_0_funcs[] = { 5, 5, 5, 5, }; - -/* I2C */ -static int mt7981_i2c0_0_pins[] = { 6, 7, }; -static int mt7981_i2c0_0_funcs[] = { 6, 6, }; - -static int mt7981_i2c0_1_pins[] = { 30, 31, }; -static int mt7981_i2c0_1_funcs[] = { 4, 4, }; - -static int mt7981_i2c0_2_pins[] = { 36, 37, }; -static int mt7981_i2c0_2_funcs[] = { 2, 2, }; - -static int mt7981_u2_phy_i2c_pins[] = { 30, 31, }; -static int mt7981_u2_phy_i2c_funcs[] = { 6, 6, }; - -static int mt7981_u3_phy_i2c_pins[] = { 32, 33, }; -static int mt7981_u3_phy_i2c_funcs[] = { 3, 3, }; - -static int mt7981_sgmii1_phy_i2c_pins[] = { 32, 33, }; -static int mt7981_sgmii1_phy_i2c_funcs[] = { 2, 2, }; - -static int mt7981_sgmii0_phy_i2c_pins[] = { 32, 33, }; -static int mt7981_sgmii0_phy_i2c_funcs[] = { 5, 5, }; - -/* DFD_NTRST */ -static int mt7981_dfd_ntrst_pins[] = { 8, }; -static int mt7981_dfd_ntrst_funcs[] = { 6, }; - -/* PWM0 */ -static int mt7981_pwm0_0_pins[] = { 13, }; -static int mt7981_pwm0_0_funcs[] = { 2, }; - -static int mt7981_pwm0_1_pins[] = { 15, }; -static int mt7981_pwm0_1_funcs[] = { 1, }; - -/* PWM1 */ -static int mt7981_pwm1_0_pins[] = { 14, }; -static int mt7981_pwm1_0_funcs[] = { 2, }; - -static int mt7981_pwm1_1_pins[] = { 15, }; -static int mt7981_pwm1_1_funcs[] = { 3, }; - -/* GBE_LED1 */ -static int mt7981_gbe_led1_pins[] = { 13, }; -static int mt7981_gbe_led1_funcs[] = { 3, }; - -/* PCM */ -static int mt7981_pcm_pins[] = { 9, 10, 11, 12, 13, 25 }; -static int mt7981_pcm_funcs[] = { 4, 4, 4, 4, 4, 4, }; - -/* UDI */ -static int mt7981_udi_pins[] = { 9, 10, 11, 12, 13, }; -static int mt7981_udi_funcs[] = { 6, 6, 6, 6, 6, }; - -/* DRV_VBUS */ -static int mt7981_drv_vbus_pins[] = { 14, }; -static int mt7981_drv_vbus_funcs[] = { 1, }; - -/* EMMC */ -static int mt7981_emmc_45_pins[] = { 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, }; -static int mt7981_emmc_45_funcs[] = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, }; - -/* SNFI */ -static int mt7981_snfi_pins[] = { 16, 17, 18, 19, 20, 21, }; -static int mt7981_snfi_funcs[] = { 3, 3, 3, 3, 3, 3, }; - -/* SPI0 */ -static int mt7981_spi0_pins[] = { 16, 17, 18, 19, }; -static int mt7981_spi0_funcs[] = { 1, 1, 1, 1, }; - -/* SPI0 */ -static int mt7981_spi0_wp_hold_pins[] = { 20, 21, }; -static int mt7981_spi0_wp_hold_funcs[] = { 1, 1, }; - -/* SPI1 */ -static int mt7981_spi1_1_pins[] = { 22, 23, 24, 25, }; -static int mt7981_spi1_1_funcs[] = { 1, 1, 1, 1, }; - -/* SPI2 */ -static int mt7981_spi2_pins[] = { 26, 27, 28, 29, }; -static int mt7981_spi2_funcs[] = { 1, 1, 1, 1, }; - -/* SPI2 */ -static int mt7981_spi2_wp_hold_pins[] = { 30, 31, }; -static int mt7981_spi2_wp_hold_funcs[] = { 1, 1, }; - -/* UART1 */ -static int mt7981_uart1_0_pins[] = { 16, 17, 18, 19, }; -static int mt7981_uart1_0_funcs[] = { 4, 4, 4, 4, }; - -static int mt7981_uart1_1_pins[] = { 26, 27, 28, 29, }; -static int mt7981_uart1_1_funcs[] = { 2, 2, 2, 2, }; - -static int mt7981_uart1_2_pins[] = { 9, 10, }; -static int mt7981_uart1_2_funcs[] = { 2, 2, }; - -/* UART2 */ -static int mt7981_uart2_1_pins[] = { 22, 23, 24, 25, }; -static int mt7981_uart2_1_funcs[] = { 3, 3, 3, 3, }; - -/* UART0 */ -static int mt7981_uart0_pins[] = { 32, 33, }; -static int mt7981_uart0_funcs[] = { 1, 1, }; - -/* PCIE_CLK_REQ */ -static int mt7981_pcie_clk_pins[] = { 34, }; -static int mt7981_pcie_clk_funcs[] = { 2, }; - -/* PCIE_WAKE_N */ -static int mt7981_pcie_wake_pins[] = { 35, }; -static int mt7981_pcie_wake_funcs[] = { 2, }; - -/* MDC_MDIO */ -static int mt7981_smi_mdc_mdio_pins[] = { 36, 37, }; -static int mt7981_smi_mdc_mdio_funcs[] = { 1, 1, }; - -static int mt7981_gbe_ext_mdc_mdio_pins[] = { 36, 37, }; -static int mt7981_gbe_ext_mdc_mdio_funcs[] = { 3, 3, }; - -/* WF0_MODE1 */ -static int mt7981_wf0_mode1_pins[] = { 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56 }; -static int mt7981_wf0_mode1_funcs[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; - -/* WF0_MODE3 */ -static int mt7981_wf0_mode3_pins[] = { 45, 46, 47, 48, 49, 51 }; -static int mt7981_wf0_mode3_funcs[] = { 2, 2, 2, 2, 2, 2 }; - -/* WF2G_LED */ -static int mt7981_wf2g_led0_pins[] = { 30, }; -static int mt7981_wf2g_led0_funcs[] = { 2, }; - -static int mt7981_wf2g_led1_pins[] = { 34, }; -static int mt7981_wf2g_led1_funcs[] = { 1, }; - -/* WF5G_LED */ -static int mt7981_wf5g_led0_pins[] = { 31, }; -static int mt7981_wf5g_led0_funcs[] = { 2, }; - -static int mt7981_wf5g_led1_pins[] = { 35, }; -static int mt7981_wf5g_led1_funcs[] = { 1, }; - -/* MT7531_INT */ -static int mt7981_mt7531_int_pins[] = { 38, }; -static int mt7981_mt7531_int_funcs[] = { 1, }; - -/* ANT_SEL */ -static int mt7981_ant_sel_pins[] = { 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 34, 35 }; -static int mt7981_ant_sel_funcs[] = { 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6 }; - -static const struct group_desc mt7981_groups[] = { - /* @GPIO(0,1): WA_AICE(2) */ - PINCTRL_PIN_GROUP("wa_aice1", mt7981_wa_aice1), - /* @GPIO(0,1): WA_AICE(3) */ - PINCTRL_PIN_GROUP("wa_aice2", mt7981_wa_aice2), - /* @GPIO(0,1): WM_UART(5) */ - PINCTRL_PIN_GROUP("wm_uart_0", mt7981_wm_uart_0), - /* @GPIO(0,1,4,5): DFD(6) */ - PINCTRL_PIN_GROUP("dfd", mt7981_dfd), - /* @GPIO(2): SYS_WATCHDOG(1) */ - PINCTRL_PIN_GROUP("watchdog", mt7981_watchdog), - /* @GPIO(3): PCIE_PERESET_N(1) */ - PINCTRL_PIN_GROUP("pcie_pereset", mt7981_pcie_pereset), - /* @GPIO(4,8) JTAG(1) */ - PINCTRL_PIN_GROUP("jtag", mt7981_jtag), - /* @GPIO(4,8) WM_JTAG(2) */ - PINCTRL_PIN_GROUP("wm_jtag_0", mt7981_wm_jtag_0), - /* @GPIO(9,13) WO0_JTAG(1) */ - PINCTRL_PIN_GROUP("wo0_jtag_0", mt7981_wo0_jtag_0), - /* @GPIO(4,7) WM_JTAG(3) */ - PINCTRL_PIN_GROUP("uart2_0", mt7981_uart2_0), - /* @GPIO(4,5) WM_JTAG(4) */ - PINCTRL_PIN_GROUP("uart2_0_tx_rx", mt7981_uart2_0_tx_rx), - /* @GPIO(8) GBE_LED0(3) */ - PINCTRL_PIN_GROUP("gbe_led0", mt7981_gbe_led0), - /* @GPIO(4,6) PTA_EXT(4) */ - PINCTRL_PIN_GROUP("pta_ext_0", mt7981_pta_ext_0), - /* @GPIO(7) PWM2(4) */ - PINCTRL_PIN_GROUP("pwm2", mt7981_pwm2), - /* @GPIO(8) NET_WO0_UART_TXD(4) */ - PINCTRL_PIN_GROUP("net_wo0_uart_txd_0", mt7981_net_wo0_uart_txd_0), - /* @GPIO(4,7) SPI1(5) */ - PINCTRL_PIN_GROUP("spi1_0", mt7981_spi1_0), - /* @GPIO(6,7) I2C(5) */ - PINCTRL_PIN_GROUP("i2c0_0", mt7981_i2c0_0), - /* @GPIO(0,1,4,5): DFD_NTRST(6) */ - PINCTRL_PIN_GROUP("dfd_ntrst", mt7981_dfd_ntrst), - /* @GPIO(9,10): WM_AICE(2) */ - PINCTRL_PIN_GROUP("wm_aice1", mt7981_wm_aice1), - /* @GPIO(13): PWM0(2) */ - PINCTRL_PIN_GROUP("pwm0_0", mt7981_pwm0_0), - /* @GPIO(15): PWM0(1) */ - PINCTRL_PIN_GROUP("pwm0_1", mt7981_pwm0_1), - /* @GPIO(14): PWM1(2) */ - PINCTRL_PIN_GROUP("pwm1_0", mt7981_pwm1_0), - /* @GPIO(15): PWM1(3) */ - PINCTRL_PIN_GROUP("pwm1_1", mt7981_pwm1_1), - /* @GPIO(14) NET_WO0_UART_TXD(3) */ - PINCTRL_PIN_GROUP("net_wo0_uart_txd_1", mt7981_net_wo0_uart_txd_1), - /* @GPIO(15) NET_WO0_UART_TXD(4) */ - PINCTRL_PIN_GROUP("net_wo0_uart_txd_2", mt7981_net_wo0_uart_txd_2), - /* @GPIO(13) GBE_LED0(3) */ - PINCTRL_PIN_GROUP("gbe_led1", mt7981_gbe_led1), - /* @GPIO(9,13) PCM(4) */ - PINCTRL_PIN_GROUP("pcm", mt7981_pcm), - /* @GPIO(13): SYS_WATCHDOG1(5) */ - PINCTRL_PIN_GROUP("watchdog1", mt7981_watchdog1), - /* @GPIO(9,13) UDI(4) */ - PINCTRL_PIN_GROUP("udi", mt7981_udi), - /* @GPIO(14) DRV_VBUS(1) */ - PINCTRL_PIN_GROUP("drv_vbus", mt7981_drv_vbus), - /* @GPIO(15,25): EMMC(2) */ - PINCTRL_PIN_GROUP("emmc_45", mt7981_emmc_45), - /* @GPIO(16,21): SNFI(3) */ - PINCTRL_PIN_GROUP("snfi", mt7981_snfi), - /* @GPIO(16,19): SPI0(1) */ - PINCTRL_PIN_GROUP("spi0", mt7981_spi0), - /* @GPIO(20,21): SPI0(1) */ - PINCTRL_PIN_GROUP("spi0_wp_hold", mt7981_spi0_wp_hold), - /* @GPIO(22,25) SPI1(1) */ - PINCTRL_PIN_GROUP("spi1_1", mt7981_spi1_1), - /* @GPIO(26,29): SPI2(1) */ - PINCTRL_PIN_GROUP("spi2", mt7981_spi2), - /* @GPIO(30,31): SPI0(1) */ - PINCTRL_PIN_GROUP("spi2_wp_hold", mt7981_spi2_wp_hold), - /* @GPIO(16,19): UART1(4) */ - PINCTRL_PIN_GROUP("uart1_0", mt7981_uart1_0), - /* @GPIO(26,29): UART1(2) */ - PINCTRL_PIN_GROUP("uart1_1", mt7981_uart1_1), - /* @GPIO(9,10): UART1(2) */ - PINCTRL_PIN_GROUP("uart1_2", mt7981_uart1_2), - /* @GPIO(22,25): UART1(3) */ - PINCTRL_PIN_GROUP("uart2_1", mt7981_uart2_1), - /* @GPIO(22,24) PTA_EXT(4) */ - PINCTRL_PIN_GROUP("pta_ext_1", mt7981_pta_ext_1), - /* @GPIO(20,21): WM_UART(4) */ - PINCTRL_PIN_GROUP("wm_aurt_1", mt7981_wm_uart_1), - /* @GPIO(30,31): WM_UART(3) */ - PINCTRL_PIN_GROUP("wm_aurt_2", mt7981_wm_uart_2), - /* @GPIO(20,24) WM_JTAG(5) */ - PINCTRL_PIN_GROUP("wm_jtag_1", mt7981_wm_jtag_1), - /* @GPIO(25,29) WO0_JTAG(5) */ - PINCTRL_PIN_GROUP("wo0_jtag_1", mt7981_wo0_jtag_1), - /* @GPIO(28,29): WA_AICE(3) */ - PINCTRL_PIN_GROUP("wa_aice3", mt7981_wa_aice3), - /* @GPIO(30,31): WM_AICE(5) */ - PINCTRL_PIN_GROUP("wm_aice2", mt7981_wm_aice2), - /* @GPIO(30,31): I2C(4) */ - PINCTRL_PIN_GROUP("i2c0_1", mt7981_i2c0_1), - /* @GPIO(30,31): I2C(6) */ - PINCTRL_PIN_GROUP("u2_phy_i2c", mt7981_u2_phy_i2c), - /* @GPIO(32,33): I2C(1) */ - PINCTRL_PIN_GROUP("uart0", mt7981_uart0), - /* @GPIO(32,33): I2C(2) */ - PINCTRL_PIN_GROUP("sgmii1_phy_i2c", mt7981_sgmii1_phy_i2c), - /* @GPIO(32,33): I2C(3) */ - PINCTRL_PIN_GROUP("u3_phy_i2c", mt7981_u3_phy_i2c), - /* @GPIO(32,33): I2C(5) */ - PINCTRL_PIN_GROUP("sgmii0_phy_i2c", mt7981_sgmii0_phy_i2c), - /* @GPIO(34): PCIE_CLK_REQ(2) */ - PINCTRL_PIN_GROUP("pcie_clk", mt7981_pcie_clk), - /* @GPIO(35): PCIE_WAKE_N(2) */ - PINCTRL_PIN_GROUP("pcie_wake", mt7981_pcie_wake), - /* @GPIO(36,37): I2C(2) */ - PINCTRL_PIN_GROUP("i2c0_2", mt7981_i2c0_2), - /* @GPIO(36,37): MDC_MDIO(1) */ - PINCTRL_PIN_GROUP("smi_mdc_mdio", mt7981_smi_mdc_mdio), - /* @GPIO(36,37): MDC_MDIO(3) */ - PINCTRL_PIN_GROUP("gbe_ext_mdc_mdio", mt7981_gbe_ext_mdc_mdio), - /* @GPIO(69,85): WF0_MODE1(1) */ - PINCTRL_PIN_GROUP("wf0_mode1", mt7981_wf0_mode1), - /* @GPIO(74,80): WF0_MODE3(3) */ - PINCTRL_PIN_GROUP("wf0_mode3", mt7981_wf0_mode3), - /* @GPIO(30): WF2G_LED(2) */ - PINCTRL_PIN_GROUP("wf2g_led0", mt7981_wf2g_led0), - /* @GPIO(34): WF2G_LED(1) */ - PINCTRL_PIN_GROUP("wf2g_led1", mt7981_wf2g_led1), - /* @GPIO(31): WF5G_LED(2) */ - PINCTRL_PIN_GROUP("wf5g_led0", mt7981_wf5g_led0), - /* @GPIO(35): WF5G_LED(1) */ - PINCTRL_PIN_GROUP("wf5g_led1", mt7981_wf5g_led1), - /* @GPIO(38): MT7531_INT(1) */ - PINCTRL_PIN_GROUP("mt7531_int", mt7981_mt7531_int), - /* @GPIO(14,15,26,17,18,19,20,21,22,23,24,25,34,35): ANT_SEL(1) */ - PINCTRL_PIN_GROUP("ant_sel", mt7981_ant_sel), -}; - -/* Joint those groups owning the same capability in user point of view which - * allows that people tend to use through the device tree. - */ -static const char *mt7981_wa_aice_groups[] = { "wa_aice1", "wa_aice2", "wm_aice1_1", - "wa_aice3", "wm_aice1_2", }; -static const char *mt7981_uart_groups[] = { "wm_uart_0", "uart2_0", - "uart1_2", "uart2_0_tx_rx", - "net_wo0_uart_txd_0", "net_wo0_uart_txd_1", "net_wo0_uart_txd_2", - "uart1_0", "uart1_1", "uart2_1", "wm_aurt_1", "wm_aurt_2", "uart0", }; -static const char *mt7981_dfd_groups[] = { "dfd", "dfd_ntrst", }; -static const char *mt7981_wdt_groups[] = { "watchdog", "watchdog1", }; -static const char *mt7981_pcie_groups[] = { "pcie_pereset", "pcie_clk", "pcie_wake", }; -static const char *mt7981_jtag_groups[] = { "jtag", "wm_jtag_0", "wo0_jtag_0", - "wo0_jtag_1", "wm_jtag_1", }; -static const char *mt7981_led_groups[] = { "gbe_led0", "gbe_led1", "wf2g_led0", - "wf2g_led1", "wf5g_led0", "wf5g_led1", }; -static const char *mt7981_pta_groups[] = { "pta_ext_0", "pta_ext_1", }; -static const char *mt7981_pwm_groups[] = { "pwm2", "pwm0_0", "pwm0_1", - "pwm1_0", "pwm1_1", }; -static const char *mt7981_spi_groups[] = { "spi1_0", "spi0", "spi0_wp_hold", "spi1_1", "spi2", - "spi2_wp_hold", }; -static const char *mt7981_i2c_groups[] = { "i2c0_0", "i2c0_1", "u2_phy_i2c", - "sgmii1_phy_i2c", "u3_phy_i2c", "sgmii0_phy_i2c", "i2c0_2", }; -static const char *mt7981_pcm_groups[] = { "pcm", }; -static const char *mt7981_udi_groups[] = { "udi", }; -static const char *mt7981_usb_groups[] = { "drv_vbus", }; -static const char *mt7981_flash_groups[] = { "emmc_45", "snfi", }; -static const char *mt7981_ethernet_groups[] = { "smi_mdc_mdio", "gbe_ext_mdc_mdio", - "wf0_mode1", "wf0_mode3", "mt7531_int", }; -static const char *mt7981_ant_groups[] = { "ant_sel", }; - -static const struct function_desc mt7981_functions[] = { - {"wa_aice", mt7981_wa_aice_groups, ARRAY_SIZE(mt7981_wa_aice_groups)}, - {"dfd", mt7981_dfd_groups, ARRAY_SIZE(mt7981_dfd_groups)}, - {"jtag", mt7981_jtag_groups, ARRAY_SIZE(mt7981_jtag_groups)}, - {"pta", mt7981_pta_groups, ARRAY_SIZE(mt7981_pta_groups)}, - {"pcm", mt7981_pcm_groups, ARRAY_SIZE(mt7981_pcm_groups)}, - {"udi", mt7981_udi_groups, ARRAY_SIZE(mt7981_udi_groups)}, - {"usb", mt7981_usb_groups, ARRAY_SIZE(mt7981_usb_groups)}, - {"ant", mt7981_ant_groups, ARRAY_SIZE(mt7981_ant_groups)}, - {"eth", mt7981_ethernet_groups, ARRAY_SIZE(mt7981_ethernet_groups)}, - {"i2c", mt7981_i2c_groups, ARRAY_SIZE(mt7981_i2c_groups)}, - {"led", mt7981_led_groups, ARRAY_SIZE(mt7981_led_groups)}, - {"pwm", mt7981_pwm_groups, ARRAY_SIZE(mt7981_pwm_groups)}, - {"spi", mt7981_spi_groups, ARRAY_SIZE(mt7981_spi_groups)}, - {"uart", mt7981_uart_groups, ARRAY_SIZE(mt7981_uart_groups)}, - {"watchdog", mt7981_wdt_groups, ARRAY_SIZE(mt7981_wdt_groups)}, - {"flash", mt7981_flash_groups, ARRAY_SIZE(mt7981_flash_groups)}, - {"pcie", mt7981_pcie_groups, ARRAY_SIZE(mt7981_pcie_groups)}, -}; - -static const struct mtk_eint_hw mt7981_eint_hw = { - .port_mask = 7, - .ports = 7, - .ap_num = ARRAY_SIZE(mt7981_pins), - .db_cnt = 16, -}; - -static const char * const mt7981_pinctrl_register_base_names[] = { - "gpio", "iocfg_rt", "iocfg_rm", "iocfg_rb", - "iocfg_lb", "iocfg_bl", "iocfg_tm", "iocfg_tl", -}; - -static struct mtk_pin_soc mt7981_data = { - .reg_cal = mt7981_reg_cals, - .pins = mt7981_pins, - .npins = ARRAY_SIZE(mt7981_pins), - .grps = mt7981_groups, - .ngrps = ARRAY_SIZE(mt7981_groups), - .funcs = mt7981_functions, - .nfuncs = ARRAY_SIZE(mt7981_functions), - .eint_hw = &mt7981_eint_hw, - .gpio_m = 0, - .ies_present = false, - .base_names = mt7981_pinctrl_register_base_names, - .nbase_names = ARRAY_SIZE(mt7981_pinctrl_register_base_names), - .bias_disable_set = mtk_pinconf_bias_disable_set, - .bias_disable_get = mtk_pinconf_bias_disable_get, - .bias_set = mtk_pinconf_bias_set, - .bias_get = mtk_pinconf_bias_get, - .pull_type = mt7981_pull_type, - .bias_set_combo = mtk_pinconf_bias_set_combo, - .bias_get_combo = mtk_pinconf_bias_get_combo, - .drive_set = mtk_pinconf_drive_set_rev1, - .drive_get = mtk_pinconf_drive_get_rev1, - .adv_pull_get = mtk_pinconf_adv_pull_get, - .adv_pull_set = mtk_pinconf_adv_pull_set, -}; - -static const struct of_device_id mt7981_pinctrl_of_match[] = { - { .compatible = "mediatek,mt7981-pinctrl", }, - {} -}; - -static int mt7981_pinctrl_probe(struct platform_device *pdev) -{ - return mtk_moore_pinctrl_probe(pdev, &mt7981_data); -} - -static struct platform_driver mt7981_pinctrl_driver = { - .driver = { - .name = "mt7981-pinctrl", - .of_match_table = mt7981_pinctrl_of_match, - }, - .probe = mt7981_pinctrl_probe, -}; - -static int __init mt7981_pinctrl_init(void) -{ - return platform_driver_register(&mt7981_pinctrl_driver); -} -arch_initcall(mt7981_pinctrl_init); diff --git a/target/linux/mediatek/files-5.15/drivers/pinctrl/mediatek/pinctrl-mt7986.c b/target/linux/mediatek/files-5.15/drivers/pinctrl/mediatek/pinctrl-mt7986.c deleted file mode 100644 index acaac9b38..000000000 --- a/target/linux/mediatek/files-5.15/drivers/pinctrl/mediatek/pinctrl-mt7986.c +++ /dev/null @@ -1,1011 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * The MT7986 driver based on Linux generic pinctrl binding. - * - * Copyright (C) 2021 MediaTek Inc. - * Author: Sam Shih - */ - -#include "pinctrl-moore.h" - -#define MT7986_PIN(_number, _name) MTK_PIN(_number, _name, 0, _number, DRV_GRP4) -#define MT7986_NOT_BALLOUT_PIN(_number) { .number = _number, .name = NULL } - -#define PIN_FIELD_BASE(_s_pin, _e_pin, _i_base, _s_addr, _x_addrs, _s_bit, \ - _x_bits) \ - PIN_FIELD_CALC(_s_pin, _e_pin, _i_base, _s_addr, _x_addrs, _s_bit, \ - _x_bits, 32, 0) - -/** - * enum - Locking variants of the iocfg bases - * - * MT7986 have multiple bases to program pin configuration listed as the below: - * iocfg_rt:0x11c30000, iocfg_rb:0x11c40000, iocfg_lt:0x11e20000, - * iocfg_lb:0x11e30000, iocfg_tr:0x11f00000, iocfg_tl:0x11f10000, - * _i_based could be used to indicate what base the pin should be mapped into. - * - * Each iocfg register base control different group of pads on the SoC - * - * - * chip carrier - * - * A B C D E F G H - * +------------------------+ - * 8 | o o o o o o o o | - * 7 | o o o o o o o o | - * 6 | o o o o o o o o | - * 5 | o o o o o o o o | - * 4 | o o o o o o o o | - * 3 | o o o o o o o o | - * 2 | o o o o o o o o | - * 1 | o o o o o o o o | - * +------------------------+ - * - * inside Chip carrier - * - * A B C D E F G H - * +------------------------+ - * 8 | | - * 7 | TL TR | - * 6 | +---------+ | - * 5 | LT | | RT | - * 4 | | | | - * 3 | LB | | RB | - * 2 | +---------+ | - * 1 | | - * +------------------------+ - * - */ - -enum { - GPIO_BASE, - IOCFG_RT_BASE, - IOCFG_RB_BASE, - IOCFG_LT_BASE, - IOCFG_LB_BASE, - IOCFG_TR_BASE, - IOCFG_TL_BASE, -}; - -static const char *const mt7986_pinctrl_register_base_names[] = { - "gpio", "iocfg_rt", "iocfg_rb", "iocfg_lt", "iocfg_lb", "iocfg_tr", - "iocfg_tl", -}; - -static const struct mtk_pin_field_calc mt7986_pin_mode_range[] = { - PIN_FIELD(0, 100, 0x300, 0x10, 0, 4), -}; - -static const struct mtk_pin_field_calc mt7986_pin_dir_range[] = { - PIN_FIELD(0, 100, 0x0, 0x10, 0, 1), -}; - -static const struct mtk_pin_field_calc mt7986_pin_di_range[] = { - PIN_FIELD(0, 100, 0x200, 0x10, 0, 1), -}; - -static const struct mtk_pin_field_calc mt7986_pin_do_range[] = { - PIN_FIELD(0, 100, 0x100, 0x10, 0, 1), -}; - -static const struct mtk_pin_field_calc mt7986_pin_ies_range[] = { - PIN_FIELD_BASE(0, 0, IOCFG_RB_BASE, 0x40, 0x10, 17, 1), - PIN_FIELD_BASE(1, 2, IOCFG_LT_BASE, 0x20, 0x10, 10, 1), - PIN_FIELD_BASE(3, 4, IOCFG_LB_BASE, 0x20, 0x10, 0, 1), - PIN_FIELD_BASE(5, 6, IOCFG_RB_BASE, 0x40, 0x10, 0, 1), - PIN_FIELD_BASE(7, 10, IOCFG_LT_BASE, 0x20, 0x10, 0, 1), - PIN_FIELD_BASE(11, 14, IOCFG_RB_BASE, 0x40, 0x10, 8, 1), - PIN_FIELD_BASE(15, 20, IOCFG_RB_BASE, 0x40, 0x10, 2, 1), - PIN_FIELD_BASE(21, 23, IOCFG_RT_BASE, 0x30, 0x10, 12, 1), - PIN_FIELD_BASE(24, 24, IOCFG_RT_BASE, 0x30, 0x10, 18, 1), - PIN_FIELD_BASE(25, 25, IOCFG_RT_BASE, 0x30, 0x10, 17, 1), - PIN_FIELD_BASE(26, 27, IOCFG_RT_BASE, 0x30, 0x10, 15, 1), - PIN_FIELD_BASE(28, 29, IOCFG_RT_BASE, 0x30, 0x10, 19, 1), - PIN_FIELD_BASE(30, 30, IOCFG_RT_BASE, 0x30, 0x10, 23, 1), - PIN_FIELD_BASE(31, 31, IOCFG_RT_BASE, 0x30, 0x10, 22, 1), - PIN_FIELD_BASE(32, 32, IOCFG_RT_BASE, 0x30, 0x10, 21, 1), - PIN_FIELD_BASE(33, 33, IOCFG_LT_BASE, 0x20, 0x10, 4, 1), - PIN_FIELD_BASE(34, 34, IOCFG_LT_BASE, 0x20, 0x10, 8, 1), - PIN_FIELD_BASE(35, 35, IOCFG_LT_BASE, 0x20, 0x10, 7, 1), - PIN_FIELD_BASE(36, 37, IOCFG_LT_BASE, 0x20, 0x10, 5, 1), - PIN_FIELD_BASE(38, 38, IOCFG_LT_BASE, 0x20, 0x10, 9, 1), - PIN_FIELD_BASE(39, 40, IOCFG_RB_BASE, 0x40, 0x10, 18, 1), - PIN_FIELD_BASE(41, 41, IOCFG_RB_BASE, 0x40, 0x10, 12, 1), - PIN_FIELD_BASE(42, 43, IOCFG_RB_BASE, 0x40, 0x10, 22, 1), - PIN_FIELD_BASE(44, 45, IOCFG_RB_BASE, 0x40, 0x10, 20, 1), - PIN_FIELD_BASE(46, 47, IOCFG_RB_BASE, 0x40, 0x10, 26, 1), - PIN_FIELD_BASE(48, 49, IOCFG_RB_BASE, 0x40, 0x10, 24, 1), - PIN_FIELD_BASE(50, 57, IOCFG_RT_BASE, 0x30, 0x10, 2, 1), - PIN_FIELD_BASE(58, 58, IOCFG_RT_BASE, 0x30, 0x10, 1, 1), - PIN_FIELD_BASE(59, 59, IOCFG_RT_BASE, 0x30, 0x10, 0, 1), - PIN_FIELD_BASE(60, 61, IOCFG_RT_BASE, 0x30, 0x10, 10, 1), - PIN_FIELD_BASE(62, 62, IOCFG_RB_BASE, 0x40, 0x10, 15, 1), - PIN_FIELD_BASE(63, 63, IOCFG_RB_BASE, 0x40, 0x10, 14, 1), - PIN_FIELD_BASE(64, 64, IOCFG_RB_BASE, 0x40, 0x10, 13, 1), - PIN_FIELD_BASE(65, 65, IOCFG_RB_BASE, 0x40, 0x10, 16, 1), - PIN_FIELD_BASE(66, 68, IOCFG_LB_BASE, 0x20, 0x10, 2, 1), - PIN_FIELD_BASE(69, 69, IOCFG_TR_BASE, 0x30, 0x10, 1, 1), - PIN_FIELD_BASE(70, 70, IOCFG_TR_BASE, 0x30, 0x10, 0, 1), - PIN_FIELD_BASE(71, 71, IOCFG_TR_BASE, 0x30, 0x10, 16, 1), - PIN_FIELD_BASE(72, 73, IOCFG_TR_BASE, 0x30, 0x10, 14, 1), - PIN_FIELD_BASE(74, 74, IOCFG_TR_BASE, 0x30, 0x10, 4, 1), - PIN_FIELD_BASE(75, 77, IOCFG_TR_BASE, 0x30, 0x10, 6, 1), - PIN_FIELD_BASE(78, 79, IOCFG_TR_BASE, 0x30, 0x10, 2, 1), - PIN_FIELD_BASE(80, 84, IOCFG_TR_BASE, 0x30, 0x10, 9, 1), - PIN_FIELD_BASE(85, 85, IOCFG_TR_BASE, 0x30, 0x10, 5, 1), - PIN_FIELD_BASE(86, 86, IOCFG_TL_BASE, 0x30, 0x10, 1, 1), - PIN_FIELD_BASE(87, 87, IOCFG_TL_BASE, 0x30, 0x10, 0, 1), - PIN_FIELD_BASE(88, 88, IOCFG_TL_BASE, 0x30, 0x10, 14, 1), - PIN_FIELD_BASE(89, 90, IOCFG_TL_BASE, 0x30, 0x10, 12, 1), - PIN_FIELD_BASE(91, 94, IOCFG_TL_BASE, 0x30, 0x10, 4, 1), - PIN_FIELD_BASE(95, 96, IOCFG_TL_BASE, 0x30, 0x10, 2, 1), - PIN_FIELD_BASE(97, 100, IOCFG_TL_BASE, 0x30, 0x10, 8, 1), -}; - -static const struct mtk_pin_field_calc mt7986_pin_smt_range[] = { - PIN_FIELD_BASE(0, 0, IOCFG_RB_BASE, 0xf0, 0x10, 17, 1), - PIN_FIELD_BASE(1, 2, IOCFG_LT_BASE, 0x90, 0x10, 10, 1), - PIN_FIELD_BASE(3, 4, IOCFG_LB_BASE, 0x90, 0x10, 0, 1), - PIN_FIELD_BASE(5, 6, IOCFG_RB_BASE, 0xf0, 0x10, 0, 1), - PIN_FIELD_BASE(7, 10, IOCFG_LT_BASE, 0x90, 0x10, 0, 1), - PIN_FIELD_BASE(11, 14, IOCFG_RB_BASE, 0xf0, 0x10, 8, 1), - PIN_FIELD_BASE(15, 20, IOCFG_RB_BASE, 0xf0, 0x10, 2, 1), - PIN_FIELD_BASE(21, 23, IOCFG_RT_BASE, 0xc0, 0x10, 12, 1), - PIN_FIELD_BASE(24, 24, IOCFG_RT_BASE, 0xc0, 0x10, 18, 1), - PIN_FIELD_BASE(25, 25, IOCFG_RT_BASE, 0xc0, 0x10, 17, 1), - PIN_FIELD_BASE(26, 27, IOCFG_RT_BASE, 0xc0, 0x10, 15, 1), - PIN_FIELD_BASE(28, 29, IOCFG_RT_BASE, 0xc0, 0x10, 19, 1), - PIN_FIELD_BASE(30, 30, IOCFG_RT_BASE, 0xc0, 0x10, 23, 1), - PIN_FIELD_BASE(31, 31, IOCFG_RT_BASE, 0xc0, 0x10, 22, 1), - PIN_FIELD_BASE(32, 32, IOCFG_RT_BASE, 0xc0, 0x10, 21, 1), - PIN_FIELD_BASE(33, 33, IOCFG_LT_BASE, 0x90, 0x10, 4, 1), - PIN_FIELD_BASE(34, 34, IOCFG_LT_BASE, 0x90, 0x10, 8, 1), - PIN_FIELD_BASE(35, 35, IOCFG_LT_BASE, 0x90, 0x10, 7, 1), - PIN_FIELD_BASE(36, 37, IOCFG_LT_BASE, 0x90, 0x10, 5, 1), - PIN_FIELD_BASE(38, 38, IOCFG_LT_BASE, 0x90, 0x10, 9, 1), - PIN_FIELD_BASE(39, 40, IOCFG_RB_BASE, 0xf0, 0x10, 18, 1), - PIN_FIELD_BASE(41, 41, IOCFG_RB_BASE, 0xf0, 0x10, 12, 1), - PIN_FIELD_BASE(42, 43, IOCFG_RB_BASE, 0xf0, 0x10, 22, 1), - PIN_FIELD_BASE(44, 45, IOCFG_RB_BASE, 0xf0, 0x10, 20, 1), - PIN_FIELD_BASE(46, 47, IOCFG_RB_BASE, 0xf0, 0x10, 26, 1), - PIN_FIELD_BASE(48, 49, IOCFG_RB_BASE, 0xf0, 0x10, 24, 1), - PIN_FIELD_BASE(50, 57, IOCFG_RT_BASE, 0xc0, 0x10, 2, 1), - PIN_FIELD_BASE(58, 58, IOCFG_RT_BASE, 0xc0, 0x10, 1, 1), - PIN_FIELD_BASE(59, 59, IOCFG_RT_BASE, 0xc0, 0x10, 0, 1), - PIN_FIELD_BASE(60, 61, IOCFG_RT_BASE, 0xc0, 0x10, 10, 1), - PIN_FIELD_BASE(62, 62, IOCFG_RB_BASE, 0xf0, 0x10, 15, 1), - PIN_FIELD_BASE(63, 63, IOCFG_RB_BASE, 0xf0, 0x10, 14, 1), - PIN_FIELD_BASE(64, 64, IOCFG_RB_BASE, 0xf0, 0x10, 13, 1), - PIN_FIELD_BASE(65, 65, IOCFG_RB_BASE, 0xf0, 0x10, 16, 1), - PIN_FIELD_BASE(66, 68, IOCFG_LB_BASE, 0x90, 0x10, 2, 1), - PIN_FIELD_BASE(69, 69, IOCFG_TR_BASE, 0x80, 0x10, 1, 1), - PIN_FIELD_BASE(70, 70, IOCFG_TR_BASE, 0x80, 0x10, 0, 1), - PIN_FIELD_BASE(71, 71, IOCFG_TR_BASE, 0x80, 0x10, 16, 1), - PIN_FIELD_BASE(72, 73, IOCFG_TR_BASE, 0x80, 0x10, 14, 1), - PIN_FIELD_BASE(74, 74, IOCFG_TR_BASE, 0x80, 0x10, 4, 1), - PIN_FIELD_BASE(75, 77, IOCFG_TR_BASE, 0x80, 0x10, 6, 1), - PIN_FIELD_BASE(78, 79, IOCFG_TR_BASE, 0x80, 0x10, 2, 1), - PIN_FIELD_BASE(80, 84, IOCFG_TR_BASE, 0x80, 0x10, 9, 1), - PIN_FIELD_BASE(85, 85, IOCFG_TR_BASE, 0x80, 0x10, 5, 1), - PIN_FIELD_BASE(86, 86, IOCFG_TL_BASE, 0x70, 0x10, 1, 1), - PIN_FIELD_BASE(87, 87, IOCFG_TL_BASE, 0x70, 0x10, 0, 1), - PIN_FIELD_BASE(88, 88, IOCFG_TL_BASE, 0x70, 0x10, 14, 1), - PIN_FIELD_BASE(89, 90, IOCFG_TL_BASE, 0x70, 0x10, 12, 1), - PIN_FIELD_BASE(91, 94, IOCFG_TL_BASE, 0x70, 0x10, 4, 1), - PIN_FIELD_BASE(95, 96, IOCFG_TL_BASE, 0x70, 0x10, 2, 1), - PIN_FIELD_BASE(97, 100, IOCFG_TL_BASE, 0x70, 0x10, 8, 1), -}; - -static const struct mtk_pin_field_calc mt7986_pin_pu_range[] = { - PIN_FIELD_BASE(69, 69, IOCFG_TR_BASE, 0x50, 0x10, 1, 1), - PIN_FIELD_BASE(70, 70, IOCFG_TR_BASE, 0x50, 0x10, 0, 1), - PIN_FIELD_BASE(71, 71, IOCFG_TR_BASE, 0x50, 0x10, 16, 1), - PIN_FIELD_BASE(72, 73, IOCFG_TR_BASE, 0x50, 0x10, 14, 1), - PIN_FIELD_BASE(74, 74, IOCFG_TR_BASE, 0x50, 0x10, 4, 1), - PIN_FIELD_BASE(75, 77, IOCFG_TR_BASE, 0x50, 0x10, 6, 1), - PIN_FIELD_BASE(78, 79, IOCFG_TR_BASE, 0x50, 0x10, 2, 1), - PIN_FIELD_BASE(80, 84, IOCFG_TR_BASE, 0x50, 0x10, 9, 1), - PIN_FIELD_BASE(85, 85, IOCFG_TR_BASE, 0x50, 0x10, 5, 1), - PIN_FIELD_BASE(86, 86, IOCFG_TL_BASE, 0x50, 0x10, 1, 1), - PIN_FIELD_BASE(87, 87, IOCFG_TL_BASE, 0x50, 0x10, 0, 1), - PIN_FIELD_BASE(88, 88, IOCFG_TL_BASE, 0x50, 0x10, 14, 1), - PIN_FIELD_BASE(89, 90, IOCFG_TL_BASE, 0x50, 0x10, 12, 1), - PIN_FIELD_BASE(91, 94, IOCFG_TL_BASE, 0x50, 0x10, 4, 1), - PIN_FIELD_BASE(95, 96, IOCFG_TL_BASE, 0x50, 0x10, 2, 1), - PIN_FIELD_BASE(97, 100, IOCFG_TL_BASE, 0x50, 0x10, 8, 1), -}; - -static const struct mtk_pin_field_calc mt7986_pin_pd_range[] = { - PIN_FIELD_BASE(69, 69, IOCFG_TR_BASE, 0x40, 0x10, 1, 1), - PIN_FIELD_BASE(70, 70, IOCFG_TR_BASE, 0x40, 0x10, 0, 1), - PIN_FIELD_BASE(71, 71, IOCFG_TR_BASE, 0x40, 0x10, 16, 1), - PIN_FIELD_BASE(72, 73, IOCFG_TR_BASE, 0x40, 0x10, 14, 1), - PIN_FIELD_BASE(74, 74, IOCFG_TR_BASE, 0x40, 0x10, 4, 1), - PIN_FIELD_BASE(75, 77, IOCFG_TR_BASE, 0x40, 0x10, 6, 1), - PIN_FIELD_BASE(78, 79, IOCFG_TR_BASE, 0x40, 0x10, 2, 1), - PIN_FIELD_BASE(80, 84, IOCFG_TR_BASE, 0x40, 0x10, 9, 1), - PIN_FIELD_BASE(85, 85, IOCFG_TR_BASE, 0x40, 0x10, 5, 1), - PIN_FIELD_BASE(86, 86, IOCFG_TL_BASE, 0x40, 0x10, 1, 1), - PIN_FIELD_BASE(87, 87, IOCFG_TL_BASE, 0x40, 0x10, 0, 1), - PIN_FIELD_BASE(88, 88, IOCFG_TL_BASE, 0x40, 0x10, 14, 1), - PIN_FIELD_BASE(89, 90, IOCFG_TL_BASE, 0x40, 0x10, 12, 1), - PIN_FIELD_BASE(91, 94, IOCFG_TL_BASE, 0x40, 0x10, 4, 1), - PIN_FIELD_BASE(95, 96, IOCFG_TL_BASE, 0x40, 0x10, 2, 1), - PIN_FIELD_BASE(97, 100, IOCFG_TL_BASE, 0x40, 0x10, 8, 1), -}; - -static const struct mtk_pin_field_calc mt7986_pin_drv_range[] = { - PIN_FIELD_BASE(0, 0, IOCFG_RB_BASE, 0x10, 0x10, 21, 3), - PIN_FIELD_BASE(1, 2, IOCFG_LT_BASE, 0x10, 0x10, 0, 3), - PIN_FIELD_BASE(3, 4, IOCFG_LB_BASE, 0x00, 0x10, 0, 1), - PIN_FIELD_BASE(5, 5, IOCFG_RB_BASE, 0x00, 0x10, 0, 3), - PIN_FIELD_BASE(6, 6, IOCFG_RB_BASE, 0x00, 0x10, 21, 3), - PIN_FIELD_BASE(7, 10, IOCFG_LT_BASE, 0x00, 0x10, 0, 3), - PIN_FIELD_BASE(11, 12, IOCFG_RB_BASE, 0x00, 0x10, 24, 3), - PIN_FIELD_BASE(13, 14, IOCFG_RB_BASE, 0x10, 0x10, 0, 3), - PIN_FIELD_BASE(15, 20, IOCFG_RB_BASE, 0x00, 0x10, 3, 3), - PIN_FIELD_BASE(21, 23, IOCFG_RT_BASE, 0x10, 0x10, 6, 3), - PIN_FIELD_BASE(24, 24, IOCFG_RT_BASE, 0x10, 0x10, 24, 3), - PIN_FIELD_BASE(25, 25, IOCFG_RT_BASE, 0x10, 0x10, 21, 3), - PIN_FIELD_BASE(26, 27, IOCFG_RT_BASE, 0x10, 0x10, 15, 3), - PIN_FIELD_BASE(28, 28, IOCFG_RT_BASE, 0x10, 0x10, 27, 3), - PIN_FIELD_BASE(29, 29, IOCFG_RT_BASE, 0x20, 0x10, 0, 3), - PIN_FIELD_BASE(30, 30, IOCFG_RT_BASE, 0x20, 0x10, 9, 3), - PIN_FIELD_BASE(31, 31, IOCFG_RT_BASE, 0x20, 0x10, 6, 3), - PIN_FIELD_BASE(32, 32, IOCFG_RT_BASE, 0x20, 0x10, 3, 3), - PIN_FIELD_BASE(33, 33, IOCFG_LT_BASE, 0x00, 0x10, 12, 3), - PIN_FIELD_BASE(34, 34, IOCFG_LT_BASE, 0x00, 0x10, 24, 3), - PIN_FIELD_BASE(35, 35, IOCFG_LT_BASE, 0x00, 0x10, 21, 3), - PIN_FIELD_BASE(36, 37, IOCFG_LT_BASE, 0x00, 0x10, 15, 3), - PIN_FIELD_BASE(38, 38, IOCFG_LT_BASE, 0x00, 0x10, 27, 3), - PIN_FIELD_BASE(39, 39, IOCFG_RB_BASE, 0x10, 0x10, 27, 3), - PIN_FIELD_BASE(40, 40, IOCFG_RB_BASE, 0x20, 0x10, 0, 3), - PIN_FIELD_BASE(41, 41, IOCFG_RB_BASE, 0x10, 0x10, 6, 3), - PIN_FIELD_BASE(42, 43, IOCFG_RB_BASE, 0x20, 0x10, 9, 3), - PIN_FIELD_BASE(44, 45, IOCFG_RB_BASE, 0x20, 0x10, 3, 3), - PIN_FIELD_BASE(46, 47, IOCFG_RB_BASE, 0x20, 0x10, 21, 3), - PIN_FIELD_BASE(48, 49, IOCFG_RB_BASE, 0x20, 0x10, 15, 3), - PIN_FIELD_BASE(50, 57, IOCFG_RT_BASE, 0x00, 0x10, 6, 3), - PIN_FIELD_BASE(58, 58, IOCFG_RT_BASE, 0x00, 0x10, 3, 3), - PIN_FIELD_BASE(59, 59, IOCFG_RT_BASE, 0x00, 0x10, 0, 3), - PIN_FIELD_BASE(60, 61, IOCFG_RT_BASE, 0x10, 0x10, 0, 3), - PIN_FIELD_BASE(62, 62, IOCFG_RB_BASE, 0x10, 0x10, 15, 3), - PIN_FIELD_BASE(63, 63, IOCFG_RB_BASE, 0x10, 0x10, 12, 3), - PIN_FIELD_BASE(64, 64, IOCFG_RB_BASE, 0x10, 0x10, 9, 3), - PIN_FIELD_BASE(65, 65, IOCFG_RB_BASE, 0x10, 0x10, 18, 3), - PIN_FIELD_BASE(66, 68, IOCFG_LB_BASE, 0x00, 0x10, 2, 3), - PIN_FIELD_BASE(69, 69, IOCFG_TR_BASE, 0x00, 0x10, 3, 3), - PIN_FIELD_BASE(70, 70, IOCFG_TR_BASE, 0x00, 0x10, 0, 3), - PIN_FIELD_BASE(71, 71, IOCFG_TR_BASE, 0x10, 0x10, 18, 3), - PIN_FIELD_BASE(72, 73, IOCFG_TR_BASE, 0x10, 0x10, 12, 3), - PIN_FIELD_BASE(74, 77, IOCFG_TR_BASE, 0x00, 0x10, 15, 3), - PIN_FIELD_BASE(78, 79, IOCFG_TR_BASE, 0x00, 0x10, 6, 3), - PIN_FIELD_BASE(80, 80, IOCFG_TR_BASE, 0x00, 0x10, 27, 3), - PIN_FIELD_BASE(81, 84, IOCFG_TR_BASE, 0x10, 0x10, 0, 3), - PIN_FIELD_BASE(85, 85, IOCFG_TR_BASE, 0x00, 0x10, 12, 3), - PIN_FIELD_BASE(86, 86, IOCFG_TL_BASE, 0x00, 0x10, 3, 3), - PIN_FIELD_BASE(87, 87, IOCFG_TL_BASE, 0x00, 0x10, 0, 3), - PIN_FIELD_BASE(88, 88, IOCFG_TL_BASE, 0x10, 0x10, 12, 3), - PIN_FIELD_BASE(89, 90, IOCFG_TL_BASE, 0x10, 0x10, 6, 3), - PIN_FIELD_BASE(91, 94, IOCFG_TL_BASE, 0x00, 0x10, 12, 3), - PIN_FIELD_BASE(95, 96, IOCFG_TL_BASE, 0x00, 0x10, 6, 3), - PIN_FIELD_BASE(97, 98, IOCFG_TL_BASE, 0x00, 0x10, 24, 3), - PIN_FIELD_BASE(99, 100, IOCFG_TL_BASE, 0x10, 0x10, 2, 3), -}; - -static const struct mtk_pin_field_calc mt7986_pin_pupd_range[] = { - PIN_FIELD_BASE(0, 0, IOCFG_RB_BASE, 0x60, 0x10, 17, 1), - PIN_FIELD_BASE(1, 2, IOCFG_LT_BASE, 0x30, 0x10, 10, 1), - PIN_FIELD_BASE(3, 4, IOCFG_LB_BASE, 0x40, 0x10, 0, 1), - PIN_FIELD_BASE(5, 6, IOCFG_RB_BASE, 0x60, 0x10, 0, 1), - PIN_FIELD_BASE(7, 10, IOCFG_LT_BASE, 0x30, 0x10, 0, 1), - PIN_FIELD_BASE(11, 14, IOCFG_RB_BASE, 0x60, 0x10, 8, 1), - PIN_FIELD_BASE(15, 20, IOCFG_RB_BASE, 0x60, 0x10, 2, 1), - PIN_FIELD_BASE(21, 23, IOCFG_RT_BASE, 0x40, 0x10, 12, 1), - PIN_FIELD_BASE(24, 24, IOCFG_RT_BASE, 0x40, 0x10, 18, 1), - PIN_FIELD_BASE(25, 25, IOCFG_RT_BASE, 0x40, 0x10, 17, 1), - PIN_FIELD_BASE(26, 27, IOCFG_RT_BASE, 0x40, 0x10, 15, 1), - PIN_FIELD_BASE(28, 29, IOCFG_RT_BASE, 0x40, 0x10, 19, 1), - PIN_FIELD_BASE(30, 30, IOCFG_RT_BASE, 0x40, 0x10, 23, 1), - PIN_FIELD_BASE(31, 31, IOCFG_RT_BASE, 0x40, 0x10, 22, 1), - PIN_FIELD_BASE(32, 32, IOCFG_RT_BASE, 0x40, 0x10, 21, 1), - PIN_FIELD_BASE(33, 33, IOCFG_LT_BASE, 0x30, 0x10, 4, 1), - PIN_FIELD_BASE(34, 34, IOCFG_LT_BASE, 0x30, 0x10, 8, 1), - PIN_FIELD_BASE(35, 35, IOCFG_LT_BASE, 0x30, 0x10, 7, 1), - PIN_FIELD_BASE(36, 37, IOCFG_LT_BASE, 0x30, 0x10, 5, 1), - PIN_FIELD_BASE(38, 38, IOCFG_LT_BASE, 0x30, 0x10, 9, 1), - PIN_FIELD_BASE(39, 40, IOCFG_RB_BASE, 0x60, 0x10, 18, 1), - PIN_FIELD_BASE(41, 41, IOCFG_RB_BASE, 0x60, 0x10, 12, 1), - PIN_FIELD_BASE(42, 43, IOCFG_RB_BASE, 0x60, 0x10, 23, 1), - PIN_FIELD_BASE(44, 45, IOCFG_RB_BASE, 0x60, 0x10, 21, 1), - PIN_FIELD_BASE(46, 47, IOCFG_RB_BASE, 0x60, 0x10, 27, 1), - PIN_FIELD_BASE(48, 49, IOCFG_RB_BASE, 0x60, 0x10, 25, 1), - PIN_FIELD_BASE(50, 57, IOCFG_RT_BASE, 0x40, 0x10, 2, 1), - PIN_FIELD_BASE(58, 58, IOCFG_RT_BASE, 0x40, 0x10, 1, 1), - PIN_FIELD_BASE(59, 59, IOCFG_RT_BASE, 0x40, 0x10, 0, 1), - PIN_FIELD_BASE(60, 61, IOCFG_RT_BASE, 0x40, 0x10, 10, 1), - PIN_FIELD_BASE(62, 62, IOCFG_RB_BASE, 0x60, 0x10, 15, 1), - PIN_FIELD_BASE(63, 63, IOCFG_RB_BASE, 0x60, 0x10, 14, 1), - PIN_FIELD_BASE(64, 64, IOCFG_RB_BASE, 0x60, 0x10, 13, 1), - PIN_FIELD_BASE(65, 65, IOCFG_RB_BASE, 0x60, 0x10, 16, 1), - PIN_FIELD_BASE(66, 68, IOCFG_LB_BASE, 0x40, 0x10, 2, 1), -}; - -static const struct mtk_pin_field_calc mt7986_pin_r0_range[] = { - PIN_FIELD_BASE(0, 0, IOCFG_RB_BASE, 0x70, 0x10, 17, 1), - PIN_FIELD_BASE(1, 2, IOCFG_LT_BASE, 0x40, 0x10, 10, 1), - PIN_FIELD_BASE(3, 4, IOCFG_LB_BASE, 0x50, 0x10, 0, 1), - PIN_FIELD_BASE(5, 6, IOCFG_RB_BASE, 0x70, 0x10, 0, 1), - PIN_FIELD_BASE(7, 10, IOCFG_LT_BASE, 0x40, 0x10, 0, 1), - PIN_FIELD_BASE(11, 14, IOCFG_RB_BASE, 0x70, 0x10, 8, 1), - PIN_FIELD_BASE(15, 20, IOCFG_RB_BASE, 0x70, 0x10, 2, 1), - PIN_FIELD_BASE(21, 23, IOCFG_RT_BASE, 0x50, 0x10, 12, 1), - PIN_FIELD_BASE(24, 24, IOCFG_RT_BASE, 0x50, 0x10, 18, 1), - PIN_FIELD_BASE(25, 25, IOCFG_RT_BASE, 0x50, 0x10, 17, 1), - PIN_FIELD_BASE(26, 27, IOCFG_RT_BASE, 0x50, 0x10, 15, 1), - PIN_FIELD_BASE(28, 29, IOCFG_RT_BASE, 0x50, 0x10, 19, 1), - PIN_FIELD_BASE(30, 30, IOCFG_RT_BASE, 0x50, 0x10, 23, 1), - PIN_FIELD_BASE(31, 31, IOCFG_RT_BASE, 0x50, 0x10, 22, 1), - PIN_FIELD_BASE(32, 32, IOCFG_RT_BASE, 0x50, 0x10, 21, 1), - PIN_FIELD_BASE(33, 33, IOCFG_LT_BASE, 0x40, 0x10, 4, 1), - PIN_FIELD_BASE(34, 34, IOCFG_LT_BASE, 0x40, 0x10, 8, 1), - PIN_FIELD_BASE(35, 35, IOCFG_LT_BASE, 0x40, 0x10, 7, 1), - PIN_FIELD_BASE(36, 37, IOCFG_LT_BASE, 0x40, 0x10, 5, 1), - PIN_FIELD_BASE(38, 38, IOCFG_LT_BASE, 0x40, 0x10, 9, 1), - PIN_FIELD_BASE(39, 40, IOCFG_RB_BASE, 0x70, 0x10, 18, 1), - PIN_FIELD_BASE(41, 41, IOCFG_RB_BASE, 0x70, 0x10, 12, 1), - PIN_FIELD_BASE(42, 43, IOCFG_RB_BASE, 0x70, 0x10, 23, 1), - PIN_FIELD_BASE(44, 45, IOCFG_RB_BASE, 0x70, 0x10, 21, 1), - PIN_FIELD_BASE(46, 47, IOCFG_RB_BASE, 0x70, 0x10, 27, 1), - PIN_FIELD_BASE(48, 49, IOCFG_RB_BASE, 0x70, 0x10, 25, 1), - PIN_FIELD_BASE(50, 57, IOCFG_RT_BASE, 0x50, 0x10, 2, 1), - PIN_FIELD_BASE(58, 58, IOCFG_RT_BASE, 0x50, 0x10, 1, 1), - PIN_FIELD_BASE(59, 59, IOCFG_RT_BASE, 0x50, 0x10, 0, 1), - PIN_FIELD_BASE(60, 61, IOCFG_RT_BASE, 0x50, 0x10, 10, 1), - PIN_FIELD_BASE(62, 62, IOCFG_RB_BASE, 0x70, 0x10, 15, 1), - PIN_FIELD_BASE(63, 63, IOCFG_RB_BASE, 0x70, 0x10, 14, 1), - PIN_FIELD_BASE(64, 64, IOCFG_RB_BASE, 0x70, 0x10, 13, 1), - PIN_FIELD_BASE(65, 65, IOCFG_RB_BASE, 0x70, 0x10, 16, 1), - PIN_FIELD_BASE(66, 68, IOCFG_LB_BASE, 0x50, 0x10, 2, 1), -}; - -static const struct mtk_pin_field_calc mt7986_pin_r1_range[] = { - PIN_FIELD_BASE(0, 0, IOCFG_RB_BASE, 0x80, 0x10, 17, 1), - PIN_FIELD_BASE(1, 2, IOCFG_LT_BASE, 0x50, 0x10, 10, 1), - PIN_FIELD_BASE(3, 4, IOCFG_LB_BASE, 0x60, 0x10, 0, 1), - PIN_FIELD_BASE(5, 6, IOCFG_RB_BASE, 0x80, 0x10, 0, 1), - PIN_FIELD_BASE(7, 10, IOCFG_LT_BASE, 0x50, 0x10, 0, 1), - PIN_FIELD_BASE(11, 14, IOCFG_RB_BASE, 0x80, 0x10, 8, 1), - PIN_FIELD_BASE(15, 20, IOCFG_RB_BASE, 0x80, 0x10, 2, 1), - PIN_FIELD_BASE(21, 23, IOCFG_RT_BASE, 0x60, 0x10, 12, 1), - PIN_FIELD_BASE(24, 24, IOCFG_RT_BASE, 0x60, 0x10, 18, 1), - PIN_FIELD_BASE(25, 25, IOCFG_RT_BASE, 0x60, 0x10, 17, 1), - PIN_FIELD_BASE(26, 27, IOCFG_RT_BASE, 0x60, 0x10, 15, 1), - PIN_FIELD_BASE(28, 29, IOCFG_RT_BASE, 0x60, 0x10, 19, 1), - PIN_FIELD_BASE(30, 30, IOCFG_RT_BASE, 0x60, 0x10, 23, 1), - PIN_FIELD_BASE(31, 31, IOCFG_RT_BASE, 0x60, 0x10, 22, 1), - PIN_FIELD_BASE(32, 32, IOCFG_RT_BASE, 0x60, 0x10, 21, 1), - PIN_FIELD_BASE(33, 33, IOCFG_LT_BASE, 0x50, 0x10, 4, 1), - PIN_FIELD_BASE(34, 34, IOCFG_LT_BASE, 0x50, 0x10, 8, 1), - PIN_FIELD_BASE(35, 35, IOCFG_LT_BASE, 0x50, 0x10, 7, 1), - PIN_FIELD_BASE(36, 37, IOCFG_LT_BASE, 0x50, 0x10, 5, 1), - PIN_FIELD_BASE(38, 38, IOCFG_LT_BASE, 0x50, 0x10, 9, 1), - PIN_FIELD_BASE(39, 40, IOCFG_RB_BASE, 0x80, 0x10, 18, 1), - PIN_FIELD_BASE(41, 41, IOCFG_RB_BASE, 0x80, 0x10, 12, 1), - PIN_FIELD_BASE(42, 43, IOCFG_RB_BASE, 0x80, 0x10, 23, 1), - PIN_FIELD_BASE(44, 45, IOCFG_RB_BASE, 0x80, 0x10, 21, 1), - PIN_FIELD_BASE(46, 47, IOCFG_RB_BASE, 0x80, 0x10, 27, 1), - PIN_FIELD_BASE(48, 49, IOCFG_RB_BASE, 0x80, 0x10, 25, 1), - PIN_FIELD_BASE(50, 57, IOCFG_RT_BASE, 0x60, 0x10, 2, 1), - PIN_FIELD_BASE(58, 58, IOCFG_RT_BASE, 0x60, 0x10, 1, 1), - PIN_FIELD_BASE(59, 59, IOCFG_RT_BASE, 0x60, 0x10, 0, 1), - PIN_FIELD_BASE(60, 61, IOCFG_RT_BASE, 0x60, 0x10, 10, 1), - PIN_FIELD_BASE(62, 62, IOCFG_RB_BASE, 0x80, 0x10, 15, 1), - PIN_FIELD_BASE(63, 63, IOCFG_RB_BASE, 0x80, 0x10, 14, 1), - PIN_FIELD_BASE(64, 64, IOCFG_RB_BASE, 0x80, 0x10, 13, 1), - PIN_FIELD_BASE(65, 65, IOCFG_RB_BASE, 0x80, 0x10, 16, 1), - PIN_FIELD_BASE(66, 68, IOCFG_LB_BASE, 0x60, 0x10, 2, 1), -}; - -static const unsigned int mt7986_pull_type[] = { - MTK_PULL_PUPD_R1R0_TYPE,/*0*/ MTK_PULL_PUPD_R1R0_TYPE,/*1*/ - MTK_PULL_PUPD_R1R0_TYPE,/*2*/ MTK_PULL_PUPD_R1R0_TYPE,/*3*/ - MTK_PULL_PUPD_R1R0_TYPE,/*4*/ MTK_PULL_PUPD_R1R0_TYPE,/*5*/ - MTK_PULL_PUPD_R1R0_TYPE,/*6*/ MTK_PULL_PUPD_R1R0_TYPE,/*7*/ - MTK_PULL_PUPD_R1R0_TYPE,/*8*/ MTK_PULL_PUPD_R1R0_TYPE,/*9*/ - MTK_PULL_PUPD_R1R0_TYPE,/*10*/ MTK_PULL_PUPD_R1R0_TYPE,/*11*/ - MTK_PULL_PUPD_R1R0_TYPE,/*12*/ MTK_PULL_PUPD_R1R0_TYPE,/*13*/ - MTK_PULL_PUPD_R1R0_TYPE,/*14*/ MTK_PULL_PUPD_R1R0_TYPE,/*15*/ - MTK_PULL_PUPD_R1R0_TYPE,/*16*/ MTK_PULL_PUPD_R1R0_TYPE,/*17*/ - MTK_PULL_PUPD_R1R0_TYPE,/*18*/ MTK_PULL_PUPD_R1R0_TYPE,/*19*/ - MTK_PULL_PUPD_R1R0_TYPE,/*20*/ MTK_PULL_PUPD_R1R0_TYPE,/*21*/ - MTK_PULL_PUPD_R1R0_TYPE,/*22*/ MTK_PULL_PUPD_R1R0_TYPE,/*23*/ - MTK_PULL_PUPD_R1R0_TYPE,/*24*/ MTK_PULL_PUPD_R1R0_TYPE,/*25*/ - MTK_PULL_PUPD_R1R0_TYPE,/*26*/ MTK_PULL_PUPD_R1R0_TYPE,/*27*/ - MTK_PULL_PUPD_R1R0_TYPE,/*28*/ MTK_PULL_PUPD_R1R0_TYPE,/*29*/ - MTK_PULL_PUPD_R1R0_TYPE,/*30*/ MTK_PULL_PUPD_R1R0_TYPE,/*31*/ - MTK_PULL_PUPD_R1R0_TYPE,/*32*/ MTK_PULL_PUPD_R1R0_TYPE,/*33*/ - MTK_PULL_PUPD_R1R0_TYPE,/*34*/ MTK_PULL_PUPD_R1R0_TYPE,/*35*/ - MTK_PULL_PUPD_R1R0_TYPE,/*36*/ MTK_PULL_PUPD_R1R0_TYPE,/*37*/ - MTK_PULL_PUPD_R1R0_TYPE,/*38*/ MTK_PULL_PUPD_R1R0_TYPE,/*39*/ - MTK_PULL_PUPD_R1R0_TYPE,/*40*/ MTK_PULL_PUPD_R1R0_TYPE,/*41*/ - MTK_PULL_PUPD_R1R0_TYPE,/*42*/ MTK_PULL_PUPD_R1R0_TYPE,/*43*/ - MTK_PULL_PUPD_R1R0_TYPE,/*44*/ MTK_PULL_PUPD_R1R0_TYPE,/*45*/ - MTK_PULL_PUPD_R1R0_TYPE,/*46*/ MTK_PULL_PUPD_R1R0_TYPE,/*47*/ - MTK_PULL_PUPD_R1R0_TYPE,/*48*/ MTK_PULL_PUPD_R1R0_TYPE,/*49*/ - MTK_PULL_PUPD_R1R0_TYPE,/*50*/ MTK_PULL_PUPD_R1R0_TYPE,/*51*/ - MTK_PULL_PUPD_R1R0_TYPE,/*52*/ MTK_PULL_PUPD_R1R0_TYPE,/*53*/ - MTK_PULL_PUPD_R1R0_TYPE,/*54*/ MTK_PULL_PUPD_R1R0_TYPE,/*55*/ - MTK_PULL_PUPD_R1R0_TYPE,/*56*/ MTK_PULL_PUPD_R1R0_TYPE,/*57*/ - MTK_PULL_PUPD_R1R0_TYPE,/*58*/ MTK_PULL_PUPD_R1R0_TYPE,/*59*/ - MTK_PULL_PUPD_R1R0_TYPE,/*60*/ MTK_PULL_PUPD_R1R0_TYPE,/*61*/ - MTK_PULL_PUPD_R1R0_TYPE,/*62*/ MTK_PULL_PUPD_R1R0_TYPE,/*63*/ - MTK_PULL_PUPD_R1R0_TYPE,/*64*/ MTK_PULL_PUPD_R1R0_TYPE,/*65*/ - MTK_PULL_PUPD_R1R0_TYPE,/*66*/ MTK_PULL_PUPD_R1R0_TYPE,/*67*/ - MTK_PULL_PUPD_R1R0_TYPE,/*68*/ MTK_PULL_PU_PD_TYPE,/*69*/ - MTK_PULL_PU_PD_TYPE,/*70*/ MTK_PULL_PU_PD_TYPE,/*71*/ - MTK_PULL_PU_PD_TYPE,/*72*/ MTK_PULL_PU_PD_TYPE,/*73*/ - MTK_PULL_PU_PD_TYPE,/*74*/ MTK_PULL_PU_PD_TYPE,/*75*/ - MTK_PULL_PU_PD_TYPE,/*76*/ MTK_PULL_PU_PD_TYPE,/*77*/ - MTK_PULL_PU_PD_TYPE,/*78*/ MTK_PULL_PU_PD_TYPE,/*79*/ - MTK_PULL_PU_PD_TYPE,/*80*/ MTK_PULL_PU_PD_TYPE,/*81*/ - MTK_PULL_PU_PD_TYPE,/*82*/ MTK_PULL_PU_PD_TYPE,/*83*/ - MTK_PULL_PU_PD_TYPE,/*84*/ MTK_PULL_PU_PD_TYPE,/*85*/ - MTK_PULL_PU_PD_TYPE,/*86*/ MTK_PULL_PU_PD_TYPE,/*87*/ - MTK_PULL_PU_PD_TYPE,/*88*/ MTK_PULL_PU_PD_TYPE,/*89*/ - MTK_PULL_PU_PD_TYPE,/*90*/ MTK_PULL_PU_PD_TYPE,/*91*/ - MTK_PULL_PU_PD_TYPE,/*92*/ MTK_PULL_PU_PD_TYPE,/*93*/ - MTK_PULL_PU_PD_TYPE,/*94*/ MTK_PULL_PU_PD_TYPE,/*95*/ - MTK_PULL_PU_PD_TYPE,/*96*/ MTK_PULL_PU_PD_TYPE,/*97*/ - MTK_PULL_PU_PD_TYPE,/*98*/ MTK_PULL_PU_PD_TYPE,/*99*/ - MTK_PULL_PU_PD_TYPE,/*100*/ -}; - -static const struct mtk_pin_reg_calc mt7986_reg_cals[] = { - [PINCTRL_PIN_REG_MODE] = MTK_RANGE(mt7986_pin_mode_range), - [PINCTRL_PIN_REG_DIR] = MTK_RANGE(mt7986_pin_dir_range), - [PINCTRL_PIN_REG_DI] = MTK_RANGE(mt7986_pin_di_range), - [PINCTRL_PIN_REG_DO] = MTK_RANGE(mt7986_pin_do_range), - [PINCTRL_PIN_REG_SMT] = MTK_RANGE(mt7986_pin_smt_range), - [PINCTRL_PIN_REG_IES] = MTK_RANGE(mt7986_pin_ies_range), - [PINCTRL_PIN_REG_DRV] = MTK_RANGE(mt7986_pin_drv_range), - [PINCTRL_PIN_REG_PU] = MTK_RANGE(mt7986_pin_pu_range), - [PINCTRL_PIN_REG_PD] = MTK_RANGE(mt7986_pin_pd_range), - [PINCTRL_PIN_REG_PUPD] = MTK_RANGE(mt7986_pin_pupd_range), - [PINCTRL_PIN_REG_R0] = MTK_RANGE(mt7986_pin_r0_range), - [PINCTRL_PIN_REG_R1] = MTK_RANGE(mt7986_pin_r1_range), -}; - -static const struct mtk_pin_desc mt7986a_pins[] = { - MT7986_PIN(0, "SYS_WATCHDOG"), - MT7986_PIN(1, "WF2G_LED"), - MT7986_PIN(2, "WF5G_LED"), - MT7986_PIN(3, "I2C_SCL"), - MT7986_PIN(4, "I2C_SDA"), - MT7986_PIN(5, "GPIO_0"), - MT7986_PIN(6, "GPIO_1"), - MT7986_PIN(7, "GPIO_2"), - MT7986_PIN(8, "GPIO_3"), - MT7986_PIN(9, "GPIO_4"), - MT7986_PIN(10, "GPIO_5"), - MT7986_PIN(11, "GPIO_6"), - MT7986_PIN(12, "GPIO_7"), - MT7986_PIN(13, "GPIO_8"), - MT7986_PIN(14, "GPIO_9"), - MT7986_PIN(15, "GPIO_10"), - MT7986_PIN(16, "GPIO_11"), - MT7986_PIN(17, "GPIO_12"), - MT7986_PIN(18, "GPIO_13"), - MT7986_PIN(19, "GPIO_14"), - MT7986_PIN(20, "GPIO_15"), - MT7986_PIN(21, "PWM0"), - MT7986_PIN(22, "PWM1"), - MT7986_PIN(23, "SPI0_CLK"), - MT7986_PIN(24, "SPI0_MOSI"), - MT7986_PIN(25, "SPI0_MISO"), - MT7986_PIN(26, "SPI0_CS"), - MT7986_PIN(27, "SPI0_HOLD"), - MT7986_PIN(28, "SPI0_WP"), - MT7986_PIN(29, "SPI1_CLK"), - MT7986_PIN(30, "SPI1_MOSI"), - MT7986_PIN(31, "SPI1_MISO"), - MT7986_PIN(32, "SPI1_CS"), - MT7986_PIN(33, "SPI2_CLK"), - MT7986_PIN(34, "SPI2_MOSI"), - MT7986_PIN(35, "SPI2_MISO"), - MT7986_PIN(36, "SPI2_CS"), - MT7986_PIN(37, "SPI2_HOLD"), - MT7986_PIN(38, "SPI2_WP"), - MT7986_PIN(39, "UART0_RXD"), - MT7986_PIN(40, "UART0_TXD"), - MT7986_PIN(41, "PCIE_PERESET_N"), - MT7986_PIN(42, "UART1_RXD"), - MT7986_PIN(43, "UART1_TXD"), - MT7986_PIN(44, "UART1_CTS"), - MT7986_PIN(45, "UART1_RTS"), - MT7986_PIN(46, "UART2_RXD"), - MT7986_PIN(47, "UART2_TXD"), - MT7986_PIN(48, "UART2_CTS"), - MT7986_PIN(49, "UART2_RTS"), - MT7986_PIN(50, "EMMC_DATA_0"), - MT7986_PIN(51, "EMMC_DATA_1"), - MT7986_PIN(52, "EMMC_DATA_2"), - MT7986_PIN(53, "EMMC_DATA_3"), - MT7986_PIN(54, "EMMC_DATA_4"), - MT7986_PIN(55, "EMMC_DATA_5"), - MT7986_PIN(56, "EMMC_DATA_6"), - MT7986_PIN(57, "EMMC_DATA_7"), - MT7986_PIN(58, "EMMC_CMD"), - MT7986_PIN(59, "EMMC_CK"), - MT7986_PIN(60, "EMMC_DSL"), - MT7986_PIN(61, "EMMC_RSTB"), - MT7986_PIN(62, "PCM_DTX"), - MT7986_PIN(63, "PCM_DRX"), - MT7986_PIN(64, "PCM_CLK"), - MT7986_PIN(65, "PCM_FS"), - MT7986_PIN(66, "MT7531_INT"), - MT7986_PIN(67, "SMI_MDC"), - MT7986_PIN(68, "SMI_MDIO"), - MT7986_PIN(69, "WF0_DIG_RESETB"), - MT7986_PIN(70, "WF0_CBA_RESETB"), - MT7986_PIN(71, "WF0_XO_REQ"), - MT7986_PIN(72, "WF0_TOP_CLK"), - MT7986_PIN(73, "WF0_TOP_DATA"), - MT7986_PIN(74, "WF0_HB1"), - MT7986_PIN(75, "WF0_HB2"), - MT7986_PIN(76, "WF0_HB3"), - MT7986_PIN(77, "WF0_HB4"), - MT7986_PIN(78, "WF0_HB0"), - MT7986_PIN(79, "WF0_HB0_B"), - MT7986_PIN(80, "WF0_HB5"), - MT7986_PIN(81, "WF0_HB6"), - MT7986_PIN(82, "WF0_HB7"), - MT7986_PIN(83, "WF0_HB8"), - MT7986_PIN(84, "WF0_HB9"), - MT7986_PIN(85, "WF0_HB10"), - MT7986_PIN(86, "WF1_DIG_RESETB"), - MT7986_PIN(87, "WF1_CBA_RESETB"), - MT7986_PIN(88, "WF1_XO_REQ"), - MT7986_PIN(89, "WF1_TOP_CLK"), - MT7986_PIN(90, "WF1_TOP_DATA"), - MT7986_PIN(91, "WF1_HB1"), - MT7986_PIN(92, "WF1_HB2"), - MT7986_PIN(93, "WF1_HB3"), - MT7986_PIN(94, "WF1_HB4"), - MT7986_PIN(95, "WF1_HB0"), - MT7986_PIN(96, "WF1_HB0_B"), - MT7986_PIN(97, "WF1_HB5"), - MT7986_PIN(98, "WF1_HB6"), - MT7986_PIN(99, "WF1_HB7"), - MT7986_PIN(100, "WF1_HB8"), -}; - -static const struct mtk_pin_desc mt7986b_pins[] = { - MT7986_PIN(0, "SYS_WATCHDOG"), - MT7986_PIN(1, "WF2G_LED"), - MT7986_PIN(2, "WF5G_LED"), - MT7986_PIN(3, "I2C_SCL"), - MT7986_PIN(4, "I2C_SDA"), - MT7986_PIN(5, "GPIO_0"), - MT7986_PIN(6, "GPIO_1"), - MT7986_PIN(7, "GPIO_2"), - MT7986_PIN(8, "GPIO_3"), - MT7986_PIN(9, "GPIO_4"), - MT7986_PIN(10, "GPIO_5"), - MT7986_PIN(11, "GPIO_6"), - MT7986_PIN(12, "GPIO_7"), - MT7986_PIN(13, "GPIO_8"), - MT7986_PIN(14, "GPIO_9"), - MT7986_PIN(15, "GPIO_10"), - MT7986_PIN(16, "GPIO_11"), - MT7986_PIN(17, "GPIO_12"), - MT7986_PIN(18, "GPIO_13"), - MT7986_PIN(19, "GPIO_14"), - MT7986_PIN(20, "GPIO_15"), - MT7986_PIN(21, "PWM0"), - MT7986_PIN(22, "PWM1"), - MT7986_PIN(23, "SPI0_CLK"), - MT7986_PIN(24, "SPI0_MOSI"), - MT7986_PIN(25, "SPI0_MISO"), - MT7986_PIN(26, "SPI0_CS"), - MT7986_PIN(27, "SPI0_HOLD"), - MT7986_PIN(28, "SPI0_WP"), - MT7986_PIN(29, "SPI1_CLK"), - MT7986_PIN(30, "SPI1_MOSI"), - MT7986_PIN(31, "SPI1_MISO"), - MT7986_PIN(32, "SPI1_CS"), - MT7986_PIN(33, "SPI2_CLK"), - MT7986_PIN(34, "SPI2_MOSI"), - MT7986_PIN(35, "SPI2_MISO"), - MT7986_PIN(36, "SPI2_CS"), - MT7986_PIN(37, "SPI2_HOLD"), - MT7986_PIN(38, "SPI2_WP"), - MT7986_PIN(39, "UART0_RXD"), - MT7986_PIN(40, "UART0_TXD"), - MT7986_NOT_BALLOUT_PIN(41), - MT7986_NOT_BALLOUT_PIN(42), - MT7986_NOT_BALLOUT_PIN(43), - MT7986_NOT_BALLOUT_PIN(44), - MT7986_NOT_BALLOUT_PIN(45), - MT7986_NOT_BALLOUT_PIN(46), - MT7986_NOT_BALLOUT_PIN(47), - MT7986_NOT_BALLOUT_PIN(48), - MT7986_NOT_BALLOUT_PIN(49), - MT7986_NOT_BALLOUT_PIN(50), - MT7986_NOT_BALLOUT_PIN(51), - MT7986_NOT_BALLOUT_PIN(52), - MT7986_NOT_BALLOUT_PIN(53), - MT7986_NOT_BALLOUT_PIN(54), - MT7986_NOT_BALLOUT_PIN(55), - MT7986_NOT_BALLOUT_PIN(56), - MT7986_NOT_BALLOUT_PIN(57), - MT7986_NOT_BALLOUT_PIN(58), - MT7986_NOT_BALLOUT_PIN(59), - MT7986_NOT_BALLOUT_PIN(60), - MT7986_NOT_BALLOUT_PIN(61), - MT7986_NOT_BALLOUT_PIN(62), - MT7986_NOT_BALLOUT_PIN(63), - MT7986_NOT_BALLOUT_PIN(64), - MT7986_NOT_BALLOUT_PIN(65), - MT7986_PIN(66, "MT7531_INT"), - MT7986_PIN(67, "SMI_MDC"), - MT7986_PIN(68, "SMI_MDIO"), - MT7986_PIN(69, "WF0_DIG_RESETB"), - MT7986_PIN(70, "WF0_CBA_RESETB"), - MT7986_PIN(71, "WF0_XO_REQ"), - MT7986_PIN(72, "WF0_TOP_CLK"), - MT7986_PIN(73, "WF0_TOP_DATA"), - MT7986_PIN(74, "WF0_HB1"), - MT7986_PIN(75, "WF0_HB2"), - MT7986_PIN(76, "WF0_HB3"), - MT7986_PIN(77, "WF0_HB4"), - MT7986_PIN(78, "WF0_HB0"), - MT7986_PIN(79, "WF0_HB0_B"), - MT7986_PIN(80, "WF0_HB5"), - MT7986_PIN(81, "WF0_HB6"), - MT7986_PIN(82, "WF0_HB7"), - MT7986_PIN(83, "WF0_HB8"), - MT7986_PIN(84, "WF0_HB9"), - MT7986_PIN(85, "WF0_HB10"), - MT7986_PIN(86, "WF1_DIG_RESETB"), - MT7986_PIN(87, "WF1_CBA_RESETB"), - MT7986_PIN(88, "WF1_XO_REQ"), - MT7986_PIN(89, "WF1_TOP_CLK"), - MT7986_PIN(90, "WF1_TOP_DATA"), - MT7986_PIN(91, "WF1_HB1"), - MT7986_PIN(92, "WF1_HB2"), - MT7986_PIN(93, "WF1_HB3"), - MT7986_PIN(94, "WF1_HB4"), - MT7986_PIN(95, "WF1_HB0"), - MT7986_PIN(96, "WF1_HB0_B"), - MT7986_PIN(97, "WF1_HB5"), - MT7986_PIN(98, "WF1_HB6"), - MT7986_PIN(99, "WF1_HB7"), - MT7986_PIN(100, "WF1_HB8"), -}; - -/* List all groups consisting of these pins dedicated to the enablement of - * certain hardware block and the corresponding mode for all of the pins. - * The hardware probably has multiple combinations of these pinouts. - */ - -static int mt7986_watchdog_pins[] = { 0, }; -static int mt7986_watchdog_funcs[] = { 1, }; - -static int mt7986_wifi_led_pins[] = { 1, 2, }; -static int mt7986_wifi_led_funcs[] = { 1, 1, }; - -static int mt7986_i2c_pins[] = { 3, 4, }; -static int mt7986_i2c_funcs[] = { 1, 1, }; - -static int mt7986_uart1_0_pins[] = { 7, 8, 9, 10, }; -static int mt7986_uart1_0_funcs[] = { 3, 3, 3, 3, }; - -static int mt7986_spi1_0_pins[] = { 11, 12, 13, 14, }; -static int mt7986_spi1_0_funcs[] = { 3, 3, 3, 3, }; - -static int mt7986_pwm1_1_pins[] = { 20, }; -static int mt7986_pwm1_1_funcs[] = { 2, }; - -static int mt7986_pwm0_pins[] = { 21, }; -static int mt7986_pwm0_funcs[] = { 1, }; - -static int mt7986_pwm1_0_pins[] = { 22, }; -static int mt7986_pwm1_0_funcs[] = { 1, }; - -static int mt7986_emmc_45_pins[] = { - 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, }; -static int mt7986_emmc_45_funcs[] = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, }; - -static int mt7986_snfi_pins[] = { 23, 24, 25, 26, 27, 28, }; -static int mt7986_snfi_funcs[] = { 1, 1, 1, 1, 1, 1, }; - -static int mt7986_spi1_1_pins[] = { 23, 24, 25, 26, }; -static int mt7986_spi1_1_funcs[] = { 3, 3, 3, 3, }; - -static int mt7986_uart1_1_pins[] = { 23, 24, 25, 26, }; -static int mt7986_uart1_1_funcs[] = { 4, 4, 4, 4, }; - -static int mt7986_spi1_2_pins[] = { 29, 30, 31, 32, }; -static int mt7986_spi1_2_funcs[] = { 1, 1, 1, 1, }; - -static int mt7986_uart1_2_rx_tx_pins[] = { 29, 30, }; -static int mt7986_uart1_2_rx_tx_funcs[] = { 3, 3, }; - -static int mt7986_uart1_2_cts_rts_pins[] = { 31, 32, }; -static int mt7986_uart1_2_cts_rts_funcs[] = { 3, 3, }; - -static int mt7986_uart2_0_rx_tx_pins[] = { 29, 30, }; -static int mt7986_uart2_0_rx_tx_funcs[] = { 4, 4, }; - -static int mt7986_uart2_0_cts_rts_pins[] = { 31, 32, }; -static int mt7986_uart2_0_cts_rts_funcs[] = { 4, 4, }; - -static int mt7986_spi0_pins[] = { 33, 34, 35, 36, }; -static int mt7986_spi0_funcs[] = { 1, 1, 1, 1, }; - -static int mt7986_spi0_wp_hold_pins[] = { 37, 38, }; -static int mt7986_spi0_wp_hold_funcs[] = { 1, 1, }; - -static int mt7986_uart2_1_pins[] = { 33, 34, 35, 36, }; -static int mt7986_uart2_1_funcs[] = { 3, 3, 3, 3, }; - -static int mt7986_uart1_3_rx_tx_pins[] = { 35, 36, }; -static int mt7986_uart1_3_rx_tx_funcs[] = { 2, 2, }; - -static int mt7986_uart1_3_cts_rts_pins[] = { 37, 38, }; -static int mt7986_uart1_3_cts_rts_funcs[] = { 2, 2, }; - -static int mt7986_spi1_3_pins[] = { 33, 34, 35, 36, }; -static int mt7986_spi1_3_funcs[] = { 4, 4, 4, 4, }; - -static int mt7986_uart0_pins[] = { 39, 40, }; -static int mt7986_uart0_funcs[] = { 1, 1, }; - -static int mt7986_pcie_reset_pins[] = { 41, }; -static int mt7986_pcie_reset_funcs[] = { 1, }; - -static int mt7986_uart1_pins[] = { 42, 43, 44, 45, }; -static int mt7986_uart1_funcs[] = { 1, 1, 1, 1, }; - -static int mt7986_uart1_rx_tx_pins[] = { 42, 43, }; -static int mt7986_uart1_rx_tx_funcs[] = { 1, 1, }; - -static int mt7986_uart1_cts_rts_pins[] = { 44, 45, }; -static int mt7986_uart1_cts_rts_funcs[] = { 1, 1, }; - -static int mt7986_uart2_pins[] = { 46, 47, 48, 49, }; -static int mt7986_uart2_funcs[] = { 1, 1, 1, 1, }; - -static int mt7986_emmc_51_pins[] = { - 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, }; -static int mt7986_emmc_51_funcs[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, }; - -static int mt7986_pcm_pins[] = { 62, 63, 64, 65, }; -static int mt7986_pcm_funcs[] = { 1, 1, 1, 1, }; - -static int mt7986_i2s_pins[] = { 62, 63, 64, 65, }; -static int mt7986_i2s_funcs[] = { 1, 1, 1, 1, }; - -static int mt7986_switch_int_pins[] = { 66, }; -static int mt7986_switch_int_funcs[] = { 1, }; - -static int mt7986_mdc_mdio_pins[] = { 67, 68, }; -static int mt7986_mdc_mdio_funcs[] = { 1, 1, }; - -static int mt7986_wf_2g_pins[] = {74, 75, 76, 77, 78, 79, 80, 81, 82, 83, }; -static int mt7986_wf_2g_funcs[] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, }; - -static int mt7986_wf_5g_pins[] = {91, 92, 93, 94, 95, 96, 97, 98, 99, 100, }; -static int mt7986_wf_5g_funcs[] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, }; - -static int mt7986_wf_dbdc_pins[] = { - 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, }; -static int mt7986_wf_dbdc_funcs[] = { - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, }; - -static int mt7986_pcie_clk_pins[] = { 9, }; -static int mt7986_pcie_clk_funcs[] = { 1, }; - -static int mt7986_pcie_wake_pins[] = { 10, }; -static int mt7986_pcie_wake_funcs[] = { 1, }; - -static const struct group_desc mt7986_groups[] = { - PINCTRL_PIN_GROUP("watchdog", mt7986_watchdog), - PINCTRL_PIN_GROUP("wifi_led", mt7986_wifi_led), - PINCTRL_PIN_GROUP("i2c", mt7986_i2c), - PINCTRL_PIN_GROUP("uart1_0", mt7986_uart1_0), - PINCTRL_PIN_GROUP("uart1_rx_tx", mt7986_uart1_rx_tx), - PINCTRL_PIN_GROUP("uart1_cts_rts", mt7986_uart1_cts_rts), - PINCTRL_PIN_GROUP("pcie_clk", mt7986_pcie_clk), - PINCTRL_PIN_GROUP("pcie_wake", mt7986_pcie_wake), - PINCTRL_PIN_GROUP("spi1_0", mt7986_spi1_0), - PINCTRL_PIN_GROUP("pwm1_1", mt7986_pwm1_1), - PINCTRL_PIN_GROUP("pwm0", mt7986_pwm0), - PINCTRL_PIN_GROUP("pwm1_0", mt7986_pwm1_0), - PINCTRL_PIN_GROUP("emmc_45", mt7986_emmc_45), - PINCTRL_PIN_GROUP("snfi", mt7986_snfi), - PINCTRL_PIN_GROUP("spi1_1", mt7986_spi1_1), - PINCTRL_PIN_GROUP("uart1_1", mt7986_uart1_1), - PINCTRL_PIN_GROUP("spi1_2", mt7986_spi1_2), - PINCTRL_PIN_GROUP("uart1_2_rx_tx", mt7986_uart1_2_rx_tx), - PINCTRL_PIN_GROUP("uart1_2_cts_rts", mt7986_uart1_2_cts_rts), - PINCTRL_PIN_GROUP("uart2_0_rx_tx", mt7986_uart2_0_rx_tx), - PINCTRL_PIN_GROUP("uart2_0_cts_rts", mt7986_uart2_0_cts_rts), - PINCTRL_PIN_GROUP("spi0", mt7986_spi0), - PINCTRL_PIN_GROUP("spi0_wp_hold", mt7986_spi0_wp_hold), - PINCTRL_PIN_GROUP("uart2_1", mt7986_uart2_1), - PINCTRL_PIN_GROUP("uart1_3_rx_tx", mt7986_uart1_3_rx_tx), - PINCTRL_PIN_GROUP("uart1_3_cts_rts", mt7986_uart1_3_cts_rts), - PINCTRL_PIN_GROUP("spi1_3", mt7986_spi1_3), - PINCTRL_PIN_GROUP("uart0", mt7986_uart0), - PINCTRL_PIN_GROUP("switch_int", mt7986_switch_int), - PINCTRL_PIN_GROUP("mdc_mdio", mt7986_mdc_mdio), - PINCTRL_PIN_GROUP("pcie_pereset", mt7986_pcie_reset), - PINCTRL_PIN_GROUP("uart1", mt7986_uart1), - PINCTRL_PIN_GROUP("uart2", mt7986_uart2), - PINCTRL_PIN_GROUP("emmc_51", mt7986_emmc_51), - PINCTRL_PIN_GROUP("pcm", mt7986_pcm), - PINCTRL_PIN_GROUP("i2s", mt7986_i2s), - PINCTRL_PIN_GROUP("wf_2g", mt7986_wf_2g), - PINCTRL_PIN_GROUP("wf_5g", mt7986_wf_5g), - PINCTRL_PIN_GROUP("wf_dbdc", mt7986_wf_dbdc), -}; - -/* Joint those groups owning the same capability in user point of view which - * allows that people tend to use through the device tree. - */ - -static const char *mt7986_audio_groups[] = { "pcm", "i2s" }; -static const char *mt7986_emmc_groups[] = { - "emmc_45", "emmc_51", }; -static const char *mt7986_ethernet_groups[] = { - "switch_int", "mdc_mdio", }; -static const char *mt7986_i2c_groups[] = { "i2c", }; -static const char *mt7986_led_groups[] = { "wifi_led", }; -static const char *mt7986_flash_groups[] = { "snfi", }; -static const char *mt7986_pcie_groups[] = { - "pcie_clk", "pcie_wake", "pcie_pereset" }; -static const char *mt7986_pwm_groups[] = { "pwm0", "pwm1_0", "pwm1_1", }; -static const char *mt7986_spi_groups[] = { - "spi0", "spi0_wp_hold", "spi1_0", "spi1_1", "spi1_2", "spi1_3", }; -static const char *mt7986_uart_groups[] = { - "uart1_0", "uart1_1", "uart1_rx_tx", "uart1_cts_rts", - "uart1_2_rx_tx", "uart1_2_cts_rts", - "uart1_3_rx_tx", "uart1_3_cts_rts", "uart2_0_rx_tx", "uart2_0_cts_rts", - "uart2_0", "uart2_1", "uart0", "uart1", "uart2", -}; -static const char *mt7986_wdt_groups[] = { "watchdog", }; -static const char *mt7986_wf_groups[] = { "wf_2g", "wf_5g", "wf_dbdc", }; - -static const struct function_desc mt7986_functions[] = { - {"audio", mt7986_audio_groups, ARRAY_SIZE(mt7986_audio_groups)}, - {"emmc", mt7986_emmc_groups, ARRAY_SIZE(mt7986_emmc_groups)}, - {"eth", mt7986_ethernet_groups, ARRAY_SIZE(mt7986_ethernet_groups)}, - {"i2c", mt7986_i2c_groups, ARRAY_SIZE(mt7986_i2c_groups)}, - {"led", mt7986_led_groups, ARRAY_SIZE(mt7986_led_groups)}, - {"flash", mt7986_flash_groups, ARRAY_SIZE(mt7986_flash_groups)}, - {"pcie", mt7986_pcie_groups, ARRAY_SIZE(mt7986_pcie_groups)}, - {"pwm", mt7986_pwm_groups, ARRAY_SIZE(mt7986_pwm_groups)}, - {"spi", mt7986_spi_groups, ARRAY_SIZE(mt7986_spi_groups)}, - {"uart", mt7986_uart_groups, ARRAY_SIZE(mt7986_uart_groups)}, - {"watchdog", mt7986_wdt_groups, ARRAY_SIZE(mt7986_wdt_groups)}, - {"wifi", mt7986_wf_groups, ARRAY_SIZE(mt7986_wf_groups)}, -}; - -static const struct mtk_eint_hw mt7986a_eint_hw = { - .port_mask = 7, - .ports = 7, - .ap_num = ARRAY_SIZE(mt7986a_pins), - .db_cnt = 16, - .db_time = debounce_time_mt6765, -}; - -static const struct mtk_eint_hw mt7986b_eint_hw = { - .port_mask = 7, - .ports = 7, - .ap_num = ARRAY_SIZE(mt7986b_pins), - .db_cnt = 16, - .db_time = debounce_time_mt6765, -}; - -static struct mtk_pin_soc mt7986a_data = { - .reg_cal = mt7986_reg_cals, - .pins = mt7986a_pins, - .npins = ARRAY_SIZE(mt7986a_pins), - .grps = mt7986_groups, - .ngrps = ARRAY_SIZE(mt7986_groups), - .funcs = mt7986_functions, - .nfuncs = ARRAY_SIZE(mt7986_functions), - .eint_hw = &mt7986a_eint_hw, - .gpio_m = 0, - .ies_present = false, - .base_names = mt7986_pinctrl_register_base_names, - .nbase_names = ARRAY_SIZE(mt7986_pinctrl_register_base_names), - .bias_disable_set = mtk_pinconf_bias_disable_set, - .bias_disable_get = mtk_pinconf_bias_disable_get, - .bias_set = mtk_pinconf_bias_set, - .bias_get = mtk_pinconf_bias_get, - .pull_type = mt7986_pull_type, - .bias_set_combo = mtk_pinconf_bias_set_combo, - .bias_get_combo = mtk_pinconf_bias_get_combo, - .drive_set = mtk_pinconf_drive_set_rev1, - .drive_get = mtk_pinconf_drive_get_rev1, - .adv_pull_get = mtk_pinconf_adv_pull_get, - .adv_pull_set = mtk_pinconf_adv_pull_set, -}; - -static struct mtk_pin_soc mt7986b_data = { - .reg_cal = mt7986_reg_cals, - .pins = mt7986b_pins, - .npins = ARRAY_SIZE(mt7986b_pins), - .grps = mt7986_groups, - .ngrps = ARRAY_SIZE(mt7986_groups), - .funcs = mt7986_functions, - .nfuncs = ARRAY_SIZE(mt7986_functions), - .eint_hw = &mt7986b_eint_hw, - .gpio_m = 0, - .ies_present = false, - .base_names = mt7986_pinctrl_register_base_names, - .nbase_names = ARRAY_SIZE(mt7986_pinctrl_register_base_names), - .bias_disable_set = mtk_pinconf_bias_disable_set, - .bias_disable_get = mtk_pinconf_bias_disable_get, - .bias_set = mtk_pinconf_bias_set, - .bias_get = mtk_pinconf_bias_get, - .pull_type = mt7986_pull_type, - .bias_set_combo = mtk_pinconf_bias_set_combo, - .bias_get_combo = mtk_pinconf_bias_get_combo, - .drive_set = mtk_pinconf_drive_set_rev1, - .drive_get = mtk_pinconf_drive_get_rev1, - .adv_pull_get = mtk_pinconf_adv_pull_get, - .adv_pull_set = mtk_pinconf_adv_pull_set, -}; - -static const struct of_device_id mt7986a_pinctrl_of_match[] = { - {.compatible = "mediatek,mt7986a-pinctrl",}, - {} -}; - -static const struct of_device_id mt7986b_pinctrl_of_match[] = { - {.compatible = "mediatek,mt7986b-pinctrl",}, - {} -}; - -static int mt7986a_pinctrl_probe(struct platform_device *pdev) -{ - return mtk_moore_pinctrl_probe(pdev, &mt7986a_data); -} - -static int mt7986b_pinctrl_probe(struct platform_device *pdev) -{ - return mtk_moore_pinctrl_probe(pdev, &mt7986b_data); -} - -static struct platform_driver mt7986a_pinctrl_driver = { - .driver = { - .name = "mt7986a-pinctrl", - .of_match_table = mt7986a_pinctrl_of_match, - }, - .probe = mt7986a_pinctrl_probe, -}; - -static struct platform_driver mt7986b_pinctrl_driver = { - .driver = { - .name = "mt7986b-pinctrl", - .of_match_table = mt7986b_pinctrl_of_match, - }, - .probe = mt7986b_pinctrl_probe, -}; - -static int __init mt7986a_pinctrl_init(void) -{ - return platform_driver_register(&mt7986a_pinctrl_driver); -} - -static int __init mt7986b_pinctrl_init(void) -{ - return platform_driver_register(&mt7986b_pinctrl_driver); -} - -arch_initcall(mt7986a_pinctrl_init); -arch_initcall(mt7986b_pinctrl_init); diff --git a/target/linux/mediatek/files-5.15/drivers/pinctrl/mediatek/pinctrl-mt7988.c b/target/linux/mediatek/files-5.15/drivers/pinctrl/mediatek/pinctrl-mt7988.c deleted file mode 100644 index 659c83e99..000000000 --- a/target/linux/mediatek/files-5.15/drivers/pinctrl/mediatek/pinctrl-mt7988.c +++ /dev/null @@ -1,1466 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * The MT7988 driver based on Linux generic pinctrl binding. - * - * Copyright (C) 2020 MediaTek Inc. - * Author: Sam Shih - */ - -#include "pinctrl-moore.h" - -enum MT7988_PINCTRL_REG_PAGE { - GPIO_BASE, - IOCFG_TR_BASE, - IOCFG_BR_BASE, - IOCFG_RB_BASE, - IOCFG_LB_BASE, - IOCFG_TL_BASE, -}; - -#define MT7988_PIN(_number, _name) MTK_PIN(_number, _name, 0, _number, DRV_GRP4) - -#define PIN_FIELD_BASE(_s_pin, _e_pin, _i_base, _s_addr, _x_addrs, _s_bit, \ - _x_bits) \ - PIN_FIELD_CALC(_s_pin, _e_pin, _i_base, _s_addr, _x_addrs, _s_bit, \ - _x_bits, 32, 0) - -#define PINS_FIELD_BASE(_s_pin, _e_pin, _i_base, _s_addr, _x_addrs, _s_bit, \ - _x_bits) \ - PIN_FIELD_CALC(_s_pin, _e_pin, _i_base, _s_addr, _x_addrs, _s_bit, \ - _x_bits, 32, 1) - -static const struct mtk_pin_field_calc mt7988_pin_mode_range[] = { - PIN_FIELD(0, 83, 0x300, 0x10, 0, 4), -}; - -static const struct mtk_pin_field_calc mt7988_pin_dir_range[] = { - PIN_FIELD(0, 83, 0x0, 0x10, 0, 1), -}; - -static const struct mtk_pin_field_calc mt7988_pin_di_range[] = { - PIN_FIELD(0, 83, 0x200, 0x10, 0, 1), -}; - -static const struct mtk_pin_field_calc mt7988_pin_do_range[] = { - PIN_FIELD(0, 83, 0x100, 0x10, 0, 1), -}; - -static const struct mtk_pin_field_calc mt7988_pin_ies_range[] = { - PIN_FIELD_BASE(0, 0, 5, 0x30, 0x10, 13, 1), - PIN_FIELD_BASE(1, 1, 5, 0x30, 0x10, 14, 1), - PIN_FIELD_BASE(2, 2, 5, 0x30, 0x10, 11, 1), - PIN_FIELD_BASE(3, 3, 5, 0x30, 0x10, 12, 1), - PIN_FIELD_BASE(4, 4, 5, 0x30, 0x10, 0, 1), - PIN_FIELD_BASE(5, 5, 5, 0x30, 0x10, 9, 1), - PIN_FIELD_BASE(6, 6, 5, 0x30, 0x10, 10, 1), - - PIN_FIELD_BASE(7, 7, 4, 0x30, 0x10, 8, 1), - PIN_FIELD_BASE(8, 8, 4, 0x30, 0x10, 6, 1), - PIN_FIELD_BASE(9, 9, 4, 0x30, 0x10, 5, 1), - PIN_FIELD_BASE(10, 10, 4, 0x30, 0x10, 3, 1), - - PIN_FIELD_BASE(11, 11, 1, 0x40, 0x10, 0, 1), - PIN_FIELD_BASE(12, 12, 1, 0x40, 0x10, 21, 1), - PIN_FIELD_BASE(13, 13, 1, 0x40, 0x10, 1, 1), - PIN_FIELD_BASE(14, 14, 1, 0x40, 0x10, 2, 1), - - PIN_FIELD_BASE(15, 15, 5, 0x30, 0x10, 7, 1), - PIN_FIELD_BASE(16, 16, 5, 0x30, 0x10, 8, 1), - PIN_FIELD_BASE(17, 17, 5, 0x30, 0x10, 3, 1), - PIN_FIELD_BASE(18, 18, 5, 0x30, 0x10, 4, 1), - - PIN_FIELD_BASE(19, 19, 4, 0x30, 0x10, 7, 1), - PIN_FIELD_BASE(20, 20, 4, 0x30, 0x10, 4, 1), - - PIN_FIELD_BASE(21, 21, 3, 0x50, 0x10, 17, 1), - PIN_FIELD_BASE(22, 22, 3, 0x50, 0x10, 23, 1), - PIN_FIELD_BASE(23, 23, 3, 0x50, 0x10, 20, 1), - PIN_FIELD_BASE(24, 24, 3, 0x50, 0x10, 19, 1), - PIN_FIELD_BASE(25, 25, 3, 0x50, 0x10, 21, 1), - PIN_FIELD_BASE(26, 26, 3, 0x50, 0x10, 22, 1), - PIN_FIELD_BASE(27, 27, 3, 0x50, 0x10, 18, 1), - PIN_FIELD_BASE(28, 28, 3, 0x50, 0x10, 25, 1), - PIN_FIELD_BASE(29, 29, 3, 0x50, 0x10, 26, 1), - PIN_FIELD_BASE(30, 30, 3, 0x50, 0x10, 27, 1), - PIN_FIELD_BASE(31, 31, 3, 0x50, 0x10, 24, 1), - PIN_FIELD_BASE(32, 32, 3, 0x50, 0x10, 28, 1), - PIN_FIELD_BASE(33, 33, 3, 0x60, 0x10, 0, 1), - PIN_FIELD_BASE(34, 34, 3, 0x50, 0x10, 31, 1), - PIN_FIELD_BASE(35, 35, 3, 0x50, 0x10, 29, 1), - PIN_FIELD_BASE(36, 36, 3, 0x50, 0x10, 30, 1), - PIN_FIELD_BASE(37, 37, 3, 0x60, 0x10, 1, 1), - PIN_FIELD_BASE(38, 38, 3, 0x50, 0x10, 11, 1), - PIN_FIELD_BASE(39, 39, 3, 0x50, 0x10, 10, 1), - PIN_FIELD_BASE(40, 40, 3, 0x50, 0x10, 0, 1), - PIN_FIELD_BASE(41, 41, 3, 0x50, 0x10, 1, 1), - PIN_FIELD_BASE(42, 42, 3, 0x50, 0x10, 9, 1), - PIN_FIELD_BASE(43, 43, 3, 0x50, 0x10, 8, 1), - PIN_FIELD_BASE(44, 44, 3, 0x50, 0x10, 7, 1), - PIN_FIELD_BASE(45, 45, 3, 0x50, 0x10, 6, 1), - PIN_FIELD_BASE(46, 46, 3, 0x50, 0x10, 5, 1), - PIN_FIELD_BASE(47, 47, 3, 0x50, 0x10, 4, 1), - PIN_FIELD_BASE(48, 48, 3, 0x50, 0x10, 3, 1), - PIN_FIELD_BASE(49, 49, 3, 0x50, 0x10, 2, 1), - PIN_FIELD_BASE(50, 50, 3, 0x50, 0x10, 15, 1), - PIN_FIELD_BASE(51, 51, 3, 0x50, 0x10, 12, 1), - PIN_FIELD_BASE(52, 52, 3, 0x50, 0x10, 13, 1), - PIN_FIELD_BASE(53, 53, 3, 0x50, 0x10, 14, 1), - PIN_FIELD_BASE(54, 54, 3, 0x50, 0x10, 16, 1), - - PIN_FIELD_BASE(55, 55, 1, 0x40, 0x10, 14, 1), - PIN_FIELD_BASE(56, 56, 1, 0x40, 0x10, 15, 1), - PIN_FIELD_BASE(57, 57, 1, 0x40, 0x10, 13, 1), - PIN_FIELD_BASE(58, 58, 1, 0x40, 0x10, 4, 1), - PIN_FIELD_BASE(59, 59, 1, 0x40, 0x10, 5, 1), - PIN_FIELD_BASE(60, 60, 1, 0x40, 0x10, 6, 1), - PIN_FIELD_BASE(61, 61, 1, 0x40, 0x10, 3, 1), - PIN_FIELD_BASE(62, 62, 1, 0x40, 0x10, 7, 1), - PIN_FIELD_BASE(63, 63, 1, 0x40, 0x10, 20, 1), - PIN_FIELD_BASE(64, 64, 1, 0x40, 0x10, 8, 1), - PIN_FIELD_BASE(65, 65, 1, 0x40, 0x10, 9, 1), - PIN_FIELD_BASE(66, 66, 1, 0x40, 0x10, 10, 1), - PIN_FIELD_BASE(67, 67, 1, 0x40, 0x10, 11, 1), - PIN_FIELD_BASE(68, 68, 1, 0x40, 0x10, 12, 1), - - PIN_FIELD_BASE(69, 69, 5, 0x30, 0x10, 1, 1), - PIN_FIELD_BASE(70, 70, 5, 0x30, 0x10, 2, 1), - PIN_FIELD_BASE(71, 71, 5, 0x30, 0x10, 5, 1), - PIN_FIELD_BASE(72, 72, 5, 0x30, 0x10, 6, 1), - - PIN_FIELD_BASE(73, 73, 4, 0x30, 0x10, 10, 1), - PIN_FIELD_BASE(74, 74, 4, 0x30, 0x10, 1, 1), - PIN_FIELD_BASE(75, 75, 4, 0x30, 0x10, 11, 1), - PIN_FIELD_BASE(76, 76, 4, 0x30, 0x10, 9, 1), - PIN_FIELD_BASE(77, 77, 4, 0x30, 0x10, 2, 1), - PIN_FIELD_BASE(78, 78, 4, 0x30, 0x10, 0, 1), - PIN_FIELD_BASE(79, 79, 4, 0x30, 0x10, 12, 1), - - PIN_FIELD_BASE(80, 80, 1, 0x40, 0x10, 18, 1), - PIN_FIELD_BASE(81, 81, 1, 0x40, 0x10, 19, 1), - PIN_FIELD_BASE(82, 82, 1, 0x40, 0x10, 16, 1), - PIN_FIELD_BASE(83, 83, 1, 0x40, 0x10, 17, 1), -}; - -static const struct mtk_pin_field_calc mt7988_pin_smt_range[] = { - PIN_FIELD_BASE(0, 0, 5, 0xc0, 0x10, 13, 1), - PIN_FIELD_BASE(1, 1, 5, 0xc0, 0x10, 14, 1), - PIN_FIELD_BASE(2, 2, 5, 0xc0, 0x10, 11, 1), - PIN_FIELD_BASE(3, 3, 5, 0xc0, 0x10, 12, 1), - PIN_FIELD_BASE(4, 4, 5, 0xc0, 0x10, 0, 1), - PIN_FIELD_BASE(5, 5, 5, 0xc0, 0x10, 9, 1), - PIN_FIELD_BASE(6, 6, 5, 0xc0, 0x10, 10, 1), - - PIN_FIELD_BASE(7, 7, 4, 0xb0, 0x10, 8, 1), - PIN_FIELD_BASE(8, 8, 4, 0xb0, 0x10, 6, 1), - PIN_FIELD_BASE(9, 9, 4, 0xb0, 0x10, 5, 1), - PIN_FIELD_BASE(10, 10, 4, 0xb0, 0x10, 3, 1), - - PIN_FIELD_BASE(11, 11, 1, 0xe0, 0x10, 0, 1), - PIN_FIELD_BASE(12, 12, 1, 0xe0, 0x10, 21, 1), - PIN_FIELD_BASE(13, 13, 1, 0xe0, 0x10, 1, 1), - PIN_FIELD_BASE(14, 14, 1, 0xe0, 0x10, 2, 1), - - PIN_FIELD_BASE(15, 15, 5, 0xc0, 0x10, 7, 1), - PIN_FIELD_BASE(16, 16, 5, 0xc0, 0x10, 8, 1), - PIN_FIELD_BASE(17, 17, 5, 0xc0, 0x10, 3, 1), - PIN_FIELD_BASE(18, 18, 5, 0xc0, 0x10, 4, 1), - - PIN_FIELD_BASE(19, 19, 4, 0xb0, 0x10, 7, 1), - PIN_FIELD_BASE(20, 20, 4, 0xb0, 0x10, 4, 1), - - PIN_FIELD_BASE(21, 21, 3, 0x140, 0x10, 17, 1), - PIN_FIELD_BASE(22, 22, 3, 0x140, 0x10, 23, 1), - PIN_FIELD_BASE(23, 23, 3, 0x140, 0x10, 20, 1), - PIN_FIELD_BASE(24, 24, 3, 0x140, 0x10, 19, 1), - PIN_FIELD_BASE(25, 25, 3, 0x140, 0x10, 21, 1), - PIN_FIELD_BASE(26, 26, 3, 0x140, 0x10, 22, 1), - PIN_FIELD_BASE(27, 27, 3, 0x140, 0x10, 18, 1), - PIN_FIELD_BASE(28, 28, 3, 0x140, 0x10, 25, 1), - PIN_FIELD_BASE(29, 29, 3, 0x140, 0x10, 26, 1), - PIN_FIELD_BASE(30, 30, 3, 0x140, 0x10, 27, 1), - PIN_FIELD_BASE(31, 31, 3, 0x140, 0x10, 24, 1), - PIN_FIELD_BASE(32, 32, 3, 0x140, 0x10, 28, 1), - PIN_FIELD_BASE(33, 33, 3, 0x150, 0x10, 0, 1), - PIN_FIELD_BASE(34, 34, 3, 0x140, 0x10, 31, 1), - PIN_FIELD_BASE(35, 35, 3, 0x140, 0x10, 29, 1), - PIN_FIELD_BASE(36, 36, 3, 0x140, 0x10, 30, 1), - PIN_FIELD_BASE(37, 37, 3, 0x150, 0x10, 1, 1), - PIN_FIELD_BASE(38, 38, 3, 0x140, 0x10, 11, 1), - PIN_FIELD_BASE(39, 39, 3, 0x140, 0x10, 10, 1), - PIN_FIELD_BASE(40, 40, 3, 0x140, 0x10, 0, 1), - PIN_FIELD_BASE(41, 41, 3, 0x140, 0x10, 1, 1), - PIN_FIELD_BASE(42, 42, 3, 0x140, 0x10, 9, 1), - PIN_FIELD_BASE(43, 43, 3, 0x140, 0x10, 8, 1), - PIN_FIELD_BASE(44, 44, 3, 0x140, 0x10, 7, 1), - PIN_FIELD_BASE(45, 45, 3, 0x140, 0x10, 6, 1), - PIN_FIELD_BASE(46, 46, 3, 0x140, 0x10, 5, 1), - PIN_FIELD_BASE(47, 47, 3, 0x140, 0x10, 4, 1), - PIN_FIELD_BASE(48, 48, 3, 0x140, 0x10, 3, 1), - PIN_FIELD_BASE(49, 49, 3, 0x140, 0x10, 2, 1), - PIN_FIELD_BASE(50, 50, 3, 0x140, 0x10, 15, 1), - PIN_FIELD_BASE(51, 51, 3, 0x140, 0x10, 12, 1), - PIN_FIELD_BASE(52, 52, 3, 0x140, 0x10, 13, 1), - PIN_FIELD_BASE(53, 53, 3, 0x140, 0x10, 14, 1), - PIN_FIELD_BASE(54, 54, 3, 0x140, 0x10, 16, 1), - - PIN_FIELD_BASE(55, 55, 1, 0xe0, 0x10, 14, 1), - PIN_FIELD_BASE(56, 56, 1, 0xe0, 0x10, 15, 1), - PIN_FIELD_BASE(57, 57, 1, 0xe0, 0x10, 13, 1), - PIN_FIELD_BASE(58, 58, 1, 0xe0, 0x10, 4, 1), - PIN_FIELD_BASE(59, 59, 1, 0xe0, 0x10, 5, 1), - PIN_FIELD_BASE(60, 60, 1, 0xe0, 0x10, 6, 1), - PIN_FIELD_BASE(61, 61, 1, 0xe0, 0x10, 3, 1), - PIN_FIELD_BASE(62, 62, 1, 0xe0, 0x10, 7, 1), - PIN_FIELD_BASE(63, 63, 1, 0xe0, 0x10, 20, 1), - PIN_FIELD_BASE(64, 64, 1, 0xe0, 0x10, 8, 1), - PIN_FIELD_BASE(65, 65, 1, 0xe0, 0x10, 9, 1), - PIN_FIELD_BASE(66, 66, 1, 0xe0, 0x10, 10, 1), - PIN_FIELD_BASE(67, 67, 1, 0xe0, 0x10, 11, 1), - PIN_FIELD_BASE(68, 68, 1, 0xe0, 0x10, 12, 1), - - PIN_FIELD_BASE(69, 69, 5, 0xc0, 0x10, 1, 1), - PIN_FIELD_BASE(70, 70, 5, 0xc0, 0x10, 2, 1), - PIN_FIELD_BASE(71, 71, 5, 0xc0, 0x10, 5, 1), - PIN_FIELD_BASE(72, 72, 5, 0xc0, 0x10, 6, 1), - - PIN_FIELD_BASE(73, 73, 4, 0xb0, 0x10, 10, 1), - PIN_FIELD_BASE(74, 74, 4, 0xb0, 0x10, 1, 1), - PIN_FIELD_BASE(75, 75, 4, 0xb0, 0x10, 11, 1), - PIN_FIELD_BASE(76, 76, 4, 0xb0, 0x10, 9, 1), - PIN_FIELD_BASE(77, 77, 4, 0xb0, 0x10, 2, 1), - PIN_FIELD_BASE(78, 78, 4, 0xb0, 0x10, 0, 1), - PIN_FIELD_BASE(79, 79, 4, 0xb0, 0x10, 12, 1), - - PIN_FIELD_BASE(80, 80, 1, 0xe0, 0x10, 18, 1), - PIN_FIELD_BASE(81, 81, 1, 0xe0, 0x10, 19, 1), - PIN_FIELD_BASE(82, 82, 1, 0xe0, 0x10, 16, 1), - PIN_FIELD_BASE(83, 83, 1, 0xe0, 0x10, 17, 1), -}; - -static const struct mtk_pin_field_calc mt7988_pin_pu_range[] = { - PIN_FIELD_BASE(7, 7, 4, 0x60, 0x10, 5, 1), - PIN_FIELD_BASE(8, 8, 4, 0x60, 0x10, 4, 1), - PIN_FIELD_BASE(9, 9, 4, 0x60, 0x10, 3, 1), - PIN_FIELD_BASE(10, 10, 4, 0x60, 0x10, 2, 1), - - PIN_FIELD_BASE(13, 13, 1, 0x70, 0x10, 0, 1), - PIN_FIELD_BASE(14, 14, 1, 0x70, 0x10, 1, 1), - PIN_FIELD_BASE(63, 63, 1, 0x70, 0x10, 2, 1), - - PIN_FIELD_BASE(75, 75, 4, 0x60, 0x10, 7, 1), - PIN_FIELD_BASE(76, 76, 4, 0x60, 0x10, 6, 1), - PIN_FIELD_BASE(77, 77, 4, 0x60, 0x10, 1, 1), - PIN_FIELD_BASE(78, 78, 4, 0x60, 0x10, 0, 1), - PIN_FIELD_BASE(79, 79, 4, 0x60, 0x10, 8, 1), -}; - -static const struct mtk_pin_field_calc mt7988_pin_pd_range[] = { - PIN_FIELD_BASE(7, 7, 4, 0x40, 0x10, 5, 1), - PIN_FIELD_BASE(8, 8, 4, 0x40, 0x10, 4, 1), - PIN_FIELD_BASE(9, 9, 4, 0x40, 0x10, 3, 1), - PIN_FIELD_BASE(10, 10, 4, 0x40, 0x10, 2, 1), - - PIN_FIELD_BASE(13, 13, 1, 0x50, 0x10, 0, 1), - PIN_FIELD_BASE(14, 14, 1, 0x50, 0x10, 1, 1), - - PIN_FIELD_BASE(15, 15, 5, 0x40, 0x10, 4, 1), - PIN_FIELD_BASE(16, 16, 5, 0x40, 0x10, 5, 1), - PIN_FIELD_BASE(17, 17, 5, 0x40, 0x10, 0, 1), - PIN_FIELD_BASE(18, 18, 5, 0x40, 0x10, 1, 1), - - PIN_FIELD_BASE(63, 63, 1, 0x50, 0x10, 2, 1), - PIN_FIELD_BASE(71, 71, 5, 0x40, 0x10, 2, 1), - PIN_FIELD_BASE(72, 72, 5, 0x40, 0x10, 3, 1), - - PIN_FIELD_BASE(75, 75, 4, 0x40, 0x10, 7, 1), - PIN_FIELD_BASE(76, 76, 4, 0x40, 0x10, 6, 1), - PIN_FIELD_BASE(77, 77, 4, 0x40, 0x10, 1, 1), - PIN_FIELD_BASE(78, 78, 4, 0x40, 0x10, 0, 1), - PIN_FIELD_BASE(79, 79, 4, 0x40, 0x10, 8, 1), -}; - -static const struct mtk_pin_field_calc mt7988_pin_drv_range[] = { - PIN_FIELD_BASE(0, 0, 5, 0x00, 0x10, 21, 3), - PIN_FIELD_BASE(1, 1, 5, 0x00, 0x10, 24, 3), - PIN_FIELD_BASE(2, 2, 5, 0x00, 0x10, 15, 3), - PIN_FIELD_BASE(3, 3, 5, 0x00, 0x10, 18, 3), - PIN_FIELD_BASE(4, 4, 5, 0x00, 0x10, 0, 3), - PIN_FIELD_BASE(5, 5, 5, 0x00, 0x10, 9, 3), - PIN_FIELD_BASE(6, 6, 5, 0x00, 0x10, 12, 3), - - PIN_FIELD_BASE(7, 7, 4, 0x00, 0x10, 24, 3), - PIN_FIELD_BASE(8, 8, 4, 0x00, 0x10, 28, 3), - PIN_FIELD_BASE(9, 9, 4, 0x00, 0x10, 15, 3), - PIN_FIELD_BASE(10, 10, 4, 0x00, 0x10, 9, 3), - - PIN_FIELD_BASE(11, 11, 1, 0x00, 0x10, 0, 3), - PIN_FIELD_BASE(12, 12, 1, 0x20, 0x10, 3, 3), - PIN_FIELD_BASE(13, 13, 1, 0x00, 0x10, 3, 3), - PIN_FIELD_BASE(14, 14, 1, 0x00, 0x10, 6, 3), - - PIN_FIELD_BASE(19, 19, 4, 0x00, 0x10, 21, 3), - PIN_FIELD_BASE(20, 20, 4, 0x00, 0x10, 12, 3), - - PIN_FIELD_BASE(21, 21, 3, 0x10, 0x10, 21, 3), - PIN_FIELD_BASE(22, 22, 3, 0x20, 0x10, 9, 3), - PIN_FIELD_BASE(23, 23, 3, 0x20, 0x10, 0, 3), - PIN_FIELD_BASE(24, 24, 3, 0x10, 0x10, 27, 3), - PIN_FIELD_BASE(25, 25, 3, 0x20, 0x10, 3, 3), - PIN_FIELD_BASE(26, 26, 3, 0x20, 0x10, 6, 3), - PIN_FIELD_BASE(27, 27, 3, 0x10, 0x10, 24, 3), - PIN_FIELD_BASE(28, 28, 3, 0x20, 0x10, 15, 3), - PIN_FIELD_BASE(29, 29, 3, 0x20, 0x10, 18, 3), - PIN_FIELD_BASE(30, 30, 3, 0x20, 0x10, 21, 3), - PIN_FIELD_BASE(31, 31, 3, 0x20, 0x10, 12, 3), - PIN_FIELD_BASE(32, 32, 3, 0x20, 0x10, 24, 3), - PIN_FIELD_BASE(33, 33, 3, 0x30, 0x10, 6, 3), - PIN_FIELD_BASE(34, 34, 3, 0x30, 0x10, 3, 3), - PIN_FIELD_BASE(35, 35, 3, 0x20, 0x10, 27, 3), - PIN_FIELD_BASE(36, 36, 3, 0x30, 0x10, 0, 3), - PIN_FIELD_BASE(37, 37, 3, 0x30, 0x10, 9, 3), - PIN_FIELD_BASE(38, 38, 3, 0x10, 0x10, 3, 3), - PIN_FIELD_BASE(39, 39, 3, 0x10, 0x10, 0, 3), - PIN_FIELD_BASE(40, 40, 3, 0x00, 0x10, 0, 3), - PIN_FIELD_BASE(41, 41, 3, 0x00, 0x10, 3, 3), - PIN_FIELD_BASE(42, 42, 3, 0x00, 0x10, 27, 3), - PIN_FIELD_BASE(43, 43, 3, 0x00, 0x10, 24, 3), - PIN_FIELD_BASE(44, 44, 3, 0x00, 0x10, 21, 3), - PIN_FIELD_BASE(45, 45, 3, 0x00, 0x10, 18, 3), - PIN_FIELD_BASE(46, 46, 3, 0x00, 0x10, 15, 3), - PIN_FIELD_BASE(47, 47, 3, 0x00, 0x10, 12, 3), - PIN_FIELD_BASE(48, 48, 3, 0x00, 0x10, 9, 3), - PIN_FIELD_BASE(49, 49, 3, 0x00, 0x10, 6, 3), - PIN_FIELD_BASE(50, 50, 3, 0x10, 0x10, 15, 3), - PIN_FIELD_BASE(51, 51, 3, 0x10, 0x10, 6, 3), - PIN_FIELD_BASE(52, 52, 3, 0x10, 0x10, 9, 3), - PIN_FIELD_BASE(53, 53, 3, 0x10, 0x10, 12, 3), - PIN_FIELD_BASE(54, 54, 3, 0x10, 0x10, 18, 3), - - PIN_FIELD_BASE(55, 55, 1, 0x10, 0x10, 12, 3), - PIN_FIELD_BASE(56, 56, 1, 0x10, 0x10, 15, 3), - PIN_FIELD_BASE(57, 57, 1, 0x10, 0x10, 9, 3), - PIN_FIELD_BASE(58, 58, 1, 0x00, 0x10, 12, 3), - PIN_FIELD_BASE(59, 59, 1, 0x00, 0x10, 15, 3), - PIN_FIELD_BASE(60, 60, 1, 0x00, 0x10, 18, 3), - PIN_FIELD_BASE(61, 61, 1, 0x00, 0x10, 9, 3), - PIN_FIELD_BASE(62, 62, 1, 0x00, 0x10, 21, 3), - PIN_FIELD_BASE(63, 63, 1, 0x20, 0x10, 0, 3), - PIN_FIELD_BASE(64, 64, 1, 0x00, 0x10, 24, 3), - PIN_FIELD_BASE(65, 65, 1, 0x00, 0x10, 27, 3), - PIN_FIELD_BASE(66, 66, 1, 0x10, 0x10, 0, 3), - PIN_FIELD_BASE(67, 67, 1, 0x10, 0x10, 3, 3), - PIN_FIELD_BASE(68, 68, 1, 0x10, 0x10, 6, 3), - - PIN_FIELD_BASE(69, 69, 5, 0x00, 0x10, 3, 3), - PIN_FIELD_BASE(70, 70, 5, 0x00, 0x10, 6, 3), - - PIN_FIELD_BASE(73, 73, 4, 0x10, 0x10, 0, 3), - PIN_FIELD_BASE(74, 74, 4, 0x00, 0x10, 3, 3), - PIN_FIELD_BASE(75, 75, 4, 0x10, 0x10, 3, 3), - PIN_FIELD_BASE(76, 76, 4, 0x00, 0x10, 27, 3), - PIN_FIELD_BASE(77, 77, 4, 0x00, 0x10, 6, 3), - PIN_FIELD_BASE(78, 78, 4, 0x00, 0x10, 0, 3), - PIN_FIELD_BASE(79, 79, 4, 0x10, 0x10, 6, 3), - - PIN_FIELD_BASE(80, 80, 1, 0x10, 0x10, 24, 3), - PIN_FIELD_BASE(81, 81, 1, 0x10, 0x10, 27, 3), - PIN_FIELD_BASE(82, 82, 1, 0x10, 0x10, 18, 3), - PIN_FIELD_BASE(83, 83, 1, 0x10, 0x10, 21, 3), -}; - -static const struct mtk_pin_field_calc mt7988_pin_pupd_range[] = { - PIN_FIELD_BASE(0, 0, 5, 0x50, 0x10, 7, 1), - PIN_FIELD_BASE(1, 1, 5, 0x50, 0x10, 8, 1), - PIN_FIELD_BASE(2, 2, 5, 0x50, 0x10, 5, 1), - PIN_FIELD_BASE(3, 3, 5, 0x50, 0x10, 6, 1), - PIN_FIELD_BASE(4, 4, 5, 0x50, 0x10, 0, 1), - PIN_FIELD_BASE(5, 5, 5, 0x50, 0x10, 3, 1), - PIN_FIELD_BASE(6, 6, 5, 0x50, 0x10, 4, 1), - - PIN_FIELD_BASE(11, 11, 1, 0x60, 0x10, 0, 1), - PIN_FIELD_BASE(12, 12, 1, 0x60, 0x10, 18, 1), - - PIN_FIELD_BASE(19, 19, 4, 0x50, 0x10, 2, 1), - PIN_FIELD_BASE(20, 20, 4, 0x50, 0x10, 1, 1), - - PIN_FIELD_BASE(21, 21, 3, 0x70, 0x10, 17, 1), - PIN_FIELD_BASE(22, 22, 3, 0x70, 0x10, 23, 1), - PIN_FIELD_BASE(23, 23, 3, 0x70, 0x10, 20, 1), - PIN_FIELD_BASE(24, 24, 3, 0x70, 0x10, 19, 1), - PIN_FIELD_BASE(25, 25, 3, 0x70, 0x10, 21, 1), - PIN_FIELD_BASE(26, 26, 3, 0x70, 0x10, 22, 1), - PIN_FIELD_BASE(27, 27, 3, 0x70, 0x10, 18, 1), - PIN_FIELD_BASE(28, 28, 3, 0x70, 0x10, 25, 1), - PIN_FIELD_BASE(29, 29, 3, 0x70, 0x10, 26, 1), - PIN_FIELD_BASE(30, 30, 3, 0x70, 0x10, 27, 1), - PIN_FIELD_BASE(31, 31, 3, 0x70, 0x10, 24, 1), - PIN_FIELD_BASE(32, 32, 3, 0x70, 0x10, 28, 1), - PIN_FIELD_BASE(33, 33, 3, 0x80, 0x10, 0, 1), - PIN_FIELD_BASE(34, 34, 3, 0x70, 0x10, 31, 1), - PIN_FIELD_BASE(35, 35, 3, 0x70, 0x10, 29, 1), - PIN_FIELD_BASE(36, 36, 3, 0x70, 0x10, 30, 1), - PIN_FIELD_BASE(37, 37, 3, 0x80, 0x10, 1, 1), - PIN_FIELD_BASE(38, 38, 3, 0x70, 0x10, 11, 1), - PIN_FIELD_BASE(39, 39, 3, 0x70, 0x10, 10, 1), - PIN_FIELD_BASE(40, 40, 3, 0x70, 0x10, 0, 1), - PIN_FIELD_BASE(41, 41, 3, 0x70, 0x10, 1, 1), - PIN_FIELD_BASE(42, 42, 3, 0x70, 0x10, 9, 1), - PIN_FIELD_BASE(43, 43, 3, 0x70, 0x10, 8, 1), - PIN_FIELD_BASE(44, 44, 3, 0x70, 0x10, 7, 1), - PIN_FIELD_BASE(45, 45, 3, 0x70, 0x10, 6, 1), - PIN_FIELD_BASE(46, 46, 3, 0x70, 0x10, 5, 1), - PIN_FIELD_BASE(47, 47, 3, 0x70, 0x10, 4, 1), - PIN_FIELD_BASE(48, 48, 3, 0x70, 0x10, 3, 1), - PIN_FIELD_BASE(49, 49, 3, 0x70, 0x10, 2, 1), - PIN_FIELD_BASE(50, 50, 3, 0x70, 0x10, 15, 1), - PIN_FIELD_BASE(51, 51, 3, 0x70, 0x10, 12, 1), - PIN_FIELD_BASE(52, 52, 3, 0x70, 0x10, 13, 1), - PIN_FIELD_BASE(53, 53, 3, 0x70, 0x10, 14, 1), - PIN_FIELD_BASE(54, 54, 3, 0x70, 0x10, 16, 1), - - PIN_FIELD_BASE(55, 55, 1, 0x60, 0x10, 12, 1), - PIN_FIELD_BASE(56, 56, 1, 0x60, 0x10, 13, 1), - PIN_FIELD_BASE(57, 57, 1, 0x60, 0x10, 11, 1), - PIN_FIELD_BASE(58, 58, 1, 0x60, 0x10, 2, 1), - PIN_FIELD_BASE(59, 59, 1, 0x60, 0x10, 3, 1), - PIN_FIELD_BASE(60, 60, 1, 0x60, 0x10, 4, 1), - PIN_FIELD_BASE(61, 61, 1, 0x60, 0x10, 1, 1), - PIN_FIELD_BASE(62, 62, 1, 0x60, 0x10, 5, 1), - PIN_FIELD_BASE(64, 64, 1, 0x60, 0x10, 6, 1), - PIN_FIELD_BASE(65, 65, 1, 0x60, 0x10, 7, 1), - PIN_FIELD_BASE(66, 66, 1, 0x60, 0x10, 8, 1), - PIN_FIELD_BASE(67, 67, 1, 0x60, 0x10, 9, 1), - PIN_FIELD_BASE(68, 68, 1, 0x60, 0x10, 10, 1), - - PIN_FIELD_BASE(69, 69, 5, 0x50, 0x10, 1, 1), - PIN_FIELD_BASE(70, 70, 5, 0x50, 0x10, 2, 1), - - PIN_FIELD_BASE(73, 73, 4, 0x50, 0x10, 3, 1), - PIN_FIELD_BASE(74, 74, 4, 0x50, 0x10, 0, 1), - - PIN_FIELD_BASE(80, 80, 1, 0x60, 0x10, 16, 1), - PIN_FIELD_BASE(81, 81, 1, 0x60, 0x10, 17, 1), - PIN_FIELD_BASE(82, 82, 1, 0x60, 0x10, 14, 1), - PIN_FIELD_BASE(83, 83, 1, 0x60, 0x10, 15, 1), -}; - -static const struct mtk_pin_field_calc mt7988_pin_r0_range[] = { - PIN_FIELD_BASE(0, 0, 5, 0x60, 0x10, 7, 1), - PIN_FIELD_BASE(1, 1, 5, 0x60, 0x10, 8, 1), - PIN_FIELD_BASE(2, 2, 5, 0x60, 0x10, 5, 1), - PIN_FIELD_BASE(3, 3, 5, 0x60, 0x10, 6, 1), - PIN_FIELD_BASE(4, 4, 5, 0x60, 0x10, 0, 1), - PIN_FIELD_BASE(5, 5, 5, 0x60, 0x10, 3, 1), - PIN_FIELD_BASE(6, 6, 5, 0x60, 0x10, 4, 1), - - PIN_FIELD_BASE(11, 11, 1, 0x80, 0x10, 0, 1), - PIN_FIELD_BASE(12, 12, 1, 0x80, 0x10, 18, 1), - - PIN_FIELD_BASE(19, 19, 4, 0x70, 0x10, 2, 1), - PIN_FIELD_BASE(20, 20, 4, 0x70, 0x10, 1, 1), - - PIN_FIELD_BASE(21, 21, 3, 0x90, 0x10, 17, 1), - PIN_FIELD_BASE(22, 22, 3, 0x90, 0x10, 23, 1), - PIN_FIELD_BASE(23, 23, 3, 0x90, 0x10, 20, 1), - PIN_FIELD_BASE(24, 24, 3, 0x90, 0x10, 19, 1), - PIN_FIELD_BASE(25, 25, 3, 0x90, 0x10, 21, 1), - PIN_FIELD_BASE(26, 26, 3, 0x90, 0x10, 22, 1), - PIN_FIELD_BASE(27, 27, 3, 0x90, 0x10, 18, 1), - PIN_FIELD_BASE(28, 28, 3, 0x90, 0x10, 25, 1), - PIN_FIELD_BASE(29, 29, 3, 0x90, 0x10, 26, 1), - PIN_FIELD_BASE(30, 30, 3, 0x90, 0x10, 27, 1), - PIN_FIELD_BASE(31, 31, 3, 0x90, 0x10, 24, 1), - PIN_FIELD_BASE(32, 32, 3, 0x90, 0x10, 28, 1), - PIN_FIELD_BASE(33, 33, 3, 0xa0, 0x10, 0, 1), - PIN_FIELD_BASE(34, 34, 3, 0x90, 0x10, 31, 1), - PIN_FIELD_BASE(35, 35, 3, 0x90, 0x10, 29, 1), - PIN_FIELD_BASE(36, 36, 3, 0x90, 0x10, 30, 1), - PIN_FIELD_BASE(37, 37, 3, 0xa0, 0x10, 1, 1), - PIN_FIELD_BASE(38, 38, 3, 0x90, 0x10, 11, 1), - PIN_FIELD_BASE(39, 39, 3, 0x90, 0x10, 10, 1), - PIN_FIELD_BASE(40, 40, 3, 0x90, 0x10, 0, 1), - PIN_FIELD_BASE(41, 41, 3, 0x90, 0x10, 1, 1), - PIN_FIELD_BASE(42, 42, 3, 0x90, 0x10, 9, 1), - PIN_FIELD_BASE(43, 43, 3, 0x90, 0x10, 8, 1), - PIN_FIELD_BASE(44, 44, 3, 0x90, 0x10, 7, 1), - PIN_FIELD_BASE(45, 45, 3, 0x90, 0x10, 6, 1), - PIN_FIELD_BASE(46, 46, 3, 0x90, 0x10, 5, 1), - PIN_FIELD_BASE(47, 47, 3, 0x90, 0x10, 4, 1), - PIN_FIELD_BASE(48, 48, 3, 0x90, 0x10, 3, 1), - PIN_FIELD_BASE(49, 49, 3, 0x90, 0x10, 2, 1), - PIN_FIELD_BASE(50, 50, 3, 0x90, 0x10, 15, 1), - PIN_FIELD_BASE(51, 51, 3, 0x90, 0x10, 12, 1), - PIN_FIELD_BASE(52, 52, 3, 0x90, 0x10, 13, 1), - PIN_FIELD_BASE(53, 53, 3, 0x90, 0x10, 14, 1), - PIN_FIELD_BASE(54, 54, 3, 0x90, 0x10, 16, 1), - - PIN_FIELD_BASE(55, 55, 1, 0x80, 0x10, 12, 1), - PIN_FIELD_BASE(56, 56, 1, 0x80, 0x10, 13, 1), - PIN_FIELD_BASE(57, 57, 1, 0x80, 0x10, 11, 1), - PIN_FIELD_BASE(58, 58, 1, 0x80, 0x10, 2, 1), - PIN_FIELD_BASE(59, 59, 1, 0x80, 0x10, 3, 1), - PIN_FIELD_BASE(60, 60, 1, 0x80, 0x10, 4, 1), - PIN_FIELD_BASE(61, 61, 1, 0x80, 0x10, 1, 1), - PIN_FIELD_BASE(62, 62, 1, 0x80, 0x10, 5, 1), - PIN_FIELD_BASE(64, 64, 1, 0x80, 0x10, 6, 1), - PIN_FIELD_BASE(65, 65, 1, 0x80, 0x10, 7, 1), - PIN_FIELD_BASE(66, 66, 1, 0x80, 0x10, 8, 1), - PIN_FIELD_BASE(67, 67, 1, 0x80, 0x10, 9, 1), - PIN_FIELD_BASE(68, 68, 1, 0x80, 0x10, 10, 1), - - PIN_FIELD_BASE(69, 69, 5, 0x60, 0x10, 1, 1), - PIN_FIELD_BASE(70, 70, 5, 0x60, 0x10, 2, 1), - - PIN_FIELD_BASE(73, 73, 4, 0x70, 0x10, 3, 1), - PIN_FIELD_BASE(74, 74, 4, 0x70, 0x10, 0, 1), - - PIN_FIELD_BASE(80, 80, 1, 0x80, 0x10, 16, 1), - PIN_FIELD_BASE(81, 81, 1, 0x80, 0x10, 17, 1), - PIN_FIELD_BASE(82, 82, 1, 0x80, 0x10, 14, 1), - PIN_FIELD_BASE(83, 83, 1, 0x80, 0x10, 15, 1), -}; - -static const struct mtk_pin_field_calc mt7988_pin_r1_range[] = { - PIN_FIELD_BASE(0, 0, 5, 0x70, 0x10, 7, 1), - PIN_FIELD_BASE(1, 1, 5, 0x70, 0x10, 8, 1), - PIN_FIELD_BASE(2, 2, 5, 0x70, 0x10, 5, 1), - PIN_FIELD_BASE(3, 3, 5, 0x70, 0x10, 6, 1), - PIN_FIELD_BASE(4, 4, 5, 0x70, 0x10, 0, 1), - PIN_FIELD_BASE(5, 5, 5, 0x70, 0x10, 3, 1), - PIN_FIELD_BASE(6, 6, 5, 0x70, 0x10, 4, 1), - - PIN_FIELD_BASE(11, 11, 1, 0x90, 0x10, 0, 1), - PIN_FIELD_BASE(12, 12, 1, 0x90, 0x10, 18, 1), - - PIN_FIELD_BASE(19, 19, 4, 0x80, 0x10, 2, 1), - PIN_FIELD_BASE(20, 20, 4, 0x80, 0x10, 1, 1), - - PIN_FIELD_BASE(21, 21, 3, 0xb0, 0x10, 17, 1), - PIN_FIELD_BASE(22, 22, 3, 0xb0, 0x10, 23, 1), - PIN_FIELD_BASE(23, 23, 3, 0xb0, 0x10, 20, 1), - PIN_FIELD_BASE(24, 24, 3, 0xb0, 0x10, 19, 1), - PIN_FIELD_BASE(25, 25, 3, 0xb0, 0x10, 21, 1), - PIN_FIELD_BASE(26, 26, 3, 0xb0, 0x10, 22, 1), - PIN_FIELD_BASE(27, 27, 3, 0xb0, 0x10, 18, 1), - PIN_FIELD_BASE(28, 28, 3, 0xb0, 0x10, 25, 1), - PIN_FIELD_BASE(29, 29, 3, 0xb0, 0x10, 26, 1), - PIN_FIELD_BASE(30, 30, 3, 0xb0, 0x10, 27, 1), - PIN_FIELD_BASE(31, 31, 3, 0xb0, 0x10, 24, 1), - PIN_FIELD_BASE(32, 32, 3, 0xb0, 0x10, 28, 1), - PIN_FIELD_BASE(33, 33, 3, 0xc0, 0x10, 0, 1), - PIN_FIELD_BASE(34, 34, 3, 0xb0, 0x10, 31, 1), - PIN_FIELD_BASE(35, 35, 3, 0xb0, 0x10, 29, 1), - PIN_FIELD_BASE(36, 36, 3, 0xb0, 0x10, 30, 1), - PIN_FIELD_BASE(37, 37, 3, 0xc0, 0x10, 1, 1), - PIN_FIELD_BASE(38, 38, 3, 0xb0, 0x10, 11, 1), - PIN_FIELD_BASE(39, 39, 3, 0xb0, 0x10, 10, 1), - PIN_FIELD_BASE(40, 40, 3, 0xb0, 0x10, 0, 1), - PIN_FIELD_BASE(41, 41, 3, 0xb0, 0x10, 1, 1), - PIN_FIELD_BASE(42, 42, 3, 0xb0, 0x10, 9, 1), - PIN_FIELD_BASE(43, 43, 3, 0xb0, 0x10, 8, 1), - PIN_FIELD_BASE(44, 44, 3, 0xb0, 0x10, 7, 1), - PIN_FIELD_BASE(45, 45, 3, 0xb0, 0x10, 6, 1), - PIN_FIELD_BASE(46, 46, 3, 0xb0, 0x10, 5, 1), - PIN_FIELD_BASE(47, 47, 3, 0xb0, 0x10, 4, 1), - PIN_FIELD_BASE(48, 48, 3, 0xb0, 0x10, 3, 1), - PIN_FIELD_BASE(49, 49, 3, 0xb0, 0x10, 2, 1), - PIN_FIELD_BASE(50, 50, 3, 0xb0, 0x10, 15, 1), - PIN_FIELD_BASE(51, 51, 3, 0xb0, 0x10, 12, 1), - PIN_FIELD_BASE(52, 52, 3, 0xb0, 0x10, 13, 1), - PIN_FIELD_BASE(53, 53, 3, 0xb0, 0x10, 14, 1), - PIN_FIELD_BASE(54, 54, 3, 0xb0, 0x10, 16, 1), - - PIN_FIELD_BASE(55, 55, 1, 0x90, 0x10, 12, 1), - PIN_FIELD_BASE(56, 56, 1, 0x90, 0x10, 13, 1), - PIN_FIELD_BASE(57, 57, 1, 0x90, 0x10, 11, 1), - PIN_FIELD_BASE(58, 58, 1, 0x90, 0x10, 2, 1), - PIN_FIELD_BASE(59, 59, 1, 0x90, 0x10, 3, 1), - PIN_FIELD_BASE(60, 60, 1, 0x90, 0x10, 4, 1), - PIN_FIELD_BASE(61, 61, 1, 0x90, 0x10, 1, 1), - PIN_FIELD_BASE(62, 62, 1, 0x90, 0x10, 5, 1), - PIN_FIELD_BASE(64, 64, 1, 0x90, 0x10, 6, 1), - PIN_FIELD_BASE(65, 65, 1, 0x90, 0x10, 7, 1), - PIN_FIELD_BASE(66, 66, 1, 0x90, 0x10, 8, 1), - PIN_FIELD_BASE(67, 67, 1, 0x90, 0x10, 9, 1), - PIN_FIELD_BASE(68, 68, 1, 0x90, 0x10, 10, 1), - - PIN_FIELD_BASE(69, 69, 5, 0x70, 0x10, 1, 1), - PIN_FIELD_BASE(70, 70, 5, 0x70, 0x10, 2, 1), - - PIN_FIELD_BASE(73, 73, 4, 0x80, 0x10, 3, 1), - PIN_FIELD_BASE(74, 74, 4, 0x80, 0x10, 0, 1), - - PIN_FIELD_BASE(80, 80, 1, 0x90, 0x10, 16, 1), - PIN_FIELD_BASE(81, 81, 1, 0x90, 0x10, 17, 1), - PIN_FIELD_BASE(82, 82, 1, 0x90, 0x10, 14, 1), - PIN_FIELD_BASE(83, 83, 1, 0x90, 0x10, 15, 1), -}; - -static const struct mtk_pin_reg_calc mt7988_reg_cals[] = { - [PINCTRL_PIN_REG_MODE] = MTK_RANGE(mt7988_pin_mode_range), - [PINCTRL_PIN_REG_DIR] = MTK_RANGE(mt7988_pin_dir_range), - [PINCTRL_PIN_REG_DI] = MTK_RANGE(mt7988_pin_di_range), - [PINCTRL_PIN_REG_DO] = MTK_RANGE(mt7988_pin_do_range), - [PINCTRL_PIN_REG_SMT] = MTK_RANGE(mt7988_pin_smt_range), - [PINCTRL_PIN_REG_IES] = MTK_RANGE(mt7988_pin_ies_range), - [PINCTRL_PIN_REG_PU] = MTK_RANGE(mt7988_pin_pu_range), - [PINCTRL_PIN_REG_PD] = MTK_RANGE(mt7988_pin_pd_range), - [PINCTRL_PIN_REG_DRV] = MTK_RANGE(mt7988_pin_drv_range), - [PINCTRL_PIN_REG_PUPD] = MTK_RANGE(mt7988_pin_pupd_range), - [PINCTRL_PIN_REG_R0] = MTK_RANGE(mt7988_pin_r0_range), - [PINCTRL_PIN_REG_R1] = MTK_RANGE(mt7988_pin_r1_range), -}; - -static const struct mtk_pin_desc mt7988_pins[] = { - MT7988_PIN(0, "UART2_RXD"), - MT7988_PIN(1, "UART2_TXD"), - MT7988_PIN(2, "UART2_CTS"), - MT7988_PIN(3, "UART2_RTS"), - MT7988_PIN(4, "GPIO_A"), - MT7988_PIN(5, "SMI_0_MDC"), - MT7988_PIN(6, "SMI_0_MDIO"), - MT7988_PIN(7, "PCIE30_2L_0_WAKE_N"), - MT7988_PIN(8, "PCIE30_2L_0_CLKREQ_N"), - MT7988_PIN(9, "PCIE30_1L_1_WAKE_N"), - MT7988_PIN(10, "PCIE30_1L_1_CLKREQ_N"), - MT7988_PIN(11, "GPIO_P"), - MT7988_PIN(12, "WATCHDOG"), - MT7988_PIN(13, "GPIO_RESET"), - MT7988_PIN(14, "GPIO_WPS"), - MT7988_PIN(15, "PMIC_I2C_SCL"), - MT7988_PIN(16, "PMIC_I2C_SDA"), - MT7988_PIN(17, "I2C_1_SCL"), - MT7988_PIN(18, "I2C_1_SDA"), - MT7988_PIN(19, "PCIE30_2L_0_PRESET_N"), - MT7988_PIN(20, "PCIE30_1L_1_PRESET_N"), - MT7988_PIN(21, "PWMD1"), - MT7988_PIN(22, "SPI0_WP"), - MT7988_PIN(23, "SPI0_HOLD"), - MT7988_PIN(24, "SPI0_CSB"), - MT7988_PIN(25, "SPI0_MISO"), - MT7988_PIN(26, "SPI0_MOSI"), - MT7988_PIN(27, "SPI0_CLK"), - MT7988_PIN(28, "SPI1_CSB"), - MT7988_PIN(29, "SPI1_MISO"), - MT7988_PIN(30, "SPI1_MOSI"), - MT7988_PIN(31, "SPI1_CLK"), - MT7988_PIN(32, "SPI2_CLK"), - MT7988_PIN(33, "SPI2_MOSI"), - MT7988_PIN(34, "SPI2_MISO"), - MT7988_PIN(35, "SPI2_CSB"), - MT7988_PIN(36, "SPI2_HOLD"), - MT7988_PIN(37, "SPI2_WP"), - MT7988_PIN(38, "EMMC_RSTB"), - MT7988_PIN(39, "EMMC_DSL"), - MT7988_PIN(40, "EMMC_CK"), - MT7988_PIN(41, "EMMC_CMD"), - MT7988_PIN(42, "EMMC_DATA_7"), - MT7988_PIN(43, "EMMC_DATA_6"), - MT7988_PIN(44, "EMMC_DATA_5"), - MT7988_PIN(45, "EMMC_DATA_4"), - MT7988_PIN(46, "EMMC_DATA_3"), - MT7988_PIN(47, "EMMC_DATA_2"), - MT7988_PIN(48, "EMMC_DATA_1"), - MT7988_PIN(49, "EMMC_DATA_0"), - MT7988_PIN(50, "PCM_FS_I2S_LRCK"), - MT7988_PIN(51, "PCM_CLK_I2S_BCLK"), - MT7988_PIN(52, "PCM_DRX_I2S_DIN"), - MT7988_PIN(53, "PCM_DTX_I2S_DOUT"), - MT7988_PIN(54, "PCM_MCK_I2S_MCLK"), - MT7988_PIN(55, "UART0_RXD"), - MT7988_PIN(56, "UART0_TXD"), - MT7988_PIN(57, "PWMD0"), - MT7988_PIN(58, "JTAG_JTDI"), - MT7988_PIN(59, "JTAG_JTDO"), - MT7988_PIN(60, "JTAG_JTMS"), - MT7988_PIN(61, "JTAG_JTCLK"), - MT7988_PIN(62, "JTAG_JTRST_N"), - MT7988_PIN(63, "USB_DRV_VBUS_P1"), - MT7988_PIN(64, "LED_A"), - MT7988_PIN(65, "LED_B"), - MT7988_PIN(66, "LED_C"), - MT7988_PIN(67, "LED_D"), - MT7988_PIN(68, "LED_E"), - MT7988_PIN(69, "GPIO_B"), - MT7988_PIN(70, "GPIO_C"), - MT7988_PIN(71, "I2C_2_SCL"), - MT7988_PIN(72, "I2C_2_SDA"), - MT7988_PIN(73, "PCIE30_2L_1_PRESET_N"), - MT7988_PIN(74, "PCIE30_1L_0_PRESET_N"), - MT7988_PIN(75, "PCIE30_2L_1_WAKE_N"), - MT7988_PIN(76, "PCIE30_2L_1_CLKREQ_N"), - MT7988_PIN(77, "PCIE30_1L_0_WAKE_N"), - MT7988_PIN(78, "PCIE30_1L_0_CLKREQ_N"), - MT7988_PIN(79, "USB_DRV_VBUS_P0"), - MT7988_PIN(80, "UART1_RXD"), - MT7988_PIN(81, "UART1_TXD"), - MT7988_PIN(82, "UART1_CTS"), - MT7988_PIN(83, "UART1_RTS"), -}; - -/* jtag */ -static int mt7988_tops_jtag0_0_pins[] = { 0, 1, 2, 3, 4 }; -static int mt7988_tops_jtag0_0_funcs[] = { 2, 2, 2, 2, 2 }; - -static int mt7988_wo0_jtag_pins[] = { 50, 51, 52, 53, 54 }; -static int mt7988_wo0_jtag_funcs[] = { 3, 3, 3, 3, 3 }; - -static int mt7988_wo1_jtag_pins[] = { 50, 51, 52, 53, 54 }; -static int mt7988_wo1_jtag_funcs[] = { 4, 4, 4, 4, 4 }; - -static int mt7988_wo2_jtag_pins[] = { 50, 51, 52, 53, 54 }; -static int mt7988_wo2_jtag_funcs[] = { 5, 5, 5, 5, 5 }; - -static int mt7988_jtag_pins[] = { 58, 59, 60, 61, 62 }; -static int mt7988_jtag_funcs[] = { 1, 1, 1, 1, 1 }; - -static int mt7988_tops_jtag0_1_pins[] = { 58, 59, 60, 61, 62 }; -static int mt7988_tops_jtag0_1_funcs[] = { 4, 4, 4, 4, 4 }; - -/* int_usxgmii */ -static int mt7988_int_usxgmii_pins[] = { 2, 3 }; -static int mt7988_int_usxgmii_funcs[] = { 3, 3 }; - -/* pwm */ -static int mt7988_pwm0_pins[] = { 57 }; -static int mt7988_pwm0_funcs[] = { 1 }; - -static int mt7988_pwm1_pins[] = { 21 }; -static int mt7988_pwm1_funcs[] = { 1 }; - -static int mt7988_pwm2_pins[] = { 80 }; -static int mt7988_pwm2_funcs[] = { 2 }; - -static int mt7988_pwm3_pins[] = { 81 }; -static int mt7988_pwm3_funcs[] = { 2 }; - -static int mt7988_pwm4_pins[] = { 82 }; -static int mt7988_pwm4_funcs[] = { 2 }; - -static int mt7988_pwm5_pins[] = { 83 }; -static int mt7988_pwm5_funcs[] = { 2 }; - -static int mt7988_pwm6_pins[] = { 69 }; -static int mt7988_pwm6_funcs[] = { 3 }; - -static int mt7988_pwm7_pins[] = { 70 }; -static int mt7988_pwm7_funcs[] = { 3 }; - -/* dfd */ -static int mt7988_dfd_pins[] = { 0, 1, 2, 3, 4 }; -static int mt7988_dfd_funcs[] = { 4, 4, 4, 4, 4 }; - -/* i2c */ -static int mt7988_xfi_phy0_i2c0_pins[] = { 0, 1 }; -static int mt7988_xfi_phy0_i2c0_funcs[] = { 5, 5 }; - -static int mt7988_xfi_phy1_i2c0_pins[] = { 0, 1 }; -static int mt7988_xfi_phy1_i2c0_funcs[] = { 6, 6 }; - -static int mt7988_xfi_phy_pll_i2c0_pins[] = { 3, 4 }; -static int mt7988_xfi_phy_pll_i2c0_funcs[] = { 5, 5 }; - -static int mt7988_xfi_phy_pll_i2c1_pins[] = { 3, 4 }; -static int mt7988_xfi_phy_pll_i2c1_funcs[] = { 6, 6 }; - -static int mt7988_i2c0_0_pins[] = { 5, 6 }; -static int mt7988_i2c0_0_funcs[] = { 2, 2 }; - -static int mt7988_i2c1_sfp_pins[] = { 5, 6 }; -static int mt7988_i2c1_sfp_funcs[] = { 4, 4 }; - -static int mt7988_xfi_pextp_phy0_i2c_pins[] = { 5, 6 }; -static int mt7988_xfi_pextp_phy0_i2c_funcs[] = { 5, 5 }; - -static int mt7988_xfi_pextp_phy1_i2c_pins[] = { 5, 6 }; -static int mt7988_xfi_pextp_phy1_i2c_funcs[] = { 6, 6 }; - -static int mt7988_i2c0_1_pins[] = { 15, 16 }; -static int mt7988_i2c0_1_funcs[] = { 1, 1 }; - -static int mt7988_u30_phy_i2c0_pins[] = { 15, 16 }; -static int mt7988_u30_phy_i2c0_funcs[] = { 2, 2 }; - -static int mt7988_u32_phy_i2c0_pins[] = { 15, 16 }; -static int mt7988_u32_phy_i2c0_funcs[] = { 3, 3 }; - -static int mt7988_xfi_phy0_i2c1_pins[] = { 15, 16 }; -static int mt7988_xfi_phy0_i2c1_funcs[] = { 5, 5 }; - -static int mt7988_xfi_phy1_i2c1_pins[] = { 15, 16 }; -static int mt7988_xfi_phy1_i2c1_funcs[] = { 6, 6 }; - -static int mt7988_xfi_phy_pll_i2c2_pins[] = { 15, 16 }; -static int mt7988_xfi_phy_pll_i2c2_funcs[] = { 7, 7 }; - -static int mt7988_i2c1_0_pins[] = { 17, 18 }; -static int mt7988_i2c1_0_funcs[] = { 1, 1 }; - -static int mt7988_u30_phy_i2c1_pins[] = { 17, 18 }; -static int mt7988_u30_phy_i2c1_funcs[] = { 2, 2 }; - -static int mt7988_u32_phy_i2c1_pins[] = { 17, 18 }; -static int mt7988_u32_phy_i2c1_funcs[] = { 3, 3 }; - -static int mt7988_xfi_phy_pll_i2c3_pins[] = { 17, 18 }; -static int mt7988_xfi_phy_pll_i2c3_funcs[] = { 4, 4 }; - -static int mt7988_sgmii0_i2c_pins[] = { 17, 18 }; -static int mt7988_sgmii0_i2c_funcs[] = { 5, 5 }; - -static int mt7988_sgmii1_i2c_pins[] = { 17, 18 }; -static int mt7988_sgmii1_i2c_funcs[] = { 6, 6 }; - -static int mt7988_i2c1_2_pins[] = { 69, 70 }; -static int mt7988_i2c1_2_funcs[] = { 2, 2 }; - -static int mt7988_i2c2_0_pins[] = { 69, 70 }; -static int mt7988_i2c2_0_funcs[] = { 4, 4 }; - -static int mt7988_i2c2_1_pins[] = { 71, 72 }; -static int mt7988_i2c2_1_funcs[] = { 1, 1 }; - -/* eth */ -static int mt7988_mdc_mdio0_pins[] = { 5, 6 }; -static int mt7988_mdc_mdio0_funcs[] = { 1, 1 }; - -static int mt7988_2p5g_ext_mdio_pins[] = { 28, 29 }; -static int mt7988_2p5g_ext_mdio_funcs[] = { 6, 6 }; - -static int mt7988_gbe_ext_mdio_pins[] = { 30, 31 }; -static int mt7988_gbe_ext_mdio_funcs[] = { 6, 6 }; - -static int mt7988_mdc_mdio1_pins[] = { 69, 70 }; -static int mt7988_mdc_mdio1_funcs[] = { 1, 1 }; - -/* pcie */ -static int mt7988_pcie_wake_n0_0_pins[] = { 7 }; -static int mt7988_pcie_wake_n0_0_funcs[] = { 1 }; - -static int mt7988_pcie_clk_req_n0_0_pins[] = { 8 }; -static int mt7988_pcie_clk_req_n0_0_funcs[] = { 1 }; - -static int mt7988_pcie_wake_n3_0_pins[] = { 9 }; -static int mt7988_pcie_wake_n3_0_funcs[] = { 1 }; - -static int mt7988_pcie_clk_req_n3_pins[] = { 10 }; -static int mt7988_pcie_clk_req_n3_funcs[] = { 1 }; - -static int mt7988_pcie_clk_req_n0_1_pins[] = { 10 }; -static int mt7988_pcie_clk_req_n0_1_funcs[] = { 2 }; - -static int mt7988_pcie_p0_phy_i2c_pins[] = { 7, 8 }; -static int mt7988_pcie_p0_phy_i2c_funcs[] = { 3, 3 }; - -static int mt7988_pcie_p1_phy_i2c_pins[] = { 7, 8 }; -static int mt7988_pcie_p1_phy_i2c_funcs[] = { 4, 4 }; - -static int mt7988_pcie_p3_phy_i2c_pins[] = { 9, 10 }; -static int mt7988_pcie_p3_phy_i2c_funcs[] = { 4, 4 }; - -static int mt7988_pcie_p2_phy_i2c_pins[] = { 7, 8 }; -static int mt7988_pcie_p2_phy_i2c_funcs[] = { 5, 5 }; - -static int mt7988_ckm_phy_i2c_pins[] = { 9, 10 }; -static int mt7988_ckm_phy_i2c_funcs[] = { 5, 5 }; - -static int mt7988_pcie_wake_n0_1_pins[] = { 13 }; -static int mt7988_pcie_wake_n0_1_funcs[] = { 2 }; - -static int mt7988_pcie_wake_n3_1_pins[] = { 14 }; -static int mt7988_pcie_wake_n3_1_funcs[] = { 2 }; - -static int mt7988_pcie_2l_0_pereset_pins[] = { 19 }; -static int mt7988_pcie_2l_0_pereset_funcs[] = { 1 }; - -static int mt7988_pcie_1l_1_pereset_pins[] = { 20 }; -static int mt7988_pcie_1l_1_pereset_funcs[] = { 1 }; - -static int mt7988_pcie_clk_req_n2_1_pins[] = { 63 }; -static int mt7988_pcie_clk_req_n2_1_funcs[] = { 2 }; - -static int mt7988_pcie_2l_1_pereset_pins[] = { 73 }; -static int mt7988_pcie_2l_1_pereset_funcs[] = { 1 }; - -static int mt7988_pcie_1l_0_pereset_pins[] = { 74 }; -static int mt7988_pcie_1l_0_pereset_funcs[] = { 1 }; - -static int mt7988_pcie_wake_n1_0_pins[] = { 75 }; -static int mt7988_pcie_wake_n1_0_funcs[] = { 1 }; - -static int mt7988_pcie_clk_req_n1_pins[] = { 76 }; -static int mt7988_pcie_clk_req_n1_funcs[] = { 1 }; - -static int mt7988_pcie_wake_n2_0_pins[] = { 77 }; -static int mt7988_pcie_wake_n2_0_funcs[] = { 1 }; - -static int mt7988_pcie_clk_req_n2_0_pins[] = { 78 }; -static int mt7988_pcie_clk_req_n2_0_funcs[] = { 1 }; - -static int mt7988_pcie_wake_n2_1_pins[] = { 79 }; -static int mt7988_pcie_wake_n2_1_funcs[] = { 2 }; - -/* pmic */ -static int mt7988_pmic_pins[] = { 11 }; -static int mt7988_pmic_funcs[] = { 1 }; - -/* watchdog */ -static int mt7988_watchdog_pins[] = { 12 }; -static int mt7988_watchdog_funcs[] = { 1 }; - -/* spi */ -static int mt7988_spi0_wp_hold_pins[] = { 22, 23 }; -static int mt7988_spi0_wp_hold_funcs[] = { 1, 1 }; - -static int mt7988_spi0_pins[] = { 24, 25, 26, 27 }; -static int mt7988_spi0_funcs[] = { 1, 1, 1, 1 }; - -static int mt7988_spi1_pins[] = { 28, 29, 30, 31 }; -static int mt7988_spi1_funcs[] = { 1, 1, 1, 1 }; - -static int mt7988_spi2_pins[] = { 32, 33, 34, 35 }; -static int mt7988_spi2_funcs[] = { 1, 1, 1, 1 }; - -static int mt7988_spi2_wp_hold_pins[] = { 36, 37 }; -static int mt7988_spi2_wp_hold_funcs[] = { 1, 1 }; - -/* flash */ -static int mt7988_snfi_pins[] = { 22, 23, 24, 25, 26, 27 }; -static int mt7988_snfi_funcs[] = { 2, 2, 2, 2, 2, 2 }; - -static int mt7988_emmc_45_pins[] = { - 21, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37 -}; -static int mt7988_emmc_45_funcs[] = { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 }; - -static int mt7988_sdcard_pins[] = { 32, 33, 34, 35, 36, 37 }; -static int mt7988_sdcard_funcs[] = { 5, 5, 5, 5, 5, 5 }; - -static int mt7988_emmc_51_pins[] = { 38, 39, 40, 41, 42, 43, - 44, 45, 46, 47, 48, 49 }; -static int mt7988_emmc_51_funcs[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; - -/* uart */ -static int mt7988_uart2_pins[] = { 0, 1, 2, 3 }; -static int mt7988_uart2_funcs[] = { 1, 1, 1, 1 }; - -static int mt7988_tops_uart0_0_pins[] = { 22, 23 }; -static int mt7988_tops_uart0_0_funcs[] = { 3, 3 }; - -static int mt7988_uart2_0_pins[] = { 28, 29, 30, 31 }; -static int mt7988_uart2_0_funcs[] = { 2, 2, 2, 2 }; - -static int mt7988_uart1_0_pins[] = { 32, 33, 34, 35 }; -static int mt7988_uart1_0_funcs[] = { 2, 2, 2, 2 }; - -static int mt7988_uart2_1_pins[] = { 32, 33, 34, 35 }; -static int mt7988_uart2_1_funcs[] = { 3, 3, 3, 3 }; - -static int mt7988_net_wo0_uart_txd_0_pins[] = { 28 }; -static int mt7988_net_wo0_uart_txd_0_funcs[] = { 3 }; - -static int mt7988_net_wo1_uart_txd_0_pins[] = { 29 }; -static int mt7988_net_wo1_uart_txd_0_funcs[] = { 3 }; - -static int mt7988_net_wo2_uart_txd_0_pins[] = { 30 }; -static int mt7988_net_wo2_uart_txd_0_funcs[] = { 3 }; - -static int mt7988_tops_uart1_0_pins[] = { 28, 29 }; -static int mt7988_tops_uart1_0_funcs[] = { 4, 4 }; - -static int mt7988_tops_uart0_1_pins[] = { 30, 31 }; -static int mt7988_tops_uart0_1_funcs[] = { 4, 4 }; - -static int mt7988_tops_uart1_1_pins[] = { 36, 37 }; -static int mt7988_tops_uart1_1_funcs[] = { 3, 3 }; - -static int mt7988_uart0_pins[] = { 55, 56 }; -static int mt7988_uart0_funcs[] = { 1, 1 }; - -static int mt7988_tops_uart0_2_pins[] = { 55, 56 }; -static int mt7988_tops_uart0_2_funcs[] = { 2, 2 }; - -static int mt7988_uart2_2_pins[] = { 50, 51, 52, 53 }; -static int mt7988_uart2_2_funcs[] = { 2, 2, 2, 2 }; - -static int mt7988_uart1_1_pins[] = { 58, 59, 60, 61 }; -static int mt7988_uart1_1_funcs[] = { 2, 2, 2, 2 }; - -static int mt7988_uart2_3_pins[] = { 58, 59, 60, 61 }; -static int mt7988_uart2_3_funcs[] = { 3, 3, 3, 3 }; - -static int mt7988_uart1_2_pins[] = { 80, 81, 82, 83 }; -static int mt7988_uart1_2_funcs[] = { 1, 1, 1, 1 }; - -static int mt7988_tops_uart1_2_pins[] = { 80, 81 }; -static int mt7988_tops_uart1_2_funcs[] = { - 4, - 4, -}; - -static int mt7988_net_wo0_uart_txd_1_pins[] = { 80 }; -static int mt7988_net_wo0_uart_txd_1_funcs[] = { 3 }; - -static int mt7988_net_wo1_uart_txd_1_pins[] = { 81 }; -static int mt7988_net_wo1_uart_txd_1_funcs[] = { 3 }; - -static int mt7988_net_wo2_uart_txd_1_pins[] = { 82 }; -static int mt7988_net_wo2_uart_txd_1_funcs[] = { 3 }; - -/* udi */ -static int mt7988_udi_pins[] = { 32, 33, 34, 35, 36 }; -static int mt7988_udi_funcs[] = { 4, 4, 4, 4, 4 }; - -/* i2s */ -static int mt7988_i2s_pins[] = { 50, 51, 52, 53, 54 }; -static int mt7988_i2s_funcs[] = { 1, 1, 1, 1, 1 }; - -/* pcm */ -static int mt7988_pcm_pins[] = { 50, 51, 52, 53 }; -static int mt7988_pcm_funcs[] = { 1, 1, 1, 1 }; - -/* led */ -static int mt7988_gbe0_led1_pins[] = { 58 }; -static int mt7988_gbe0_led1_funcs[] = { 6 }; -static int mt7988_gbe1_led1_pins[] = { 59 }; -static int mt7988_gbe1_led1_funcs[] = { 6 }; -static int mt7988_gbe2_led1_pins[] = { 60 }; -static int mt7988_gbe2_led1_funcs[] = { 6 }; -static int mt7988_gbe3_led1_pins[] = { 61 }; -static int mt7988_gbe3_led1_funcs[] = { 6 }; - -static int mt7988_2p5gbe_led1_pins[] = { 62 }; -static int mt7988_2p5gbe_led1_funcs[] = { 6 }; - -static int mt7988_gbe0_led0_pins[] = { 64 }; -static int mt7988_gbe0_led0_funcs[] = { 1 }; -static int mt7988_gbe1_led0_pins[] = { 65 }; -static int mt7988_gbe1_led0_funcs[] = { 1 }; -static int mt7988_gbe2_led0_pins[] = { 66 }; -static int mt7988_gbe2_led0_funcs[] = { 1 }; -static int mt7988_gbe3_led0_pins[] = { 67 }; -static int mt7988_gbe3_led0_funcs[] = { 1 }; - -static int mt7988_2p5gbe_led0_pins[] = { 68 }; -static int mt7988_2p5gbe_led0_funcs[] = { 1 }; - -/* usb */ -static int mt7988_drv_vbus_p1_pins[] = { 63 }; -static int mt7988_drv_vbus_p1_funcs[] = { 1 }; - -static int mt7988_drv_vbus_pins[] = { 79 }; -static int mt7988_drv_vbus_funcs[] = { 1 }; - -static const struct group_desc mt7988_groups[] = { - /* @GPIO(0,1,2,3): uart2 */ - PINCTRL_PIN_GROUP("uart2", mt7988_uart2), - /* @GPIO(0,1,2,3,4): tops_jtag0_0 */ - PINCTRL_PIN_GROUP("tops_jtag0_0", mt7988_tops_jtag0_0), - /* @GPIO(2,3): int_usxgmii */ - PINCTRL_PIN_GROUP("int_usxgmii", mt7988_int_usxgmii), - /* @GPIO(0,1,2,3,4): dfd */ - PINCTRL_PIN_GROUP("dfd", mt7988_dfd), - /* @GPIO(0,1): xfi_phy0_i2c0 */ - PINCTRL_PIN_GROUP("xfi_phy0_i2c0", mt7988_xfi_phy0_i2c0), - /* @GPIO(0,1): xfi_phy1_i2c0 */ - PINCTRL_PIN_GROUP("xfi_phy1_i2c0", mt7988_xfi_phy1_i2c0), - /* @GPIO(3,4): xfi_phy_pll_i2c0 */ - PINCTRL_PIN_GROUP("xfi_phy_pll_i2c0", mt7988_xfi_phy_pll_i2c0), - /* @GPIO(3,4): xfi_phy_pll_i2c1 */ - PINCTRL_PIN_GROUP("xfi_phy_pll_i2c1", mt7988_xfi_phy_pll_i2c1), - /* @GPIO(5,6) i2c0_0 */ - PINCTRL_PIN_GROUP("i2c0_0", mt7988_i2c0_0), - /* @GPIO(5,6) i2c1_sfp */ - PINCTRL_PIN_GROUP("i2c1_sfp", mt7988_i2c1_sfp), - /* @GPIO(5,6) xfi_pextp_phy0_i2c */ - PINCTRL_PIN_GROUP("xfi_pextp_phy0_i2c", mt7988_xfi_pextp_phy0_i2c), - /* @GPIO(5,6) xfi_pextp_phy1_i2c */ - PINCTRL_PIN_GROUP("xfi_pextp_phy1_i2c", mt7988_xfi_pextp_phy1_i2c), - /* @GPIO(5,6) mdc_mdio0 */ - PINCTRL_PIN_GROUP("mdc_mdio0", mt7988_mdc_mdio0), - /* @GPIO(7): pcie_wake_n0_0 */ - PINCTRL_PIN_GROUP("pcie_wake_n0_0", mt7988_pcie_wake_n0_0), - /* @GPIO(8): pcie_clk_req_n0_0 */ - PINCTRL_PIN_GROUP("pcie_clk_req_n0_0", mt7988_pcie_clk_req_n0_0), - /* @GPIO(9): pcie_wake_n3_0 */ - PINCTRL_PIN_GROUP("pcie_wake_n3_0", mt7988_pcie_wake_n3_0), - /* @GPIO(10): pcie_clk_req_n3 */ - PINCTRL_PIN_GROUP("pcie_clk_req_n3", mt7988_pcie_clk_req_n3), - /* @GPIO(10): pcie_clk_req_n0_1 */ - PINCTRL_PIN_GROUP("pcie_clk_req_n0_1", mt7988_pcie_clk_req_n0_1), - /* @GPIO(7,8) pcie_p0_phy_i2c */ - PINCTRL_PIN_GROUP("pcie_p0_phy_i2c", mt7988_pcie_p0_phy_i2c), - /* @GPIO(7,8) pcie_p1_phy_i2c */ - PINCTRL_PIN_GROUP("pcie_p1_phy_i2c", mt7988_pcie_p1_phy_i2c), - /* @GPIO(7,8) pcie_p2_phy_i2c */ - PINCTRL_PIN_GROUP("pcie_p2_phy_i2c", mt7988_pcie_p2_phy_i2c), - /* @GPIO(9,10) pcie_p3_phy_i2c */ - PINCTRL_PIN_GROUP("pcie_p3_phy_i2c", mt7988_pcie_p3_phy_i2c), - /* @GPIO(9,10) ckm_phy_i2c */ - PINCTRL_PIN_GROUP("ckm_phy_i2c", mt7988_ckm_phy_i2c), - /* @GPIO(11): pmic */ - PINCTRL_PIN_GROUP("pcie_pmic", mt7988_pmic), - /* @GPIO(12): watchdog */ - PINCTRL_PIN_GROUP("watchdog", mt7988_watchdog), - /* @GPIO(13): pcie_wake_n0_1 */ - PINCTRL_PIN_GROUP("pcie_wake_n0_1", mt7988_pcie_wake_n0_1), - /* @GPIO(14): pcie_wake_n3_1 */ - PINCTRL_PIN_GROUP("pcie_wake_n3_1", mt7988_pcie_wake_n3_1), - /* @GPIO(15,16) i2c0_1 */ - PINCTRL_PIN_GROUP("i2c0_1", mt7988_i2c0_1), - /* @GPIO(15,16) u30_phy_i2c0 */ - PINCTRL_PIN_GROUP("u30_phy_i2c0", mt7988_u30_phy_i2c0), - /* @GPIO(15,16) u32_phy_i2c0 */ - PINCTRL_PIN_GROUP("u32_phy_i2c0", mt7988_u32_phy_i2c0), - /* @GPIO(15,16) xfi_phy0_i2c1 */ - PINCTRL_PIN_GROUP("xfi_phy0_i2c1", mt7988_xfi_phy0_i2c1), - /* @GPIO(15,16) xfi_phy1_i2c1 */ - PINCTRL_PIN_GROUP("xfi_phy1_i2c1", mt7988_xfi_phy1_i2c1), - /* @GPIO(15,16) xfi_phy_pll_i2c2 */ - PINCTRL_PIN_GROUP("xfi_phy_pll_i2c2", mt7988_xfi_phy_pll_i2c2), - /* @GPIO(17,18) i2c1_0 */ - PINCTRL_PIN_GROUP("i2c1_0", mt7988_i2c1_0), - /* @GPIO(17,18) u30_phy_i2c1 */ - PINCTRL_PIN_GROUP("u30_phy_i2c1", mt7988_u30_phy_i2c1), - /* @GPIO(17,18) u32_phy_i2c1 */ - PINCTRL_PIN_GROUP("u32_phy_i2c1", mt7988_u32_phy_i2c1), - /* @GPIO(17,18) xfi_phy_pll_i2c3 */ - PINCTRL_PIN_GROUP("xfi_phy_pll_i2c3", mt7988_xfi_phy_pll_i2c3), - /* @GPIO(17,18) sgmii0_i2c */ - PINCTRL_PIN_GROUP("sgmii0_i2c", mt7988_sgmii0_i2c), - /* @GPIO(17,18) sgmii1_i2c */ - PINCTRL_PIN_GROUP("sgmii1_i2c", mt7988_sgmii1_i2c), - /* @GPIO(19): pcie_2l_0_pereset */ - PINCTRL_PIN_GROUP("pcie_2l_0_pereset", mt7988_pcie_2l_0_pereset), - /* @GPIO(20): pcie_1l_1_pereset */ - PINCTRL_PIN_GROUP("pcie_1l_1_pereset", mt7988_pcie_1l_1_pereset), - /* @GPIO(21): pwm1 */ - PINCTRL_PIN_GROUP("pwm1", mt7988_pwm1), - /* @GPIO(22,23) spi0_wp_hold */ - PINCTRL_PIN_GROUP("spi0_wp_hold", mt7988_spi0_wp_hold), - /* @GPIO(24,25,26,27) spi0 */ - PINCTRL_PIN_GROUP("spi0", mt7988_spi0), - /* @GPIO(28,29,30,31) spi1 */ - PINCTRL_PIN_GROUP("spi1", mt7988_spi1), - /* @GPIO(32,33,34,35) spi2 */ - PINCTRL_PIN_GROUP("spi2", mt7988_spi2), - /* @GPIO(36,37) spi2_wp_hold */ - PINCTRL_PIN_GROUP("spi2_wp_hold", mt7988_spi2_wp_hold), - /* @GPIO(22,23,24,25,26,27) snfi */ - PINCTRL_PIN_GROUP("snfi", mt7988_snfi), - /* @GPIO(22,23) tops_uart0_0 */ - PINCTRL_PIN_GROUP("tops_uart0_0", mt7988_tops_uart0_0), - /* @GPIO(28,29,30,31) uart2_0 */ - PINCTRL_PIN_GROUP("uart2_0", mt7988_uart2_0), - /* @GPIO(32,33,34,35) uart1_0 */ - PINCTRL_PIN_GROUP("uart1_0", mt7988_uart1_0), - /* @GPIO(32,33,34,35) uart2_1 */ - PINCTRL_PIN_GROUP("uart2_1", mt7988_uart2_1), - /* @GPIO(28) net_wo0_uart_txd_0 */ - PINCTRL_PIN_GROUP("net_wo0_uart_txd_0", mt7988_net_wo0_uart_txd_0), - /* @GPIO(29) net_wo1_uart_txd_0 */ - PINCTRL_PIN_GROUP("net_wo1_uart_txd_0", mt7988_net_wo1_uart_txd_0), - /* @GPIO(30) net_wo2_uart_txd_0 */ - PINCTRL_PIN_GROUP("net_wo2_uart_txd_0", mt7988_net_wo2_uart_txd_0), - /* @GPIO(28,29) tops_uart1_0 */ - PINCTRL_PIN_GROUP("tops_uart0_0", mt7988_tops_uart1_0), - /* @GPIO(30,31) tops_uart0_1 */ - PINCTRL_PIN_GROUP("tops_uart0_1", mt7988_tops_uart0_1), - /* @GPIO(36,37) tops_uart1_1 */ - PINCTRL_PIN_GROUP("tops_uart1_1", mt7988_tops_uart1_1), - /* @GPIO(32,33,34,35,36) udi */ - PINCTRL_PIN_GROUP("udi", mt7988_udi), - /* @GPIO(21,28,29,30,31,32,33,34,35,36,37) emmc_45 */ - PINCTRL_PIN_GROUP("emmc_45", mt7988_emmc_45), - /* @GPIO(32,33,34,35,36,37) sdcard */ - PINCTRL_PIN_GROUP("sdcard", mt7988_sdcard), - /* @GPIO(38,39,40,41,42,43,44,45,46,47,48,49) emmc_51 */ - PINCTRL_PIN_GROUP("emmc_51", mt7988_emmc_51), - /* @GPIO(28,29) 2p5g_ext_mdio */ - PINCTRL_PIN_GROUP("2p5g_ext_mdio", mt7988_2p5g_ext_mdio), - /* @GPIO(30,31) gbe_ext_mdio */ - PINCTRL_PIN_GROUP("gbe_ext_mdio", mt7988_gbe_ext_mdio), - /* @GPIO(50,51,52,53,54) i2s */ - PINCTRL_PIN_GROUP("i2s", mt7988_i2s), - /* @GPIO(50,51,52,53) pcm */ - PINCTRL_PIN_GROUP("pcm", mt7988_pcm), - /* @GPIO(55,56) uart0 */ - PINCTRL_PIN_GROUP("uart0", mt7988_uart0), - /* @GPIO(55,56) tops_uart0_2 */ - PINCTRL_PIN_GROUP("tops_uart0_2", mt7988_tops_uart0_2), - /* @GPIO(50,51,52,53) uart2_2 */ - PINCTRL_PIN_GROUP("uart2_2", mt7988_uart2_2), - /* @GPIO(50,51,52,53,54) wo0_jtag */ - PINCTRL_PIN_GROUP("wo0_jtag", mt7988_wo0_jtag), - /* @GPIO(50,51,52,53,54) wo1-wo1_jtag */ - PINCTRL_PIN_GROUP("wo1_jtag", mt7988_wo1_jtag), - /* @GPIO(50,51,52,53,54) wo2_jtag */ - PINCTRL_PIN_GROUP("wo2_jtag", mt7988_wo2_jtag), - /* @GPIO(57) pwm0 */ - PINCTRL_PIN_GROUP("pwm0", mt7988_pwm0), - /* @GPIO(58,59,60,61,62) jtag */ - PINCTRL_PIN_GROUP("jtag", mt7988_jtag), - /* @GPIO(58,59,60,61,62) tops_jtag0_1 */ - PINCTRL_PIN_GROUP("tops_jtag0_1", mt7988_tops_jtag0_1), - /* @GPIO(58,59,60,61) uart2_3 */ - PINCTRL_PIN_GROUP("uart2_3", mt7988_uart2_3), - /* @GPIO(58,59,60,61) uart1_1 */ - PINCTRL_PIN_GROUP("uart1_1", mt7988_uart1_1), - /* @GPIO(58,59,60,61) gbe_led1 */ - PINCTRL_PIN_GROUP("gbe0_led1", mt7988_gbe0_led1), - PINCTRL_PIN_GROUP("gbe1_led1", mt7988_gbe1_led1), - PINCTRL_PIN_GROUP("gbe2_led1", mt7988_gbe2_led1), - PINCTRL_PIN_GROUP("gbe3_led1", mt7988_gbe3_led1), - /* @GPIO(62) 2p5gbe_led1 */ - PINCTRL_PIN_GROUP("2p5gbe_led1", mt7988_2p5gbe_led1), - /* @GPIO(64,65,66,67) gbe_led0 */ - PINCTRL_PIN_GROUP("gbe0_led0", mt7988_gbe0_led0), - PINCTRL_PIN_GROUP("gbe1_led0", mt7988_gbe1_led0), - PINCTRL_PIN_GROUP("gbe2_led0", mt7988_gbe2_led0), - PINCTRL_PIN_GROUP("gbe3_led0", mt7988_gbe3_led0), - /* @GPIO(68) 2p5gbe_led0 */ - PINCTRL_PIN_GROUP("2p5gbe_led0", mt7988_2p5gbe_led0), - /* @GPIO(63) drv_vbus_p1 */ - PINCTRL_PIN_GROUP("drv_vbus_p1", mt7988_drv_vbus_p1), - /* @GPIO(63) pcie_clk_req_n2_1 */ - PINCTRL_PIN_GROUP("pcie_clk_req_n2_1", mt7988_pcie_clk_req_n2_1), - /* @GPIO(69, 70) mdc_mdio1 */ - PINCTRL_PIN_GROUP("mdc_mdio1", mt7988_mdc_mdio1), - /* @GPIO(69, 70) i2c1_2 */ - PINCTRL_PIN_GROUP("i2c1_2", mt7988_i2c1_2), - /* @GPIO(69) pwm6 */ - PINCTRL_PIN_GROUP("pwm6", mt7988_pwm6), - /* @GPIO(70) pwm7 */ - PINCTRL_PIN_GROUP("pwm7", mt7988_pwm7), - /* @GPIO(69,70) i2c2_0 */ - PINCTRL_PIN_GROUP("i2c2_0", mt7988_i2c2_0), - /* @GPIO(71,72) i2c2_1 */ - PINCTRL_PIN_GROUP("i2c2_1", mt7988_i2c2_1), - /* @GPIO(73) pcie_2l_1_pereset */ - PINCTRL_PIN_GROUP("pcie_2l_1_pereset", mt7988_pcie_2l_1_pereset), - /* @GPIO(74) pcie_1l_0_pereset */ - PINCTRL_PIN_GROUP("pcie_1l_0_pereset", mt7988_pcie_1l_0_pereset), - /* @GPIO(75) pcie_wake_n1_0 */ - PINCTRL_PIN_GROUP("pcie_wake_n1_0", mt7988_pcie_wake_n1_0), - /* @GPIO(76) pcie_clk_req_n1 */ - PINCTRL_PIN_GROUP("pcie_clk_req_n1", mt7988_pcie_clk_req_n1), - /* @GPIO(77) pcie_wake_n2_0 */ - PINCTRL_PIN_GROUP("pcie_wake_n2_0", mt7988_pcie_wake_n2_0), - /* @GPIO(78) pcie_clk_req_n2_0 */ - PINCTRL_PIN_GROUP("pcie_clk_req_n2_0", mt7988_pcie_clk_req_n2_0), - /* @GPIO(79) drv_vbus */ - PINCTRL_PIN_GROUP("drv_vbus", mt7988_drv_vbus), - /* @GPIO(79) pcie_wake_n2_1 */ - PINCTRL_PIN_GROUP("pcie_wake_n2_1", mt7988_pcie_wake_n2_1), - /* @GPIO(80,81,82,83) uart1_2 */ - PINCTRL_PIN_GROUP("uart1_2", mt7988_uart1_2), - /* @GPIO(80) pwm2 */ - PINCTRL_PIN_GROUP("pwm2", mt7988_pwm2), - /* @GPIO(81) pwm3 */ - PINCTRL_PIN_GROUP("pwm3", mt7988_pwm3), - /* @GPIO(82) pwm4 */ - PINCTRL_PIN_GROUP("pwm4", mt7988_pwm4), - /* @GPIO(83) pwm5 */ - PINCTRL_PIN_GROUP("pwm5", mt7988_pwm5), - /* @GPIO(80) net_wo0_uart_txd_0 */ - PINCTRL_PIN_GROUP("net_wo0_uart_txd_0", mt7988_net_wo0_uart_txd_0), - /* @GPIO(81) net_wo1_uart_txd_0 */ - PINCTRL_PIN_GROUP("net_wo1_uart_txd_0", mt7988_net_wo1_uart_txd_0), - /* @GPIO(82) net_wo2_uart_txd_0 */ - PINCTRL_PIN_GROUP("net_wo2_uart_txd_0", mt7988_net_wo2_uart_txd_0), - /* @GPIO(80,81) tops_uart1_2 */ - PINCTRL_PIN_GROUP("tops_uart1_2", mt7988_tops_uart1_2), - /* @GPIO(80) net_wo0_uart_txd_1 */ - PINCTRL_PIN_GROUP("net_wo0_uart_txd_1", mt7988_net_wo0_uart_txd_1), - /* @GPIO(81) net_wo1_uart_txd_1 */ - PINCTRL_PIN_GROUP("net_wo1_uart_txd_1", mt7988_net_wo1_uart_txd_1), - /* @GPIO(82) net_wo2_uart_txd_1 */ - PINCTRL_PIN_GROUP("net_wo2_uart_txd_1", mt7988_net_wo2_uart_txd_1), -}; - -/* Joint those groups owning the same capability in user point of view which - * allows that people tend to use through the device tree. - */ -static const char *mt7988_jtag_groups[] = { - "tops_jtag0_0", "wo0_jtag", "wo1_jtag", - "wo2_jtag", "jtag", "tops_jtag0_1", -}; -static const char *mt7988_int_usxgmii_groups[] = { - "int_usxgmii", -}; -static const char *mt7988_pwm_groups[] = { - "pwm0", "pwm1", "pwm2", "pwm3", "pwm4", "pwm5", "pwm6", "pwm7" -}; -static const char *mt7988_dfd_groups[] = { - "dfd", -}; -static const char *mt7988_i2c_groups[] = { - "xfi_phy0_i2c0", - "xfi_phy1_i2c0", - "xfi_phy_pll_i2c0", - "xfi_phy_pll_i2c1", - "i2c0_0", - "i2c1_sfp", - "xfi_pextp_phy0_i2c", - "xfi_pextp_phy1_i2c", - "i2c0_1", - "u30_phy_i2c0", - "u32_phy_i2c0", - "xfi_phy0_i2c1", - "xfi_phy1_i2c1", - "xfi_phy_pll_i2c2", - "i2c1_0", - "u30_phy_i2c1", - "u32_phy_i2c1", - "xfi_phy_pll_i2c3", - "sgmii0_i2c", - "sgmii1_i2c", - "i2c1_2", - "i2c2_0", - "i2c2_1", -}; -static const char *mt7988_ethernet_groups[] = { - "mdc_mdio0", - "2p5g_ext_mdio", - "gbe_ext_mdio", - "mdc_mdio1", -}; -static const char *mt7988_pcie_groups[] = { - "pcie_wake_n0_0", "pcie_clk_req_n0_0", "pcie_wake_n3_0", - "pcie_clk_req_n3", "pcie_p0_phy_i2c", "pcie_p1_phy_i2c", - "pcie_p3_phy_i2c", "pcie_p2_phy_i2c", "ckm_phy_i2c", - "pcie_wake_n0_1", "pcie_wake_n3_1", "pcie_2l_0_pereset", - "pcie_1l_1_pereset", "pcie_clk_req_n2_1", "pcie_2l_1_pereset", - "pcie_1l_0_pereset", "pcie_wake_n1_0", "pcie_clk_req_n1", - "pcie_wake_n2_0", "pcie_clk_req_n2_0", "pcie_wake_n2_1", - "pcie_clk_req_n0_1" -}; -static const char *mt7988_pmic_groups[] = { - "pmic", -}; -static const char *mt7988_wdt_groups[] = { - "watchdog", -}; -static const char *mt7988_spi_groups[] = { - "spi0", "spi0_wp_hold", "spi1", "spi2", "spi2_wp_hold", -}; -static const char *mt7988_flash_groups[] = { "emmc_45", "sdcard", "snfi", - "emmc_51" }; -static const char *mt7988_uart_groups[] = { - "uart2", - "tops_uart0_0", - "uart2_0", - "uart1_0", - "uart2_1", - "net_wo0_uart_txd_0", - "net_wo1_uart_txd_0", - "net_wo2_uart_txd_0", - "tops_uart1_0", - "ops_uart0_1", - "ops_uart1_1", - "uart0", - "tops_uart0_2", - "uart1_1", - "uart2_3", - "uart1_2", - "tops_uart1_2", - "net_wo0_uart_txd_1", - "net_wo1_uart_txd_1", - "net_wo2_uart_txd_1", -}; -static const char *mt7988_udi_groups[] = { - "udi", -}; -static const char *mt7988_audio_groups[] = { - "i2s", "pcm", -}; -static const char *mt7988_led_groups[] = { - "gbe0_led1", "gbe1_led1", "gbe2_led1", "gbe3_led1", "2p5gbe_led1", - "gbe0_led0", "gbe1_led0", "gbe2_led0", "gbe3_led0", "2p5gbe_led0", - "wf5g_led0", "wf5g_led1", -}; -static const char *mt7988_usb_groups[] = { - "drv_vbus", - "drv_vbus_p1", -}; - -static const struct function_desc mt7988_functions[] = { - { "audio", mt7988_audio_groups, ARRAY_SIZE(mt7988_audio_groups) }, - { "jtag", mt7988_jtag_groups, ARRAY_SIZE(mt7988_jtag_groups) }, - { "int_usxgmii", mt7988_int_usxgmii_groups, - ARRAY_SIZE(mt7988_int_usxgmii_groups) }, - { "pwm", mt7988_pwm_groups, ARRAY_SIZE(mt7988_pwm_groups) }, - { "dfd", mt7988_dfd_groups, ARRAY_SIZE(mt7988_dfd_groups) }, - { "i2c", mt7988_i2c_groups, ARRAY_SIZE(mt7988_i2c_groups) }, - { "eth", mt7988_ethernet_groups, ARRAY_SIZE(mt7988_ethernet_groups) }, - { "pcie", mt7988_pcie_groups, ARRAY_SIZE(mt7988_pcie_groups) }, - { "pmic", mt7988_pmic_groups, ARRAY_SIZE(mt7988_pmic_groups) }, - { "watchdog", mt7988_wdt_groups, ARRAY_SIZE(mt7988_wdt_groups) }, - { "spi", mt7988_spi_groups, ARRAY_SIZE(mt7988_spi_groups) }, - { "flash", mt7988_flash_groups, ARRAY_SIZE(mt7988_flash_groups) }, - { "uart", mt7988_uart_groups, ARRAY_SIZE(mt7988_uart_groups) }, - { "udi", mt7988_udi_groups, ARRAY_SIZE(mt7988_udi_groups) }, - { "usb", mt7988_usb_groups, ARRAY_SIZE(mt7988_usb_groups) }, - { "led", mt7988_led_groups, ARRAY_SIZE(mt7988_led_groups) }, -}; - -static const struct mtk_eint_hw mt7988_eint_hw = { - .port_mask = 7, - .ports = 7, - .ap_num = ARRAY_SIZE(mt7988_pins), - .db_cnt = 16, -}; - -static const char *mt7988_pinctrl_register_base_names[] = { - "gpio_base", "iocfg_tr_base", "iocfg_br_base", - "iocfg_rb_base", "iocfg_lb_base", "iocfg_tl_base", -}; - -static struct mtk_pin_soc mt7988_data = { - .reg_cal = mt7988_reg_cals, - .pins = mt7988_pins, - .npins = ARRAY_SIZE(mt7988_pins), - .grps = mt7988_groups, - .ngrps = ARRAY_SIZE(mt7988_groups), - .funcs = mt7988_functions, - .nfuncs = ARRAY_SIZE(mt7988_functions), - .eint_hw = &mt7988_eint_hw, - .gpio_m = 0, - .ies_present = false, - .base_names = mt7988_pinctrl_register_base_names, - .nbase_names = ARRAY_SIZE(mt7988_pinctrl_register_base_names), - .bias_disable_set = mtk_pinconf_bias_disable_set, - .bias_disable_get = mtk_pinconf_bias_disable_get, - .bias_set = mtk_pinconf_bias_set, - .bias_get = mtk_pinconf_bias_get, - .drive_set = mtk_pinconf_drive_set_rev1, - .drive_get = mtk_pinconf_drive_get_rev1, - .adv_pull_get = mtk_pinconf_adv_pull_get, - .adv_pull_set = mtk_pinconf_adv_pull_set, -}; - -static const struct of_device_id mt7988_pinctrl_of_match[] = { - { - .compatible = "mediatek,mt7988-pinctrl", - }, - {} -}; - -static int mt7988_pinctrl_probe(struct platform_device *pdev) -{ - return mtk_moore_pinctrl_probe(pdev, &mt7988_data); -} - -static struct platform_driver mt7988_pinctrl_driver = { - .driver = { - .name = "mt7988-pinctrl", - .of_match_table = mt7988_pinctrl_of_match, - }, - .probe = mt7988_pinctrl_probe, -}; - -static int __init mt7988_pinctrl_init(void) -{ - return platform_driver_register(&mt7988_pinctrl_driver); -} -arch_initcall(mt7988_pinctrl_init); diff --git a/target/linux/mediatek/files-5.15/include/dt-bindings/clock/mediatek,mt7981-clk.h b/target/linux/mediatek/files-5.15/include/dt-bindings/clock/mediatek,mt7981-clk.h deleted file mode 100644 index 192f8cefb..000000000 --- a/target/linux/mediatek/files-5.15/include/dt-bindings/clock/mediatek,mt7981-clk.h +++ /dev/null @@ -1,215 +0,0 @@ -/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ -/* - * Copyright (c) 2021 MediaTek Inc. - * Author: Wenzhen.Yu - * Author: Jianhui Zhao - * Author: Daniel Golle - */ - -#ifndef _DT_BINDINGS_CLK_MT7981_H -#define _DT_BINDINGS_CLK_MT7981_H - -/* TOPCKGEN */ -#define CLK_TOP_CB_CKSQ_40M 0 -#define CLK_TOP_CB_M_416M 1 -#define CLK_TOP_CB_M_D2 2 -#define CLK_TOP_CB_M_D3 3 -#define CLK_TOP_M_D3_D2 4 -#define CLK_TOP_CB_M_D4 5 -#define CLK_TOP_CB_M_D8 6 -#define CLK_TOP_M_D8_D2 7 -#define CLK_TOP_CB_MM_720M 8 -#define CLK_TOP_CB_MM_D2 9 -#define CLK_TOP_CB_MM_D3 10 -#define CLK_TOP_CB_MM_D3_D5 11 -#define CLK_TOP_CB_MM_D4 12 -#define CLK_TOP_CB_MM_D6 13 -#define CLK_TOP_MM_D6_D2 14 -#define CLK_TOP_CB_MM_D8 15 -#define CLK_TOP_CB_APLL2_196M 16 -#define CLK_TOP_APLL2_D2 17 -#define CLK_TOP_APLL2_D4 18 -#define CLK_TOP_NET1_2500M 19 -#define CLK_TOP_CB_NET1_D4 20 -#define CLK_TOP_CB_NET1_D5 21 -#define CLK_TOP_NET1_D5_D2 22 -#define CLK_TOP_NET1_D5_D4 23 -#define CLK_TOP_CB_NET1_D8 24 -#define CLK_TOP_NET1_D8_D2 25 -#define CLK_TOP_NET1_D8_D4 26 -#define CLK_TOP_CB_NET2_800M 27 -#define CLK_TOP_CB_NET2_D2 28 -#define CLK_TOP_CB_NET2_D4 29 -#define CLK_TOP_NET2_D4_D2 30 -#define CLK_TOP_NET2_D4_D4 31 -#define CLK_TOP_CB_NET2_D6 32 -#define CLK_TOP_CB_WEDMCU_208M 33 -#define CLK_TOP_CB_SGM_325M 34 -#define CLK_TOP_CKSQ_40M_D2 35 -#define CLK_TOP_CB_RTC_32K 36 -#define CLK_TOP_CB_RTC_32P7K 37 -#define CLK_TOP_USB_TX250M 38 -#define CLK_TOP_FAUD 39 -#define CLK_TOP_NFI1X 40 -#define CLK_TOP_USB_EQ_RX250M 41 -#define CLK_TOP_USB_CDR_CK 42 -#define CLK_TOP_USB_LN0_CK 43 -#define CLK_TOP_SPINFI_BCK 44 -#define CLK_TOP_SPI 45 -#define CLK_TOP_SPIM_MST 46 -#define CLK_TOP_UART_BCK 47 -#define CLK_TOP_PWM_BCK 48 -#define CLK_TOP_I2C_BCK 49 -#define CLK_TOP_PEXTP_TL 50 -#define CLK_TOP_EMMC_208M 51 -#define CLK_TOP_EMMC_400M 52 -#define CLK_TOP_DRAMC_REF 53 -#define CLK_TOP_DRAMC_MD32 54 -#define CLK_TOP_SYSAXI 55 -#define CLK_TOP_SYSAPB 56 -#define CLK_TOP_ARM_DB_MAIN 57 -#define CLK_TOP_AP2CNN_HOST 58 -#define CLK_TOP_NETSYS 59 -#define CLK_TOP_NETSYS_500M 60 -#define CLK_TOP_NETSYS_WED_MCU 61 -#define CLK_TOP_NETSYS_2X 62 -#define CLK_TOP_SGM_325M 63 -#define CLK_TOP_SGM_REG 64 -#define CLK_TOP_F26M 65 -#define CLK_TOP_EIP97B 66 -#define CLK_TOP_USB3_PHY 67 -#define CLK_TOP_AUD 68 -#define CLK_TOP_A1SYS 69 -#define CLK_TOP_AUD_L 70 -#define CLK_TOP_A_TUNER 71 -#define CLK_TOP_U2U3_REF 72 -#define CLK_TOP_U2U3_SYS 73 -#define CLK_TOP_U2U3_XHCI 74 -#define CLK_TOP_USB_FRMCNT 75 -#define CLK_TOP_NFI1X_SEL 76 -#define CLK_TOP_SPINFI_SEL 77 -#define CLK_TOP_SPI_SEL 78 -#define CLK_TOP_SPIM_MST_SEL 79 -#define CLK_TOP_UART_SEL 80 -#define CLK_TOP_PWM_SEL 81 -#define CLK_TOP_I2C_SEL 82 -#define CLK_TOP_PEXTP_TL_SEL 83 -#define CLK_TOP_EMMC_208M_SEL 84 -#define CLK_TOP_EMMC_400M_SEL 85 -#define CLK_TOP_F26M_SEL 86 -#define CLK_TOP_DRAMC_SEL 87 -#define CLK_TOP_DRAMC_MD32_SEL 88 -#define CLK_TOP_SYSAXI_SEL 89 -#define CLK_TOP_SYSAPB_SEL 90 -#define CLK_TOP_ARM_DB_MAIN_SEL 91 -#define CLK_TOP_AP2CNN_HOST_SEL 92 -#define CLK_TOP_NETSYS_SEL 93 -#define CLK_TOP_NETSYS_500M_SEL 94 -#define CLK_TOP_NETSYS_MCU_SEL 95 -#define CLK_TOP_NETSYS_2X_SEL 96 -#define CLK_TOP_SGM_325M_SEL 97 -#define CLK_TOP_SGM_REG_SEL 98 -#define CLK_TOP_EIP97B_SEL 99 -#define CLK_TOP_USB3_PHY_SEL 100 -#define CLK_TOP_AUD_SEL 101 -#define CLK_TOP_A1SYS_SEL 102 -#define CLK_TOP_AUD_L_SEL 103 -#define CLK_TOP_A_TUNER_SEL 104 -#define CLK_TOP_U2U3_SEL 105 -#define CLK_TOP_U2U3_SYS_SEL 106 -#define CLK_TOP_U2U3_XHCI_SEL 107 -#define CLK_TOP_USB_FRMCNT_SEL 108 -#define CLK_TOP_AUD_I2S_M 109 - -/* INFRACFG */ -#define CLK_INFRA_66M_MCK 0 -#define CLK_INFRA_UART0_SEL 1 -#define CLK_INFRA_UART1_SEL 2 -#define CLK_INFRA_UART2_SEL 3 -#define CLK_INFRA_SPI0_SEL 4 -#define CLK_INFRA_SPI1_SEL 5 -#define CLK_INFRA_SPI2_SEL 6 -#define CLK_INFRA_PWM1_SEL 7 -#define CLK_INFRA_PWM2_SEL 8 -#define CLK_INFRA_PWM3_SEL 9 -#define CLK_INFRA_PWM_BSEL 10 -#define CLK_INFRA_PCIE_SEL 11 -#define CLK_INFRA_GPT_STA 12 -#define CLK_INFRA_PWM_HCK 13 -#define CLK_INFRA_PWM_STA 14 -#define CLK_INFRA_PWM1_CK 15 -#define CLK_INFRA_PWM2_CK 16 -#define CLK_INFRA_PWM3_CK 17 -#define CLK_INFRA_CQ_DMA_CK 18 -#define CLK_INFRA_AUD_BUS_CK 19 -#define CLK_INFRA_AUD_26M_CK 20 -#define CLK_INFRA_AUD_L_CK 21 -#define CLK_INFRA_AUD_AUD_CK 22 -#define CLK_INFRA_AUD_EG2_CK 23 -#define CLK_INFRA_DRAMC_26M_CK 24 -#define CLK_INFRA_DBG_CK 25 -#define CLK_INFRA_AP_DMA_CK 26 -#define CLK_INFRA_SEJ_CK 27 -#define CLK_INFRA_SEJ_13M_CK 28 -#define CLK_INFRA_THERM_CK 29 -#define CLK_INFRA_I2C0_CK 30 -#define CLK_INFRA_UART0_CK 31 -#define CLK_INFRA_UART1_CK 32 -#define CLK_INFRA_UART2_CK 33 -#define CLK_INFRA_SPI2_CK 34 -#define CLK_INFRA_SPI2_HCK_CK 35 -#define CLK_INFRA_NFI1_CK 36 -#define CLK_INFRA_SPINFI1_CK 37 -#define CLK_INFRA_NFI_HCK_CK 38 -#define CLK_INFRA_SPI0_CK 39 -#define CLK_INFRA_SPI1_CK 40 -#define CLK_INFRA_SPI0_HCK_CK 41 -#define CLK_INFRA_SPI1_HCK_CK 42 -#define CLK_INFRA_FRTC_CK 43 -#define CLK_INFRA_MSDC_CK 44 -#define CLK_INFRA_MSDC_HCK_CK 45 -#define CLK_INFRA_MSDC_133M_CK 46 -#define CLK_INFRA_MSDC_66M_CK 47 -#define CLK_INFRA_ADC_26M_CK 48 -#define CLK_INFRA_ADC_FRC_CK 49 -#define CLK_INFRA_FBIST2FPC_CK 50 -#define CLK_INFRA_I2C_MCK_CK 51 -#define CLK_INFRA_I2C_PCK_CK 52 -#define CLK_INFRA_IUSB_133_CK 53 -#define CLK_INFRA_IUSB_66M_CK 54 -#define CLK_INFRA_IUSB_SYS_CK 55 -#define CLK_INFRA_IUSB_CK 56 -#define CLK_INFRA_IPCIE_CK 57 -#define CLK_INFRA_IPCIE_PIPE_CK 58 -#define CLK_INFRA_IPCIER_CK 59 -#define CLK_INFRA_IPCIEB_CK 60 - -/* APMIXEDSYS */ -#define CLK_APMIXED_ARMPLL 0 -#define CLK_APMIXED_NET2PLL 1 -#define CLK_APMIXED_MMPLL 2 -#define CLK_APMIXED_SGMPLL 3 -#define CLK_APMIXED_WEDMCUPLL 4 -#define CLK_APMIXED_NET1PLL 5 -#define CLK_APMIXED_MPLL 6 -#define CLK_APMIXED_APLL2 7 - -/* SGMIISYS_0 */ -#define CLK_SGM0_TX_EN 0 -#define CLK_SGM0_RX_EN 1 -#define CLK_SGM0_CK0_EN 2 -#define CLK_SGM0_CDR_CK0_EN 3 - -/* SGMIISYS_1 */ -#define CLK_SGM1_TX_EN 0 -#define CLK_SGM1_RX_EN 1 -#define CLK_SGM1_CK1_EN 2 -#define CLK_SGM1_CDR_CK1_EN 3 - -/* ETHSYS */ -#define CLK_ETH_FE_EN 0 -#define CLK_ETH_GP2_EN 1 -#define CLK_ETH_GP1_EN 2 -#define CLK_ETH_WOCPU0_EN 3 - -#endif /* _DT_BINDINGS_CLK_MT7981_H */ diff --git a/target/linux/mediatek/files-5.15/include/dt-bindings/clock/mediatek,mt7988-clk.h b/target/linux/mediatek/files-5.15/include/dt-bindings/clock/mediatek,mt7988-clk.h deleted file mode 100644 index 77cfea4a8..000000000 --- a/target/linux/mediatek/files-5.15/include/dt-bindings/clock/mediatek,mt7988-clk.h +++ /dev/null @@ -1,276 +0,0 @@ -/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ -/* - * Copyright (c) 2023 MediaTek Inc. - * Author: Sam Shih - * Author: Xiufeng Li - */ - -#ifndef _DT_BINDINGS_CLK_MT7988_H -#define _DT_BINDINGS_CLK_MT7988_H - -/* APMIXEDSYS */ - -#define CLK_APMIXED_NETSYSPLL 0 -#define CLK_APMIXED_MPLL 1 -#define CLK_APMIXED_MMPLL 2 -#define CLK_APMIXED_APLL2 3 -#define CLK_APMIXED_NET1PLL 4 -#define CLK_APMIXED_NET2PLL 5 -#define CLK_APMIXED_WEDMCUPLL 6 -#define CLK_APMIXED_SGMPLL 7 -#define CLK_APMIXED_ARM_B 8 -#define CLK_APMIXED_CCIPLL2_B 9 -#define CLK_APMIXED_USXGMIIPLL 10 -#define CLK_APMIXED_MSDCPLL 11 - -/* TOPCKGEN */ - -#define CLK_TOP_XTAL 0 -#define CLK_TOP_XTAL_D2 1 -#define CLK_TOP_RTC_32K 2 -#define CLK_TOP_RTC_32P7K 3 -#define CLK_TOP_MPLL_D2 4 -#define CLK_TOP_MPLL_D3_D2 5 -#define CLK_TOP_MPLL_D4 6 -#define CLK_TOP_MPLL_D8 7 -#define CLK_TOP_MPLL_D8_D2 8 -#define CLK_TOP_MMPLL_D2 9 -#define CLK_TOP_MMPLL_D3_D5 10 -#define CLK_TOP_MMPLL_D4 11 -#define CLK_TOP_MMPLL_D6_D2 12 -#define CLK_TOP_MMPLL_D8 13 -#define CLK_TOP_APLL2_D4 14 -#define CLK_TOP_NET1PLL_D4 15 -#define CLK_TOP_NET1PLL_D5 16 -#define CLK_TOP_NET1PLL_D5_D2 17 -#define CLK_TOP_NET1PLL_D5_D4 18 -#define CLK_TOP_NET1PLL_D8 19 -#define CLK_TOP_NET1PLL_D8_D2 20 -#define CLK_TOP_NET1PLL_D8_D4 21 -#define CLK_TOP_NET1PLL_D8_D8 22 -#define CLK_TOP_NET1PLL_D8_D16 23 -#define CLK_TOP_NET2PLL_D2 24 -#define CLK_TOP_NET2PLL_D4 25 -#define CLK_TOP_NET2PLL_D4_D4 26 -#define CLK_TOP_NET2PLL_D4_D8 27 -#define CLK_TOP_NET2PLL_D6 28 -#define CLK_TOP_NET2PLL_D8 29 -#define CLK_TOP_NETSYS_SEL 30 -#define CLK_TOP_NETSYS_500M_SEL 31 -#define CLK_TOP_NETSYS_2X_SEL 32 -#define CLK_TOP_NETSYS_GSW_SEL 33 -#define CLK_TOP_ETH_GMII_SEL 34 -#define CLK_TOP_NETSYS_MCU_SEL 35 -#define CLK_TOP_NETSYS_PAO_2X_SEL 36 -#define CLK_TOP_EIP197_SEL 37 -#define CLK_TOP_AXI_INFRA_SEL 38 -#define CLK_TOP_UART_SEL 39 -#define CLK_TOP_EMMC_250M_SEL 40 -#define CLK_TOP_EMMC_400M_SEL 41 -#define CLK_TOP_SPI_SEL 42 -#define CLK_TOP_SPIM_MST_SEL 43 -#define CLK_TOP_NFI1X_SEL 44 -#define CLK_TOP_SPINFI_SEL 45 -#define CLK_TOP_PWM_SEL 46 -#define CLK_TOP_I2C_SEL 47 -#define CLK_TOP_PCIE_MBIST_250M_SEL 48 -#define CLK_TOP_PEXTP_TL_SEL 49 -#define CLK_TOP_PEXTP_TL_P1_SEL 50 -#define CLK_TOP_PEXTP_TL_P2_SEL 51 -#define CLK_TOP_PEXTP_TL_P3_SEL 52 -#define CLK_TOP_USB_SYS_SEL 53 -#define CLK_TOP_USB_SYS_P1_SEL 54 -#define CLK_TOP_USB_XHCI_SEL 55 -#define CLK_TOP_USB_XHCI_P1_SEL 56 -#define CLK_TOP_USB_FRMCNT_SEL 57 -#define CLK_TOP_USB_FRMCNT_P1_SEL 58 -#define CLK_TOP_AUD_SEL 59 -#define CLK_TOP_A1SYS_SEL 60 -#define CLK_TOP_AUD_L_SEL 61 -#define CLK_TOP_A_TUNER_SEL 62 -#define CLK_TOP_SSPXTP_SEL 63 -#define CLK_TOP_USB_PHY_SEL 64 -#define CLK_TOP_USXGMII_SBUS_0_SEL 65 -#define CLK_TOP_USXGMII_SBUS_1_SEL 66 -#define CLK_TOP_SGM_0_SEL 67 -#define CLK_TOP_SGM_SBUS_0_SEL 68 -#define CLK_TOP_SGM_1_SEL 69 -#define CLK_TOP_SGM_SBUS_1_SEL 70 -#define CLK_TOP_XFI_PHY_0_XTAL_SEL 71 -#define CLK_TOP_XFI_PHY_1_XTAL_SEL 72 -#define CLK_TOP_SYSAXI_SEL 73 -#define CLK_TOP_SYSAPB_SEL 74 -#define CLK_TOP_ETH_REFCK_50M_SEL 75 -#define CLK_TOP_ETH_SYS_200M_SEL 76 -#define CLK_TOP_ETH_SYS_SEL 77 -#define CLK_TOP_ETH_XGMII_SEL 78 -#define CLK_TOP_BUS_TOPS_SEL 79 -#define CLK_TOP_NPU_TOPS_SEL 80 -#define CLK_TOP_DRAMC_SEL 81 -#define CLK_TOP_DRAMC_MD32_SEL 82 -#define CLK_TOP_INFRA_F26M_SEL 83 -#define CLK_TOP_PEXTP_P0_SEL 84 -#define CLK_TOP_PEXTP_P1_SEL 85 -#define CLK_TOP_PEXTP_P2_SEL 86 -#define CLK_TOP_PEXTP_P3_SEL 87 -#define CLK_TOP_DA_XTP_GLB_P0_SEL 88 -#define CLK_TOP_DA_XTP_GLB_P1_SEL 89 -#define CLK_TOP_DA_XTP_GLB_P2_SEL 90 -#define CLK_TOP_DA_XTP_GLB_P3_SEL 91 -#define CLK_TOP_CKM_SEL 92 -#define CLK_TOP_DA_SEL 93 -#define CLK_TOP_PEXTP_SEL 94 -#define CLK_TOP_TOPS_P2_26M_SEL 95 -#define CLK_TOP_MCUSYS_BACKUP_625M_SEL 96 -#define CLK_TOP_NETSYS_SYNC_250M_SEL 97 -#define CLK_TOP_MACSEC_SEL 98 -#define CLK_TOP_NETSYS_TOPS_400M_SEL 99 -#define CLK_TOP_NETSYS_PPEFB_250M_SEL 100 -#define CLK_TOP_NETSYS_WARP_SEL 101 -#define CLK_TOP_ETH_MII_SEL 102 -#define CLK_TOP_NPU_SEL 103 -#define CLK_TOP_AUD_I2S_M 104 - -/* MCUSYS */ - -#define CLK_MCU_BUS_DIV_SEL 0 -#define CLK_MCU_ARM_DIV_SEL 1 - -/* INFRACFG_AO */ - -#define CLK_INFRA_MUX_UART0_SEL 0 -#define CLK_INFRA_MUX_UART1_SEL 1 -#define CLK_INFRA_MUX_UART2_SEL 2 -#define CLK_INFRA_MUX_SPI0_SEL 3 -#define CLK_INFRA_MUX_SPI1_SEL 4 -#define CLK_INFRA_MUX_SPI2_SEL 5 -#define CLK_INFRA_PWM_SEL 6 -#define CLK_INFRA_PWM_CK1_SEL 7 -#define CLK_INFRA_PWM_CK2_SEL 8 -#define CLK_INFRA_PWM_CK3_SEL 9 -#define CLK_INFRA_PWM_CK4_SEL 10 -#define CLK_INFRA_PWM_CK5_SEL 11 -#define CLK_INFRA_PWM_CK6_SEL 12 -#define CLK_INFRA_PWM_CK7_SEL 13 -#define CLK_INFRA_PWM_CK8_SEL 14 -#define CLK_INFRA_PCIE_GFMUX_TL_O_P0_SEL 15 -#define CLK_INFRA_PCIE_GFMUX_TL_O_P1_SEL 16 -#define CLK_INFRA_PCIE_GFMUX_TL_O_P2_SEL 17 -#define CLK_INFRA_PCIE_GFMUX_TL_O_P3_SEL 18 - -/* INFRACFG */ - -#define CLK_INFRA_PCIE_PERI_26M_CK_P0 19 -#define CLK_INFRA_PCIE_PERI_26M_CK_P1 20 -#define CLK_INFRA_PCIE_PERI_26M_CK_P2 21 -#define CLK_INFRA_PCIE_PERI_26M_CK_P3 22 -#define CLK_INFRA_66M_GPT_BCK 23 -#define CLK_INFRA_66M_PWM_HCK 24 -#define CLK_INFRA_66M_PWM_BCK 25 -#define CLK_INFRA_66M_PWM_CK1 26 -#define CLK_INFRA_66M_PWM_CK2 27 -#define CLK_INFRA_66M_PWM_CK3 28 -#define CLK_INFRA_66M_PWM_CK4 29 -#define CLK_INFRA_66M_PWM_CK5 30 -#define CLK_INFRA_66M_PWM_CK6 31 -#define CLK_INFRA_66M_PWM_CK7 32 -#define CLK_INFRA_66M_PWM_CK8 33 -#define CLK_INFRA_133M_CQDMA_BCK 34 -#define CLK_INFRA_66M_AUD_SLV_BCK 35 -#define CLK_INFRA_AUD_26M 36 -#define CLK_INFRA_AUD_L 37 -#define CLK_INFRA_AUD_AUD 38 -#define CLK_INFRA_AUD_EG2 39 -#define CLK_INFRA_DRAMC_F26M 40 -#define CLK_INFRA_133M_DBG_ACKM 41 -#define CLK_INFRA_66M_AP_DMA_BCK 42 -#define CLK_INFRA_66M_SEJ_BCK 43 -#define CLK_INFRA_PRE_CK_SEJ_F13M 44 -#define CLK_INFRA_26M_THERM_SYSTEM 45 -#define CLK_INFRA_I2C_BCK 46 -#define CLK_INFRA_52M_UART0_CK 47 -#define CLK_INFRA_52M_UART1_CK 48 -#define CLK_INFRA_52M_UART2_CK 49 -#define CLK_INFRA_NFI 50 -#define CLK_INFRA_SPINFI 51 -#define CLK_INFRA_66M_NFI_HCK 52 -#define CLK_INFRA_104M_SPI0 53 -#define CLK_INFRA_104M_SPI1 54 -#define CLK_INFRA_104M_SPI2_BCK 55 -#define CLK_INFRA_66M_SPI0_HCK 56 -#define CLK_INFRA_66M_SPI1_HCK 57 -#define CLK_INFRA_66M_SPI2_HCK 58 -#define CLK_INFRA_66M_FLASHIF_AXI 59 -#define CLK_INFRA_RTC 60 -#define CLK_INFRA_26M_ADC_BCK 61 -#define CLK_INFRA_RC_ADC 62 -#define CLK_INFRA_MSDC400 63 -#define CLK_INFRA_MSDC2_HCK 64 -#define CLK_INFRA_133M_MSDC_0_HCK 65 -#define CLK_INFRA_66M_MSDC_0_HCK 66 -#define CLK_INFRA_133M_CPUM_BCK 67 -#define CLK_INFRA_BIST2FPC 68 -#define CLK_INFRA_I2C_X16W_MCK_CK_P1 69 -#define CLK_INFRA_I2C_X16W_PCK_CK_P1 70 -#define CLK_INFRA_133M_USB_HCK 71 -#define CLK_INFRA_133M_USB_HCK_CK_P1 72 -#define CLK_INFRA_66M_USB_HCK 73 -#define CLK_INFRA_66M_USB_HCK_CK_P1 74 -#define CLK_INFRA_USB_SYS 75 -#define CLK_INFRA_USB_SYS_CK_P1 76 -#define CLK_INFRA_USB_REF 77 -#define CLK_INFRA_USB_CK_P1 78 -#define CLK_INFRA_USB_FRMCNT 79 -#define CLK_INFRA_USB_FRMCNT_CK_P1 80 -#define CLK_INFRA_USB_PIPE 81 -#define CLK_INFRA_USB_PIPE_CK_P1 82 -#define CLK_INFRA_USB_UTMI 83 -#define CLK_INFRA_USB_UTMI_CK_P1 84 -#define CLK_INFRA_USB_XHCI 85 -#define CLK_INFRA_USB_XHCI_CK_P1 86 -#define CLK_INFRA_PCIE_GFMUX_TL_P0 87 -#define CLK_INFRA_PCIE_GFMUX_TL_P1 88 -#define CLK_INFRA_PCIE_GFMUX_TL_P2 89 -#define CLK_INFRA_PCIE_GFMUX_TL_P3 90 -#define CLK_INFRA_PCIE_PIPE_P0 91 -#define CLK_INFRA_PCIE_PIPE_P1 92 -#define CLK_INFRA_PCIE_PIPE_P2 93 -#define CLK_INFRA_PCIE_PIPE_P3 94 -#define CLK_INFRA_133M_PCIE_CK_P0 95 -#define CLK_INFRA_133M_PCIE_CK_P1 96 -#define CLK_INFRA_133M_PCIE_CK_P2 97 -#define CLK_INFRA_133M_PCIE_CK_P3 98 - -/* ETHDMA */ - -#define CLK_ETHDMA_XGP1_EN 0 -#define CLK_ETHDMA_XGP2_EN 1 -#define CLK_ETHDMA_XGP3_EN 2 -#define CLK_ETHDMA_FE_EN 3 -#define CLK_ETHDMA_GP2_EN 4 -#define CLK_ETHDMA_GP1_EN 5 -#define CLK_ETHDMA_GP3_EN 6 -#define CLK_ETHDMA_ESW_EN 7 -#define CLK_ETHDMA_CRYPT0_EN 8 -#define CLK_ETHDMA_NR_CLK 9 - -/* SGMIISYS_0 */ - -#define CLK_SGM0_TX_EN 0 -#define CLK_SGM0_RX_EN 1 -#define CLK_SGMII0_NR_CLK 2 - -/* SGMIISYS_1 */ - -#define CLK_SGM1_TX_EN 0 -#define CLK_SGM1_RX_EN 1 -#define CLK_SGMII1_NR_CLK 2 - -/* ETHWARP */ - -#define CLK_ETHWARP_WOCPU2_EN 0 -#define CLK_ETHWARP_WOCPU1_EN 1 -#define CLK_ETHWARP_WOCPU0_EN 2 -#define CLK_ETHWARP_NR_CLK 3 - -#endif /* _DT_BINDINGS_CLK_MT7988_H */ diff --git a/target/linux/mediatek/files-5.15/include/dt-bindings/clock/mt7986-clk.h b/target/linux/mediatek/files-5.15/include/dt-bindings/clock/mt7986-clk.h deleted file mode 100644 index 5a9b16932..000000000 --- a/target/linux/mediatek/files-5.15/include/dt-bindings/clock/mt7986-clk.h +++ /dev/null @@ -1,169 +0,0 @@ -/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ -/* - * Copyright (c) 2021 MediaTek Inc. - * Author: Sam Shih - */ - -#ifndef _DT_BINDINGS_CLK_MT7986_H -#define _DT_BINDINGS_CLK_MT7986_H - -/* APMIXEDSYS */ - -#define CLK_APMIXED_ARMPLL 0 -#define CLK_APMIXED_NET2PLL 1 -#define CLK_APMIXED_MMPLL 2 -#define CLK_APMIXED_SGMPLL 3 -#define CLK_APMIXED_WEDMCUPLL 4 -#define CLK_APMIXED_NET1PLL 5 -#define CLK_APMIXED_MPLL 6 -#define CLK_APMIXED_APLL2 7 - -/* TOPCKGEN */ - -#define CLK_TOP_XTAL 0 -#define CLK_TOP_XTAL_D2 1 -#define CLK_TOP_RTC_32K 2 -#define CLK_TOP_RTC_32P7K 3 -#define CLK_TOP_MPLL_D2 4 -#define CLK_TOP_MPLL_D4 5 -#define CLK_TOP_MPLL_D8 6 -#define CLK_TOP_MPLL_D8_D2 7 -#define CLK_TOP_MPLL_D3_D2 8 -#define CLK_TOP_MMPLL_D2 9 -#define CLK_TOP_MMPLL_D4 10 -#define CLK_TOP_MMPLL_D8 11 -#define CLK_TOP_MMPLL_D8_D2 12 -#define CLK_TOP_MMPLL_D3_D8 13 -#define CLK_TOP_MMPLL_U2PHY 14 -#define CLK_TOP_APLL2_D4 15 -#define CLK_TOP_NET1PLL_D4 16 -#define CLK_TOP_NET1PLL_D5 17 -#define CLK_TOP_NET1PLL_D5_D2 18 -#define CLK_TOP_NET1PLL_D5_D4 19 -#define CLK_TOP_NET1PLL_D8_D2 20 -#define CLK_TOP_NET1PLL_D8_D4 21 -#define CLK_TOP_NET2PLL_D4 22 -#define CLK_TOP_NET2PLL_D4_D2 23 -#define CLK_TOP_NET2PLL_D3_D2 24 -#define CLK_TOP_WEDMCUPLL_D5_D2 25 -#define CLK_TOP_NFI1X_SEL 26 -#define CLK_TOP_SPINFI_SEL 27 -#define CLK_TOP_SPI_SEL 28 -#define CLK_TOP_SPIM_MST_SEL 29 -#define CLK_TOP_UART_SEL 30 -#define CLK_TOP_PWM_SEL 31 -#define CLK_TOP_I2C_SEL 32 -#define CLK_TOP_PEXTP_TL_SEL 33 -#define CLK_TOP_EMMC_250M_SEL 34 -#define CLK_TOP_EMMC_416M_SEL 35 -#define CLK_TOP_F_26M_ADC_SEL 36 -#define CLK_TOP_DRAMC_SEL 37 -#define CLK_TOP_DRAMC_MD32_SEL 38 -#define CLK_TOP_SYSAXI_SEL 39 -#define CLK_TOP_SYSAPB_SEL 40 -#define CLK_TOP_ARM_DB_MAIN_SEL 41 -#define CLK_TOP_ARM_DB_JTSEL 42 -#define CLK_TOP_NETSYS_SEL 43 -#define CLK_TOP_NETSYS_500M_SEL 44 -#define CLK_TOP_NETSYS_MCU_SEL 45 -#define CLK_TOP_NETSYS_2X_SEL 46 -#define CLK_TOP_SGM_325M_SEL 47 -#define CLK_TOP_SGM_REG_SEL 48 -#define CLK_TOP_A1SYS_SEL 49 -#define CLK_TOP_CONN_MCUSYS_SEL 50 -#define CLK_TOP_EIP_B_SEL 51 -#define CLK_TOP_PCIE_PHY_SEL 52 -#define CLK_TOP_USB3_PHY_SEL 53 -#define CLK_TOP_F26M_SEL 54 -#define CLK_TOP_AUD_L_SEL 55 -#define CLK_TOP_A_TUNER_SEL 56 -#define CLK_TOP_U2U3_SEL 57 -#define CLK_TOP_U2U3_SYS_SEL 58 -#define CLK_TOP_U2U3_XHCI_SEL 59 -#define CLK_TOP_DA_U2_REFSEL 60 -#define CLK_TOP_DA_U2_CK_1P_SEL 61 -#define CLK_TOP_AP2CNN_HOST_SEL 62 -#define CLK_TOP_JTAG 63 - -/* INFRACFG */ - -#define CLK_INFRA_SYSAXI_D2 0 -#define CLK_INFRA_UART0_SEL 1 -#define CLK_INFRA_UART1_SEL 2 -#define CLK_INFRA_UART2_SEL 3 -#define CLK_INFRA_SPI0_SEL 4 -#define CLK_INFRA_SPI1_SEL 5 -#define CLK_INFRA_PWM1_SEL 6 -#define CLK_INFRA_PWM2_SEL 7 -#define CLK_INFRA_PWM_BSEL 8 -#define CLK_INFRA_PCIE_SEL 9 -#define CLK_INFRA_GPT_STA 10 -#define CLK_INFRA_PWM_HCK 11 -#define CLK_INFRA_PWM_STA 12 -#define CLK_INFRA_PWM1_CK 13 -#define CLK_INFRA_PWM2_CK 14 -#define CLK_INFRA_CQ_DMA_CK 15 -#define CLK_INFRA_EIP97_CK 16 -#define CLK_INFRA_AUD_BUS_CK 17 -#define CLK_INFRA_AUD_26M_CK 18 -#define CLK_INFRA_AUD_L_CK 19 -#define CLK_INFRA_AUD_AUD_CK 20 -#define CLK_INFRA_AUD_EG2_CK 21 -#define CLK_INFRA_DRAMC_26M_CK 22 -#define CLK_INFRA_DBG_CK 23 -#define CLK_INFRA_AP_DMA_CK 24 -#define CLK_INFRA_SEJ_CK 25 -#define CLK_INFRA_SEJ_13M_CK 26 -#define CLK_INFRA_THERM_CK 27 -#define CLK_INFRA_I2C0_CK 28 -#define CLK_INFRA_UART0_CK 29 -#define CLK_INFRA_UART1_CK 30 -#define CLK_INFRA_UART2_CK 31 -#define CLK_INFRA_NFI1_CK 32 -#define CLK_INFRA_SPINFI1_CK 33 -#define CLK_INFRA_NFI_HCK_CK 34 -#define CLK_INFRA_SPI0_CK 35 -#define CLK_INFRA_SPI1_CK 36 -#define CLK_INFRA_SPI0_HCK_CK 37 -#define CLK_INFRA_SPI1_HCK_CK 38 -#define CLK_INFRA_FRTC_CK 39 -#define CLK_INFRA_MSDC_CK 40 -#define CLK_INFRA_MSDC_HCK_CK 41 -#define CLK_INFRA_MSDC_133M_CK 42 -#define CLK_INFRA_MSDC_66M_CK 43 -#define CLK_INFRA_ADC_26M_CK 44 -#define CLK_INFRA_ADC_FRC_CK 45 -#define CLK_INFRA_FBIST2FPC_CK 46 -#define CLK_INFRA_IUSB_133_CK 47 -#define CLK_INFRA_IUSB_66M_CK 48 -#define CLK_INFRA_IUSB_SYS_CK 49 -#define CLK_INFRA_IUSB_CK 50 -#define CLK_INFRA_IPCIE_CK 51 -#define CLK_INFRA_IPCIE_PIPE_CK 52 -#define CLK_INFRA_IPCIER_CK 53 -#define CLK_INFRA_IPCIEB_CK 54 -#define CLK_INFRA_TRNG_CK 55 - -/* SGMIISYS_0 */ - -#define CLK_SGMII0_TX250M_EN 0 -#define CLK_SGMII0_RX250M_EN 1 -#define CLK_SGMII0_CDR_REF 2 -#define CLK_SGMII0_CDR_FB 3 - -/* SGMIISYS_1 */ - -#define CLK_SGMII1_TX250M_EN 0 -#define CLK_SGMII1_RX250M_EN 1 -#define CLK_SGMII1_CDR_REF 2 -#define CLK_SGMII1_CDR_FB 3 - -/* ETHSYS */ - -#define CLK_ETH_FE_EN 0 -#define CLK_ETH_GP2_EN 1 -#define CLK_ETH_GP1_EN 2 -#define CLK_ETH_WOCPU1_EN 3 -#define CLK_ETH_WOCPU0_EN 4 - -#endif /* _DT_BINDINGS_CLK_MT7986_H */ diff --git a/target/linux/mediatek/files-5.15/include/dt-bindings/reset/mt7986-resets.h b/target/linux/mediatek/files-5.15/include/dt-bindings/reset/mt7986-resets.h deleted file mode 100644 index af3d16c81..000000000 --- a/target/linux/mediatek/files-5.15/include/dt-bindings/reset/mt7986-resets.h +++ /dev/null @@ -1,55 +0,0 @@ -/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */ -/* - * Copyright (c) 2022 MediaTek Inc. - * Author: Sam Shih - */ - -#ifndef _DT_BINDINGS_RESET_CONTROLLER_MT7986 -#define _DT_BINDINGS_RESET_CONTROLLER_MT7986 - -/* INFRACFG resets */ -#define MT7986_INFRACFG_PEXTP_MAC_SW_RST 6 -#define MT7986_INFRACFG_SSUSB_SW_RST 7 -#define MT7986_INFRACFG_EIP97_SW_RST 8 -#define MT7986_INFRACFG_AUDIO_SW_RST 13 -#define MT7986_INFRACFG_CQ_DMA_SW_RST 14 - -#define MT7986_INFRACFG_TRNG_SW_RST 17 -#define MT7986_INFRACFG_AP_DMA_SW_RST 32 -#define MT7986_INFRACFG_I2C_SW_RST 33 -#define MT7986_INFRACFG_NFI_SW_RST 34 -#define MT7986_INFRACFG_SPI0_SW_RST 35 -#define MT7986_INFRACFG_SPI1_SW_RST 36 -#define MT7986_INFRACFG_UART0_SW_RST 37 -#define MT7986_INFRACFG_UART1_SW_RST 38 -#define MT7986_INFRACFG_UART2_SW_RST 39 -#define MT7986_INFRACFG_AUXADC_SW_RST 43 - -#define MT7986_INFRACFG_APXGPT_SW_RST 66 -#define MT7986_INFRACFG_PWM_SW_RST 68 - -#define MT7986_INFRACFG_SW_RST_NUM 69 - -/* TOPRGU resets */ -#define MT7986_TOPRGU_APMIXEDSYS_SW_RST 0 -#define MT7986_TOPRGU_SGMII0_SW_RST 1 -#define MT7986_TOPRGU_SGMII1_SW_RST 2 -#define MT7986_TOPRGU_INFRA_SW_RST 3 -#define MT7986_TOPRGU_U2PHY_SW_RST 5 -#define MT7986_TOPRGU_PCIE_SW_RST 6 -#define MT7986_TOPRGU_SSUSB_SW_RST 7 -#define MT7986_TOPRGU_ETHDMA_SW_RST 20 -#define MT7986_TOPRGU_CONSYS_SW_RST 23 - -#define MT7986_TOPRGU_SW_RST_NUM 24 - -/* ETHSYS Subsystem resets */ -#define MT7986_ETHSYS_FE_SW_RST 6 -#define MT7986_ETHSYS_PMTR_SW_RST 8 -#define MT7986_ETHSYS_GMAC_SW_RST 23 -#define MT7986_ETHSYS_PPE0_SW_RST 30 -#define MT7986_ETHSYS_PPE1_SW_RST 31 - -#define MT7986_ETHSYS_SW_RST_NUM 32 - -#endif /* _DT_BINDINGS_RESET_CONTROLLER_MT7986 */ diff --git a/target/linux/mediatek/files-6.1/arch/arm64/boot/dts/mediatek/mt7981.dtsi b/target/linux/mediatek/files-6.1/arch/arm64/boot/dts/mediatek/mt7981.dtsi deleted file mode 100644 index 05d4b7d91..000000000 --- a/target/linux/mediatek/files-6.1/arch/arm64/boot/dts/mediatek/mt7981.dtsi +++ /dev/null @@ -1,808 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0 OR MIT) -/* - * Copyright (c) 2020 MediaTek Inc. - * Author: Sam.Shih - * Author: Jianhui Zhao - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/ { - compatible = "mediatek,mt7981"; - interrupt-parent = <&gic>; - #address-cells = <2>; - #size-cells = <2>; - - cpus { - #address-cells = <1>; - #size-cells = <0>; - - cpu@0 { - device_type = "cpu"; - compatible = "arm,cortex-a53"; - enable-method = "psci"; - reg = <0x0>; - }; - - cpu@1 { - device_type = "cpu"; - compatible = "arm,cortex-a53"; - enable-method = "psci"; - reg = <0x1>; - }; - }; - - pwm: pwm@10048000 { - compatible = "mediatek,mt7981-pwm"; - reg = <0 0x10048000 0 0x1000>; - #pwm-cells = <2>; - clocks = <&infracfg CLK_INFRA_PWM_STA>, - <&infracfg CLK_INFRA_PWM_HCK>, - <&infracfg CLK_INFRA_PWM1_CK>, - <&infracfg CLK_INFRA_PWM2_CK>, - <&infracfg CLK_INFRA_PWM3_CK>; - clock-names = "top", "main", "pwm1", "pwm2", "pwm3"; - }; - - fan: pwm-fan { - compatible = "pwm-fan"; - /* cooling level (0, 1, 2, 3) : (0% duty, 50% duty, 75% duty, 100% duty) */ - cooling-levels = <0 128 192 255>; - #cooling-cells = <2>; - status = "disabled"; - }; - - thermal-zones { - cpu_thermal: cpu-thermal { - polling-delay-passive = <1000>; - polling-delay = <1000>; - thermal-sensors = <&thermal 0>; - trips { - cpu_trip_crit: crit { - temperature = <125000>; - hysteresis = <2000>; - type = "critical"; - }; - - cpu_trip_hot: hot { - temperature = <120000>; - hysteresis = <2000>; - type = "hot"; - }; - - cpu_trip_active_high: active-high { - temperature = <115000>; - hysteresis = <2000>; - type = "active"; - }; - - cpu_trip_active_med: active-med { - temperature = <85000>; - hysteresis = <2000>; - type = "active"; - }; - - cpu_trip_active_low: active-low { - temperature = <60000>; - hysteresis = <2000>; - type = "active"; - }; - }; - - cooling-maps { - cpu-active-high { - /* active: set fan to cooling level 3 */ - cooling-device = <&fan 3 3>; - trip = <&cpu_trip_active_high>; - }; - - cpu-active-med { - /* active: set fan to cooling level 2 */ - cooling-device = <&fan 2 2>; - trip = <&cpu_trip_active_med>; - }; - - cpu-active-low { - /* passive: set fan to cooling level 1 */ - cooling-device = <&fan 1 1>; - trip = <&cpu_trip_active_low>; - }; - }; - }; - }; - - thermal: thermal@1100c800 { - #thermal-sensor-cells = <1>; - compatible = "mediatek,mt7981-thermal", "mediatek,mt7986-thermal"; - reg = <0 0x1100c800 0 0x800>; - interrupts = ; - clocks = <&infracfg CLK_INFRA_THERM_CK>, - <&infracfg CLK_INFRA_ADC_26M_CK>; - clock-names = "therm", "auxadc"; - mediatek,auxadc = <&auxadc>; - mediatek,apmixedsys = <&apmixedsys>; - nvmem-cells = <&thermal_calibration>; - nvmem-cell-names = "calibration-data"; - }; - - auxadc: adc@1100d000 { - compatible = "mediatek,mt7981-auxadc", - "mediatek,mt7986-auxadc", - "mediatek,mt7622-auxadc"; - reg = <0 0x1100d000 0 0x1000>; - clocks = <&infracfg CLK_INFRA_ADC_26M_CK>, - <&infracfg CLK_INFRA_ADC_FRC_CK>; - clock-names = "main", "32k"; - #io-channel-cells = <1>; - }; - - wdma: wdma@15104800 { - compatible = "mediatek,wed-wdma"; - reg = <0 0x15104800 0 0x400>, - <0 0x15104c00 0 0x400>; - }; - - ap2woccif: ap2woccif@151a5000 { - compatible = "mediatek,ap2woccif"; - reg = <0 0x151a5000 0 0x1000>, - <0 0x151ad000 0 0x1000>; - interrupt-parent = <&gic>; - interrupts = , - ; - }; - - reserved-memory { - #address-cells = <2>; - #size-cells = <2>; - ranges; - - /* 64 KiB reserved for ramoops/pstore */ - ramoops@42ff0000 { - compatible = "ramoops"; - reg = <0 0x42ff0000 0 0x10000>; - record-size = <0x1000>; - }; - - /* 192 KiB reserved for ARM Trusted Firmware (BL31) */ - secmon_reserved: secmon@43000000 { - reg = <0 0x43000000 0 0x30000>; - no-map; - }; - - wmcpu_emi: wmcpu-reserved@47c80000 { - reg = <0 0x47c80000 0 0x100000>; - no-map; - }; - - wo_emi0: wo-emi@47d80000 { - reg = <0 0x47d80000 0 0x40000>; - no-map; - }; - - wo_data: wo-data@47dc0000 { - reg = <0 0x47dc0000 0 0x240000>; - no-map; - }; - }; - - psci { - compatible = "arm,psci-0.2"; - method = "smc"; - }; - - trng { - compatible = "mediatek,mt7981-rng"; - }; - - clk40m: oscillator@0 { - compatible = "fixed-clock"; - #clock-cells = <0>; - clock-frequency = <40000000>; - clock-output-names = "clkxtal"; - }; - - infracfg: infracfg@10001000 { - compatible = "mediatek,mt7981-infracfg", "syscon"; - reg = <0 0x10001000 0 0x1000>; - #clock-cells = <1>; - }; - - topckgen: topckgen@1001B000 { - compatible = "mediatek,mt7981-topckgen", "syscon"; - reg = <0 0x1001B000 0 0x1000>; - #clock-cells = <1>; - }; - - apmixedsys: apmixedsys@1001E000 { - compatible = "mediatek,mt7981-apmixedsys", "mediatek,mt7986-apmixedsys", "syscon"; - reg = <0 0x1001E000 0 0x1000>; - #clock-cells = <1>; - }; - - timer { - compatible = "arm,armv8-timer"; - interrupt-parent = <&gic>; - clock-frequency = <13000000>; - interrupts = , - , - , - ; - - }; - - watchdog: watchdog@1001c000 { - compatible = "mediatek,mt7986-wdt", - "mediatek,mt6589-wdt"; - reg = <0 0x1001c000 0 0x1000>; - interrupts = ; - #reset-cells = <1>; - status = "disabled"; - }; - - gic: interrupt-controller@c000000 { - compatible = "arm,gic-v3"; - #interrupt-cells = <3>; - interrupt-parent = <&gic>; - interrupt-controller; - reg = <0 0x0c000000 0 0x40000>, /* GICD */ - <0 0x0c080000 0 0x200000>; /* GICR */ - - interrupts = ; - }; - - uart0: serial@11002000 { - compatible = "mediatek,mt6577-uart"; - reg = <0 0x11002000 0 0x400>; - interrupts = ; - clocks = <&infracfg CLK_INFRA_UART0_SEL>, - <&infracfg CLK_INFRA_UART0_CK>; - clock-names = "baud", "bus"; - assigned-clocks = <&topckgen CLK_TOP_UART_SEL>, - <&infracfg CLK_INFRA_UART0_SEL>; - assigned-clock-parents = <&topckgen CLK_TOP_CB_CKSQ_40M>, - <&topckgen CLK_TOP_UART_SEL>; - pinctrl-0 = <&uart0_pins>; - pinctrl-names = "default"; - status = "disabled"; - }; - - uart1: serial@11003000 { - compatible = "mediatek,mt6577-uart"; - reg = <0 0x11003000 0 0x400>; - interrupts = ; - clocks = <&infracfg CLK_INFRA_UART1_SEL>, - <&infracfg CLK_INFRA_UART1_CK>; - clock-names = "baud", "bus"; - assigned-clocks = <&topckgen CLK_TOP_UART_SEL>, - <&infracfg CLK_INFRA_UART1_SEL>; - assigned-clock-parents = <&topckgen CLK_TOP_CB_CKSQ_40M>, - <&topckgen CLK_TOP_UART_SEL>; - status = "disabled"; - }; - - uart2: serial@11004000 { - compatible = "mediatek,mt6577-uart"; - reg = <0 0x11004000 0 0x400>; - interrupts = ; - clocks = <&infracfg CLK_INFRA_UART2_SEL>, - <&infracfg CLK_INFRA_UART2_CK>; - clock-names = "baud", "bus"; - assigned-clocks = <&topckgen CLK_TOP_UART_SEL>, - <&infracfg CLK_INFRA_UART2_SEL>; - assigned-clock-parents = <&topckgen CLK_TOP_CB_CKSQ_40M>, - <&topckgen CLK_TOP_UART_SEL>; - status = "disabled"; - }; - - i2c0: i2c@11007000 { - compatible = "mediatek,mt7981-i2c"; - reg = <0 0x11007000 0 0x1000>, - <0 0x10217080 0 0x80>; - interrupts = ; - clock-div = <1>; - clocks = <&infracfg CLK_INFRA_I2C0_CK>, - <&infracfg CLK_INFRA_AP_DMA_CK>, - <&infracfg CLK_INFRA_I2C_MCK_CK>, - <&infracfg CLK_INFRA_I2C_PCK_CK>; - clock-names = "main", "dma", "arb", "pmic"; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; - }; - - pcie: pcie@11280000 { - compatible = "mediatek,mt7981-pcie", - "mediatek,mt7986-pcie"; - device_type = "pci"; - reg = <0 0x11280000 0 0x4000>; - reg-names = "pcie-mac"; - #address-cells = <3>; - #size-cells = <2>; - interrupts = ; - bus-range = <0x00 0xff>; - ranges = <0x82000000 0 0x20000000 - 0x0 0x20000000 0 0x10000000>; - status = "disabled"; - - clocks = <&infracfg CLK_INFRA_IPCIE_CK>, - <&infracfg CLK_INFRA_IPCIE_PIPE_CK>, - <&infracfg CLK_INFRA_IPCIER_CK>, - <&infracfg CLK_INFRA_IPCIEB_CK>; - - phys = <&u3port0 PHY_TYPE_PCIE>; - phy-names = "pcie-phy"; - - #interrupt-cells = <1>; - interrupt-map-mask = <0 0 0 7>; - interrupt-map = <0 0 0 1 &pcie_intc 0>, - <0 0 0 2 &pcie_intc 1>, - <0 0 0 3 &pcie_intc 2>, - <0 0 0 4 &pcie_intc 3>; - pcie_intc: interrupt-controller { - interrupt-controller; - #address-cells = <0>; - #interrupt-cells = <1>; - }; - }; - - crypto: crypto@10320000 { - compatible = "inside-secure,safexcel-eip97"; - reg = <0 0x10320000 0 0x40000>; - interrupts = , - , - , - ; - interrupt-names = "ring0", "ring1", "ring2", "ring3"; - clocks = <&topckgen CLK_TOP_EIP97B>; - clock-names = "top_eip97_ck"; - assigned-clocks = <&topckgen CLK_TOP_EIP97B_SEL>; - assigned-clock-parents = <&topckgen CLK_TOP_CB_NET1_D5>; - }; - - pio: pinctrl@11d00000 { - compatible = "mediatek,mt7981-pinctrl"; - reg = <0 0x11d00000 0 0x1000>, - <0 0x11c00000 0 0x1000>, - <0 0x11c10000 0 0x1000>, - <0 0x11d20000 0 0x1000>, - <0 0x11e00000 0 0x1000>, - <0 0x11e20000 0 0x1000>, - <0 0x11f00000 0 0x1000>, - <0 0x11f10000 0 0x1000>, - <0 0x1000b000 0 0x1000>; - reg-names = "gpio", "iocfg_rt", "iocfg_rm", - "iocfg_rb", "iocfg_lb", "iocfg_bl", - "iocfg_tm", "iocfg_tl", "eint"; - gpio-controller; - #gpio-cells = <2>; - gpio-ranges = <&pio 0 0 56>; - interrupt-controller; - interrupts = ; - interrupt-parent = <&gic>; - #interrupt-cells = <2>; - - mdio_pins: mdc-mdio-pins { - mux { - function = "eth"; - groups = "smi_mdc_mdio"; - }; - }; - - uart0_pins: uart0-pins { - mux { - function = "uart"; - groups = "uart0"; - }; - }; - - wifi_dbdc_pins: wifi-dbdc-pins { - mux { - function = "eth"; - groups = "wf0_mode1"; - }; - conf { - pins = "WF_HB1", "WF_HB2", "WF_HB3", "WF_HB4", - "WF_HB0", "WF_HB0_B", "WF_HB5", "WF_HB6", - "WF_HB7", "WF_HB8", "WF_HB9", "WF_HB10", - "WF_TOP_CLK", "WF_TOP_DATA", "WF_XO_REQ", - "WF_CBA_RESETB", "WF_DIG_RESETB"; - drive-strength = <4>; - }; - }; - - gbe_led0_pins: gbe-led0-pins { - mux { - function = "led"; - groups = "gbe_led0"; - }; - }; - - gbe_led1_pins: gbe-led1-pins { - mux { - function = "led"; - groups = "gbe_led1"; - }; - }; - }; - - ethsys: syscon@15000000 { - #address-cells = <1>; - #size-cells = <1>; - compatible = "mediatek,mt7981-ethsys", - "mediatek,mt7986-ethsys", - "syscon"; - reg = <0 0x15000000 0 0x1000>; - #clock-cells = <1>; - #reset-cells = <1>; - }; - - wed: wed@15010000 { - compatible = "mediatek,mt7981-wed", - "mediatek,mt7986-wed", - "syscon"; - reg = <0 0x15010000 0 0x1000>; - interrupt-parent = <&gic>; - interrupts = ; - memory-region = <&wo_emi0>, <&wo_data>; - memory-region-names = "wo-emi", "wo-data"; - mediatek,wo-ccif = <&wo_ccif0>; - mediatek,wo-ilm = <&wo_ilm0>; - mediatek,wo-dlm = <&wo_dlm0>; - mediatek,wo-cpuboot = <&wo_cpuboot>; - }; - - eth: ethernet@15100000 { - compatible = "mediatek,mt7981-eth"; - reg = <0 0x15100000 0 0x80000>; - interrupts = , - , - , - ; - clocks = <ðsys CLK_ETH_FE_EN>, - <ðsys CLK_ETH_GP2_EN>, - <ðsys CLK_ETH_GP1_EN>, - <ðsys CLK_ETH_WOCPU0_EN>, - <&sgmiisys0 CLK_SGM0_TX_EN>, - <&sgmiisys0 CLK_SGM0_RX_EN>, - <&sgmiisys0 CLK_SGM0_CK0_EN>, - <&sgmiisys0 CLK_SGM0_CDR_CK0_EN>, - <&sgmiisys1 CLK_SGM1_TX_EN>, - <&sgmiisys1 CLK_SGM1_RX_EN>, - <&sgmiisys1 CLK_SGM1_CK1_EN>, - <&sgmiisys1 CLK_SGM1_CDR_CK1_EN>, - <&topckgen CLK_TOP_SGM_REG>, - <&topckgen CLK_TOP_NETSYS_SEL>, - <&topckgen CLK_TOP_NETSYS_500M_SEL>; - clock-names = "fe", "gp2", "gp1", "wocpu0", - "sgmii_tx250m", "sgmii_rx250m", - "sgmii_cdr_ref", "sgmii_cdr_fb", - "sgmii2_tx250m", "sgmii2_rx250m", - "sgmii2_cdr_ref", "sgmii2_cdr_fb", - "sgmii_ck", "netsys0", "netsys1"; - assigned-clocks = <&topckgen CLK_TOP_NETSYS_2X_SEL>, - <&topckgen CLK_TOP_SGM_325M_SEL>; - assigned-clock-parents = <&topckgen CLK_TOP_CB_NET2_800M>, - <&topckgen CLK_TOP_CB_SGM_325M>; - mediatek,ethsys = <ðsys>; - mediatek,sgmiisys = <&sgmiisys0>, <&sgmiisys1>; - mediatek,infracfg = <&topmisc>; - mediatek,wed = <&wed>; - #reset-cells = <1>; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; - - mdio_bus: mdio-bus { - #address-cells = <1>; - #size-cells = <0>; - - int_gbe_phy: ethernet-phy@0 { - reg = <0>; - compatible = "ethernet-phy-ieee802.3-c22"; - phy-mode = "gmii"; - phy-is-integrated; - nvmem-cells = <&phy_calibration>; - nvmem-cell-names = "phy-cal-data"; - - leds { - #address-cells = <1>; - #size-cells = <0>; - - int_gbe_phy_led0: int-gbe-phy-led0@0 { - reg = <0>; - function = LED_FUNCTION_LAN; - status = "disabled"; - }; - - int_gbe_phy_led1: int-gbe-phy-led1@1 { - reg = <1>; - function = LED_FUNCTION_LAN; - status = "disabled"; - }; - }; - }; - }; - }; - - wo_dlm0: syscon@151e8000 { - compatible = "mediatek,mt7986-wo-dlm", "syscon"; - reg = <0 0x151e8000 0 0x2000>; - }; - - wo_ilm0: syscon@151e0000 { - compatible = "mediatek,mt7986-wo-ilm", "syscon"; - reg = <0 0x151e0000 0 0x8000>; - }; - - wo_cpuboot: syscon@15194000 { - compatible = "mediatek,mt7986-wo-cpuboot", "syscon"; - reg = <0 0x15194000 0 0x1000>; - }; - - wo_ccif0: syscon@151a5000 { - compatible = "mediatek,mt7986-wo-ccif", "syscon"; - reg = <0 0x151a5000 0 0x1000>; - interrupt-parent = <&gic>; - interrupts = ; - }; - - sgmiisys0: syscon@10060000 { - compatible = "mediatek,mt7981-sgmiisys_0", "mediatek,mt7986-sgmiisys_0", "syscon"; - reg = <0 0x10060000 0 0x1000>; - mediatek,pnswap; - #clock-cells = <1>; - }; - - sgmiisys1: syscon@10070000 { - compatible = "mediatek,mt7981-sgmiisys_1", "mediatek,mt7986-sgmiisys_1", "syscon"; - reg = <0 0x10070000 0 0x1000>; - #clock-cells = <1>; - }; - - topmisc: topmisc@11d10000 { - compatible = "mediatek,mt7981-topmisc", "syscon"; - reg = <0 0x11d10000 0 0x10000>; - #clock-cells = <1>; - }; - - snand: snfi@11005000 { - compatible = "mediatek,mt7986-snand"; - reg = <0 0x11005000 0 0x1000>, <0 0x11006000 0 0x1000>; - reg-names = "nfi", "ecc"; - interrupts = ; - clocks = <&infracfg CLK_INFRA_SPINFI1_CK>, - <&infracfg CLK_INFRA_NFI1_CK>, - <&infracfg CLK_INFRA_NFI_HCK_CK>; - clock-names = "pad_clk", "nfi_clk", "nfi_hclk"; - assigned-clocks = <&topckgen CLK_TOP_SPINFI_SEL>, - <&topckgen CLK_TOP_NFI1X_SEL>; - assigned-clock-parents = <&topckgen CLK_TOP_CB_M_D8>, - <&topckgen CLK_TOP_CB_M_D8>; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; - }; - - mmc0: mmc@11230000 { - compatible = "mediatek,mt7986-mmc", - "mediatek,mt7981-mmc"; - reg = <0 0x11230000 0 0x1000>, <0 0x11c20000 0 0x1000>; - interrupts = ; - clocks = <&infracfg CLK_INFRA_MSDC_CK>, - <&infracfg CLK_INFRA_MSDC_HCK_CK>, - <&infracfg CLK_INFRA_MSDC_66M_CK>, - <&infracfg CLK_INFRA_MSDC_133M_CK>; - assigned-clocks = <&topckgen CLK_TOP_EMMC_208M_SEL>, - <&topckgen CLK_TOP_EMMC_400M_SEL>; - assigned-clock-parents = <&topckgen CLK_TOP_CB_M_D2>, - <&topckgen CLK_TOP_CB_NET2_D2>; - clock-names = "source", "hclk", "axi_cg", "ahb_cg"; - status = "disabled"; - }; - - wed_pcie: wed_pcie@10003000 { - compatible = "mediatek,wed_pcie"; - reg = <0 0x10003000 0 0x10>; - }; - - spi0: spi@1100a000 { - compatible = "mediatek,mt7986-spi-ipm", "mediatek,spi-ipm"; - #address-cells = <1>; - #size-cells = <0>; - reg = <0 0x1100a000 0 0x100>; - interrupts = ; - clocks = <&topckgen CLK_TOP_CB_M_D2>, - <&topckgen CLK_TOP_SPI_SEL>, - <&infracfg CLK_INFRA_SPI0_CK>, - <&infracfg CLK_INFRA_SPI0_HCK_CK>; - - clock-names = "parent-clk", "sel-clk", "spi-clk", "hclk"; - status = "disabled"; - }; - - spi1: spi@1100b000 { - compatible = "mediatek,mt7986-spi-ipm", "mediatek,spi-ipm"; - #address-cells = <1>; - #size-cells = <0>; - reg = <0 0x1100b000 0 0x100>; - interrupts = ; - clocks = <&topckgen CLK_TOP_CB_M_D2>, - <&topckgen CLK_TOP_SPIM_MST_SEL>, - <&infracfg CLK_INFRA_SPI1_CK>, - <&infracfg CLK_INFRA_SPI1_HCK_CK>; - clock-names = "parent-clk", "sel-clk", "spi-clk", "hclk"; - status = "disabled"; - }; - - spi2: spi@11009000 { - compatible = "mediatek,mt7986-spi-ipm", "mediatek,spi-ipm"; - #address-cells = <1>; - #size-cells = <0>; - reg = <0 0x11009000 0 0x100>; - interrupts = ; - clocks = <&topckgen CLK_TOP_CB_M_D2>, - <&topckgen CLK_TOP_SPI_SEL>, - <&infracfg CLK_INFRA_SPI2_CK>, - <&infracfg CLK_INFRA_SPI2_HCK_CK>; - clock-names = "parent-clk", "sel-clk", "spi-clk", "hclk"; - status = "disabled"; - }; - - consys: consys@10000000 { - compatible = "mediatek,mt7981-consys"; - reg = <0 0x10000000 0 0x8600000>; - memory-region = <&wmcpu_emi>; - }; - - xhci: usb@11200000 { - compatible = "mediatek,mt7986-xhci", - "mediatek,mtk-xhci"; - reg = <0 0x11200000 0 0x2e00>, - <0 0x11203e00 0 0x0100>; - reg-names = "mac", "ippc"; - interrupts = ; - clocks = <&infracfg CLK_INFRA_IUSB_SYS_CK>, - <&infracfg CLK_INFRA_IUSB_CK>, - <&infracfg CLK_INFRA_IUSB_133_CK>, - <&infracfg CLK_INFRA_IUSB_66M_CK>, - <&topckgen CLK_TOP_U2U3_XHCI_SEL>; - clock-names = "sys_ck", - "ref_ck", - "mcu_ck", - "dma_ck", - "xhci_ck"; - phys = <&u2port0 PHY_TYPE_USB2>, - <&u3port0 PHY_TYPE_USB3>; - vusb33-supply = <®_3p3v>; - status = "disabled"; - }; - - usb_phy: usb-phy@11e10000 { - compatible = "mediatek,mt7981", - "mediatek,generic-tphy-v2"; - #address-cells = <1>; - #size-cells = <1>; - ranges = <0 0 0x11e10000 0x1700>; - status = "disabled"; - - u2port0: usb-phy@0 { - reg = <0x0 0x700>; - clocks = <&topckgen CLK_TOP_USB_FRMCNT_SEL>; - clock-names = "ref"; - #phy-cells = <1>; - }; - - u3port0: usb-phy@700 { - reg = <0x700 0x900>; - clocks = <&topckgen CLK_TOP_USB3_PHY_SEL>; - clock-names = "ref"; - #phy-cells = <1>; - mediatek,syscon-type = <&topmisc 0x218 0>; - status = "okay"; - }; - }; - - reg_3p3v: regulator-3p3v { - compatible = "regulator-fixed"; - regulator-name = "fixed-3.3V"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - regulator-boot-on; - regulator-always-on; - }; - - efuse: efuse@11f20000 { - compatible = "mediatek,mt7981-efuse", - "mediatek,efuse"; - reg = <0 0x11f20000 0 0x1000>; - #address-cells = <1>; - #size-cells = <1>; - status = "okay"; - - thermal_calibration: thermal-calib@274 { - reg = <0x274 0xc>; - }; - - phy_calibration: phy-calib@8dc { - reg = <0x8dc 0x10>; - }; - - comb_rx_imp_p0: usb3-rx-imp@8c8 { - reg = <0x8c8 1>; - bits = <0 5>; - }; - - comb_tx_imp_p0: usb3-tx-imp@8c8 { - reg = <0x8c8 2>; - bits = <5 5>; - }; - - comb_intr_p0: usb3-intr@8c9 { - reg = <0x8c9 1>; - bits = <2 6>; - }; - }; - - afe: audio-controller@11210000 { - compatible = "mediatek,mt79xx-audio"; - reg = <0 0x11210000 0 0x9000>; - interrupts = ; - clocks = <&infracfg CLK_INFRA_AUD_BUS_CK>, - <&infracfg CLK_INFRA_AUD_26M_CK>, - <&infracfg CLK_INFRA_AUD_L_CK>, - <&infracfg CLK_INFRA_AUD_AUD_CK>, - <&infracfg CLK_INFRA_AUD_EG2_CK>, - <&topckgen CLK_TOP_AUD_SEL>; - clock-names = "aud_bus_ck", - "aud_26m_ck", - "aud_l_ck", - "aud_aud_ck", - "aud_eg2_ck", - "aud_sel"; - assigned-clocks = <&topckgen CLK_TOP_AUD_SEL>, - <&topckgen CLK_TOP_A1SYS_SEL>, - <&topckgen CLK_TOP_AUD_L_SEL>, - <&topckgen CLK_TOP_A_TUNER_SEL>; - assigned-clock-parents = <&topckgen CLK_TOP_CB_APLL2_196M>, - <&topckgen CLK_TOP_APLL2_D4>, - <&topckgen CLK_TOP_CB_APLL2_196M>, - <&topckgen CLK_TOP_APLL2_D4>; - status = "disabled"; - }; - - ice: ice_debug { - compatible = "mediatek,mt7981-ice_debug", - "mediatek,mt2701-ice_debug"; - clocks = <&infracfg CLK_INFRA_DBG_CK>; - clock-names = "ice_dbg"; - }; - - wifi: wifi@18000000 { - compatible = "mediatek,mt7981-wmac"; - resets = <&watchdog MT7986_TOPRGU_CONSYS_SW_RST>; - reset-names = "consys"; - pinctrl-0 = <&wifi_dbdc_pins>; - pinctrl-names = "dbdc"; - clocks = <&topckgen CLK_TOP_NETSYS_MCU_SEL>, - <&topckgen CLK_TOP_AP2CNN_HOST_SEL>; - clock-names = "mcu", "ap2conn"; - reg = <0 0x18000000 0 0x1000000>, - <0 0x10003000 0 0x1000>, - <0 0x11d10000 0 0x1000>; - interrupts = , - , - , - ; - memory-region = <&wmcpu_emi>; - status = "disabled"; - }; -}; diff --git a/target/linux/mediatek/files-6.1/arch/arm64/boot/dts/mediatek/mt7986a-rfb-spim-nand.dts b/target/linux/mediatek/files-6.1/arch/arm64/boot/dts/mediatek/mt7986a-rfb-spim-nand.dts deleted file mode 100644 index 83a37150c..000000000 --- a/target/linux/mediatek/files-6.1/arch/arm64/boot/dts/mediatek/mt7986a-rfb-spim-nand.dts +++ /dev/null @@ -1,52 +0,0 @@ -/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */ - -#include "mt7986a-rfb.dtsi" - -/ { - compatible = "mediatek,mt7986a-rfb-snand"; -}; - -&spi0 { - status = "okay"; - - spi_nand: spi_nand@0 { - #address-cells = <1>; - #size-cells = <1>; - compatible = "spi-nand"; - reg = <1>; - spi-max-frequency = <10000000>; - spi-tx-buswidth = <4>; - spi-rx-buswidth = <4>; - - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - partition@0 { - label = "BL2"; - reg = <0x00000 0x0100000>; - read-only; - }; - partition@100000 { - label = "u-boot-env"; - reg = <0x0100000 0x0080000>; - }; - factory: partition@180000 { - label = "Factory"; - reg = <0x180000 0x0200000>; - }; - partition@380000 { - label = "FIP"; - reg = <0x380000 0x0200000>; - }; - partition@580000 { - label = "ubi"; - reg = <0x580000 0x4000000>; - }; - }; - }; -}; - -&wifi { - mediatek,mtd-eeprom = <&factory 0>; -}; diff --git a/target/linux/mediatek/files-6.1/arch/arm64/boot/dts/mediatek/mt7986a-rfb-spim-nor.dts b/target/linux/mediatek/files-6.1/arch/arm64/boot/dts/mediatek/mt7986a-rfb-spim-nor.dts deleted file mode 100644 index 868365a99..000000000 --- a/target/linux/mediatek/files-6.1/arch/arm64/boot/dts/mediatek/mt7986a-rfb-spim-nor.dts +++ /dev/null @@ -1,51 +0,0 @@ -/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */ - -#include "mt7986a-rfb.dtsi" - -/ { - compatible = "mediatek,mt7986a-rfb-snor"; -}; - -&spi0 { - status = "okay"; - - spi_nor: spi_nor@0 { - #address-cells = <1>; - #size-cells = <1>; - compatible = "jedec,spi-nor"; - reg = <0>; - spi-max-frequency = <52000000>; - spi-tx-buswidth = <4>; - spi-rx-buswidth = <4>; - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - partition@00000 { - label = "BL2"; - reg = <0x00000 0x0040000>; - }; - partition@40000 { - label = "u-boot-env"; - reg = <0x40000 0x0010000>; - }; - factory: partition@50000 { - label = "Factory"; - reg = <0x50000 0x00B0000>; - }; - partition@100000 { - label = "FIP"; - reg = <0x100000 0x0080000>; - }; - partition@180000 { - label = "firmware"; - reg = <0x180000 0xE00000>; - }; - }; - }; -}; - -&wifi { - mediatek,mtd-eeprom = <&factory 0>; -}; diff --git a/target/linux/mediatek/files-6.1/arch/arm64/boot/dts/mediatek/mt7986a-rfb.dtsi b/target/linux/mediatek/files-6.1/arch/arm64/boot/dts/mediatek/mt7986a-rfb.dtsi deleted file mode 100644 index 1ab56e37f..000000000 --- a/target/linux/mediatek/files-6.1/arch/arm64/boot/dts/mediatek/mt7986a-rfb.dtsi +++ /dev/null @@ -1,389 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0 OR MIT) -/* - * Copyright (C) 2021 MediaTek Inc. - * Author: Sam.Shih - */ - -/dts-v1/; -#include "mt7986a.dtsi" - -/ { - model = "MediaTek MT7986a RFB"; - compatible = "mediatek,mt7986a-rfb"; - - aliases { - serial0 = &uart0; - }; - - chosen { - stdout-path = "serial0:115200n8"; - }; - - memory { - reg = <0 0x40000000 0 0x40000000>; - }; - - reg_1p8v: regulator-1p8v { - compatible = "regulator-fixed"; - regulator-name = "fixed-1.8V"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - regulator-boot-on; - regulator-always-on; - }; - - reg_3p3v: regulator-3p3v { - compatible = "regulator-fixed"; - regulator-name = "fixed-3.3V"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - regulator-boot-on; - regulator-always-on; - }; - - reg_5v: regulator-5v { - compatible = "regulator-fixed"; - regulator-name = "fixed-5V"; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; - regulator-boot-on; - regulator-always-on; - }; -}; - -ð { - status = "okay"; - - gmac0: mac@0 { - compatible = "mediatek,eth-mac"; - reg = <0>; - phy-mode = "2500base-x"; - - fixed-link { - speed = <2500>; - full-duplex; - pause; - }; - }; - - gmac1: mac@1 { - compatible = "mediatek,eth-mac"; - reg = <1>; - phy-mode = "2500base-x"; - }; - - mdio: mdio-bus { - #address-cells = <1>; - #size-cells = <0>; - }; -}; - -&wifi { - status = "okay"; - pinctrl-names = "default", "dbdc"; - pinctrl-0 = <&wf_2g_5g_pins>; - pinctrl-1 = <&wf_dbdc_pins>; -}; - -&mdio { - phy5: phy@5 { - compatible = "ethernet-phy-id67c9.de0a"; - reg = <5>; - - reset-gpios = <&pio 6 1>; - reset-deassert-us = <20000>; - }; - - phy6: phy@6 { - compatible = "ethernet-phy-id67c9.de0a"; - reg = <6>; - }; - - switch: switch@0 { - compatible = "mediatek,mt7531"; - reg = <31>; - reset-gpios = <&pio 5 0>; - }; -}; - -&crypto { - status = "okay"; -}; - -&mmc0 { - pinctrl-names = "default", "state_uhs"; - pinctrl-0 = <&mmc0_pins_default>; - pinctrl-1 = <&mmc0_pins_uhs>; - bus-width = <8>; - max-frequency = <200000000>; - cap-mmc-highspeed; - mmc-hs200-1_8v; - mmc-hs400-1_8v; - hs400-ds-delay = <0x14014>; - vmmc-supply = <®_3p3v>; - vqmmc-supply = <®_1p8v>; - non-removable; - no-sd; - no-sdio; - status = "okay"; -}; - -&pcie { - pinctrl-names = "default"; - pinctrl-0 = <&pcie_pins>; - status = "okay"; -}; - -&pcie_phy { - status = "okay"; -}; - -&pio { - mmc0_pins_default: mmc0-pins { - mux { - function = "emmc"; - groups = "emmc_51"; - }; - conf-cmd-dat { - pins = "EMMC_DATA_0", "EMMC_DATA_1", "EMMC_DATA_2", - "EMMC_DATA_3", "EMMC_DATA_4", "EMMC_DATA_5", - "EMMC_DATA_6", "EMMC_DATA_7", "EMMC_CMD"; - input-enable; - drive-strength = <4>; - mediatek,pull-up-adv = <1>; /* pull-up 10K */ - }; - conf-clk { - pins = "EMMC_CK"; - drive-strength = <6>; - mediatek,pull-down-adv = <2>; /* pull-down 50K */ - }; - conf-ds { - pins = "EMMC_DSL"; - mediatek,pull-down-adv = <2>; /* pull-down 50K */ - }; - conf-rst { - pins = "EMMC_RSTB"; - drive-strength = <4>; - mediatek,pull-up-adv = <1>; /* pull-up 10K */ - }; - }; - - mmc0_pins_uhs: mmc0-uhs-pins { - mux { - function = "emmc"; - groups = "emmc_51"; - }; - conf-cmd-dat { - pins = "EMMC_DATA_0", "EMMC_DATA_1", "EMMC_DATA_2", - "EMMC_DATA_3", "EMMC_DATA_4", "EMMC_DATA_5", - "EMMC_DATA_6", "EMMC_DATA_7", "EMMC_CMD"; - input-enable; - drive-strength = <4>; - mediatek,pull-up-adv = <1>; /* pull-up 10K */ - }; - conf-clk { - pins = "EMMC_CK"; - drive-strength = <6>; - mediatek,pull-down-adv = <2>; /* pull-down 50K */ - }; - conf-ds { - pins = "EMMC_DSL"; - mediatek,pull-down-adv = <2>; /* pull-down 50K */ - }; - conf-rst { - pins = "EMMC_RSTB"; - drive-strength = <4>; - mediatek,pull-up-adv = <1>; /* pull-up 10K */ - }; - }; - - pcie_pins: pcie-pins { - mux { - function = "pcie"; - groups = "pcie_clk", "pcie_wake", "pcie_pereset"; - }; - }; - - spic_pins_g2: spic-pins-29-to-32 { - mux { - function = "spi"; - groups = "spi1_2"; - }; - }; - - spi_flash_pins: spi-flash-pins-33-to-38 { - mux { - function = "spi"; - groups = "spi0", "spi0_wp_hold"; - }; - conf-pu { - pins = "SPI2_CS", "SPI2_HOLD", "SPI2_WP"; - drive-strength = <8>; - mediatek,pull-up-adv = <0>; /* bias-disable */ - }; - conf-pd { - pins = "SPI2_CLK", "SPI2_MOSI", "SPI2_MISO"; - drive-strength = <8>; - mediatek,pull-down-adv = <0>; /* bias-disable */ - }; - }; - - uart1_pins: uart1-pins { - mux { - function = "uart"; - groups = "uart1"; - }; - }; - - uart2_pins: uart2-pins { - mux { - function = "uart"; - groups = "uart2"; - }; - }; - - wf_2g_5g_pins: wf_2g_5g-pins { - mux { - function = "wifi"; - groups = "wf_2g", "wf_5g"; - }; - conf { - pins = "WF0_HB1", "WF0_HB2", "WF0_HB3", "WF0_HB4", - "WF0_HB0", "WF0_HB0_B", "WF0_HB5", "WF0_HB6", - "WF0_HB7", "WF0_HB8", "WF0_HB9", "WF0_HB10", - "WF0_TOP_CLK", "WF0_TOP_DATA", "WF1_HB1", - "WF1_HB2", "WF1_HB3", "WF1_HB4", "WF1_HB0", - "WF1_HB5", "WF1_HB6", "WF1_HB7", "WF1_HB8", - "WF1_TOP_CLK", "WF1_TOP_DATA"; - drive-strength = <4>; - }; - }; - - wf_dbdc_pins: wf_dbdc-pins { - mux { - function = "wifi"; - groups = "wf_dbdc"; - }; - conf { - pins = "WF0_HB1", "WF0_HB2", "WF0_HB3", "WF0_HB4", - "WF0_HB0", "WF0_HB0_B", "WF0_HB5", "WF0_HB6", - "WF0_HB7", "WF0_HB8", "WF0_HB9", "WF0_HB10", - "WF0_TOP_CLK", "WF0_TOP_DATA", "WF1_HB1", - "WF1_HB2", "WF1_HB3", "WF1_HB4", "WF1_HB0", - "WF1_HB5", "WF1_HB6", "WF1_HB7", "WF1_HB8", - "WF1_TOP_CLK", "WF1_TOP_DATA"; - drive-strength = <4>; - }; - }; -}; - -&spi0 { - pinctrl-names = "default"; - pinctrl-0 = <&spi_flash_pins>; - cs-gpios = <0>, <0>; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; -}; - -&spi1 { - pinctrl-names = "default"; - pinctrl-0 = <&spic_pins_g2>; - status = "okay"; - - proslic_spi: proslic_spi@0 { - compatible = "silabs,proslic_spi"; - reg = <0>; - spi-max-frequency = <10000000>; - spi-cpha = <1>; - spi-cpol = <1>; - channel_count = <1>; - debug_level = <4>; /* 1 = TRC, 2 = DBG, 4 = ERR */ - reset_gpio = <&pio 7 0>; - ig,enable-spi = <1>; /* 1: Enable, 0: Disable */ - }; -}; - -&gmac1 { - phy-mode = "2500base-x"; - phy-connection-type = "2500base-x"; - phy-handle = <&phy6>; -}; - -&switch { - ports { - #address-cells = <1>; - #size-cells = <0>; - - port@0 { - reg = <0>; - label = "lan1"; - }; - - port@1 { - reg = <1>; - label = "lan2"; - }; - - port@2 { - reg = <2>; - label = "lan3"; - }; - - port@3 { - reg = <3>; - label = "lan4"; - }; - - port@4 { - reg = <4>; - label = "wan"; - }; - - port@5 { - reg = <5>; - label = "lan6"; - - phy-mode = "2500base-x"; - phy-handle = <&phy5>; - }; - - port@6 { - reg = <6>; - ethernet = <&gmac0>; - phy-mode = "2500base-x"; - - fixed-link { - speed = <2500>; - full-duplex; - pause; - }; - }; - }; -}; - -&ssusb { - vusb33-supply = <®_3p3v>; - vbus-supply = <®_5v>; - status = "okay"; -}; - -&uart0 { - status = "okay"; -}; - -&uart1 { - pinctrl-names = "default"; - pinctrl-0 = <&uart1_pins>; - status = "okay"; -}; - -&uart2 { - pinctrl-names = "default"; - pinctrl-0 = <&uart2_pins>; - status = "okay"; -}; - -&usb_phy { - status = "okay"; -}; diff --git a/target/linux/mediatek/files-6.1/arch/arm64/boot/dts/mediatek/mt7988a-rfb-emmc.dtso b/target/linux/mediatek/files-6.1/arch/arm64/boot/dts/mediatek/mt7988a-rfb-emmc.dtso deleted file mode 100644 index 3f8ac2ae3..000000000 --- a/target/linux/mediatek/files-6.1/arch/arm64/boot/dts/mediatek/mt7988a-rfb-emmc.dtso +++ /dev/null @@ -1,33 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0 OR MIT) -/* - * Copyright (C) 2021 MediaTek Inc. - * Author: Frank Wunderlich - */ - -/dts-v1/; -/plugin/; - -/ { - compatible = "mediatek,mt7988a-rfb", "mediatek,mt7988a"; - - fragment@0 { - target = <&mmc0>; - __overlay__ { - pinctrl-names = "default", "state_uhs"; - pinctrl-0 = <&mmc0_pins_emmc_51>; - pinctrl-1 = <&mmc0_pins_emmc_51>; - bus-width = <8>; - max-frequency = <200000000>; - cap-mmc-highspeed; - mmc-hs200-1_8v; - mmc-hs400-1_8v; - hs400-ds-delay = <0x12814>; - vqmmc-supply = <®_1p8v>; - vmmc-supply = <®_3p3v>; - non-removable; - no-sd; - no-sdio; - status = "okay"; - }; - }; -}; diff --git a/target/linux/mediatek/files-6.1/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth1-aqr.dtso b/target/linux/mediatek/files-6.1/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth1-aqr.dtso deleted file mode 100644 index d21a61ad1..000000000 --- a/target/linux/mediatek/files-6.1/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth1-aqr.dtso +++ /dev/null @@ -1,41 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0 OR MIT) -/* - * Copyright (C) 2022 MediaTek Inc. - * Author: Sam.Shih - */ - -/dts-v1/; -/plugin/; - -#include - -/ { - compatible = "mediatek,mt7988a-rfb", "mediatek,mt7988a"; - - fragment@0 { - target = <&mdio_bus>; - __overlay__ { - #address-cells = <1>; - #size-cells = <0>; - - /* external Aquantia AQR113C */ - phy0: ethernet-phy@0 { - reg = <0>; - compatible = "ethernet-phy-ieee802.3-c45"; - reset-gpios = <&pio 72 GPIO_ACTIVE_LOW>; - reset-assert-us = <100000>; - reset-deassert-us = <221000>; - }; - }; - }; - - fragment@1 { - target = <&gmac1>; - __overlay__ { - phy-mode = "usxgmii"; - phy-connection-type = "usxgmii"; - phy = <&phy0>; - status = "okay"; - }; - }; -}; diff --git a/target/linux/mediatek/files-6.1/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth1-i2p5g-phy.dtso b/target/linux/mediatek/files-6.1/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth1-i2p5g-phy.dtso deleted file mode 100644 index 86ab7566d..000000000 --- a/target/linux/mediatek/files-6.1/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth1-i2p5g-phy.dtso +++ /dev/null @@ -1,30 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0 OR MIT) -/* - * Copyright (C) 2022 MediaTek Inc. - * Author: Sam.Shih - */ - -/dts-v1/; -/plugin/; - -/ { - compatible = "mediatek,mt7988a-rfb", "mediatek,mt7988a"; - - fragment@0 { - target = <&gmac1>; - __overlay__ { - phy-mode = "internal"; - phy-connection-type = "internal"; - phy = <&int_2p5g_phy>; - status = "okay"; - }; - }; - - fragment@1 { - target = <&int_2p5g_phy>; - __overlay__ { - pinctrl-names = "i2p5gbe-led"; - pinctrl-0 = <&i2p5gbe_led0_pins>; - }; - }; -}; diff --git a/target/linux/mediatek/files-6.1/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth1-mxl.dtso b/target/linux/mediatek/files-6.1/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth1-mxl.dtso deleted file mode 100644 index 34a23bbd7..000000000 --- a/target/linux/mediatek/files-6.1/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth1-mxl.dtso +++ /dev/null @@ -1,39 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0 OR MIT) -/* - * Copyright (C) 2022 MediaTek Inc. - * Author: Sam.Shih - */ - -/dts-v1/; -/plugin/; - -#include - -/ { - compatible = "mediatek,mt7988a-rfb", "mediatek,mt7988a"; - - fragment@0 { - target = <&mdio_bus>; - __overlay__ { - #address-cells = <1>; - #size-cells = <0>; - - /* external Maxlinear GPY211C */ - phy13: ethernet-phy@13 { - reg = <13>; - compatible = "ethernet-phy-ieee802.3-c45"; - phy-mode = "2500base-x"; - }; - }; - }; - - fragment@1 { - target = <&gmac1>; - __overlay__ { - phy-mode = "2500base-x"; - phy-connection-type = "2500base-x"; - phy = <&phy13>; - status = "okay"; - }; - }; -}; diff --git a/target/linux/mediatek/files-6.1/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth1-sfp.dtso b/target/linux/mediatek/files-6.1/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth1-sfp.dtso deleted file mode 100644 index ba40a119c..000000000 --- a/target/linux/mediatek/files-6.1/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth1-sfp.dtso +++ /dev/null @@ -1,47 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0 OR MIT) -/* - * Copyright (C) 2022 MediaTek Inc. - * Author: Sam.Shih - */ - -/dts-v1/; -/plugin/; - -#include - -/ { - compatible = "mediatek,mt7988a-rfb", "mediatek,mt7988a"; - - fragment@0 { - target = <&i2c2>; - __overlay__ { - pinctrl-names = "default"; - pinctrl-0 = <&i2c2_0_pins>; - status = "okay"; - }; - }; - - fragment@1 { - target-path = "/"; - __overlay__ { - sfp_esp1: sfp@1 { - compatible = "sff,sfp"; - i2c-bus = <&i2c2>; - mod-def0-gpios = <&pio 82 GPIO_ACTIVE_LOW>; - los-gpios = <&pio 81 GPIO_ACTIVE_HIGH>; - tx-disable-gpios = <&pio 36 GPIO_ACTIVE_HIGH>; - maximum-power-milliwatt = <3000>; - }; - }; - }; - - fragment@2 { - target = <&gmac1>; - __overlay__ { - phy-mode = "10gbase-r"; - managed = "in-band-status"; - sfp = <&sfp_esp1>; - status = "okay"; - }; - }; -}; diff --git a/target/linux/mediatek/files-6.1/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth2-aqr.dtso b/target/linux/mediatek/files-6.1/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth2-aqr.dtso deleted file mode 100644 index 140391fc4..000000000 --- a/target/linux/mediatek/files-6.1/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth2-aqr.dtso +++ /dev/null @@ -1,41 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0 OR MIT) -/* - * Copyright (C) 2022 MediaTek Inc. - * Author: Sam.Shih - */ - -/dts-v1/; -/plugin/; - -#include - -/ { - compatible = "mediatek,mt7988a-rfb", "mediatek,mt7988a"; - - fragment@0 { - target = <&mdio_bus>; - __overlay__ { - #address-cells = <1>; - #size-cells = <0>; - - /* external Aquantia AQR113C */ - phy8: ethernet-phy@8 { - reg = <8>; - compatible = "ethernet-phy-ieee802.3-c45"; - reset-gpios = <&pio 71 GPIO_ACTIVE_LOW>; - reset-assert-us = <100000>; - reset-deassert-us = <221000>; - }; - }; - }; - - fragment@1 { - target = <&gmac2>; - __overlay__ { - phy-mode = "usxgmii"; - phy-connection-type = "usxgmii"; - phy = <&phy8>; - status = "okay"; - }; - }; -}; diff --git a/target/linux/mediatek/files-6.1/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth2-mxl.dtso b/target/linux/mediatek/files-6.1/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth2-mxl.dtso deleted file mode 100644 index 19e0b2799..000000000 --- a/target/linux/mediatek/files-6.1/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth2-mxl.dtso +++ /dev/null @@ -1,39 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0 OR MIT) -/* - * Copyright (C) 2022 MediaTek Inc. - * Author: Sam.Shih - */ - -/dts-v1/; -/plugin/; - -#include - -/ { - compatible = "mediatek,mt7988a-rfb", "mediatek,mt7988a"; - - fragment@0 { - target = <&mdio_bus>; - __overlay__ { - #address-cells = <1>; - #size-cells = <0>; - - /* external Maxlinear GPY211C */ - phy5: ethernet-phy@5 { - reg = <5>; - compatible = "ethernet-phy-ieee802.3-c45"; - phy-mode = "2500base-x"; - }; - }; - }; - - fragment@1 { - target = <&gmac2>; - __overlay__ { - phy-mode = "2500base-x"; - phy-connection-type = "2500base-x"; - phy = <&phy5>; - status = "okay"; - }; - }; -}; diff --git a/target/linux/mediatek/files-6.1/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth2-sfp.dtso b/target/linux/mediatek/files-6.1/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth2-sfp.dtso deleted file mode 100644 index b9aabd272..000000000 --- a/target/linux/mediatek/files-6.1/arch/arm64/boot/dts/mediatek/mt7988a-rfb-eth2-sfp.dtso +++ /dev/null @@ -1,47 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0 OR MIT) -/* - * Copyright (C) 2022 MediaTek Inc. - * Author: Sam.Shih - */ - -/dts-v1/; -/plugin/; - -#include - -/ { - compatible = "mediatek,mt7988a-rfb", "mediatek,mt7988a"; - - fragment@0 { - target = <&i2c1>; - __overlay__ { - pinctrl-names = "default"; - pinctrl-0 = <&i2c1_sfp_pins>; - status = "okay"; - }; - }; - - fragment@1 { - target-path = "/"; - __overlay__ { - sfp_esp0: sfp@0 { - compatible = "sff,sfp"; - i2c-bus = <&i2c1>; - mod-def0-gpios = <&pio 35 GPIO_ACTIVE_LOW>; - los-gpios = <&pio 33 GPIO_ACTIVE_HIGH>; - tx-disable-gpios = <&pio 29 GPIO_ACTIVE_HIGH>; - maximum-power-milliwatt = <3000>; - }; - }; - }; - - fragment@2 { - target = <&gmac2>; - __overlay__ { - phy-mode = "10gbase-r"; - managed = "in-band-status"; - sfp = <&sfp_esp0>; - status = "okay"; - }; - }; -}; diff --git a/target/linux/mediatek/files-6.1/arch/arm64/boot/dts/mediatek/mt7988a-rfb-sd.dtso b/target/linux/mediatek/files-6.1/arch/arm64/boot/dts/mediatek/mt7988a-rfb-sd.dtso deleted file mode 100644 index 04472cc12..000000000 --- a/target/linux/mediatek/files-6.1/arch/arm64/boot/dts/mediatek/mt7988a-rfb-sd.dtso +++ /dev/null @@ -1,31 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0 OR MIT) -/* - * Copyright (C) 2023 MediaTek Inc. - * Author: Frank Wunderlich - */ - -/dts-v1/; -/plugin/; - -#include - -/ { - compatible = "mediatek,mt7988a-rfb", "mediatek,mt7988a"; - - fragment@1 { - target-path = <&mmc0>; - __overlay__ { - pinctrl-names = "default", "state_uhs"; - pinctrl-0 = <&mmc0_pins_sdcard>; - pinctrl-1 = <&mmc0_pins_sdcard>; - cd-gpios = <&pio 69 GPIO_ACTIVE_LOW>; - bus-width = <4>; - max-frequency = <52000000>; - cap-sd-highspeed; - vmmc-supply = <®_3p3v>; - vqmmc-supply = <®_3p3v>; - no-mmc; - status = "okay"; - }; - }; -}; diff --git a/target/linux/mediatek/files-6.1/arch/arm64/boot/dts/mediatek/mt7988a-rfb-snfi-nand.dtso b/target/linux/mediatek/files-6.1/arch/arm64/boot/dts/mediatek/mt7988a-rfb-snfi-nand.dtso deleted file mode 100644 index 618016517..000000000 --- a/target/linux/mediatek/files-6.1/arch/arm64/boot/dts/mediatek/mt7988a-rfb-snfi-nand.dtso +++ /dev/null @@ -1,69 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0 OR MIT) -/* - * Copyright (C) 2022 MediaTek Inc. - * Author: Sam.Shih - */ - -/dts-v1/; -/plugin/; - -/ { - compatible = "mediatek,mt7988a-rfb", "mediatek,mt7988a"; - - fragment@0 { - target = <&snand>; - __overlay__ { - status = "okay"; - - flash@0 { - compatible = "spi-nand"; - reg = <0>; - spi-max-frequency = <52000000>; - spi-tx-buswidth = <4>; - spi-rx-buswidth = <4>; - mediatek,nmbm; - mediatek,bmt-max-ratio = <1>; - mediatek,bmt-max-reserved-blocks = <64>; - - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - partition@0 { - label = "BL2"; - reg = <0x00000 0x0100000>; - read-only; - }; - - partition@100000 { - label = "u-boot-env"; - reg = <0x0100000 0x0080000>; - }; - - partition@180000 { - label = "Factory"; - reg = <0x180000 0x0400000>; - }; - - partition@580000 { - label = "FIP"; - reg = <0x580000 0x0200000>; - }; - - partition@780000 { - label = "ubi"; - reg = <0x780000 0x7080000>; - }; - }; - }; - }; - }; - - fragment@1 { - target = <&bch>; - __overlay__ { - status = "okay"; - }; - }; -}; diff --git a/target/linux/mediatek/files-6.1/arch/arm64/boot/dts/mediatek/mt7988a-rfb-spim-nand.dtso b/target/linux/mediatek/files-6.1/arch/arm64/boot/dts/mediatek/mt7988a-rfb-spim-nand.dtso deleted file mode 100644 index e63436fa5..000000000 --- a/target/linux/mediatek/files-6.1/arch/arm64/boot/dts/mediatek/mt7988a-rfb-spim-nand.dtso +++ /dev/null @@ -1,64 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0 OR MIT) -/* - * Copyright (C) 2022 MediaTek Inc. - * Author: Sam.Shih - */ - -/dts-v1/; -/plugin/; - -/ { - compatible = "mediatek,mt7988a-rfb", "mediatek,mt7988a"; - - fragment@0 { - target = <&spi0>; - __overlay__ { - pinctrl-names = "default"; - pinctrl-0 = <&spi0_flash_pins>; - status = "okay"; - - flash@0 { - compatible = "spi-nand"; - reg = <0>; - spi-max-frequency = <52000000>; - spi-tx-buswidth = <4>; - spi-rx-buswidth = <4>; - mediatek,nmbm; - mediatek,bmt-max-ratio = <1>; - mediatek,bmt-max-reserved-blocks = <64>; - - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - partition@0 { - label = "BL2"; - reg = <0x00000 0x0100000>; - read-only; - }; - - partition@100000 { - label = "u-boot-env"; - reg = <0x0100000 0x0080000>; - }; - - partition@180000 { - label = "Factory"; - reg = <0x180000 0x0400000>; - }; - - partition@580000 { - label = "FIP"; - reg = <0x580000 0x0200000>; - }; - - partition@780000 { - label = "ubi"; - reg = <0x780000 0x7080000>; - }; - }; - }; - }; - }; -}; diff --git a/target/linux/mediatek/files-6.1/arch/arm64/boot/dts/mediatek/mt7988a-rfb-spim-nor.dtso b/target/linux/mediatek/files-6.1/arch/arm64/boot/dts/mediatek/mt7988a-rfb-spim-nor.dtso deleted file mode 100644 index 33bd57b3f..000000000 --- a/target/linux/mediatek/files-6.1/arch/arm64/boot/dts/mediatek/mt7988a-rfb-spim-nor.dtso +++ /dev/null @@ -1,59 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0 OR MIT) -/* - * Copyright (C) 2022 MediaTek Inc. - * Author: Sam.Shih - */ - -/dts-v1/; -/plugin/; - -/ { - compatible = "mediatek,mt7988a-rfb", "mediatek,mt7988a"; - - fragment@0 { - target = <&spi2>; - __overlay__ { - pinctrl-names = "default"; - pinctrl-0 = <&spi2_flash_pins>; - status = "okay"; - - flash@0 { - #address-cells = <1>; - #size-cells = <1>; - compatible = "jedec,spi-nor"; - spi-cal-enable; - spi-cal-mode = "read-data"; - spi-cal-datalen = <7>; - spi-cal-data = /bits/ 8 < - 0x53 0x46 0x5F 0x42 0x4F 0x4F 0x54>; /* SF_BOOT */ - spi-cal-addrlen = <1>; - spi-cal-addr = /bits/ 32 <0x0>; - reg = <0>; - spi-max-frequency = <52000000>; - spi-tx-bus-width = <4>; - spi-rx-bus-width = <4>; - - partition@00000 { - label = "BL2"; - reg = <0x00000 0x0040000>; - }; - partition@40000 { - label = "u-boot-env"; - reg = <0x40000 0x0010000>; - }; - partition@50000 { - label = "Factory"; - reg = <0x50000 0x0200000>; - }; - partition@250000 { - label = "FIP"; - reg = <0x250000 0x0080000>; - }; - partition@2D0000 { - label = "firmware"; - reg = <0x2D0000 0x1D30000>; - }; - }; - }; - }; -}; diff --git a/target/linux/mediatek/files-6.1/arch/arm64/boot/dts/mediatek/mt7988a-rfb.dts b/target/linux/mediatek/files-6.1/arch/arm64/boot/dts/mediatek/mt7988a-rfb.dts deleted file mode 100644 index 11dbf9830..000000000 --- a/target/linux/mediatek/files-6.1/arch/arm64/boot/dts/mediatek/mt7988a-rfb.dts +++ /dev/null @@ -1,200 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0 OR MIT) -/* - * Copyright (C) 2022 MediaTek Inc. - * Author: Sam.Shih - */ - -/dts-v1/; -#include "mt7988a.dtsi" -#include -#include -#include - -/ { - model = "MediaTek MT7988A Reference Board"; - compatible = "mediatek,mt7988a-rfb", - "mediatek,mt7988"; - - chosen { - bootargs = "console=ttyS0,115200n1 loglevel=8 \ - earlycon=uart8250,mmio32,0x11000000 \ - pci=pcie_bus_perf"; - }; - - memory { - reg = <0 0x40000000 0 0x40000000>; - }; -}; - -ð { - pinctrl-0 = <&mdio0_pins>; - pinctrl-names = "default"; -}; - -&gmac0 { - status = "okay"; -}; - -&cpu0 { - proc-supply = <&rt5190_buck3>; -}; - -&cpu1 { - proc-supply = <&rt5190_buck3>; -}; - -&cpu2 { - proc-supply = <&rt5190_buck3>; -}; - -&cpu3 { - proc-supply = <&rt5190_buck3>; -}; - -&cci { - proc-supply = <&rt5190_buck3>; -}; - -ð { - status = "okay"; -}; - -&switch { - status = "okay"; -}; - -&gsw_phy0 { - pinctrl-names = "gbe-led"; - pinctrl-0 = <&gbe0_led0_pins>; -}; - -&gsw_phy0_led0 { - status = "okay"; - color = ; -}; - -&gsw_phy1 { - pinctrl-names = "gbe-led"; - pinctrl-0 = <&gbe1_led0_pins>; -}; - -&gsw_phy1_led0 { - status = "okay"; - color = ; -}; - -&gsw_phy2 { - pinctrl-names = "gbe-led"; - pinctrl-0 = <&gbe2_led0_pins>; -}; - -&gsw_phy2_led0 { - status = "okay"; - color = ; -}; - -&gsw_phy3 { - pinctrl-names = "gbe-led"; - pinctrl-0 = <&gbe3_led0_pins>; -}; - -&gsw_phy3_led0 { - status = "okay"; - color = ; -}; - -&i2c0 { - pinctrl-names = "default"; - pinctrl-0 = <&i2c0_pins>; - status = "okay"; - - rt5190a_64: rt5190a@64 { - compatible = "richtek,rt5190a"; - reg = <0x64>; - /*interrupts-extended = <&gpio26 0 IRQ_TYPE_LEVEL_LOW>;*/ - vin2-supply = <&rt5190_buck1>; - vin3-supply = <&rt5190_buck1>; - vin4-supply = <&rt5190_buck1>; - - regulators { - rt5190_buck1: buck1 { - regulator-name = "rt5190a-buck1"; - regulator-min-microvolt = <5090000>; - regulator-max-microvolt = <5090000>; - regulator-allowed-modes = - ; - regulator-boot-on; - regulator-always-on; - }; - buck2 { - regulator-name = "vcore"; - regulator-min-microvolt = <600000>; - regulator-max-microvolt = <1400000>; - regulator-boot-on; - regulator-always-on; - }; - rt5190_buck3: buck3 { - regulator-name = "vproc"; - regulator-min-microvolt = <600000>; - regulator-max-microvolt = <1400000>; - regulator-boot-on; - }; - buck4 { - regulator-name = "rt5190a-buck4"; - regulator-min-microvolt = <850000>; - regulator-max-microvolt = <850000>; - regulator-allowed-modes = - ; - regulator-boot-on; - regulator-always-on; - }; - ldo { - regulator-name = "rt5190a-ldo"; - regulator-min-microvolt = <1200000>; - regulator-max-microvolt = <1200000>; - regulator-boot-on; - regulator-always-on; - }; - }; - }; -}; - -&pcie0 { - status = "okay"; -}; - -&pcie1 { - status = "okay"; -}; - -&pcie2 { - status = "disabled"; -}; - -&pcie3 { - status = "okay"; -}; - -&ssusb0 { - status = "okay"; -}; - -&ssusb1 { - status = "okay"; -}; - -&tphy { - status = "okay"; -}; - -&uart0 { - status = "okay"; -}; - -&watchdog { - status = "okay"; -}; - -&xphy { - status = "okay"; -}; diff --git a/target/linux/mediatek/files-6.1/arch/arm64/boot/dts/mediatek/mt7988a.dtsi b/target/linux/mediatek/files-6.1/arch/arm64/boot/dts/mediatek/mt7988a.dtsi deleted file mode 100644 index 7fed1e138..000000000 --- a/target/linux/mediatek/files-6.1/arch/arm64/boot/dts/mediatek/mt7988a.dtsi +++ /dev/null @@ -1,1441 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0 OR MIT) -/* - * Copyright (C) 2023 MediaTek Inc. - * Author: Sam.Shih - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -/ { - compatible = "mediatek,mt7988"; - interrupt-parent = <&gic>; - #address-cells = <2>; - #size-cells = <2>; - - clk40m: oscillator@0 { - compatible = "fixed-clock"; - clock-frequency = <40000000>; - #clock-cells = <0>; - clock-output-names = "clkxtal"; - }; - - cpus { - #address-cells = <1>; - #size-cells = <0>; - cpu0: cpu@0 { - device_type = "cpu"; - compatible = "arm,cortex-a73"; - enable-method = "psci"; - reg = <0x0>; - clocks = <&mcusys CLK_MCU_ARM_DIV_SEL>, - <&topckgen CLK_TOP_XTAL>; - clock-names = "cpu", "intermediate"; - operating-points-v2 = <&cluster0_opp>; - mediatek,cci = <&cci>; - }; - - cpu1: cpu@1 { - device_type = "cpu"; - compatible = "arm,cortex-a73"; - enable-method = "psci"; - reg = <0x1>; - clocks = <&mcusys CLK_MCU_ARM_DIV_SEL>, - <&topckgen CLK_TOP_XTAL>; - clock-names = "cpu", "intermediate"; - operating-points-v2 = <&cluster0_opp>; - mediatek,cci = <&cci>; - }; - - cpu2: cpu@2 { - device_type = "cpu"; - compatible = "arm,cortex-a73"; - enable-method = "psci"; - reg = <0x2>; - clocks = <&mcusys CLK_MCU_ARM_DIV_SEL>, - <&topckgen CLK_TOP_XTAL>; - clock-names = "cpu", "intermediate"; - operating-points-v2 = <&cluster0_opp>; - mediatek,cci = <&cci>; - }; - - cpu3: cpu@3 { - device_type = "cpu"; - compatible = "arm,cortex-a73"; - enable-method = "psci"; - reg = <0x3>; - clocks = <&mcusys CLK_MCU_ARM_DIV_SEL>, - <&topckgen CLK_TOP_XTAL>; - clock-names = "cpu", "intermediate"; - operating-points-v2 = <&cluster0_opp>; - mediatek,cci = <&cci>; - }; - - cluster0_opp: opp_table0 { - compatible = "operating-points-v2"; - opp-shared; - opp00 { - opp-hz = /bits/ 64 <800000000>; - opp-microvolt = <850000>; - }; - opp01 { - opp-hz = /bits/ 64 <1100000000>; - opp-microvolt = <850000>; - }; - opp02 { - opp-hz = /bits/ 64 <1500000000>; - opp-microvolt = <850000>; - }; - opp03 { - opp-hz = /bits/ 64 <1800000000>; - opp-microvolt = <900000>; - }; - }; - }; - - cci: cci { - compatible = "mediatek,mt7988-cci", - "mediatek,mt8183-cci"; - clocks = <&mcusys CLK_MCU_BUS_DIV_SEL>, - <&topckgen CLK_TOP_XTAL>; - clock-names = "cci", "intermediate"; - operating-points-v2 = <&cci_opp>; - }; - - cci_opp: opp_table_cci { - compatible = "operating-points-v2"; - opp-shared; - opp00 { - opp-hz = /bits/ 64 <480000000>; - opp-microvolt = <850000>; - }; - opp01 { - opp-hz = /bits/ 64 <660000000>; - opp-microvolt = <850000>; - }; - opp02 { - opp-hz = /bits/ 64 <900000000>; - opp-microvolt = <850000>; - }; - opp03 { - opp-hz = /bits/ 64 <1080000000>; - opp-microvolt = <900000>; - }; - }; - - pmu { - compatible = "arm,cortex-a73-pmu"; - interrupt-parent = <&gic>; - interrupt = ; - }; - - psci { - compatible = "arm,psci-0.2"; - method = "smc"; - }; - - reserved-memory { - #address-cells = <2>; - #size-cells = <2>; - ranges; - - /* 320 KiB reserved for ARM Trusted Firmware (BL31 and BL32) */ - secmon_reserved: secmon@43000000 { - reg = <0 0x43000000 0 0x50000>; - no-map; - }; - }; - - thermal-zones { - cpu_thermal: cpu-thermal { - polling-delay-passive = <1000>; - polling-delay = <1000>; - thermal-sensors = <&lvts 0>; - trips { - cpu_trip_crit: crit { - temperature = <125000>; - hysteresis = <2000>; - type = "critical"; - }; - - cpu_trip_hot: hot { - temperature = <120000>; - hysteresis = <2000>; - type = "hot"; - }; - - cpu_trip_active_high: active-high { - temperature = <115000>; - hysteresis = <2000>; - type = "active"; - }; - - cpu_trip_active_med: active-med { - temperature = <85000>; - hysteresis = <2000>; - type = "active"; - }; - - cpu_trip_active_low: active-low { - temperature = <40000>; - hysteresis = <2000>; - type = "active"; - }; - }; - - cooling-maps { - cpu-active-high { - /* active: set fan to cooling level 2 */ - cooling-device = <&fan 3 3>; - trip = <&cpu_trip_active_high>; - }; - - cpu-active-low { - /* active: set fan to cooling level 1 */ - cooling-device = <&fan 2 2>; - trip = <&cpu_trip_active_med>; - }; - - cpu-passive { - /* passive: set fan to cooling level 0 */ - cooling-device = <&fan 1 1>; - trip = <&cpu_trip_active_low>; - }; - }; - }; - }; - - timer { - compatible = "arm,armv8-timer"; - interrupt-parent = <&gic>; - interrupts = , - , - , - ; - }; - - reg_1p8v: regulator-1p8v { - compatible = "regulator-fixed"; - regulator-name = "fixed-1.8V"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - regulator-boot-on; - regulator-always-on; - }; - - reg_3p3v: regulator-3p3v { - compatible = "regulator-fixed"; - regulator-name = "fixed-3.3V"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - regulator-boot-on; - regulator-always-on; - }; - - soc { - #address-cells = <2>; - #size-cells = <2>; - compatible = "simple-bus"; - ranges; - - gic: interrupt-controller@c000000 { - compatible = "arm,gic-v3"; - #interrupt-cells = <3>; - interrupt-parent = <&gic>; - interrupt-controller; - reg = <0 0x0c000000 0 0x40000>, /* GICD */ - <0 0x0c080000 0 0x200000>, /* GICR */ - <0 0x0c400000 0 0x2000>, /* GICC */ - <0 0x0c410000 0 0x1000>, /* GICH */ - <0 0x0c420000 0 0x2000>; /* GICV */ - - interrupts = ; - }; - - phyfw: phy-firmware@f000000 { - compatible = "mediatek,2p5gphy-fw"; - reg = <0 0x0f000000 0 0x8000>, - <0 0x0f100000 0 0x20000>, - <0 0x0f0f0000 0 0x200>; - }; - - infracfg: infracfg@10001000 { - compatible = "mediatek,mt7988-infracfg", "syscon"; - reg = <0 0x10001000 0 0x1000>; - #clock-cells = <1>; - }; - - topckgen: topckgen@1001b000 { - compatible = "mediatek,mt7988-topckgen", "syscon"; - reg = <0 0x1001b000 0 0x1000>; - #clock-cells = <1>; - }; - - watchdog: watchdog@1001c000 { - compatible = "mediatek,mt7988-wdt", - "mediatek,mt6589-wdt", - "syscon"; - reg = <0 0x1001c000 0 0x1000>; - interrupts = ; - #reset-cells = <1>; - }; - - apmixedsys: apmixedsys@1001e000 { - compatible = "mediatek,mt7988-apmixedsys"; - reg = <0 0x1001e000 0 0x1000>; - #clock-cells = <1>; - }; - - pio: pinctrl@1001f000 { - compatible = "mediatek,mt7988-pinctrl", "syscon"; - reg = <0 0x1001f000 0 0x1000>, - <0 0x11c10000 0 0x1000>, - <0 0x11d00000 0 0x1000>, - <0 0x11d20000 0 0x1000>, - <0 0x11e00000 0 0x1000>, - <0 0x11f00000 0 0x1000>, - <0 0x1000b000 0 0x1000>; - reg-names = "gpio_base", "iocfg_tr_base", - "iocfg_br_base", "iocfg_rb_base", - "iocfg_lb_base", "iocfg_tl_base", "eint"; - gpio-controller; - #gpio-cells = <2>; - gpio-ranges = <&pio 0 0 84>; - interrupt-controller; - interrupts = ; - interrupt-parent = <&gic>; - #interrupt-cells = <2>; - - mdio0_pins: mdio0-pins { - mux { - function = "eth"; - groups = "mdc_mdio0"; - }; - - conf { - groups = "mdc_mdio0"; - drive-strength = ; - }; - }; - - i2c0_pins: i2c0-pins-g0 { - mux { - function = "i2c"; - groups = "i2c0_1"; - }; - }; - - i2c1_pins: i2c1-pins-g0 { - mux { - function = "i2c"; - groups = "i2c1_0"; - }; - }; - - i2c1_sfp_pins: i2c1-sfp-pins-g0 { - mux { - function = "i2c"; - groups = "i2c1_sfp"; - }; - }; - - i2c2_pins: i2c2-pins { - mux { - function = "i2c"; - groups = "i2c2"; - }; - }; - - i2c2_0_pins: i2c2-pins-g0 { - mux { - function = "i2c"; - groups = "i2c2_0"; - }; - }; - - i2c2_1_pins: i2c2-pins-g1 { - mux { - function = "i2c"; - groups = "i2c2_1"; - }; - }; - - gbe0_led0_pins: gbe0-led0-pins { - mux { - function = "led"; - groups = "gbe0_led0"; - }; - }; - - gbe1_led0_pins: gbe1-led0-pins { - mux { - function = "led"; - groups = "gbe1_led0"; - }; - }; - - gbe2_led0_pins: gbe2-led0-pins { - mux { - function = "led"; - groups = "gbe2_led0"; - }; - }; - - gbe3_led0_pins: gbe3-led0-pins { - mux { - function = "led"; - groups = "gbe3_led0"; - }; - }; - - gbe0_led1_pins: gbe0-led1-pins { - mux { - function = "led"; - groups = "gbe0_led1"; - }; - }; - - gbe1_led1_pins: gbe1-led1-pins { - mux { - function = "led"; - groups = "gbe1_led1"; - }; - }; - - gbe2_led1_pins: gbe2-led1-pins { - mux { - function = "led"; - groups = "gbe2_led1"; - }; - }; - - gbe3_led1_pins: gbe3-led1-pins { - mux { - function = "led"; - groups = "gbe3_led1"; - }; - }; - - i2p5gbe_led0_pins: 2p5gbe-led0-pins { - mux { - function = "led"; - groups = "2p5gbe_led0"; - }; - }; - - i2p5gbe_led1_pins: 2p5gbe-led1-pins { - mux { - function = "led"; - groups = "2p5gbe_led1"; - }; - }; - - mmc0_pins_emmc_45: mmc0-pins-emmc-45 { - mux { - function = "flash"; - groups = "emmc_45"; - }; - }; - - mmc0_pins_emmc_51: mmc0-pins-emmc-51 { - mux { - function = "flash"; - groups = "emmc_51"; - }; - }; - - mmc0_pins_sdcard: mmc0-pins-sdcard { - mux { - function = "flash"; - groups = "sdcard"; - }; - }; - - uart0_pins: uart0-pins { - mux { - function = "uart"; - groups = "uart0"; - }; - }; - - snfi_pins: snfi-pins { - mux { - function = "flash"; - groups = "snfi"; - }; - }; - - spi0_pins: spi0-pins { - mux { - function = "spi"; - groups = "spi0"; - }; - }; - - spi0_flash_pins: spi0-flash-pins { - mux { - function = "spi"; - groups = "spi0", "spi0_wp_hold"; - }; - }; - - spi1_pins: spi1-pins { - mux { - function = "spi"; - groups = "spi1"; - }; - }; - - spi2_pins: spi2-pins { - mux { - function = "spi"; - groups = "spi2"; - }; - }; - - spi2_flash_pins: spi2-flash-pins { - mux { - function = "spi"; - groups = "spi2", "spi2_wp_hold"; - }; - }; - - pcie0_pins: pcie0-pins { - mux { - function = "pcie"; - groups = "pcie_2l_0_pereset", "pcie_clk_req_n0_0", - "pcie_wake_n0_0"; - }; - }; - - pcie1_pins: pcie1-pins { - mux { - function = "pcie"; - groups = "pcie_2l_1_pereset", "pcie_clk_req_n1", - "pcie_wake_n1_0"; - }; - }; - - pcie2_pins: pcie2-pins { - mux { - function = "pcie"; - groups = "pcie_1l_0_pereset", "pcie_clk_req_n2_0", - "pcie_wake_n2_0"; - }; - }; - - pcie3_pins: pcie3-pins { - mux { - function = "pcie"; - groups = "pcie_1l_1_pereset", "pcie_clk_req_n3", - "pcie_wake_n3_0"; - }; - }; - }; - - sgmiisys0: syscon@10060000 { - compatible = "mediatek,mt7988-sgmiisys", - "mediatek,mt7988-sgmiisys_0", - "syscon"; - reg = <0 0x10060000 0 0x1000>; - #clock-cells = <1>; - }; - - sgmiisys1: syscon@10070000 { - compatible = "mediatek,mt7988-sgmiisys", - "mediatek,mt7988-sgmiisys_1", - "syscon"; - reg = <0 0x10070000 0 0x1000>; - #clock-cells = <1>; - }; - - usxgmiisys0: usxgmiisys@10080000 { - compatible = "mediatek,mt7988-usxgmiisys", - "mediatek,mt7988-usxgmiisys_0", - "syscon"; - reg = <0 0x10080000 0 0x1000>; - #clock-cells = <1>; - }; - - usxgmiisys1: usxgmiisys@10081000 { - compatible = "mediatek,mt7988-usxgmiisys", - "mediatek,mt7988-usxgmiisys_1", - "syscon"; - reg = <0 0x10081000 0 0x1000>; - #clock-cells = <1>; - }; - - xfi_pextp0: xfi-pextp@11f20000 { - compatible = "mediatek,mt7988-xfi-pextp", - "mediatek,mt7988-xfi-pextp_0", - "syscon"; - reg = <0 0x11f20000 0 0x10000>; - #clock-cells = <1>; - }; - - xfi_pextp1: xfi-pextp@11f30000 { - compatible = "mediatek,mt7988-xfi-pextp", - "mediatek,mt7988-xfi-pextp_1", - "syscon"; - reg = <0 0x11f30000 0 0x10000>; - #clock-cells = <1>; - }; - - xfi_pll: xfi-pll@11f40000 { - compatible = "mediatek,mt7988-xfi-pll", "syscon"; - reg = <0 0x11f40000 0 0x1000>; - #clock-cells = <1>; - }; - - mcusys: mcusys@100e0000 { - compatible = "mediatek,mt7988-mcusys", "syscon"; - reg = <0 0x100e0000 0 0x1000>; - #clock-cells = <1>; - }; - - uart0: serial@11000000 { - compatible = "mediatek,mt7986-uart", - "mediatek,mt6577-uart"; - reg = <0 0x11000000 0 0x100>; - interrupts = ; - /* - * 8250-mtk driver don't control "baud" clock since commit - * e32a83c70cf9 (kernel v5.7), but both "baud" and "bus" clocks - * still need to be passed to the driver to prevent probe fail - */ - clocks = <&topckgen CLK_TOP_UART_SEL>, - <&infracfg CLK_INFRA_52M_UART0_CK>; - clock-names = "baud", "bus"; - assigned-clocks = <&topckgen CLK_TOP_UART_SEL>, - <&infracfg CLK_INFRA_MUX_UART0_SEL>; - assigned-clock-parents = <&topckgen CLK_TOP_XTAL>, - <&topckgen CLK_TOP_UART_SEL>; - pinctrl-names = "default"; - pinctrl-0 = <&uart0_pins>; - status = "disabled"; - }; - - snand: spi@11001000 { - compatible = "mediatek,mt7986-snand"; - reg = <0 0x11001000 0 0x1000>; - interrupts = ; - clocks = <&infracfg CLK_INFRA_SPINFI>, - <&infracfg CLK_INFRA_NFI>; - clock-names = "pad_clk", "nfi_clk"; - assigned-clocks = <&topckgen CLK_TOP_SPINFI_SEL>, - <&topckgen CLK_TOP_NFI1X_SEL>; - assigned-clock-parents = <&topckgen CLK_TOP_MPLL_D8>, - <&topckgen CLK_TOP_MPLL_D8>; - nand-ecc-engine = <&bch>; - mediatek,quad-spi; - #address-cells = <1>; - #size-cells = <0>; - pinctrl-names = "default"; - pinctrl-0 = <&snfi_pins>; - status = "disabled"; - }; - - bch: ecc@11002000 { - compatible = "mediatek,mt7686-ecc"; - reg = <0 0x11002000 0 0x1000>; - interrupts = ; - clocks = <&topckgen CLK_TOP_NFI1X_SEL>; - clock-names = "nfiecc_clk"; - status = "disabled"; - }; - - i2c0: i2c@11003000 { - compatible = "mediatek,mt7988-i2c", - "mediatek,mt7981-i2c"; - reg = <0 0x11003000 0 0x1000>, - <0 0x10217080 0 0x80>; - interrupts = ; - clock-div = <1>; - clocks = <&infracfg CLK_INFRA_I2C_BCK>, - <&infracfg CLK_INFRA_66M_AP_DMA_BCK>; - clock-names = "main", "dma"; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; - }; - - i2c1: i2c@11004000 { - compatible = "mediatek,mt7988-i2c", - "mediatek,mt7981-i2c"; - reg = <0 0x11004000 0 0x1000>, - <0 0x10217100 0 0x80>; - interrupts = ; - clock-div = <1>; - clocks = <&infracfg CLK_INFRA_I2C_BCK>, - <&infracfg CLK_INFRA_66M_AP_DMA_BCK>; - clock-names = "main", "dma"; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; - }; - - i2c2: i2c@11005000 { - compatible = "mediatek,mt7988-i2c", - "mediatek,mt7981-i2c"; - reg = <0 0x11005000 0 0x1000>, - <0 0x10217180 0 0x80>; - interrupts = ; - clock-div = <1>; - clocks = <&infracfg CLK_INFRA_I2C_BCK>, - <&infracfg CLK_INFRA_66M_AP_DMA_BCK>; - clock-names = "main", "dma"; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; - }; - - spi0: spi@11007000 { - compatible = "mediatek,ipm-spi-quad", "mediatek,spi-ipm"; - reg = <0 0x11007000 0 0x100>; - interrupts = ; - clocks = <&topckgen CLK_TOP_MPLL_D2>, - <&topckgen CLK_TOP_SPI_SEL>, - <&infracfg CLK_INFRA_104M_SPI0>, - <&infracfg CLK_INFRA_66M_SPI0_HCK>; - clock-names = "parent-clk", "sel-clk", "spi-clk", - "spi-hclk"; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; - }; - - spi1: spi@11008000 { - compatible = "mediatek,ipm-spi-single", "mediatek,spi-ipm"; - reg = <0 0x11008000 0 0x100>; - interrupts = ; - clocks = <&topckgen CLK_TOP_MPLL_D2>, - <&topckgen CLK_TOP_SPI_SEL>, - <&infracfg CLK_INFRA_104M_SPI1>, - <&infracfg CLK_INFRA_66M_SPI1_HCK>; - clock-names = "parent-clk", "sel-clk", "spi-clk", - "spi-hclk"; - #address-cells = <1>; - #size-cells = <0>; - pinctrl-names = "default"; - pinctrl-0 = <&spi1_pins>; - status = "disabled"; - }; - - spi2: spi@11009000 { - compatible = "mediatek,ipm-spi-quad", "mediatek,spi-ipm"; - reg = <0 0x11009000 0 0x100>; - interrupts = ; - clocks = <&topckgen CLK_TOP_MPLL_D2>, - <&topckgen CLK_TOP_SPI_SEL>, - <&infracfg CLK_INFRA_104M_SPI2_BCK>, - <&infracfg CLK_INFRA_66M_SPI2_HCK>; - clock-names = "parent-clk", "sel-clk", "spi-clk", - "spi-hclk"; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; - }; - - pwm: pwm@10048000 { - compatible = "mediatek,mt7988-pwm"; - reg = <0 0x10048000 0 0x1000>; - #pwm-cells = <2>; - clocks = <&infracfg CLK_INFRA_66M_PWM_BCK>, - <&infracfg CLK_INFRA_66M_PWM_HCK>, - <&infracfg CLK_INFRA_66M_PWM_CK1>, - <&infracfg CLK_INFRA_66M_PWM_CK2>, - <&infracfg CLK_INFRA_66M_PWM_CK3>, - <&infracfg CLK_INFRA_66M_PWM_CK4>, - <&infracfg CLK_INFRA_66M_PWM_CK5>, - <&infracfg CLK_INFRA_66M_PWM_CK6>, - <&infracfg CLK_INFRA_66M_PWM_CK7>, - <&infracfg CLK_INFRA_66M_PWM_CK8>; - clock-names = "top", "main", "pwm1", "pwm2", "pwm3", - "pwm4","pwm5","pwm6","pwm7","pwm8"; - status = "disabled"; - }; - - fan: pwm-fan { - compatible = "pwm-fan"; - /* cooling level (0, 1, 2) : (0% duty, 50% duty, 100% duty) */ - cooling-levels = <0 128 255>; - #cooling-cells = <2>; - #thermal-sensor-cells = <1>; - status = "disabled"; - }; - - lvts: lvts@1100a000 { - compatible = "mediatek,mt7988-lvts"; - #thermal-sensor-cells = <1>; - reg = <0 0x1100a000 0 0x1000>; - clocks = <&infracfg CLK_INFRA_26M_THERM_SYSTEM>; - clock-names = "lvts_clk"; - nvmem-cells = <&lvts_calibration>; - nvmem-cell-names = "e_data1"; - }; - - crypto: crypto@15600000 { - compatible = "inside-secure,safexcel-eip197b"; - reg = <0 0x15600000 0 0x180000>; - interrupts = , - , - , - ; - interrupt-names = "ring0", "ring1", "ring2", "ring3"; - status = "okay"; - }; - - afe: audio-controller@11210000 { - compatible = "mediatek,mt79xx-audio"; - reg = <0 0x11210000 0 0x9000>; - interrupts = ; - clocks = <&infracfg CLK_INFRA_66M_AUD_SLV_BCK>, - <&infracfg CLK_INFRA_AUD_26M>, - <&infracfg CLK_INFRA_AUD_L>, - <&infracfg CLK_INFRA_AUD_AUD>, - <&infracfg CLK_INFRA_AUD_EG2>, - <&topckgen CLK_TOP_AUD_SEL>, - <&topckgen CLK_TOP_AUD_I2S_M>; - clock-names = "aud_bus_ck", - "aud_26m_ck", - "aud_l_ck", - "aud_aud_ck", - "aud_eg2_ck", - "aud_sel", - "aud_i2s_m"; - assigned-clocks = <&topckgen CLK_TOP_AUD_SEL>, - <&topckgen CLK_TOP_A1SYS_SEL>, - <&topckgen CLK_TOP_AUD_L_SEL>, - <&topckgen CLK_TOP_A_TUNER_SEL>; - assigned-clock-parents = <&apmixedsys CLK_APMIXED_APLL2>, - <&topckgen CLK_TOP_APLL2_D4>, - <&apmixedsys CLK_APMIXED_APLL2>, - <&topckgen CLK_TOP_APLL2_D4>; - status = "disabled"; - }; - - pcie2: pcie@11280000 { - compatible = "mediatek,mt7988-pcie", - "mediatek,mt7986-pcie", - "mediatek,mt8192-pcie"; - device_type = "pci"; - #address-cells = <3>; - #size-cells = <2>; - reg = <0 0x11280000 0 0x2000>; - reg-names = "pcie-mac"; - linux,pci-domain = <3>; - interrupts = ; - bus-range = <0x00 0xff>; - ranges = <0x81000000 0x00 0x20000000 0x00 - 0x20000000 0x00 0x00200000>, - <0x82000000 0x00 0x20200000 0x00 - 0x20200000 0x00 0x07e00000>; - clocks = <&infracfg CLK_INFRA_PCIE_PIPE_P2>, - <&infracfg CLK_INFRA_PCIE_GFMUX_TL_P2>, - <&infracfg CLK_INFRA_PCIE_PERI_26M_CK_P2>, - <&infracfg CLK_INFRA_133M_PCIE_CK_P2>; - clock-names = "pl_250m", "tl_26m", "peri_26m", - "top_133m"; - pinctrl-names = "default"; - pinctrl-0 = <&pcie2_pins>; - status = "disabled"; - - phys = <&xphyu3port0 PHY_TYPE_PCIE>; - phy-names = "pcie-phy"; - - #interrupt-cells = <1>; - interrupt-map-mask = <0 0 0 0x7>; - interrupt-map = <0 0 0 1 &pcie_intc2 0>, - <0 0 0 2 &pcie_intc2 1>, - <0 0 0 3 &pcie_intc2 2>, - <0 0 0 4 &pcie_intc2 3>; - pcie_intc2: interrupt-controller { - #address-cells = <0>; - #interrupt-cells = <1>; - interrupt-controller; - }; - }; - - pcie3: pcie@11290000 { - compatible = "mediatek,mt7988-pcie", - "mediatek,mt7986-pcie", - "mediatek,mt8192-pcie"; - device_type = "pci"; - #address-cells = <3>; - #size-cells = <2>; - reg = <0 0x11290000 0 0x2000>; - reg-names = "pcie-mac"; - linux,pci-domain = <2>; - interrupts = ; - bus-range = <0x00 0xff>; - ranges = <0x81000000 0x00 0x28000000 0x00 - 0x28000000 0x00 0x00200000>, - <0x82000000 0x00 0x28200000 0x00 - 0x28200000 0x00 0x07e00000>; - clocks = <&infracfg CLK_INFRA_PCIE_PIPE_P3>, - <&infracfg CLK_INFRA_PCIE_GFMUX_TL_P3>, - <&infracfg CLK_INFRA_PCIE_PERI_26M_CK_P3>, - <&infracfg CLK_INFRA_133M_PCIE_CK_P3>; - clock-names = "pl_250m", "tl_26m", "peri_26m", - "top_133m"; - pinctrl-names = "default"; - pinctrl-0 = <&pcie3_pins>; - status = "disabled"; - - #interrupt-cells = <1>; - interrupt-map-mask = <0 0 0 0x7>; - interrupt-map = <0 0 0 1 &pcie_intc3 0>, - <0 0 0 2 &pcie_intc3 1>, - <0 0 0 3 &pcie_intc3 2>, - <0 0 0 4 &pcie_intc3 3>; - pcie_intc3: interrupt-controller { - #address-cells = <0>; - #interrupt-cells = <1>; - interrupt-controller; - }; - }; - - pcie0: pcie@11300000 { - compatible = "mediatek,mt7988-pcie", - "mediatek,mt7986-pcie", - "mediatek,mt8192-pcie"; - device_type = "pci"; - #address-cells = <3>; - #size-cells = <2>; - reg = <0 0x11300000 0 0x2000>; - reg-names = "pcie-mac"; - linux,pci-domain = <0>; - interrupts = ; - bus-range = <0x00 0xff>; - ranges = <0x81000000 0x00 0x30000000 0x00 - 0x30000000 0x00 0x00200000>, - <0x82000000 0x00 0x30200000 0x00 - 0x30200000 0x00 0x07e00000>; - clocks = <&infracfg CLK_INFRA_PCIE_PIPE_P0>, - <&infracfg CLK_INFRA_PCIE_GFMUX_TL_P0>, - <&infracfg CLK_INFRA_PCIE_PERI_26M_CK_P0>, - <&infracfg CLK_INFRA_133M_PCIE_CK_P0>; - clock-names = "pl_250m", "tl_26m", "peri_26m", - "top_133m"; - pinctrl-names = "default"; - pinctrl-0 = <&pcie0_pins>; - status = "disabled"; - - #interrupt-cells = <1>; - interrupt-map-mask = <0 0 0 0x7>; - interrupt-map = <0 0 0 1 &pcie_intc0 0>, - <0 0 0 2 &pcie_intc0 1>, - <0 0 0 3 &pcie_intc0 2>, - <0 0 0 4 &pcie_intc0 3>; - pcie_intc0: interrupt-controller { - #address-cells = <0>; - #interrupt-cells = <1>; - interrupt-controller; - }; - }; - - pcie1: pcie@11310000 { - compatible = "mediatek,mt7988-pcie", - "mediatek,mt7986-pcie", - "mediatek,mt8192-pcie"; - device_type = "pci"; - #address-cells = <3>; - #size-cells = <2>; - reg = <0 0x11310000 0 0x2000>; - reg-names = "pcie-mac"; - linux,pci-domain = <1>; - interrupts = ; - bus-range = <0x00 0xff>; - ranges = <0x81000000 0x00 0x38000000 0x00 - 0x38000000 0x00 0x00200000>, - <0x82000000 0x00 0x38200000 0x00 - 0x38200000 0x00 0x07e00000>; - clocks = <&infracfg CLK_INFRA_PCIE_PIPE_P1>, - <&infracfg CLK_INFRA_PCIE_GFMUX_TL_P1>, - <&infracfg CLK_INFRA_PCIE_PERI_26M_CK_P1>, - <&infracfg CLK_INFRA_133M_PCIE_CK_P1>; - clock-names = "pl_250m", "tl_26m", "peri_26m", - "top_133m"; - pinctrl-names = "default"; - pinctrl-0 = <&pcie1_pins>; - status = "disabled"; - - #interrupt-cells = <1>; - interrupt-map-mask = <0 0 0 0x7>; - interrupt-map = <0 0 0 1 &pcie_intc1 0>, - <0 0 0 2 &pcie_intc1 1>, - <0 0 0 3 &pcie_intc1 2>, - <0 0 0 4 &pcie_intc1 3>; - pcie_intc1: interrupt-controller { - #address-cells = <0>; - #interrupt-cells = <1>; - interrupt-controller; - }; - }; - - ssusb0: usb@11190000 { - compatible = "mediatek,mt7988-xhci", - "mediatek,mtk-xhci"; - reg = <0 0x11190000 0 0x2e00>, - <0 0x11193e00 0 0x0100>; - reg-names = "mac", "ippc"; - interrupts = ; - phys = <&xphyu2port0 PHY_TYPE_USB2>, - <&xphyu3port0 PHY_TYPE_USB3>; - clocks = <&infracfg CLK_INFRA_USB_SYS>, - <&infracfg CLK_INFRA_USB_XHCI>, - <&infracfg CLK_INFRA_USB_REF>, - <&infracfg CLK_INFRA_66M_USB_HCK>, - <&infracfg CLK_INFRA_133M_USB_HCK>; - clock-names = "sys_ck", - "xhci_ck", - "ref_ck", - "mcu_ck", - "dma_ck"; - #address-cells = <2>; - #size-cells = <2>; - mediatek,p0_speed_fixup; - status = "disabled"; - }; - - ssusb1: usb@11200000 { - compatible = "mediatek,mt7988-xhci", - "mediatek,mtk-xhci"; - reg = <0 0x11200000 0 0x2e00>, - <0 0x11203e00 0 0x0100>; - reg-names = "mac", "ippc"; - interrupts = ; - phys = <&tphyu2port0 PHY_TYPE_USB2>, - <&tphyu3port0 PHY_TYPE_USB3>; - clocks = <&infracfg CLK_INFRA_USB_SYS_CK_P1>, - <&infracfg CLK_INFRA_USB_XHCI_CK_P1>, - <&infracfg CLK_INFRA_USB_CK_P1>, - <&infracfg CLK_INFRA_66M_USB_HCK_CK_P1>, - <&infracfg CLK_INFRA_133M_USB_HCK_CK_P1>; - clock-names = "sys_ck", - "xhci_ck", - "ref_ck", - "mcu_ck", - "dma_ck"; - #address-cells = <2>; - #size-cells = <2>; - status = "disabled"; - }; - - mmc0: mmc@11230000 { - compatible = "mediatek,mt7986-mmc", - "mediatek,mt7981-mmc"; - reg = <0 0x11230000 0 0x1000>, - <0 0x11D60000 0 0x1000>; - interrupts = ; - clocks = <&infracfg CLK_INFRA_MSDC400>, - <&infracfg CLK_INFRA_MSDC2_HCK>, - <&infracfg CLK_INFRA_66M_MSDC_0_HCK>, - <&infracfg CLK_INFRA_133M_MSDC_0_HCK>; - assigned-clocks = <&topckgen CLK_TOP_EMMC_250M_SEL>, - <&topckgen CLK_TOP_EMMC_400M_SEL>; - assigned-clock-parents = <&topckgen CLK_TOP_NET1PLL_D5_D2>, - <&apmixedsys CLK_APMIXED_MSDCPLL>; - clock-names = "source", - "hclk", - "axi_cg", - "ahb_cg"; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; - }; - - tphy: tphy@11c50000 { - compatible = "mediatek,mt7988", - "mediatek,generic-tphy-v2"; - #address-cells = <2>; - #size-cells = <2>; - ranges; - status = "disabled"; - tphyu2port0: usb-phy@11c50000 { - reg = <0 0x11c50000 0 0x700>; - clocks = <&infracfg CLK_INFRA_USB_UTMI_CK_P1>; - clock-names = "ref"; - #phy-cells = <1>; - }; - tphyu3port0: usb-phy@11c50700 { - reg = <0 0x11c50700 0 0x900>; - clocks = <&infracfg CLK_INFRA_USB_PIPE_CK_P1>; - clock-names = "ref"; - #phy-cells = <1>; - mediatek,usb3-pll-ssc-delta; - mediatek,usb3-pll-ssc-delta1; - }; - }; - - topmisc: topmisc@11d10000 { - compatible = "mediatek,mt7988-topmisc", "syscon", - "mediatek,mt7988-power-controller"; - reg = <0 0x11d10000 0 0x10000>; - #clock-cells = <1>; - #power-domain-cells = <1>; - #address-cells = <1>; - #size-cells = <0>; - }; - - xphy: xphy@11e10000 { - compatible = "mediatek,mt7988", - "mediatek,xsphy"; - #address-cells = <2>; - #size-cells = <2>; - ranges; - status = "disabled"; - - xphyu2port0: usb-phy@11e10000 { - reg = <0 0x11e10000 0 0x400>; - clocks = <&infracfg CLK_INFRA_USB_UTMI>; - clock-names = "ref"; - #phy-cells = <1>; - }; - - xphyu3port0: usb-phy@11e13000 { - reg = <0 0x11e13400 0 0x500>; - clocks = <&infracfg CLK_INFRA_USB_PIPE>; - clock-names = "ref"; - #phy-cells = <1>; - mediatek,syscon-type = <&topmisc 0x218 0>; - }; - }; - - efuse: efuse@11f50000 { - compatible = "mediatek,efuse"; - reg = <0 0x11f50000 0 0x1000>; - #address-cells = <1>; - #size-cells = <1>; - - lvts_calibration: calib@918 { - reg = <0x918 0x28>; - }; - phy_calibration_p0: calib@940 { - reg = <0x940 0x10>; - }; - phy_calibration_p1: calib@954 { - reg = <0x954 0x10>; - }; - phy_calibration_p2: calib@968 { - reg = <0x968 0x10>; - }; - phy_calibration_p3: calib@97c { - reg = <0x97c 0x10>; - }; - cpufreq_calibration: calib@278 { - reg = <0x278 0x1>; - }; - }; - - ethsys: syscon@15000000 { - #address-cells = <1>; - #size-cells = <1>; - compatible = "mediatek,mt7988-ethsys", "syscon"; - reg = <0 0x15000000 0 0x1000>; - #clock-cells = <1>; - #reset-cells = <1>; - }; - - switch: switch@15020000 { - #address-cells = <1>; - #size-cells = <1>; - compatible = "mediatek,mt7988-switch"; - reg = <0 0x15020000 0 0x8000>; - interrupt-controller; - #interrupt-cells = <1>; - interrupt-parent = <&gic>; - interrupts = ; - resets = <ðrst 0>; - - ports { - #address-cells = <1>; - #size-cells = <0>; - - port@0 { - reg = <0>; - label = "lan0"; - phy-mode = "internal"; - phy-handle = <&gsw_phy0>; - }; - - port@1 { - reg = <1>; - label = "lan1"; - phy-mode = "internal"; - phy-handle = <&gsw_phy1>; - }; - - port@2 { - reg = <2>; - label = "lan2"; - phy-mode = "internal"; - phy-handle = <&gsw_phy2>; - }; - - port@3 { - reg = <3>; - label = "lan3"; - phy-mode = "internal"; - phy-handle = <&gsw_phy3>; - }; - - port@6 { - reg = <6>; - ethernet = <&gmac0>; - phy-mode = "internal"; - - fixed-link { - speed = <10000>; - full-duplex; - pause; - }; - }; - }; - - mdio { - #address-cells = <1>; - #size-cells = <0>; - mediatek,pio = <&pio>; - - gsw_phy0: ethernet-phy@0 { - compatible = "ethernet-phy-ieee802.3-c22"; - reg = <0>; - phy-mode = "internal"; - nvmem-cells = <&phy_calibration_p0>; - nvmem-cell-names = "phy-cal-data"; - - leds { - #address-cells = <1>; - #size-cells = <0>; - - gsw_phy0_led0: gsw-phy0-led0@0 { - reg = <0>; - function = LED_FUNCTION_LAN; - status = "disabled"; - }; - - gsw_phy0_led1: gsw-phy0-led1@1 { - reg = <1>; - function = LED_FUNCTION_LAN; - status = "disabled"; - }; - }; - }; - - gsw_phy1: ethernet-phy@1 { - compatible = "ethernet-phy-ieee802.3-c22"; - reg = <1>; - phy-mode = "internal"; - nvmem-cells = <&phy_calibration_p1>; - nvmem-cell-names = "phy-cal-data"; - - leds { - #address-cells = <1>; - #size-cells = <0>; - - gsw_phy1_led0: gsw-phy1-led0@0 { - reg = <0>; - function = LED_FUNCTION_LAN; - status = "disabled"; - }; - - gsw_phy1_led1: gsw-phy1-led1@1 { - reg = <1>; - function = LED_FUNCTION_LAN; - status = "disabled"; - }; - }; - }; - - gsw_phy2: ethernet-phy@2 { - compatible = "ethernet-phy-ieee802.3-c22"; - reg = <2>; - phy-mode = "internal"; - nvmem-cells = <&phy_calibration_p2>; - nvmem-cell-names = "phy-cal-data"; - - leds { - #address-cells = <1>; - #size-cells = <0>; - - gsw_phy2_led0: gsw-phy2-led0@0 { - reg = <0>; - function = LED_FUNCTION_LAN; - status = "disabled"; - }; - - gsw_phy2_led1: gsw-phy2-led1@1 { - reg = <1>; - function = LED_FUNCTION_LAN; - status = "disabled"; - }; - }; - }; - - gsw_phy3: ethernet-phy@3 { - compatible = "ethernet-phy-ieee802.3-c22"; - reg = <3>; - phy-mode = "internal"; - nvmem-cells = <&phy_calibration_p3>; - nvmem-cell-names = "phy-cal-data"; - - leds { - #address-cells = <1>; - #size-cells = <0>; - - gsw_phy3_led0: gsw-phy3-led0@0 { - reg = <0>; - function = LED_FUNCTION_LAN; - status = "disabled"; - }; - - gsw_phy3_led1: gsw-phy3-led1@1 { - reg = <1>; - function = LED_FUNCTION_LAN; - status = "disabled"; - }; - }; - }; - }; - }; - - ethwarp: syscon@15031000 { - compatible = "mediatek,mt7988-ethwarp", "syscon", "simple-mfd"; - reg = <0 0x15031000 0 0x1000>; - #clock-cells = <1>; - - ethrst: reset-controller { - compatible = "ti,syscon-reset"; - #reset-cells = <1>; - ti,reset-bits = < - 0x8 9 0x8 9 0 0 (ASSERT_SET | DEASSERT_CLEAR | STATUS_NONE) - >; - }; - }; - - eth: ethernet@15100000 { - compatible = "mediatek,mt7988-eth"; - reg = <0 0x15100000 0 0x80000>, - <0 0x15400000 0 0x380000>; - interrupts = , - , - , - ; - clocks = <ðsys CLK_ETHDMA_XGP1_EN>, - <ðsys CLK_ETHDMA_XGP2_EN>, - <ðsys CLK_ETHDMA_XGP3_EN>, - <ðsys CLK_ETHDMA_FE_EN>, - <ðsys CLK_ETHDMA_GP2_EN>, - <ðsys CLK_ETHDMA_GP1_EN>, - <ðsys CLK_ETHDMA_GP3_EN>, - <ðsys CLK_ETHDMA_ESW_EN>, - <ðsys CLK_ETHDMA_CRYPT0_EN>, - <&sgmiisys0 CLK_SGM0_TX_EN>, - <&sgmiisys0 CLK_SGM0_RX_EN>, - <&sgmiisys1 CLK_SGM1_TX_EN>, - <&sgmiisys1 CLK_SGM1_RX_EN>, - <ðwarp CLK_ETHWARP_WOCPU2_EN>, - <ðwarp CLK_ETHWARP_WOCPU1_EN>, - <ðwarp CLK_ETHWARP_WOCPU0_EN>, - <&topckgen CLK_TOP_USXGMII_SBUS_0_SEL>, - <&topckgen CLK_TOP_USXGMII_SBUS_1_SEL>, - <&topckgen CLK_TOP_SGM_0_SEL>, - <&topckgen CLK_TOP_SGM_1_SEL>, - <&topckgen CLK_TOP_XFI_PHY_0_XTAL_SEL>, - <&topckgen CLK_TOP_XFI_PHY_1_XTAL_SEL>, - <&topckgen CLK_TOP_ETH_GMII_SEL>, - <&topckgen CLK_TOP_ETH_REFCK_50M_SEL>, - <&topckgen CLK_TOP_ETH_SYS_200M_SEL>, - <&topckgen CLK_TOP_ETH_SYS_SEL>, - <&topckgen CLK_TOP_ETH_XGMII_SEL>, - <&topckgen CLK_TOP_ETH_MII_SEL>, - <&topckgen CLK_TOP_NETSYS_SEL>, - <&topckgen CLK_TOP_NETSYS_500M_SEL>, - <&topckgen CLK_TOP_NETSYS_PAO_2X_SEL>, - <&topckgen CLK_TOP_NETSYS_SYNC_250M_SEL>, - <&topckgen CLK_TOP_NETSYS_PPEFB_250M_SEL>, - <&topckgen CLK_TOP_NETSYS_WARP_SEL>; - clock-names = "xgp1", "xgp2", "xgp3", "fe", "gp2", "gp1", - "gp3", "esw", "crypto", "sgmii_tx250m", - "sgmii_rx250m", "sgmii2_tx250m", "sgmii2_rx250m", - "ethwarp_wocpu2", "ethwarp_wocpu1", - "ethwarp_wocpu0", "top_usxgmii0_sel", - "top_usxgmii1_sel", "top_sgm0_sel", - "top_sgm1_sel", "top_xfi_phy0_xtal_sel", - "top_xfi_phy1_xtal_sel", "top_eth_gmii_sel", - "top_eth_refck_50m_sel", "top_eth_sys_200m_sel", - "top_eth_sys_sel", "top_eth_xgmii_sel", - "top_eth_mii_sel", "top_netsys_sel", - "top_netsys_500m_sel", "top_netsys_pao_2x_sel", - "top_netsys_sync_250m_sel", - "top_netsys_ppefb_250m_sel", - "top_netsys_warp_sel"; - assigned-clocks = <&topckgen CLK_TOP_NETSYS_2X_SEL>, - <&topckgen CLK_TOP_NETSYS_GSW_SEL>, - <&topckgen CLK_TOP_USXGMII_SBUS_0_SEL>, - <&topckgen CLK_TOP_USXGMII_SBUS_1_SEL>, - <&topckgen CLK_TOP_SGM_0_SEL>, - <&topckgen CLK_TOP_SGM_1_SEL>; - assigned-clock-parents = <&apmixedsys CLK_APMIXED_NET2PLL>, - <&topckgen CLK_TOP_NET1PLL_D4>, - <&topckgen CLK_TOP_NET1PLL_D8_D4>, - <&topckgen CLK_TOP_NET1PLL_D8_D4>, - <&apmixedsys CLK_APMIXED_SGMPLL>, - <&apmixedsys CLK_APMIXED_SGMPLL>; - mediatek,ethsys = <ðsys>; - mediatek,sgmiisys = <&sgmiisys0>, <&sgmiisys1>; - mediatek,usxgmiisys = <&usxgmiisys0>, <&usxgmiisys1>; - mediatek,xfi-pextp = <&xfi_pextp0>, <&xfi_pextp1>; - mediatek,xfi-pll = <&xfi_pll>; - mediatek,infracfg = <&topmisc>; - mediatek,toprgu = <&watchdog>; - #reset-cells = <1>; - #address-cells = <1>; - #size-cells = <0>; - - gmac0: mac@0 { - compatible = "mediatek,eth-mac"; - reg = <0>; - phy-mode = "internal"; - status = "disabled"; - - fixed-link { - speed = <10000>; - full-duplex; - pause; - }; - }; - - gmac1: mac@1 { - compatible = "mediatek,eth-mac"; - reg = <1>; - status = "disabled"; - }; - - gmac2: mac@2 { - compatible = "mediatek,eth-mac"; - reg = <2>; - status = "disabled"; - }; - - mdio_bus: mdio-bus { - #address-cells = <1>; - #size-cells = <0>; - - /* internal 2.5G PHY */ - int_2p5g_phy: ethernet-phy@15 { - reg = <15>; - compatible = "ethernet-phy-ieee802.3-c45"; - phy-mode = "internal"; - }; - }; - }; - }; -}; diff --git a/target/linux/mediatek/files-6.1/drivers/clk/mediatek/clk-mt7988-apmixed.c b/target/linux/mediatek/files-6.1/drivers/clk/mediatek/clk-mt7988-apmixed.c deleted file mode 100644 index 3f1edc231..000000000 --- a/target/linux/mediatek/files-6.1/drivers/clk/mediatek/clk-mt7988-apmixed.c +++ /dev/null @@ -1,113 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (c) 2023 MediaTek Inc. - * Author: Sam Shih - * Author: Xiufeng Li - */ - -#include -#include -#include -#include -#include -#include "clk-mtk.h" -#include "clk-gate.h" -#include "clk-mux.h" -#include "clk-pll.h" -#include - -#define MT7988_PLL_FMAX (2500UL * MHZ) -#define MT7988_PCW_CHG_SHIFT 2 - -#define PLL_xtal(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _rst_bar_mask, \ - _pcwbits, _pd_reg, _pd_shift, _tuner_reg, _tuner_en_reg, \ - _tuner_en_bit, _pcw_reg, _pcw_shift, _pcw_chg_reg, \ - _div_table) \ - { \ - .id = _id, .name = _name, .reg = _reg, .pwr_reg = _pwr_reg, \ - .en_mask = _en_mask, .flags = _flags, \ - .rst_bar_mask = BIT(_rst_bar_mask), .fmax = MT7988_PLL_FMAX, \ - .pcwbits = _pcwbits, .pd_reg = _pd_reg, \ - .pd_shift = _pd_shift, .tuner_reg = _tuner_reg, \ - .tuner_en_reg = _tuner_en_reg, .tuner_en_bit = _tuner_en_bit, \ - .pcw_reg = _pcw_reg, .pcw_shift = _pcw_shift, \ - .pcw_chg_reg = _pcw_chg_reg, \ - .pcw_chg_shift = MT7988_PCW_CHG_SHIFT, \ - .div_table = _div_table, .parent_name = "clkxtal", \ - } - -#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _rst_bar_mask, \ - _pcwbits, _pd_reg, _pd_shift, _tuner_reg, _tuner_en_reg, \ - _tuner_en_bit, _pcw_reg, _pcw_shift, _pcw_chg_reg) \ - PLL_xtal(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _rst_bar_mask, \ - _pcwbits, _pd_reg, _pd_shift, _tuner_reg, _tuner_en_reg, \ - _tuner_en_bit, _pcw_reg, _pcw_shift, _pcw_chg_reg, NULL) - -static const struct mtk_pll_data plls[] = { - PLL(CLK_APMIXED_NETSYSPLL, "netsyspll", 0x0104, 0x0110, 0x00000001, 0, - 0, 32, 0x0104, 4, 0, 0, 0, 0x0108, 0, 0x0104), - PLL(CLK_APMIXED_MPLL, "mpll", 0x0114, 0x0120, 0xff000001, HAVE_RST_BAR, - 23, 32, 0x0114, 4, 0, 0, 0, 0x0118, 0, 0x0114), - PLL(CLK_APMIXED_MMPLL, "mmpll", 0x0124, 0x0130, 0xff000001, - HAVE_RST_BAR, 23, 32, 0x0124, 4, 0, 0, 0, 0x0128, 0, 0x0124), - PLL(CLK_APMIXED_APLL2, "apll2", 0x0134, 0x0140, 0x00000001, 0, 0, 32, - 0x0134, 4, 0x0704, 0x0700, 1, 0x0138, 0, 0x0134), - PLL(CLK_APMIXED_NET1PLL, "net1pll", 0x0144, 0x0150, 0xff000001, - HAVE_RST_BAR, 23, 32, 0x0144, 4, 0, 0, 0, 0x0148, 0, 0x0144), - PLL(CLK_APMIXED_NET2PLL, "net2pll", 0x0154, 0x0160, 0xff000001, - (HAVE_RST_BAR | PLL_AO), 23, 32, 0x0154, 4, 0, 0, 0, 0x0158, 0, - 0x0154), - PLL(CLK_APMIXED_WEDMCUPLL, "wedmcupll", 0x0164, 0x0170, 0x00000001, 0, - 0, 32, 0x0164, 4, 0, 0, 0, 0x0168, 0, 0x0164), - PLL(CLK_APMIXED_SGMPLL, "sgmpll", 0x0174, 0x0180, 0x00000001, 0, 0, 32, - 0x0174, 4, 0, 0, 0, 0x0178, 0, 0x0174), - PLL(CLK_APMIXED_ARM_B, "arm_b", 0x0204, 0x0210, 0xff000001, - (HAVE_RST_BAR | PLL_AO), 23, 32, 0x0204, 4, 0, 0, 0, 0x0208, 0, - 0x0204), - PLL(CLK_APMIXED_CCIPLL2_B, "ccipll2_b", 0x0214, 0x0220, 0xff000001, - HAVE_RST_BAR, 23, 32, 0x0214, 4, 0, 0, 0, 0x0218, 0, 0x0214), - PLL(CLK_APMIXED_USXGMIIPLL, "usxgmiipll", 0x0304, 0x0310, 0xff000001, - HAVE_RST_BAR, 23, 32, 0x0304, 4, 0, 0, 0, 0x0308, 0, 0x0304), - PLL(CLK_APMIXED_MSDCPLL, "msdcpll", 0x0314, 0x0320, 0x00000001, 0, 0, - 32, 0x0314, 4, 0, 0, 0, 0x0318, 0, 0x0314), -}; - -static const struct of_device_id of_match_clk_mt7988_apmixed[] = { - { .compatible = "mediatek,mt7988-apmixedsys", }, - { /* sentinel */ } -}; - -static int clk_mt7988_apmixed_probe(struct platform_device *pdev) -{ - struct clk_hw_onecell_data *clk_data; - struct device_node *node = pdev->dev.of_node; - int r; - - clk_data = mtk_alloc_clk_data(ARRAY_SIZE(plls)); - if (!clk_data) - return -ENOMEM; - - mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data); - - r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); - if (r) { - pr_err("%s(): could not register clock provider: %d\n", - __func__, r); - goto free_apmixed_data; - } - return r; - -free_apmixed_data: - mtk_free_clk_data(clk_data); - return r; -} - -static struct platform_driver clk_mt7988_apmixed_drv = { - .probe = clk_mt7988_apmixed_probe, - .driver = { - .name = "clk-mt7988-apmixed", - .of_match_table = of_match_clk_mt7988_apmixed, - }, -}; -builtin_platform_driver(clk_mt7988_apmixed_drv); -MODULE_LICENSE("GPL"); diff --git a/target/linux/mediatek/files-6.1/drivers/clk/mediatek/clk-mt7988-eth.c b/target/linux/mediatek/files-6.1/drivers/clk/mediatek/clk-mt7988-eth.c deleted file mode 100644 index 14b877f8c..000000000 --- a/target/linux/mediatek/files-6.1/drivers/clk/mediatek/clk-mt7988-eth.c +++ /dev/null @@ -1,141 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (c) 2023 MediaTek Inc. - * Author: Sam Shih - * Author: Xiufeng Li - */ - -#include -#include -#include -#include -#include -#include "clk-mtk.h" -#include "clk-gate.h" -#include - -static const struct mtk_gate_regs ethdma_cg_regs = { - .set_ofs = 0x30, - .clr_ofs = 0x30, - .sta_ofs = 0x30, -}; - -#define GATE_ETHDMA(_id, _name, _parent, _shift) \ - { \ - .id = _id, .name = _name, .parent_name = _parent, \ - .regs = ðdma_cg_regs, .shift = _shift, \ - .ops = &mtk_clk_gate_ops_no_setclr_inv, \ - } - -static const struct mtk_gate ethdma_clks[] = { - GATE_ETHDMA(CLK_ETHDMA_XGP1_EN, "ethdma_xgp1_en", "top_xtal", 0), - GATE_ETHDMA(CLK_ETHDMA_XGP2_EN, "ethdma_xgp2_en", "top_xtal", 1), - GATE_ETHDMA(CLK_ETHDMA_XGP3_EN, "ethdma_xgp3_en", "top_xtal", 2), - GATE_ETHDMA(CLK_ETHDMA_FE_EN, "ethdma_fe_en", "netsys_2x_sel", 6), - GATE_ETHDMA(CLK_ETHDMA_GP2_EN, "ethdma_gp2_en", "top_xtal", 7), - GATE_ETHDMA(CLK_ETHDMA_GP1_EN, "ethdma_gp1_en", "top_xtal", 8), - GATE_ETHDMA(CLK_ETHDMA_GP3_EN, "ethdma_gp3_en", "top_xtal", 10), - GATE_ETHDMA(CLK_ETHDMA_ESW_EN, "ethdma_esw_en", "netsys_gsw_sel", 16), - GATE_ETHDMA(CLK_ETHDMA_CRYPT0_EN, "ethdma_crypt0_en", "eip197_sel", - 29), -}; - -static const struct mtk_clk_desc ethdma_desc = { - .clks = ethdma_clks, - .num_clks = ARRAY_SIZE(ethdma_clks), -}; - -static const struct mtk_gate_regs sgmii0_cg_regs = { - .set_ofs = 0xe4, - .clr_ofs = 0xe4, - .sta_ofs = 0xe4, -}; - -#define GATE_SGMII0(_id, _name, _parent, _shift) \ - { \ - .id = _id, .name = _name, .parent_name = _parent, \ - .regs = &sgmii0_cg_regs, .shift = _shift, \ - .ops = &mtk_clk_gate_ops_no_setclr_inv, \ - } - -static const struct mtk_gate sgmii0_clks[] = { - GATE_SGMII0(CLK_SGM0_TX_EN, "sgm0_tx_en", "top_xtal", 2), - GATE_SGMII0(CLK_SGM0_RX_EN, "sgm0_rx_en", "top_xtal", 3), -}; - -static const struct mtk_clk_desc sgmii0_desc = { - .clks = sgmii0_clks, - .num_clks = ARRAY_SIZE(sgmii0_clks), -}; - -static const struct mtk_gate_regs sgmii1_cg_regs = { - .set_ofs = 0xe4, - .clr_ofs = 0xe4, - .sta_ofs = 0xe4, -}; - -#define GATE_SGMII1(_id, _name, _parent, _shift) \ - { \ - .id = _id, .name = _name, .parent_name = _parent, \ - .regs = &sgmii1_cg_regs, .shift = _shift, \ - .ops = &mtk_clk_gate_ops_no_setclr_inv, \ - } - -static const struct mtk_gate sgmii1_clks[] = { - GATE_SGMII1(CLK_SGM1_TX_EN, "sgm1_tx_en", "top_xtal", 2), - GATE_SGMII1(CLK_SGM1_RX_EN, "sgm1_rx_en", "top_xtal", 3), -}; - -static const struct mtk_clk_desc sgmii1_desc = { - .clks = sgmii1_clks, - .num_clks = ARRAY_SIZE(sgmii1_clks), -}; - -static const struct mtk_gate_regs ethwarp_cg_regs = { - .set_ofs = 0x14, - .clr_ofs = 0x14, - .sta_ofs = 0x14, -}; - -#define GATE_ETHWARP(_id, _name, _parent, _shift) \ - { \ - .id = _id, .name = _name, .parent_name = _parent, \ - .regs = ðwarp_cg_regs, .shift = _shift, \ - .ops = &mtk_clk_gate_ops_no_setclr_inv, \ - } - -static const struct mtk_gate ethwarp_clks[] = { - GATE_ETHWARP(CLK_ETHWARP_WOCPU2_EN, "ethwarp_wocpu2_en", - "netsys_mcu_sel", 13), - GATE_ETHWARP(CLK_ETHWARP_WOCPU1_EN, "ethwarp_wocpu1_en", - "netsys_mcu_sel", 14), - GATE_ETHWARP(CLK_ETHWARP_WOCPU0_EN, "ethwarp_wocpu0_en", - "netsys_mcu_sel", 15), -}; - -static const struct mtk_clk_desc ethwarp_desc = { - .clks = ethwarp_clks, - .num_clks = ARRAY_SIZE(ethwarp_clks), -}; - -static const struct of_device_id of_match_clk_mt7986_eth[] = { - { .compatible = "mediatek,mt7988-ethsys", .data = ðdma_desc }, - { .compatible = "mediatek,mt7988-sgmiisys_0", .data = &sgmii0_desc }, - { .compatible = "mediatek,mt7988-sgmiisys_1", .data = &sgmii1_desc }, - { .compatible = "mediatek,mt7988-ethwarp", .data = ðwarp_desc }, - { /* sentinel */ } -}; -MODULE_DEVICE_TABLE(of, of_match_clk_mt7988_eth); - -static struct platform_driver clk_mt7988_eth_drv = { - .driver = { - .name = "clk-mt7988-eth", - .of_match_table = of_match_clk_mt7986_eth, - }, - .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, -}; -module_platform_driver(clk_mt7988_eth_drv); - -MODULE_DESCRIPTION("MediaTek MT7988 Ethernet clocks driver"); -MODULE_LICENSE("GPL"); diff --git a/target/linux/mediatek/files-6.1/drivers/clk/mediatek/clk-mt7988-infracfg.c b/target/linux/mediatek/files-6.1/drivers/clk/mediatek/clk-mt7988-infracfg.c deleted file mode 100644 index a5d21d756..000000000 --- a/target/linux/mediatek/files-6.1/drivers/clk/mediatek/clk-mt7988-infracfg.c +++ /dev/null @@ -1,376 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (c) 2023 MediaTek Inc. - * Author: Sam Shih - * Author: Xiufeng Li - */ - -#include -#include -#include -#include -#include -#include "clk-mtk.h" -#include "clk-gate.h" -#include "clk-mux.h" -#include - -static DEFINE_SPINLOCK(mt7988_clk_lock); - -static const char *const infra_mux_uart0_parents[] __initconst = { - "csw_infra_f26m_sel", "uart_sel" -}; - -static const char *const infra_mux_uart1_parents[] __initconst = { - "csw_infra_f26m_sel", "uart_sel" -}; - -static const char *const infra_mux_uart2_parents[] __initconst = { - "csw_infra_f26m_sel", "uart_sel" -}; - -static const char *const infra_mux_spi0_parents[] __initconst = { "i2c_sel", - "spi_sel" }; - -static const char *const infra_mux_spi1_parents[] __initconst = { - "i2c_sel", "spim_mst_sel" -}; - -static const char *const infra_pwm_bck_parents[] __initconst = { - "top_rtc_32p7k", "csw_infra_f26m_sel", "sysaxi_sel", "pwm_sel" -}; - -static const char *const infra_pcie_gfmux_tl_ck_o_p0_parents[] __initconst = { - "top_rtc_32p7k", "csw_infra_f26m_sel", "csw_infra_f26m_sel", - "pextp_tl_sel" -}; - -static const char *const infra_pcie_gfmux_tl_ck_o_p1_parents[] __initconst = { - "top_rtc_32p7k", "csw_infra_f26m_sel", "csw_infra_f26m_sel", - "pextp_tl_p1_sel" -}; - -static const char *const infra_pcie_gfmux_tl_ck_o_p2_parents[] __initconst = { - "top_rtc_32p7k", "csw_infra_f26m_sel", "csw_infra_f26m_sel", - "pextp_tl_p2_sel" -}; - -static const char *const infra_pcie_gfmux_tl_ck_o_p3_parents[] __initconst = { - "top_rtc_32p7k", "csw_infra_f26m_sel", "csw_infra_f26m_sel", - "pextp_tl_p3_sel" -}; - -static const struct mtk_mux infra_muxes[] = { - /* MODULE_CLK_SEL_0 */ - MUX_GATE_CLR_SET_UPD(CLK_INFRA_MUX_UART0_SEL, "infra_mux_uart0_sel", - infra_mux_uart0_parents, 0x0018, 0x0010, 0x0014, - 0, 1, -1, -1, -1), - MUX_GATE_CLR_SET_UPD(CLK_INFRA_MUX_UART1_SEL, "infra_mux_uart1_sel", - infra_mux_uart1_parents, 0x0018, 0x0010, 0x0014, - 1, 1, -1, -1, -1), - MUX_GATE_CLR_SET_UPD(CLK_INFRA_MUX_UART2_SEL, "infra_mux_uart2_sel", - infra_mux_uart2_parents, 0x0018, 0x0010, 0x0014, - 2, 1, -1, -1, -1), - MUX_GATE_CLR_SET_UPD(CLK_INFRA_MUX_SPI0_SEL, "infra_mux_spi0_sel", - infra_mux_spi0_parents, 0x0018, 0x0010, 0x0014, 4, - 1, -1, -1, -1), - MUX_GATE_CLR_SET_UPD(CLK_INFRA_MUX_SPI1_SEL, "infra_mux_spi1_sel", - infra_mux_spi1_parents, 0x0018, 0x0010, 0x0014, 5, - 1, -1, -1, -1), - MUX_GATE_CLR_SET_UPD(CLK_INFRA_MUX_SPI2_SEL, "infra_mux_spi2_sel", - infra_mux_spi0_parents, 0x0018, 0x0010, 0x0014, 6, - 1, -1, -1, -1), - MUX_GATE_CLR_SET_UPD(CLK_INFRA_PWM_SEL, "infra_pwm_sel", - infra_pwm_bck_parents, 0x0018, 0x0010, 0x0014, 14, - 2, -1, -1, -1), - MUX_GATE_CLR_SET_UPD(CLK_INFRA_PWM_CK1_SEL, "infra_pwm_ck1_sel", - infra_pwm_bck_parents, 0x0018, 0x0010, 0x0014, 16, - 2, -1, -1, -1), - MUX_GATE_CLR_SET_UPD(CLK_INFRA_PWM_CK2_SEL, "infra_pwm_ck2_sel", - infra_pwm_bck_parents, 0x0018, 0x0010, 0x0014, 18, - 2, -1, -1, -1), - MUX_GATE_CLR_SET_UPD(CLK_INFRA_PWM_CK3_SEL, "infra_pwm_ck3_sel", - infra_pwm_bck_parents, 0x0018, 0x0010, 0x0014, 20, - 2, -1, -1, -1), - MUX_GATE_CLR_SET_UPD(CLK_INFRA_PWM_CK4_SEL, "infra_pwm_ck4_sel", - infra_pwm_bck_parents, 0x0018, 0x0010, 0x0014, 22, - 2, -1, -1, -1), - MUX_GATE_CLR_SET_UPD(CLK_INFRA_PWM_CK5_SEL, "infra_pwm_ck5_sel", - infra_pwm_bck_parents, 0x0018, 0x0010, 0x0014, 24, - 2, -1, -1, -1), - MUX_GATE_CLR_SET_UPD(CLK_INFRA_PWM_CK6_SEL, "infra_pwm_ck6_sel", - infra_pwm_bck_parents, 0x0018, 0x0010, 0x0014, 26, - 2, -1, -1, -1), - MUX_GATE_CLR_SET_UPD(CLK_INFRA_PWM_CK7_SEL, "infra_pwm_ck7_sel", - infra_pwm_bck_parents, 0x0018, 0x0010, 0x0014, 28, - 2, -1, -1, -1), - MUX_GATE_CLR_SET_UPD(CLK_INFRA_PWM_CK8_SEL, "infra_pwm_ck8_sel", - infra_pwm_bck_parents, 0x0018, 0x0010, 0x0014, 30, - 2, -1, -1, -1), - /* MODULE_CLK_SEL_1 */ - MUX_GATE_CLR_SET_UPD(CLK_INFRA_PCIE_GFMUX_TL_O_P0_SEL, - "infra_pcie_gfmux_tl_o_p0_sel", - infra_pcie_gfmux_tl_ck_o_p0_parents, 0x0028, - 0x0020, 0x0024, 0, 2, -1, -1, -1), - MUX_GATE_CLR_SET_UPD(CLK_INFRA_PCIE_GFMUX_TL_O_P1_SEL, - "infra_pcie_gfmux_tl_o_p1_sel", - infra_pcie_gfmux_tl_ck_o_p1_parents, 0x0028, - 0x0020, 0x0024, 2, 2, -1, -1, -1), - MUX_GATE_CLR_SET_UPD(CLK_INFRA_PCIE_GFMUX_TL_O_P2_SEL, - "infra_pcie_gfmux_tl_o_p2_sel", - infra_pcie_gfmux_tl_ck_o_p2_parents, 0x0028, - 0x0020, 0x0024, 4, 2, -1, -1, -1), - MUX_GATE_CLR_SET_UPD(CLK_INFRA_PCIE_GFMUX_TL_O_P3_SEL, - "infra_pcie_gfmux_tl_o_p3_sel", - infra_pcie_gfmux_tl_ck_o_p3_parents, 0x0028, - 0x0020, 0x0024, 6, 2, -1, -1, -1), -}; - -static const struct mtk_gate_regs infra0_cg_regs = { - .set_ofs = 0x10, - .clr_ofs = 0x14, - .sta_ofs = 0x18, -}; - -static const struct mtk_gate_regs infra1_cg_regs = { - .set_ofs = 0x40, - .clr_ofs = 0x44, - .sta_ofs = 0x48, -}; - -static const struct mtk_gate_regs infra2_cg_regs = { - .set_ofs = 0x50, - .clr_ofs = 0x54, - .sta_ofs = 0x58, -}; - -static const struct mtk_gate_regs infra3_cg_regs = { - .set_ofs = 0x60, - .clr_ofs = 0x64, - .sta_ofs = 0x68, -}; - -#define GATE_INFRA0_FLAGS(_id, _name, _parent, _shift, _flags) \ - { \ - .id = _id, .name = _name, .parent_name = _parent, \ - .regs = &infra0_cg_regs, .shift = _shift, \ - .ops = &mtk_clk_gate_ops_setclr, .flags = _flags, \ - } - -#define GATE_INFRA1_FLAGS(_id, _name, _parent, _shift, _flags) \ - { \ - .id = _id, .name = _name, .parent_name = _parent, \ - .regs = &infra1_cg_regs, .shift = _shift, \ - .ops = &mtk_clk_gate_ops_setclr, .flags = _flags, \ - } - -#define GATE_INFRA2_FLAGS(_id, _name, _parent, _shift, _flags) \ - { \ - .id = _id, .name = _name, .parent_name = _parent, \ - .regs = &infra2_cg_regs, .shift = _shift, \ - .ops = &mtk_clk_gate_ops_setclr, .flags = _flags, \ - } - -#define GATE_INFRA3_FLAGS(_id, _name, _parent, _shift, _flags) \ - { \ - .id = _id, .name = _name, .parent_name = _parent, \ - .regs = &infra3_cg_regs, .shift = _shift, \ - .ops = &mtk_clk_gate_ops_setclr, .flags = _flags, \ - } - -#define GATE_INFRA0(_id, _name, _parent, _shift) \ - GATE_INFRA0_FLAGS(_id, _name, _parent, _shift, 0) - -#define GATE_INFRA1(_id, _name, _parent, _shift) \ - GATE_INFRA1_FLAGS(_id, _name, _parent, _shift, 0) - -#define GATE_INFRA2(_id, _name, _parent, _shift) \ - GATE_INFRA2_FLAGS(_id, _name, _parent, _shift, 0) - -#define GATE_INFRA3(_id, _name, _parent, _shift) \ - GATE_INFRA3_FLAGS(_id, _name, _parent, _shift, 0) - -#define GATE_CRITICAL(_id, _name, _parent, _regs, _shift) { \ - .id = _id, .name = _name, .parent_name = _parent, \ - .regs = _regs, .shift = _shift, \ - .flags = CLK_IS_CRITICAL, \ - .ops = &mtk_clk_gate_ops_setclr, \ - } - -static const struct mtk_gate infra_clks[] = { - /* INFRA0 */ - GATE_INFRA0(CLK_INFRA_PCIE_PERI_26M_CK_P0, - "infra_pcie_peri_ck_26m_ck_p0", "csw_infra_f26m_sel", 7), - GATE_INFRA0(CLK_INFRA_PCIE_PERI_26M_CK_P1, - "infra_pcie_peri_ck_26m_ck_p1", "csw_infra_f26m_sel", 8), - GATE_INFRA0(CLK_INFRA_PCIE_PERI_26M_CK_P2, - "infra_pcie_peri_ck_26m_ck_p2", "csw_infra_f26m_sel", 9), - GATE_INFRA0(CLK_INFRA_PCIE_PERI_26M_CK_P3, - "infra_pcie_peri_ck_26m_ck_p3", "csw_infra_f26m_sel", 10), - /* INFRA1 */ - GATE_INFRA1(CLK_INFRA_66M_GPT_BCK, "infra_hf_66m_gpt_bck", - "sysaxi_sel", 0), - GATE_INFRA1(CLK_INFRA_66M_PWM_HCK, "infra_hf_66m_pwm_hck", - "sysaxi_sel", 1), - GATE_INFRA1(CLK_INFRA_66M_PWM_BCK, "infra_hf_66m_pwm_bck", - "infra_pwm_sel", 2), - GATE_INFRA1(CLK_INFRA_66M_PWM_CK1, "infra_hf_66m_pwm_ck1", - "infra_pwm_ck1_sel", 3), - GATE_INFRA1(CLK_INFRA_66M_PWM_CK2, "infra_hf_66m_pwm_ck2", - "infra_pwm_ck2_sel", 4), - GATE_INFRA1(CLK_INFRA_66M_PWM_CK3, "infra_hf_66m_pwm_ck3", - "infra_pwm_ck3_sel", 5), - GATE_INFRA1(CLK_INFRA_66M_PWM_CK4, "infra_hf_66m_pwm_ck4", - "infra_pwm_ck4_sel", 6), - GATE_INFRA1(CLK_INFRA_66M_PWM_CK5, "infra_hf_66m_pwm_ck5", - "infra_pwm_ck5_sel", 7), - GATE_INFRA1(CLK_INFRA_66M_PWM_CK6, "infra_hf_66m_pwm_ck6", - "infra_pwm_ck6_sel", 8), - GATE_INFRA1(CLK_INFRA_66M_PWM_CK7, "infra_hf_66m_pwm_ck7", - "infra_pwm_ck7_sel", 9), - GATE_INFRA1(CLK_INFRA_66M_PWM_CK8, "infra_hf_66m_pwm_ck8", - "infra_pwm_ck8_sel", 10), - GATE_INFRA1(CLK_INFRA_133M_CQDMA_BCK, "infra_hf_133m_cqdma_bck", - "sysaxi_sel", 12), - GATE_INFRA1(CLK_INFRA_66M_AUD_SLV_BCK, "infra_66m_aud_slv_bck", - "sysaxi_sel", 13), - GATE_INFRA1(CLK_INFRA_AUD_26M, "infra_f_faud_26m", - "csw_infra_f26m_sel", 14), - GATE_INFRA1(CLK_INFRA_AUD_L, "infra_f_faud_l", "aud_l_sel", 15), - GATE_INFRA1(CLK_INFRA_AUD_AUD, "infra_f_aud_aud", "a1sys_sel", 16), - GATE_INFRA1(CLK_INFRA_AUD_EG2, "infra_f_faud_eg2", "a_tuner_sel", 18), - GATE_INFRA1_FLAGS(CLK_INFRA_DRAMC_F26M, "infra_dramc_f26m", - "csw_infra_f26m_sel", 19, CLK_IS_CRITICAL), - // JTAG - GATE_INFRA1_FLAGS(CLK_INFRA_133M_DBG_ACKM, "infra_hf_133m_dbg_ackm", - "sysaxi_sel", 20, CLK_IS_CRITICAL), - GATE_INFRA1(CLK_INFRA_66M_AP_DMA_BCK, "infra_66m_ap_dma_bck", - "sysaxi_sel", 21), - GATE_INFRA1(CLK_INFRA_66M_SEJ_BCK, "infra_hf_66m_sej_bck", - "sysaxi_sel", 29), - GATE_INFRA1(CLK_INFRA_PRE_CK_SEJ_F13M, "infra_pre_ck_sej_f13m", - "csw_infra_f26m_sel", 30), - /* INFRA2 */ - GATE_INFRA2(CLK_INFRA_26M_THERM_SYSTEM, "infra_hf_26m_therm_system", - "csw_infra_f26m_sel", 0), - GATE_INFRA2(CLK_INFRA_I2C_BCK, "infra_i2c_bck", "i2c_sel", 1), - GATE_INFRA2(CLK_INFRA_52M_UART0_CK, "infra_f_52m_uart0", - "infra_mux_uart0_sel", 3), - GATE_INFRA2(CLK_INFRA_52M_UART1_CK, "infra_f_52m_uart1", - "infra_mux_uart1_sel", 4), - GATE_INFRA2(CLK_INFRA_52M_UART2_CK, "infra_f_52m_uart2", - "infra_mux_uart2_sel", 5), - GATE_INFRA2(CLK_INFRA_NFI, "infra_f_fnfi", "nfi1x_sel", 9), - GATE_INFRA2(CLK_INFRA_SPINFI, "infra_f_fspinfi", "spinfi_sel", 10), - GATE_INFRA2_FLAGS(CLK_INFRA_66M_NFI_HCK, "infra_hf_66m_nfi_hck", - "sysaxi_sel", 11, CLK_IS_CRITICAL), - GATE_INFRA2_FLAGS(CLK_INFRA_104M_SPI0, "infra_hf_104m_spi0", - "infra_mux_spi0_sel", 12, CLK_IS_CRITICAL), - GATE_INFRA2(CLK_INFRA_104M_SPI1, "infra_hf_104m_spi1", - "infra_mux_spi1_sel", 13), - GATE_INFRA2(CLK_INFRA_104M_SPI2_BCK, "infra_hf_104m_spi2_bck", - "infra_mux_spi2_sel", 14), - GATE_INFRA2_FLAGS(CLK_INFRA_66M_SPI0_HCK, "infra_hf_66m_spi0_hck", - "sysaxi_sel", 15, CLK_IS_CRITICAL), - GATE_INFRA2(CLK_INFRA_66M_SPI1_HCK, "infra_hf_66m_spi1_hck", - "sysaxi_sel", 16), - GATE_INFRA2(CLK_INFRA_66M_SPI2_HCK, "infra_hf_66m_spi2_hck", - "sysaxi_sel", 17), - GATE_INFRA2(CLK_INFRA_66M_FLASHIF_AXI, "infra_hf_66m_flashif_axi", - "sysaxi_sel", 18), - GATE_CRITICAL(CLK_INFRA_RTC, "infra_f_frtc", "top_rtc_32k", &infra2_cg_regs, 19), - GATE_INFRA2(CLK_INFRA_26M_ADC_BCK, "infra_f_26m_adc_bck", - "csw_infra_f26m_sel", 20), - GATE_INFRA2(CLK_INFRA_RC_ADC, "infra_f_frc_adc", "infra_f_26m_adc_bck", - 21), - GATE_INFRA2(CLK_INFRA_MSDC400, "infra_f_fmsdc400", "emmc_400m_sel", - 22), - GATE_INFRA2(CLK_INFRA_MSDC2_HCK, "infra_f_fmsdc2_hck", "emmc_250m_sel", - 23), - GATE_INFRA2(CLK_INFRA_133M_MSDC_0_HCK, "infra_hf_133m_msdc_0_hck", - "sysaxi_sel", 24), - GATE_INFRA2(CLK_INFRA_66M_MSDC_0_HCK, "infra_66m_msdc_0_hck", - "sysaxi_sel", 25), - GATE_INFRA2(CLK_INFRA_133M_CPUM_BCK, "infra_hf_133m_cpum_bck", - "sysaxi_sel", 26), - GATE_INFRA2(CLK_INFRA_BIST2FPC, "infra_hf_fbist2fpc", "nfi1x_sel", 27), - GATE_INFRA2(CLK_INFRA_I2C_X16W_MCK_CK_P1, - "infra_hf_i2c_x16w_mck_ck_p1", "sysaxi_sel", 29), - GATE_INFRA2(CLK_INFRA_I2C_X16W_PCK_CK_P1, - "infra_hf_i2c_x16w_pck_ck_p1", "sysaxi_sel", 31), - /* INFRA3 */ - GATE_INFRA3(CLK_INFRA_133M_USB_HCK, "infra_133m_usb_hck", "sysaxi_sel", - 0), - GATE_INFRA3(CLK_INFRA_133M_USB_HCK_CK_P1, "infra_133m_usb_hck_ck_p1", - "sysaxi_sel", 1), - GATE_INFRA3(CLK_INFRA_66M_USB_HCK, "infra_66m_usb_hck", "sysaxi_sel", - 2), - GATE_INFRA3(CLK_INFRA_66M_USB_HCK_CK_P1, "infra_66m_usb_hck_ck_p1", - "sysaxi_sel", 3), - GATE_INFRA3(CLK_INFRA_USB_SYS, "infra_usb_sys", "usb_sys_sel", 4), - GATE_INFRA3(CLK_INFRA_USB_SYS_CK_P1, "infra_usb_sys_ck_p1", - "usb_sys_p1_sel", 5), - GATE_INFRA3(CLK_INFRA_USB_REF, "infra_usb_ref", "top_xtal", 6), - GATE_INFRA3(CLK_INFRA_USB_CK_P1, "infra_usb_ck_p1", "top_xtal", 7), - GATE_INFRA3_FLAGS(CLK_INFRA_USB_FRMCNT, "infra_usb_frmcnt", - "usb_frmcnt_sel", 8, CLK_IS_CRITICAL), - GATE_INFRA3_FLAGS(CLK_INFRA_USB_FRMCNT_CK_P1, "infra_usb_frmcnt_ck_p1", - "usb_frmcnt_p1_sel", 9, CLK_IS_CRITICAL), - GATE_INFRA3(CLK_INFRA_USB_PIPE, "infra_usb_pipe", "sspxtp_sel", 10), - GATE_INFRA3(CLK_INFRA_USB_PIPE_CK_P1, "infra_usb_pipe_ck_p1", - "usb_phy_sel", 11), - GATE_INFRA3(CLK_INFRA_USB_UTMI, "infra_usb_utmi", "top_xtal", 12), - GATE_INFRA3(CLK_INFRA_USB_UTMI_CK_P1, "infra_usb_utmi_ck_p1", - "top_xtal", 13), - GATE_INFRA3(CLK_INFRA_USB_XHCI, "infra_usb_xhci", "usb_xhci_sel", 14), - GATE_INFRA3(CLK_INFRA_USB_XHCI_CK_P1, "infra_usb_xhci_ck_p1", - "usb_xhci_p1_sel", 15), - GATE_INFRA3(CLK_INFRA_PCIE_GFMUX_TL_P0, "infra_pcie_gfmux_tl_ck_p0", - "infra_pcie_gfmux_tl_o_p0_sel", 20), - GATE_INFRA3(CLK_INFRA_PCIE_GFMUX_TL_P1, "infra_pcie_gfmux_tl_ck_p1", - "infra_pcie_gfmux_tl_o_p1_sel", 21), - GATE_INFRA3(CLK_INFRA_PCIE_GFMUX_TL_P2, "infra_pcie_gfmux_tl_ck_p2", - "infra_pcie_gfmux_tl_o_p2_sel", 22), - GATE_INFRA3(CLK_INFRA_PCIE_GFMUX_TL_P3, "infra_pcie_gfmux_tl_ck_p3", - "infra_pcie_gfmux_tl_o_p3_sel", 23), - GATE_INFRA3(CLK_INFRA_PCIE_PIPE_P0, "infra_pcie_pipe_ck_p0", - "top_xtal", 24), - GATE_INFRA3(CLK_INFRA_PCIE_PIPE_P1, "infra_pcie_pipe_ck_p1", - "top_xtal", 25), - GATE_INFRA3(CLK_INFRA_PCIE_PIPE_P2, "infra_pcie_pipe_ck_p2", - "top_xtal", 26), - GATE_INFRA3(CLK_INFRA_PCIE_PIPE_P3, "infra_pcie_pipe_ck_p3", - "top_xtal", 27), - GATE_INFRA3(CLK_INFRA_133M_PCIE_CK_P0, "infra_133m_pcie_ck_p0", - "sysaxi_sel", 28), - GATE_INFRA3(CLK_INFRA_133M_PCIE_CK_P1, "infra_133m_pcie_ck_p1", - "sysaxi_sel", 29), - GATE_INFRA3(CLK_INFRA_133M_PCIE_CK_P2, "infra_133m_pcie_ck_p2", - "sysaxi_sel", 30), - GATE_INFRA3(CLK_INFRA_133M_PCIE_CK_P3, "infra_133m_pcie_ck_p3", - "sysaxi_sel", 31), -}; - -static const struct mtk_clk_desc infra_desc = { - .clks = infra_clks, - .num_clks = ARRAY_SIZE(infra_clks), - .mux_clks = infra_muxes, - .num_mux_clks = ARRAY_SIZE(infra_muxes), - .clk_lock = &mt7988_clk_lock, -}; - -static const struct of_device_id of_match_clk_mt7988_infracfg[] = { - { .compatible = "mediatek,mt7988-infracfg", .data = &infra_desc }, - { /* sentinel */ } -}; -MODULE_DEVICE_TABLE(of, of_match_clk_mt7988_infracfg); - -static struct platform_driver clk_mt7988_infracfg_drv = { - .driver = { - .name = "clk-mt7988-infracfg", - .of_match_table = of_match_clk_mt7988_infracfg, - }, - .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, -}; -module_platform_driver(clk_mt7988_infracfg_drv); diff --git a/target/linux/mediatek/files-6.1/drivers/clk/mediatek/clk-mt7988-topckgen.c b/target/linux/mediatek/files-6.1/drivers/clk/mediatek/clk-mt7988-topckgen.c deleted file mode 100644 index b0745d650..000000000 --- a/target/linux/mediatek/files-6.1/drivers/clk/mediatek/clk-mt7988-topckgen.c +++ /dev/null @@ -1,446 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (c) 2023 MediaTek Inc. - * Author: Sam Shih - * Author: Xiufeng Li - */ - -#include -#include -#include -#include -#include -#include "clk-mtk.h" -#include "clk-gate.h" -#include "clk-mux.h" -#include - -static DEFINE_SPINLOCK(mt7988_clk_lock); - -static const struct mtk_fixed_clk top_fixed_clks[] = { - FIXED_CLK(CLK_TOP_XTAL, "top_xtal", "clkxtal", 40000000), -}; - -static const struct mtk_fixed_factor top_divs[] = { - FACTOR(CLK_TOP_XTAL_D2, "top_xtal_d2", "top_xtal", 1, 2), - FACTOR(CLK_TOP_RTC_32K, "top_rtc_32k", "top_xtal", 1, 1250), - FACTOR(CLK_TOP_RTC_32P7K, "top_rtc_32p7k", "top_xtal", 1, 1220), - FACTOR(CLK_TOP_MPLL_D2, "mpll_d2", "mpll", 1, 2), - FACTOR(CLK_TOP_MPLL_D3_D2, "mpll_d3_d2", "mpll", 1, 2), - FACTOR(CLK_TOP_MPLL_D4, "mpll_d4", "mpll", 1, 4), - FACTOR(CLK_TOP_MPLL_D8, "mpll_d8", "mpll", 1, 8), - FACTOR(CLK_TOP_MPLL_D8_D2, "mpll_d8_d2", "mpll", 1, 16), - FACTOR(CLK_TOP_MMPLL_D2, "mmpll_d2", "mmpll", 1, 2), - FACTOR(CLK_TOP_MMPLL_D3_D5, "mmpll_d3_d5", "mmpll", 1, 15), - FACTOR(CLK_TOP_MMPLL_D4, "mmpll_d4", "mmpll", 1, 4), - FACTOR(CLK_TOP_MMPLL_D6_D2, "mmpll_d6_d2", "mmpll", 1, 12), - FACTOR(CLK_TOP_MMPLL_D8, "mmpll_d8", "mmpll", 1, 8), - FACTOR(CLK_TOP_APLL2_D4, "apll2_d4", "apll2", 1, 4), - FACTOR(CLK_TOP_NET1PLL_D4, "net1pll_d4", "net1pll", 1, 4), - FACTOR(CLK_TOP_NET1PLL_D5, "net1pll_d5", "net1pll", 1, 5), - FACTOR(CLK_TOP_NET1PLL_D5_D2, "net1pll_d5_d2", "net1pll", 1, 10), - FACTOR(CLK_TOP_NET1PLL_D5_D4, "net1pll_d5_d4", "net1pll", 1, 20), - FACTOR(CLK_TOP_NET1PLL_D8, "net1pll_d8", "net1pll", 1, 8), - FACTOR(CLK_TOP_NET1PLL_D8_D2, "net1pll_d8_d2", "net1pll", 1, 16), - FACTOR(CLK_TOP_NET1PLL_D8_D4, "net1pll_d8_d4", "net1pll", 1, 32), - FACTOR(CLK_TOP_NET1PLL_D8_D8, "net1pll_d8_d8", "net1pll", 1, 64), - FACTOR(CLK_TOP_NET1PLL_D8_D16, "net1pll_d8_d16", "net1pll", 1, 128), - FACTOR(CLK_TOP_NET2PLL_D2, "net2pll_d2", "net2pll", 1, 2), - FACTOR(CLK_TOP_NET2PLL_D4, "net2pll_d4", "net2pll", 1, 4), - FACTOR(CLK_TOP_NET2PLL_D4_D4, "net2pll_d4_d4", "net2pll", 1, 16), - FACTOR(CLK_TOP_NET2PLL_D4_D8, "net2pll_d4_d8", "net2pll", 1, 32), - FACTOR(CLK_TOP_NET2PLL_D6, "net2pll_d6", "net2pll", 1, 6), - FACTOR(CLK_TOP_NET2PLL_D8, "net2pll_d8", "net2pll", 1, 8), -}; - -static const char *const netsys_parents[] = { "top_xtal", "net2pll_d2", - "mmpll_d2" }; - -static const char *const netsys_500m_parents[] = { "top_xtal", "net1pll_d5", - "net1pll_d5_d2" }; - -static const char *const netsys_2x_parents[] = { "top_xtal", "net2pll", - "mmpll" }; - -static const char *const netsys_gsw_parents[] = { "top_xtal", "net1pll_d4", - "net1pll_d5" }; - -static const char *const eth_gmii_parents[] = { "top_xtal", "net1pll_d5_d4" }; - -static const char *const netsys_mcu_parents[] = { "top_xtal", "net2pll", - "mmpll", "net1pll_d4", - "net1pll_d5", "mpll" }; - -static const char *const eip197_parents[] = { "top_xtal", "netsyspll", - "net2pll", "mmpll", - "net1pll_d4", "net1pll_d5" }; - -static const char *const axi_infra_parents[] = { "top_xtal", "net1pll_d8_d2" }; - -static const char *const uart_parents[] = { "top_xtal", "mpll_d8", - "mpll_d8_d2" }; - -static const char *const emmc_250m_parents[] = { "top_xtal", "net1pll_d5_d2", - "mmpll_d4" }; - -static const char *const emmc_400m_parents[] = { "top_xtal", "msdcpll", - "mmpll_d2", "mpll_d2", - "mmpll_d4", "net1pll_d8_d2" }; - -static const char *const spi_parents[] = { "top_xtal", "mpll_d2", - "mmpll_d4", "net1pll_d8_d2", - "net2pll_d6", "net1pll_d5_d4", - "mpll_d4", "net1pll_d8_d4" }; - -static const char *const nfi1x_parents[] = { "top_xtal", "mmpll_d4", - "net1pll_d8_d2", "net2pll_d6", - "mpll_d4", "mmpll_d8", - "net1pll_d8_d4", "mpll_d8" }; - -static const char *const spinfi_parents[] = { "top_xtal_d2", "top_xtal", - "net1pll_d5_d4", "mpll_d4", - "mmpll_d8", "net1pll_d8_d4", - "mmpll_d6_d2", "mpll_d8" }; - -static const char *const pwm_parents[] = { "top_xtal", "net1pll_d8_d2", - "net1pll_d5_d4", "mpll_d4", - "mpll_d8_d2", "top_rtc_32k" }; - -static const char *const i2c_parents[] = { "top_xtal", "net1pll_d5_d4", - "mpll_d4", "net1pll_d8_d4" }; - -static const char *const pcie_mbist_250m_parents[] = { "top_xtal", - "net1pll_d5_d2" }; - -static const char *const pextp_tl_ck_parents[] = { "top_xtal", "net2pll_d6", - "mmpll_d8", "mpll_d8_d2", - "top_rtc_32k" }; - -static const char *const usb_frmcnt_parents[] = { "top_xtal", "mmpll_d3_d5" }; - -static const char *const aud_parents[] = { "top_xtal", "apll2" }; - -static const char *const a1sys_parents[] = { "top_xtal", "apll2_d4" }; - -static const char *const aud_l_parents[] = { "top_xtal", "apll2", - "mpll_d8_d2" }; - -static const char *const sspxtp_parents[] = { "top_xtal_d2", "mpll_d8_d2" }; - -static const char *const usxgmii_sbus_0_parents[] = { "top_xtal", - "net1pll_d8_d4" }; - -static const char *const sgm_0_parents[] = { "top_xtal", "sgmpll" }; - -static const char *const sysapb_parents[] = { "top_xtal", "mpll_d3_d2" }; - -static const char *const eth_refck_50m_parents[] = { "top_xtal", - "net2pll_d4_d4" }; - -static const char *const eth_sys_200m_parents[] = { "top_xtal", "net2pll_d4" }; - -static const char *const eth_xgmii_parents[] = { "top_xtal_d2", - "net1pll_d8_d8", - "net1pll_d8_d16" }; - -static const char *const bus_tops_parents[] = { "top_xtal", "net1pll_d5", - "net2pll_d2" }; - -static const char *const npu_tops_parents[] = { "top_xtal", "net2pll" }; - -static const char *const dramc_md32_parents[] = { "top_xtal", "mpll_d2", - "wedmcupll" }; - -static const char *const da_xtp_glb_p0_parents[] = { "top_xtal", - "net2pll_d8" }; - -static const char *const mcusys_backup_625m_parents[] = { "top_xtal", - "net1pll_d4" }; - -static const char *const macsec_parents[] = { "top_xtal", "sgmpll", - "net1pll_d8" }; - -static const char *const netsys_tops_400m_parents[] = { "top_xtal", - "net2pll_d2" }; - -static const char *const eth_mii_parents[] = { "top_xtal_d2", - "net2pll_d4_d8" }; - -static const struct mtk_mux top_muxes[] = { - /* CLK_CFG_0 */ - MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_SEL, "netsys_sel", netsys_parents, - 0x000, 0x004, 0x008, 0, 2, 7, 0x1c0, 0), - MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_500M_SEL, "netsys_500m_sel", - netsys_500m_parents, 0x000, 0x004, 0x008, 8, 2, - 15, 0x1C0, 1), - MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_2X_SEL, "netsys_2x_sel", - netsys_2x_parents, 0x000, 0x004, 0x008, 16, 2, 23, - 0x1C0, 2), - MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_GSW_SEL, "netsys_gsw_sel", - netsys_gsw_parents, 0x000, 0x004, 0x008, 24, 2, - 31, 0x1C0, 3), - /* CLK_CFG_1 */ - MUX_GATE_CLR_SET_UPD(CLK_TOP_ETH_GMII_SEL, "eth_gmii_sel", - eth_gmii_parents, 0x010, 0x014, 0x018, 0, 1, 7, - 0x1C0, 4), - MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_MCU_SEL, "netsys_mcu_sel", - netsys_mcu_parents, 0x010, 0x014, 0x018, 8, 3, 15, - 0x1C0, 5), - MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_PAO_2X_SEL, "netsys_pao_2x_sel", - netsys_mcu_parents, 0x010, 0x014, 0x018, 16, 3, - 23, 0x1C0, 6), - MUX_GATE_CLR_SET_UPD(CLK_TOP_EIP197_SEL, "eip197_sel", eip197_parents, - 0x010, 0x014, 0x018, 24, 3, 31, 0x1c0, 7), - /* CLK_CFG_2 */ - MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_AXI_INFRA_SEL, "axi_infra_sel", - axi_infra_parents, 0x020, 0x024, 0x028, 0, - 1, 7, 0x1C0, 8, CLK_IS_CRITICAL), - MUX_GATE_CLR_SET_UPD(CLK_TOP_UART_SEL, "uart_sel", uart_parents, 0x020, - 0x024, 0x028, 8, 2, 15, 0x1c0, 9), - MUX_GATE_CLR_SET_UPD(CLK_TOP_EMMC_250M_SEL, "emmc_250m_sel", - emmc_250m_parents, 0x020, 0x024, 0x028, 16, 2, 23, - 0x1C0, 10), - MUX_GATE_CLR_SET_UPD(CLK_TOP_EMMC_400M_SEL, "emmc_400m_sel", - emmc_400m_parents, 0x020, 0x024, 0x028, 24, 3, 31, - 0x1C0, 11), - /* CLK_CFG_3 */ - MUX_GATE_CLR_SET_UPD(CLK_TOP_SPI_SEL, "spi_sel", spi_parents, 0x030, - 0x034, 0x038, 0, 3, 7, 0x1c0, 12), - MUX_GATE_CLR_SET_UPD(CLK_TOP_SPIM_MST_SEL, "spim_mst_sel", spi_parents, - 0x030, 0x034, 0x038, 8, 3, 15, 0x1c0, 13), - MUX_GATE_CLR_SET_UPD(CLK_TOP_NFI1X_SEL, "nfi1x_sel", nfi1x_parents, - 0x030, 0x034, 0x038, 16, 3, 23, 0x1c0, 14), - MUX_GATE_CLR_SET_UPD(CLK_TOP_SPINFI_SEL, "spinfi_sel", spinfi_parents, - 0x030, 0x034, 0x038, 24, 3, 31, 0x1c0, 15), - /* CLK_CFG_4 */ - MUX_GATE_CLR_SET_UPD(CLK_TOP_PWM_SEL, "pwm_sel", pwm_parents, 0x040, - 0x044, 0x048, 0, 3, 7, 0x1c0, 16), - MUX_GATE_CLR_SET_UPD(CLK_TOP_I2C_SEL, "i2c_sel", i2c_parents, 0x040, - 0x044, 0x048, 8, 2, 15, 0x1c0, 17), - MUX_GATE_CLR_SET_UPD(CLK_TOP_PCIE_MBIST_250M_SEL, - "pcie_mbist_250m_sel", pcie_mbist_250m_parents, - 0x040, 0x044, 0x048, 16, 1, 23, 0x1C0, 18), - MUX_GATE_CLR_SET_UPD(CLK_TOP_PEXTP_TL_SEL, "pextp_tl_sel", - pextp_tl_ck_parents, 0x040, 0x044, 0x048, 24, 3, - 31, 0x1C0, 19), - /* CLK_CFG_5 */ - MUX_GATE_CLR_SET_UPD(CLK_TOP_PEXTP_TL_P1_SEL, "pextp_tl_p1_sel", - pextp_tl_ck_parents, 0x050, 0x054, 0x058, 0, 3, 7, - 0x1C0, 20), - MUX_GATE_CLR_SET_UPD(CLK_TOP_PEXTP_TL_P2_SEL, "pextp_tl_p2_sel", - pextp_tl_ck_parents, 0x050, 0x054, 0x058, 8, 3, - 15, 0x1C0, 21), - MUX_GATE_CLR_SET_UPD(CLK_TOP_PEXTP_TL_P3_SEL, "pextp_tl_p3_sel", - pextp_tl_ck_parents, 0x050, 0x054, 0x058, 16, 3, - 23, 0x1C0, 22), - MUX_GATE_CLR_SET_UPD(CLK_TOP_USB_SYS_SEL, "usb_sys_sel", - eth_gmii_parents, 0x050, 0x054, 0x058, 24, 1, 31, - 0x1C0, 23), - /* CLK_CFG_6 */ - MUX_GATE_CLR_SET_UPD(CLK_TOP_USB_SYS_P1_SEL, "usb_sys_p1_sel", - eth_gmii_parents, 0x060, 0x064, 0x068, 0, 1, 7, - 0x1C0, 24), - MUX_GATE_CLR_SET_UPD(CLK_TOP_USB_XHCI_SEL, "usb_xhci_sel", - eth_gmii_parents, 0x060, 0x064, 0x068, 8, 1, 15, - 0x1C0, 25), - MUX_GATE_CLR_SET_UPD(CLK_TOP_USB_XHCI_P1_SEL, "usb_xhci_p1_sel", - eth_gmii_parents, 0x060, 0x064, 0x068, 16, 1, 23, - 0x1C0, 26), - MUX_GATE_CLR_SET_UPD(CLK_TOP_USB_FRMCNT_SEL, "usb_frmcnt_sel", - usb_frmcnt_parents, 0x060, 0x064, 0x068, 24, 1, - 31, 0x1C0, 27), - /* CLK_CFG_7 */ - MUX_GATE_CLR_SET_UPD(CLK_TOP_USB_FRMCNT_P1_SEL, "usb_frmcnt_p1_sel", - usb_frmcnt_parents, 0x070, 0x074, 0x078, 0, 1, 7, - 0x1C0, 28), - MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_SEL, "aud_sel", aud_parents, 0x070, - 0x074, 0x078, 8, 1, 15, 0x1c0, 29), - MUX_GATE_CLR_SET_UPD(CLK_TOP_A1SYS_SEL, "a1sys_sel", a1sys_parents, - 0x070, 0x074, 0x078, 16, 1, 23, 0x1c0, 30), - MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_L_SEL, "aud_l_sel", aud_l_parents, - 0x070, 0x074, 0x078, 24, 2, 31, 0x1c4, 0), - /* CLK_CFG_8 */ - MUX_GATE_CLR_SET_UPD(CLK_TOP_A_TUNER_SEL, "a_tuner_sel", a1sys_parents, - 0x080, 0x084, 0x088, 0, 1, 7, 0x1c4, 1), - MUX_GATE_CLR_SET_UPD(CLK_TOP_SSPXTP_SEL, "sspxtp_sel", sspxtp_parents, - 0x080, 0x084, 0x088, 8, 1, 15, 0x1c4, 2), - MUX_GATE_CLR_SET_UPD(CLK_TOP_USB_PHY_SEL, "usb_phy_sel", - sspxtp_parents, 0x080, 0x084, 0x088, 16, 1, 23, - 0x1c4, 3), - MUX_GATE_CLR_SET_UPD(CLK_TOP_USXGMII_SBUS_0_SEL, "usxgmii_sbus_0_sel", - usxgmii_sbus_0_parents, 0x080, 0x084, 0x088, 24, - 1, 31, 0x1C4, 4), - /* CLK_CFG_9 */ - MUX_GATE_CLR_SET_UPD(CLK_TOP_USXGMII_SBUS_1_SEL, "usxgmii_sbus_1_sel", - usxgmii_sbus_0_parents, 0x090, 0x094, 0x098, 0, 1, - 7, 0x1C4, 5), - MUX_GATE_CLR_SET_UPD(CLK_TOP_SGM_0_SEL, "sgm_0_sel", sgm_0_parents, - 0x090, 0x094, 0x098, 8, 1, 15, 0x1c4, 6), - MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SGM_SBUS_0_SEL, "sgm_sbus_0_sel", - usxgmii_sbus_0_parents, 0x090, 0x094, 0x098, - 16, 1, 23, 0x1C4, 7, CLK_IS_CRITICAL), - MUX_GATE_CLR_SET_UPD(CLK_TOP_SGM_1_SEL, "sgm_1_sel", sgm_0_parents, - 0x090, 0x094, 0x098, 24, 1, 31, 0x1c4, 8), - /* CLK_CFG_10 */ - MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SGM_SBUS_1_SEL, "sgm_sbus_1_sel", - usxgmii_sbus_0_parents, 0x0a0, 0x0a4, 0x0a8, - 0, 1, 7, 0x1C4, 9, CLK_IS_CRITICAL), - MUX_GATE_CLR_SET_UPD(CLK_TOP_XFI_PHY_0_XTAL_SEL, "xfi_phy_0_xtal_sel", - sspxtp_parents, 0x0a0, 0x0a4, 0x0a8, 8, 1, 15, - 0x1C4, 10), - MUX_GATE_CLR_SET_UPD(CLK_TOP_XFI_PHY_1_XTAL_SEL, "xfi_phy_1_xtal_sel", - sspxtp_parents, 0x0a0, 0x0a4, 0x0a8, 16, 1, 23, - 0x1C4, 11), - /* CLK_CFG_11 */ - MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SYSAXI_SEL, "sysaxi_sel", - axi_infra_parents, 0x0a0, 0x0a4, 0x0a8, 24, - 1, 31, 0x1C4, 12, CLK_IS_CRITICAL), - MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SYSAPB_SEL, "sysapb_sel", - sysapb_parents, 0x0b0, 0x0b4, 0x0b8, 0, 1, - 7, 0x1c4, 13, CLK_IS_CRITICAL), - MUX_GATE_CLR_SET_UPD(CLK_TOP_ETH_REFCK_50M_SEL, "eth_refck_50m_sel", - eth_refck_50m_parents, 0x0b0, 0x0b4, 0x0b8, 8, 1, - 15, 0x1C4, 14), - MUX_GATE_CLR_SET_UPD(CLK_TOP_ETH_SYS_200M_SEL, "eth_sys_200m_sel", - eth_sys_200m_parents, 0x0b0, 0x0b4, 0x0b8, 16, 1, - 23, 0x1C4, 15), - MUX_GATE_CLR_SET_UPD(CLK_TOP_ETH_SYS_SEL, "eth_sys_sel", - pcie_mbist_250m_parents, 0x0b0, 0x0b4, 0x0b8, 24, - 1, 31, 0x1C4, 16), - /* CLK_CFG_12 */ - MUX_GATE_CLR_SET_UPD(CLK_TOP_ETH_XGMII_SEL, "eth_xgmii_sel", - eth_xgmii_parents, 0x0c0, 0x0c4, 0x0c8, 0, 2, 7, - 0x1C4, 17), - MUX_GATE_CLR_SET_UPD(CLK_TOP_BUS_TOPS_SEL, "bus_tops_sel", - bus_tops_parents, 0x0c0, 0x0c4, 0x0c8, 8, 2, 15, - 0x1C4, 18), - MUX_GATE_CLR_SET_UPD(CLK_TOP_NPU_TOPS_SEL, "npu_tops_sel", - npu_tops_parents, 0x0c0, 0x0c4, 0x0c8, 16, 1, 23, - 0x1C4, 19), - MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_DRAMC_SEL, "dramc_sel", - sspxtp_parents, 0x0c0, 0x0c4, 0x0c8, 24, 1, - 31, 0x1C4, 20, CLK_IS_CRITICAL), - /* CLK_CFG_13 */ - MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_DRAMC_MD32_SEL, "dramc_md32_sel", - dramc_md32_parents, 0x0d0, 0x0d4, 0x0d8, 0, - 2, 7, 0x1C4, 21, CLK_IS_CRITICAL), - MUX_GATE_CLR_SET_UPD_FLAGS( - CLK_TOP_INFRA_F26M_SEL, "csw_infra_f26m_sel", sspxtp_parents, - 0x0d0, 0x0d4, 0x0d8, 8, 1, 15, 0x1C4, 22, CLK_IS_CRITICAL), - MUX_GATE_CLR_SET_UPD(CLK_TOP_PEXTP_P0_SEL, "pextp_p0_sel", - sspxtp_parents, 0x0d0, 0x0d4, 0x0d8, 16, 1, 23, - 0x1C4, 23), - MUX_GATE_CLR_SET_UPD(CLK_TOP_PEXTP_P1_SEL, "pextp_p1_sel", - sspxtp_parents, 0x0d0, 0x0d4, 0x0d8, 24, 1, 31, - 0x1C4, 24), - /* CLK_CFG_14 */ - MUX_GATE_CLR_SET_UPD(CLK_TOP_PEXTP_P2_SEL, "pextp_p2_sel", - sspxtp_parents, 0x0e0, 0x0e4, 0x0e8, 0, 1, 7, - 0x1C4, 25), - MUX_GATE_CLR_SET_UPD(CLK_TOP_PEXTP_P3_SEL, "pextp_p3_sel", - sspxtp_parents, 0x0e0, 0x0e4, 0x0e8, 8, 1, 15, - 0x1C4, 26), - MUX_GATE_CLR_SET_UPD(CLK_TOP_DA_XTP_GLB_P0_SEL, "da_xtp_glb_p0_sel", - da_xtp_glb_p0_parents, 0x0e0, 0x0e4, 0x0e8, 16, 1, - 23, 0x1C4, 27), - MUX_GATE_CLR_SET_UPD(CLK_TOP_DA_XTP_GLB_P1_SEL, "da_xtp_glb_p1_sel", - da_xtp_glb_p0_parents, 0x0e0, 0x0e4, 0x0e8, 24, 1, - 31, 0x1C4, 28), - /* CLK_CFG_15 */ - MUX_GATE_CLR_SET_UPD(CLK_TOP_DA_XTP_GLB_P2_SEL, "da_xtp_glb_p2_sel", - da_xtp_glb_p0_parents, 0x0f0, 0x0f4, 0x0f8, 0, 1, - 7, 0x1C4, 29), - MUX_GATE_CLR_SET_UPD(CLK_TOP_DA_XTP_GLB_P3_SEL, "da_xtp_glb_p3_sel", - da_xtp_glb_p0_parents, 0x0f0, 0x0f4, 0x0f8, 8, 1, - 15, 0x1C4, 30), - MUX_GATE_CLR_SET_UPD(CLK_TOP_CKM_SEL, "ckm_sel", sspxtp_parents, 0x0F0, - 0x0f4, 0x0f8, 16, 1, 23, 0x1c8, 0), - MUX_GATE_CLR_SET_UPD(CLK_TOP_DA_SEL, "da_sel", sspxtp_parents, 0x0f0, - 0x0f4, 0x0f8, 24, 1, 31, 0x1C8, 1), - /* CLK_CFG_16 */ - MUX_GATE_CLR_SET_UPD(CLK_TOP_PEXTP_SEL, "pextp_sel", sspxtp_parents, - 0x0100, 0x104, 0x108, 0, 1, 7, 0x1c8, 2), - MUX_GATE_CLR_SET_UPD(CLK_TOP_TOPS_P2_26M_SEL, "tops_p2_26m_sel", - sspxtp_parents, 0x0100, 0x104, 0x108, 8, 1, 15, - 0x1C8, 3), - MUX_GATE_CLR_SET_UPD(CLK_TOP_MCUSYS_BACKUP_625M_SEL, - "mcusys_backup_625m_sel", - mcusys_backup_625m_parents, 0x0100, 0x104, 0x108, - 16, 1, 23, 0x1C8, 4), - MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_SYNC_250M_SEL, - "netsys_sync_250m_sel", pcie_mbist_250m_parents, - 0x0100, 0x104, 0x108, 24, 1, 31, 0x1c8, 5), - /* CLK_CFG_17 */ - MUX_GATE_CLR_SET_UPD(CLK_TOP_MACSEC_SEL, "macsec_sel", macsec_parents, - 0x0110, 0x114, 0x118, 0, 2, 7, 0x1c8, 6), - MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_TOPS_400M_SEL, - "netsys_tops_400m_sel", netsys_tops_400m_parents, - 0x0110, 0x114, 0x118, 8, 1, 15, 0x1c8, 7), - MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_PPEFB_250M_SEL, - "netsys_ppefb_250m_sel", pcie_mbist_250m_parents, - 0x0110, 0x114, 0x118, 16, 1, 23, 0x1c8, 8), - MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_WARP_SEL, "netsys_warp_sel", - netsys_parents, 0x0110, 0x114, 0x118, 24, 2, 31, - 0x1C8, 9), - /* CLK_CFG_18 */ - MUX_GATE_CLR_SET_UPD(CLK_TOP_ETH_MII_SEL, "eth_mii_sel", - eth_mii_parents, 0x0120, 0x124, 0x128, 0, 1, 7, - 0x1c8, 10), - MUX_GATE_CLR_SET_UPD(CLK_TOP_NPU_SEL, "ck_npu_sel", netsys_2x_parents, - 0x0120, 0x124, 0x128, 8, 2, 15, 0x1c8, 11), -}; - -static const struct mtk_composite top_aud_divs[] = { - DIV_GATE(CLK_TOP_AUD_I2S_M, "aud_i2s_m", "aud_sel", 0x0420, 0, 0x0420, - 8, 8), -}; - -static const struct mtk_clk_desc topck_desc = { - .fixed_clks = top_fixed_clks, - .num_fixed_clks = ARRAY_SIZE(top_fixed_clks), - .factor_clks = top_divs, - .num_factor_clks = ARRAY_SIZE(top_divs), - .mux_clks = top_muxes, - .num_mux_clks = ARRAY_SIZE(top_muxes), - .composite_clks = top_aud_divs, - .num_composite_clks = ARRAY_SIZE(top_aud_divs), - .clk_lock = &mt7988_clk_lock, -}; - -static const char *const mcu_bus_div_parents[] = { "top_xtal", "ccipll2_b", - "net1pll_d4" }; - -static const char *const mcu_arm_div_parents[] = { "top_xtal", "arm_b", - "net1pll_d4" }; - -static struct mtk_composite mcu_muxes[] = { - /* bus_pll_divider_cfg */ - MUX_GATE_FLAGS(CLK_MCU_BUS_DIV_SEL, "mcu_bus_div_sel", - mcu_bus_div_parents, 0x7C0, 9, 2, -1, CLK_IS_CRITICAL), - /* mp2_pll_divider_cfg */ - MUX_GATE_FLAGS(CLK_MCU_ARM_DIV_SEL, "mcu_arm_div_sel", - mcu_arm_div_parents, 0x7A8, 9, 2, -1, CLK_IS_CRITICAL), -}; - -static const struct mtk_clk_desc mcusys_desc = { - .composite_clks = mcu_muxes, - .num_composite_clks = ARRAY_SIZE(mcu_muxes), -}; - -static const struct of_device_id of_match_clk_mt7988_topckgen[] = { - { .compatible = "mediatek,mt7988-topckgen", .data = &topck_desc }, - { .compatible = "mediatek,mt7988-mcusys", .data = &mcusys_desc }, - { /* sentinel */ } -}; -MODULE_DEVICE_TABLE(of, of_match_clk_mt7988_topckgen); - -static struct platform_driver clk_mt7988_topckgen_drv = { - .probe = mtk_clk_simple_probe, - .remove = mtk_clk_simple_remove, - .driver = { - .name = "clk-mt7988-topckgen", - .of_match_table = of_match_clk_mt7988_topckgen, - }, -}; -module_platform_driver(clk_mt7988_topckgen_drv); -MODULE_LICENSE("GPL"); diff --git a/target/linux/mediatek/files-6.1/drivers/net/phy/mediatek-2p5ge.c b/target/linux/mediatek/files-6.1/drivers/net/phy/mediatek-2p5ge.c deleted file mode 100644 index c12e6b8eb..000000000 --- a/target/linux/mediatek/files-6.1/drivers/net/phy/mediatek-2p5ge.c +++ /dev/null @@ -1,262 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -#include -#include -#include -#include -#include -#include -#include -#include - -#define MEDAITEK_2P5GE_PHY_DMB_FW "mediatek/mediatek-2p5ge-phy-dmb.bin" -#define MEDIATEK_2P5GE_PHY_PMB_FW "mediatek/mediatek-2p5ge-phy-pmb.bin" - -#define MD32_EN_CFG 0x18 -#define MD32_EN BIT(0) - -#define BASE100T_STATUS_EXTEND 0x10 -#define BASE1000T_STATUS_EXTEND 0x11 -#define EXTEND_CTRL_AND_STATUS 0x16 - -#define PHY_AUX_CTRL_STATUS 0x1d -#define PHY_AUX_DPX_MASK GENMASK(5, 5) -#define PHY_AUX_SPEED_MASK GENMASK(4, 2) - -/* Registers on MDIO_MMD_VEND1 */ -#define MTK_PHY_LINK_STATUS_MISC 0xa2 -#define MTK_PHY_FDX_ENABLE BIT(5) - -/* Registers on MDIO_MMD_VEND2 */ -#define MTK_PHY_LED0_ON_CTRL 0x24 -#define MTK_PHY_LED0_ON_LINK1000 BIT(0) -#define MTK_PHY_LED0_ON_LINK100 BIT(1) -#define MTK_PHY_LED0_ON_LINK10 BIT(2) -#define MTK_PHY_LED0_ON_LINK2500 BIT(7) -#define MTK_PHY_LED0_POLARITY BIT(14) - -#define MTK_PHY_LED1_ON_CTRL 0x26 -#define MTK_PHY_LED1_ON_FDX BIT(4) -#define MTK_PHY_LED1_ON_HDX BIT(5) -#define MTK_PHY_LED1_POLARITY BIT(14) - -enum { - PHY_AUX_SPD_10 = 0, - PHY_AUX_SPD_100, - PHY_AUX_SPD_1000, - PHY_AUX_SPD_2500, -}; - -static int mt798x_2p5ge_phy_config_init(struct phy_device *phydev) -{ - int ret; - int i; - const struct firmware *fw; - struct device *dev = &phydev->mdio.dev; - struct device_node *np; - void __iomem *dmb_addr; - void __iomem *pmb_addr; - void __iomem *mcucsr_base; - u16 reg; - struct pinctrl *pinctrl; - - np = of_find_compatible_node(NULL, NULL, "mediatek,2p5gphy-fw"); - if (!np) - return -ENOENT; - - dmb_addr = of_iomap(np, 0); - if (!dmb_addr) - return -ENOMEM; - pmb_addr = of_iomap(np, 1); - if (!pmb_addr) - return -ENOMEM; - mcucsr_base = of_iomap(np, 2); - if (!mcucsr_base) - return -ENOMEM; - - ret = request_firmware(&fw, MEDAITEK_2P5GE_PHY_DMB_FW, dev); - if (ret) { - dev_err(dev, "failed to load firmware: %s, ret: %d\n", - MEDAITEK_2P5GE_PHY_DMB_FW, ret); - return ret; - } - for (i = 0; i < fw->size - 1; i += 4) - writel(*((uint32_t *)(fw->data + i)), dmb_addr + i); - release_firmware(fw); - - ret = request_firmware(&fw, MEDIATEK_2P5GE_PHY_PMB_FW, dev); - if (ret) { - dev_err(dev, "failed to load firmware: %s, ret: %d\n", - MEDIATEK_2P5GE_PHY_PMB_FW, ret); - return ret; - } - for (i = 0; i < fw->size - 1; i += 4) - writel(*((uint32_t *)(fw->data + i)), pmb_addr + i); - release_firmware(fw); - - reg = readw(mcucsr_base + MD32_EN_CFG); - writew(reg | MD32_EN, mcucsr_base + MD32_EN_CFG); - dev_dbg(dev, "Firmware loading/trigger ok.\n"); - - /* Setup LED */ - phy_clear_bits_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_LED0_ON_CTRL, - MTK_PHY_LED0_POLARITY); - - phy_set_bits_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_LED0_ON_CTRL, - MTK_PHY_LED0_ON_LINK10 | - MTK_PHY_LED0_ON_LINK100 | - MTK_PHY_LED0_ON_LINK1000 | - MTK_PHY_LED0_ON_LINK2500); - - phy_set_bits_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_LED1_ON_CTRL, - MTK_PHY_LED1_ON_FDX | MTK_PHY_LED1_ON_HDX); - - pinctrl = devm_pinctrl_get_select(&phydev->mdio.dev, "i2p5gbe-led"); - if (IS_ERR(pinctrl)) { - dev_err(&phydev->mdio.dev, "Fail to set LED pins!\n"); - return PTR_ERR(pinctrl); - } - - return 0; -} - -static int mt798x_2p5ge_phy_config_aneg(struct phy_device *phydev) -{ - bool changed = false; - u32 adv; - int ret; - - if (phydev->autoneg == AUTONEG_DISABLE) { - /* Configure half duplex with genphy_setup_forced, - * because genphy_c45_pma_setup_forced does not support. - */ - return phydev->duplex != DUPLEX_FULL - ? genphy_setup_forced(phydev) - : genphy_c45_pma_setup_forced(phydev); - } - - ret = genphy_c45_an_config_aneg(phydev); - if (ret < 0) - return ret; - if (ret > 0) - changed = true; - - adv = linkmode_adv_to_mii_ctrl1000_t(phydev->advertising); - ret = phy_modify_changed(phydev, MII_CTRL1000, - ADVERTISE_1000FULL | ADVERTISE_1000HALF, - adv); - if (ret < 0) - return ret; - if (ret > 0) - changed = true; - - return genphy_c45_check_and_restart_aneg(phydev, changed); -} - -static int mt798x_2p5ge_phy_get_features(struct phy_device *phydev) -{ - int ret; - - ret = genphy_read_abilities(phydev); - if (ret) - return ret; - - /* We don't support HDX at MAC layer on mt798x. - * So mask phy's HDX capabilities, too. - */ - linkmode_set_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT, - phydev->supported); - linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT, - phydev->supported); - linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, - phydev->supported); - linkmode_set_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, - phydev->supported); - linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, phydev->supported); - - return 0; -} - -static int mt798x_2p5ge_phy_read_status(struct phy_device *phydev) -{ - int ret; - - ret = genphy_update_link(phydev); - if (ret) - return ret; - - phydev->speed = SPEED_UNKNOWN; - phydev->duplex = DUPLEX_UNKNOWN; - phydev->pause = 0; - phydev->asym_pause = 0; - - if (!phydev->link) - return 0; - - if (phydev->autoneg == AUTONEG_ENABLE && phydev->autoneg_complete) { - ret = genphy_c45_read_lpa(phydev); - if (ret < 0) - return ret; - - /* Read the link partner's 1G advertisement */ - ret = phy_read(phydev, MII_STAT1000); - if (ret < 0) - return ret; - mii_stat1000_mod_linkmode_lpa_t(phydev->lp_advertising, ret); - } else if (phydev->autoneg == AUTONEG_DISABLE) { - linkmode_zero(phydev->lp_advertising); - } - - ret = phy_read(phydev, PHY_AUX_CTRL_STATUS); - if (ret < 0) - return ret; - - switch (FIELD_GET(PHY_AUX_SPEED_MASK, ret)) { - case PHY_AUX_SPD_10: - phydev->speed = SPEED_10; - break; - case PHY_AUX_SPD_100: - phydev->speed = SPEED_100; - break; - case PHY_AUX_SPD_1000: - phydev->speed = SPEED_1000; - break; - case PHY_AUX_SPD_2500: - phydev->speed = SPEED_2500; - phydev->duplex = DUPLEX_FULL; /* 2.5G must be FDX */ - break; - } - - ret = phy_read_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_LINK_STATUS_MISC); - if (ret < 0) - return ret; - - phydev->duplex = (ret & MTK_PHY_FDX_ENABLE) ? DUPLEX_FULL : DUPLEX_HALF; - - return 0; -} - -static struct phy_driver mtk_gephy_driver[] = { - { - PHY_ID_MATCH_EXACT(0x00339c11), - .name = "MediaTek MT798x 2.5GbE PHY", - .config_init = mt798x_2p5ge_phy_config_init, - .config_aneg = mt798x_2p5ge_phy_config_aneg, - .get_features = mt798x_2p5ge_phy_get_features, - .read_status = mt798x_2p5ge_phy_read_status, - }, -}; - -module_phy_driver(mtk_gephy_driver); - -static struct mdio_device_id __maybe_unused mtk_2p5ge_phy_tbl[] = { - { PHY_ID_MATCH_VENDOR(0x00339c00) }, - { } -}; - -MODULE_DESCRIPTION("MediaTek 2.5Gb Ethernet PHY driver"); -MODULE_AUTHOR("SkyLake Huang "); -MODULE_LICENSE("GPL"); - -MODULE_DEVICE_TABLE(mdio, mtk_2p5ge_phy_tbl); -MODULE_FIRMWARE(MEDAITEK_2P5GE_PHY_DMB_FW); -MODULE_FIRMWARE(MEDIATEK_2P5GE_PHY_PMB_FW); diff --git a/target/linux/mediatek/files-6.1/drivers/pinctrl/mediatek/pinctrl-mt7988.c b/target/linux/mediatek/files-6.1/drivers/pinctrl/mediatek/pinctrl-mt7988.c deleted file mode 100644 index 49c0be1bb..000000000 --- a/target/linux/mediatek/files-6.1/drivers/pinctrl/mediatek/pinctrl-mt7988.c +++ /dev/null @@ -1,1466 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * The MT7988 driver based on Linux generic pinctrl binding. - * - * Copyright (C) 2020 MediaTek Inc. - * Author: Sam Shih - */ - -#include "pinctrl-moore.h" - -enum MT7988_PINCTRL_REG_PAGE { - GPIO_BASE, - IOCFG_TR_BASE, - IOCFG_BR_BASE, - IOCFG_RB_BASE, - IOCFG_LB_BASE, - IOCFG_TL_BASE, -}; - -#define MT7988_PIN(_number, _name) MTK_PIN(_number, _name, 0, _number, DRV_GRP4) - -#define PIN_FIELD_BASE(_s_pin, _e_pin, _i_base, _s_addr, _x_addrs, _s_bit, \ - _x_bits) \ - PIN_FIELD_CALC(_s_pin, _e_pin, _i_base, _s_addr, _x_addrs, _s_bit, \ - _x_bits, 32, 0) - -#define PINS_FIELD_BASE(_s_pin, _e_pin, _i_base, _s_addr, _x_addrs, _s_bit, \ - _x_bits) \ - PIN_FIELD_CALC(_s_pin, _e_pin, _i_base, _s_addr, _x_addrs, _s_bit, \ - _x_bits, 32, 1) - -static const struct mtk_pin_field_calc mt7988_pin_mode_range[] = { - PIN_FIELD(0, 83, 0x300, 0x10, 0, 4), -}; - -static const struct mtk_pin_field_calc mt7988_pin_dir_range[] = { - PIN_FIELD(0, 83, 0x0, 0x10, 0, 1), -}; - -static const struct mtk_pin_field_calc mt7988_pin_di_range[] = { - PIN_FIELD(0, 83, 0x200, 0x10, 0, 1), -}; - -static const struct mtk_pin_field_calc mt7988_pin_do_range[] = { - PIN_FIELD(0, 83, 0x100, 0x10, 0, 1), -}; - -static const struct mtk_pin_field_calc mt7988_pin_ies_range[] = { - PIN_FIELD_BASE(0, 0, 5, 0x30, 0x10, 13, 1), - PIN_FIELD_BASE(1, 1, 5, 0x30, 0x10, 14, 1), - PIN_FIELD_BASE(2, 2, 5, 0x30, 0x10, 11, 1), - PIN_FIELD_BASE(3, 3, 5, 0x30, 0x10, 12, 1), - PIN_FIELD_BASE(4, 4, 5, 0x30, 0x10, 0, 1), - PIN_FIELD_BASE(5, 5, 5, 0x30, 0x10, 9, 1), - PIN_FIELD_BASE(6, 6, 5, 0x30, 0x10, 10, 1), - - PIN_FIELD_BASE(7, 7, 4, 0x30, 0x10, 8, 1), - PIN_FIELD_BASE(8, 8, 4, 0x30, 0x10, 6, 1), - PIN_FIELD_BASE(9, 9, 4, 0x30, 0x10, 5, 1), - PIN_FIELD_BASE(10, 10, 4, 0x30, 0x10, 3, 1), - - PIN_FIELD_BASE(11, 11, 1, 0x40, 0x10, 0, 1), - PIN_FIELD_BASE(12, 12, 1, 0x40, 0x10, 21, 1), - PIN_FIELD_BASE(13, 13, 1, 0x40, 0x10, 1, 1), - PIN_FIELD_BASE(14, 14, 1, 0x40, 0x10, 2, 1), - - PIN_FIELD_BASE(15, 15, 5, 0x30, 0x10, 7, 1), - PIN_FIELD_BASE(16, 16, 5, 0x30, 0x10, 8, 1), - PIN_FIELD_BASE(17, 17, 5, 0x30, 0x10, 3, 1), - PIN_FIELD_BASE(18, 18, 5, 0x30, 0x10, 4, 1), - - PIN_FIELD_BASE(19, 19, 4, 0x30, 0x10, 7, 1), - PIN_FIELD_BASE(20, 20, 4, 0x30, 0x10, 4, 1), - - PIN_FIELD_BASE(21, 21, 3, 0x50, 0x10, 17, 1), - PIN_FIELD_BASE(22, 22, 3, 0x50, 0x10, 23, 1), - PIN_FIELD_BASE(23, 23, 3, 0x50, 0x10, 20, 1), - PIN_FIELD_BASE(24, 24, 3, 0x50, 0x10, 19, 1), - PIN_FIELD_BASE(25, 25, 3, 0x50, 0x10, 21, 1), - PIN_FIELD_BASE(26, 26, 3, 0x50, 0x10, 22, 1), - PIN_FIELD_BASE(27, 27, 3, 0x50, 0x10, 18, 1), - PIN_FIELD_BASE(28, 28, 3, 0x50, 0x10, 25, 1), - PIN_FIELD_BASE(29, 29, 3, 0x50, 0x10, 26, 1), - PIN_FIELD_BASE(30, 30, 3, 0x50, 0x10, 27, 1), - PIN_FIELD_BASE(31, 31, 3, 0x50, 0x10, 24, 1), - PIN_FIELD_BASE(32, 32, 3, 0x50, 0x10, 28, 1), - PIN_FIELD_BASE(33, 33, 3, 0x60, 0x10, 0, 1), - PIN_FIELD_BASE(34, 34, 3, 0x50, 0x10, 31, 1), - PIN_FIELD_BASE(35, 35, 3, 0x50, 0x10, 29, 1), - PIN_FIELD_BASE(36, 36, 3, 0x50, 0x10, 30, 1), - PIN_FIELD_BASE(37, 37, 3, 0x60, 0x10, 1, 1), - PIN_FIELD_BASE(38, 38, 3, 0x50, 0x10, 11, 1), - PIN_FIELD_BASE(39, 39, 3, 0x50, 0x10, 10, 1), - PIN_FIELD_BASE(40, 40, 3, 0x50, 0x10, 0, 1), - PIN_FIELD_BASE(41, 41, 3, 0x50, 0x10, 1, 1), - PIN_FIELD_BASE(42, 42, 3, 0x50, 0x10, 9, 1), - PIN_FIELD_BASE(43, 43, 3, 0x50, 0x10, 8, 1), - PIN_FIELD_BASE(44, 44, 3, 0x50, 0x10, 7, 1), - PIN_FIELD_BASE(45, 45, 3, 0x50, 0x10, 6, 1), - PIN_FIELD_BASE(46, 46, 3, 0x50, 0x10, 5, 1), - PIN_FIELD_BASE(47, 47, 3, 0x50, 0x10, 4, 1), - PIN_FIELD_BASE(48, 48, 3, 0x50, 0x10, 3, 1), - PIN_FIELD_BASE(49, 49, 3, 0x50, 0x10, 2, 1), - PIN_FIELD_BASE(50, 50, 3, 0x50, 0x10, 15, 1), - PIN_FIELD_BASE(51, 51, 3, 0x50, 0x10, 12, 1), - PIN_FIELD_BASE(52, 52, 3, 0x50, 0x10, 13, 1), - PIN_FIELD_BASE(53, 53, 3, 0x50, 0x10, 14, 1), - PIN_FIELD_BASE(54, 54, 3, 0x50, 0x10, 16, 1), - - PIN_FIELD_BASE(55, 55, 1, 0x40, 0x10, 14, 1), - PIN_FIELD_BASE(56, 56, 1, 0x40, 0x10, 15, 1), - PIN_FIELD_BASE(57, 57, 1, 0x40, 0x10, 13, 1), - PIN_FIELD_BASE(58, 58, 1, 0x40, 0x10, 4, 1), - PIN_FIELD_BASE(59, 59, 1, 0x40, 0x10, 5, 1), - PIN_FIELD_BASE(60, 60, 1, 0x40, 0x10, 6, 1), - PIN_FIELD_BASE(61, 61, 1, 0x40, 0x10, 3, 1), - PIN_FIELD_BASE(62, 62, 1, 0x40, 0x10, 7, 1), - PIN_FIELD_BASE(63, 63, 1, 0x40, 0x10, 20, 1), - PIN_FIELD_BASE(64, 64, 1, 0x40, 0x10, 8, 1), - PIN_FIELD_BASE(65, 65, 1, 0x40, 0x10, 9, 1), - PIN_FIELD_BASE(66, 66, 1, 0x40, 0x10, 10, 1), - PIN_FIELD_BASE(67, 67, 1, 0x40, 0x10, 11, 1), - PIN_FIELD_BASE(68, 68, 1, 0x40, 0x10, 12, 1), - - PIN_FIELD_BASE(69, 69, 5, 0x30, 0x10, 1, 1), - PIN_FIELD_BASE(70, 70, 5, 0x30, 0x10, 2, 1), - PIN_FIELD_BASE(71, 71, 5, 0x30, 0x10, 5, 1), - PIN_FIELD_BASE(72, 72, 5, 0x30, 0x10, 6, 1), - - PIN_FIELD_BASE(73, 73, 4, 0x30, 0x10, 10, 1), - PIN_FIELD_BASE(74, 74, 4, 0x30, 0x10, 1, 1), - PIN_FIELD_BASE(75, 75, 4, 0x30, 0x10, 11, 1), - PIN_FIELD_BASE(76, 76, 4, 0x30, 0x10, 9, 1), - PIN_FIELD_BASE(77, 77, 4, 0x30, 0x10, 2, 1), - PIN_FIELD_BASE(78, 78, 4, 0x30, 0x10, 0, 1), - PIN_FIELD_BASE(79, 79, 4, 0x30, 0x10, 12, 1), - - PIN_FIELD_BASE(80, 80, 1, 0x40, 0x10, 18, 1), - PIN_FIELD_BASE(81, 81, 1, 0x40, 0x10, 19, 1), - PIN_FIELD_BASE(82, 82, 1, 0x40, 0x10, 16, 1), - PIN_FIELD_BASE(83, 83, 1, 0x40, 0x10, 17, 1), -}; - -static const struct mtk_pin_field_calc mt7988_pin_smt_range[] = { - PIN_FIELD_BASE(0, 0, 5, 0xc0, 0x10, 13, 1), - PIN_FIELD_BASE(1, 1, 5, 0xc0, 0x10, 14, 1), - PIN_FIELD_BASE(2, 2, 5, 0xc0, 0x10, 11, 1), - PIN_FIELD_BASE(3, 3, 5, 0xc0, 0x10, 12, 1), - PIN_FIELD_BASE(4, 4, 5, 0xc0, 0x10, 0, 1), - PIN_FIELD_BASE(5, 5, 5, 0xc0, 0x10, 9, 1), - PIN_FIELD_BASE(6, 6, 5, 0xc0, 0x10, 10, 1), - - PIN_FIELD_BASE(7, 7, 4, 0xb0, 0x10, 8, 1), - PIN_FIELD_BASE(8, 8, 4, 0xb0, 0x10, 6, 1), - PIN_FIELD_BASE(9, 9, 4, 0xb0, 0x10, 5, 1), - PIN_FIELD_BASE(10, 10, 4, 0xb0, 0x10, 3, 1), - - PIN_FIELD_BASE(11, 11, 1, 0xe0, 0x10, 0, 1), - PIN_FIELD_BASE(12, 12, 1, 0xe0, 0x10, 21, 1), - PIN_FIELD_BASE(13, 13, 1, 0xe0, 0x10, 1, 1), - PIN_FIELD_BASE(14, 14, 1, 0xe0, 0x10, 2, 1), - - PIN_FIELD_BASE(15, 15, 5, 0xc0, 0x10, 7, 1), - PIN_FIELD_BASE(16, 16, 5, 0xc0, 0x10, 8, 1), - PIN_FIELD_BASE(17, 17, 5, 0xc0, 0x10, 3, 1), - PIN_FIELD_BASE(18, 18, 5, 0xc0, 0x10, 4, 1), - - PIN_FIELD_BASE(19, 19, 4, 0xb0, 0x10, 7, 1), - PIN_FIELD_BASE(20, 20, 4, 0xb0, 0x10, 4, 1), - - PIN_FIELD_BASE(21, 21, 3, 0x140, 0x10, 17, 1), - PIN_FIELD_BASE(22, 22, 3, 0x140, 0x10, 23, 1), - PIN_FIELD_BASE(23, 23, 3, 0x140, 0x10, 20, 1), - PIN_FIELD_BASE(24, 24, 3, 0x140, 0x10, 19, 1), - PIN_FIELD_BASE(25, 25, 3, 0x140, 0x10, 21, 1), - PIN_FIELD_BASE(26, 26, 3, 0x140, 0x10, 22, 1), - PIN_FIELD_BASE(27, 27, 3, 0x140, 0x10, 18, 1), - PIN_FIELD_BASE(28, 28, 3, 0x140, 0x10, 25, 1), - PIN_FIELD_BASE(29, 29, 3, 0x140, 0x10, 26, 1), - PIN_FIELD_BASE(30, 30, 3, 0x140, 0x10, 27, 1), - PIN_FIELD_BASE(31, 31, 3, 0x140, 0x10, 24, 1), - PIN_FIELD_BASE(32, 32, 3, 0x140, 0x10, 28, 1), - PIN_FIELD_BASE(33, 33, 3, 0x150, 0x10, 0, 1), - PIN_FIELD_BASE(34, 34, 3, 0x140, 0x10, 31, 1), - PIN_FIELD_BASE(35, 35, 3, 0x140, 0x10, 29, 1), - PIN_FIELD_BASE(36, 36, 3, 0x140, 0x10, 30, 1), - PIN_FIELD_BASE(37, 37, 3, 0x150, 0x10, 1, 1), - PIN_FIELD_BASE(38, 38, 3, 0x140, 0x10, 11, 1), - PIN_FIELD_BASE(39, 39, 3, 0x140, 0x10, 10, 1), - PIN_FIELD_BASE(40, 40, 3, 0x140, 0x10, 0, 1), - PIN_FIELD_BASE(41, 41, 3, 0x140, 0x10, 1, 1), - PIN_FIELD_BASE(42, 42, 3, 0x140, 0x10, 9, 1), - PIN_FIELD_BASE(43, 43, 3, 0x140, 0x10, 8, 1), - PIN_FIELD_BASE(44, 44, 3, 0x140, 0x10, 7, 1), - PIN_FIELD_BASE(45, 45, 3, 0x140, 0x10, 6, 1), - PIN_FIELD_BASE(46, 46, 3, 0x140, 0x10, 5, 1), - PIN_FIELD_BASE(47, 47, 3, 0x140, 0x10, 4, 1), - PIN_FIELD_BASE(48, 48, 3, 0x140, 0x10, 3, 1), - PIN_FIELD_BASE(49, 49, 3, 0x140, 0x10, 2, 1), - PIN_FIELD_BASE(50, 50, 3, 0x140, 0x10, 15, 1), - PIN_FIELD_BASE(51, 51, 3, 0x140, 0x10, 12, 1), - PIN_FIELD_BASE(52, 52, 3, 0x140, 0x10, 13, 1), - PIN_FIELD_BASE(53, 53, 3, 0x140, 0x10, 14, 1), - PIN_FIELD_BASE(54, 54, 3, 0x140, 0x10, 16, 1), - - PIN_FIELD_BASE(55, 55, 1, 0xe0, 0x10, 14, 1), - PIN_FIELD_BASE(56, 56, 1, 0xe0, 0x10, 15, 1), - PIN_FIELD_BASE(57, 57, 1, 0xe0, 0x10, 13, 1), - PIN_FIELD_BASE(58, 58, 1, 0xe0, 0x10, 4, 1), - PIN_FIELD_BASE(59, 59, 1, 0xe0, 0x10, 5, 1), - PIN_FIELD_BASE(60, 60, 1, 0xe0, 0x10, 6, 1), - PIN_FIELD_BASE(61, 61, 1, 0xe0, 0x10, 3, 1), - PIN_FIELD_BASE(62, 62, 1, 0xe0, 0x10, 7, 1), - PIN_FIELD_BASE(63, 63, 1, 0xe0, 0x10, 20, 1), - PIN_FIELD_BASE(64, 64, 1, 0xe0, 0x10, 8, 1), - PIN_FIELD_BASE(65, 65, 1, 0xe0, 0x10, 9, 1), - PIN_FIELD_BASE(66, 66, 1, 0xe0, 0x10, 10, 1), - PIN_FIELD_BASE(67, 67, 1, 0xe0, 0x10, 11, 1), - PIN_FIELD_BASE(68, 68, 1, 0xe0, 0x10, 12, 1), - - PIN_FIELD_BASE(69, 69, 5, 0xc0, 0x10, 1, 1), - PIN_FIELD_BASE(70, 70, 5, 0xc0, 0x10, 2, 1), - PIN_FIELD_BASE(71, 71, 5, 0xc0, 0x10, 5, 1), - PIN_FIELD_BASE(72, 72, 5, 0xc0, 0x10, 6, 1), - - PIN_FIELD_BASE(73, 73, 4, 0xb0, 0x10, 10, 1), - PIN_FIELD_BASE(74, 74, 4, 0xb0, 0x10, 1, 1), - PIN_FIELD_BASE(75, 75, 4, 0xb0, 0x10, 11, 1), - PIN_FIELD_BASE(76, 76, 4, 0xb0, 0x10, 9, 1), - PIN_FIELD_BASE(77, 77, 4, 0xb0, 0x10, 2, 1), - PIN_FIELD_BASE(78, 78, 4, 0xb0, 0x10, 0, 1), - PIN_FIELD_BASE(79, 79, 4, 0xb0, 0x10, 12, 1), - - PIN_FIELD_BASE(80, 80, 1, 0xe0, 0x10, 18, 1), - PIN_FIELD_BASE(81, 81, 1, 0xe0, 0x10, 19, 1), - PIN_FIELD_BASE(82, 82, 1, 0xe0, 0x10, 16, 1), - PIN_FIELD_BASE(83, 83, 1, 0xe0, 0x10, 17, 1), -}; - -static const struct mtk_pin_field_calc mt7988_pin_pu_range[] = { - PIN_FIELD_BASE(7, 7, 4, 0x60, 0x10, 5, 1), - PIN_FIELD_BASE(8, 8, 4, 0x60, 0x10, 4, 1), - PIN_FIELD_BASE(9, 9, 4, 0x60, 0x10, 3, 1), - PIN_FIELD_BASE(10, 10, 4, 0x60, 0x10, 2, 1), - - PIN_FIELD_BASE(13, 13, 1, 0x70, 0x10, 0, 1), - PIN_FIELD_BASE(14, 14, 1, 0x70, 0x10, 1, 1), - PIN_FIELD_BASE(63, 63, 1, 0x70, 0x10, 2, 1), - - PIN_FIELD_BASE(75, 75, 4, 0x60, 0x10, 7, 1), - PIN_FIELD_BASE(76, 76, 4, 0x60, 0x10, 6, 1), - PIN_FIELD_BASE(77, 77, 4, 0x60, 0x10, 1, 1), - PIN_FIELD_BASE(78, 78, 4, 0x60, 0x10, 0, 1), - PIN_FIELD_BASE(79, 79, 4, 0x60, 0x10, 8, 1), -}; - -static const struct mtk_pin_field_calc mt7988_pin_pd_range[] = { - PIN_FIELD_BASE(7, 7, 4, 0x40, 0x10, 5, 1), - PIN_FIELD_BASE(8, 8, 4, 0x40, 0x10, 4, 1), - PIN_FIELD_BASE(9, 9, 4, 0x40, 0x10, 3, 1), - PIN_FIELD_BASE(10, 10, 4, 0x40, 0x10, 2, 1), - - PIN_FIELD_BASE(13, 13, 1, 0x50, 0x10, 0, 1), - PIN_FIELD_BASE(14, 14, 1, 0x50, 0x10, 1, 1), - - PIN_FIELD_BASE(15, 15, 5, 0x40, 0x10, 4, 1), - PIN_FIELD_BASE(16, 16, 5, 0x40, 0x10, 5, 1), - PIN_FIELD_BASE(17, 17, 5, 0x40, 0x10, 0, 1), - PIN_FIELD_BASE(18, 18, 5, 0x40, 0x10, 1, 1), - - PIN_FIELD_BASE(63, 63, 1, 0x50, 0x10, 2, 1), - PIN_FIELD_BASE(71, 71, 5, 0x40, 0x10, 2, 1), - PIN_FIELD_BASE(72, 72, 5, 0x40, 0x10, 3, 1), - - PIN_FIELD_BASE(75, 75, 4, 0x40, 0x10, 7, 1), - PIN_FIELD_BASE(76, 76, 4, 0x40, 0x10, 6, 1), - PIN_FIELD_BASE(77, 77, 4, 0x40, 0x10, 1, 1), - PIN_FIELD_BASE(78, 78, 4, 0x40, 0x10, 0, 1), - PIN_FIELD_BASE(79, 79, 4, 0x40, 0x10, 8, 1), -}; - -static const struct mtk_pin_field_calc mt7988_pin_drv_range[] = { - PIN_FIELD_BASE(0, 0, 5, 0x00, 0x10, 21, 3), - PIN_FIELD_BASE(1, 1, 5, 0x00, 0x10, 24, 3), - PIN_FIELD_BASE(2, 2, 5, 0x00, 0x10, 15, 3), - PIN_FIELD_BASE(3, 3, 5, 0x00, 0x10, 18, 3), - PIN_FIELD_BASE(4, 4, 5, 0x00, 0x10, 0, 3), - PIN_FIELD_BASE(5, 5, 5, 0x00, 0x10, 9, 3), - PIN_FIELD_BASE(6, 6, 5, 0x00, 0x10, 12, 3), - - PIN_FIELD_BASE(7, 7, 4, 0x00, 0x10, 24, 3), - PIN_FIELD_BASE(8, 8, 4, 0x00, 0x10, 28, 3), - PIN_FIELD_BASE(9, 9, 4, 0x00, 0x10, 15, 3), - PIN_FIELD_BASE(10, 10, 4, 0x00, 0x10, 9, 3), - - PIN_FIELD_BASE(11, 11, 1, 0x00, 0x10, 0, 3), - PIN_FIELD_BASE(12, 12, 1, 0x20, 0x10, 3, 3), - PIN_FIELD_BASE(13, 13, 1, 0x00, 0x10, 3, 3), - PIN_FIELD_BASE(14, 14, 1, 0x00, 0x10, 6, 3), - - PIN_FIELD_BASE(19, 19, 4, 0x00, 0x10, 21, 3), - PIN_FIELD_BASE(20, 20, 4, 0x00, 0x10, 12, 3), - - PIN_FIELD_BASE(21, 21, 3, 0x10, 0x10, 21, 3), - PIN_FIELD_BASE(22, 22, 3, 0x20, 0x10, 9, 3), - PIN_FIELD_BASE(23, 23, 3, 0x20, 0x10, 0, 3), - PIN_FIELD_BASE(24, 24, 3, 0x10, 0x10, 27, 3), - PIN_FIELD_BASE(25, 25, 3, 0x20, 0x10, 3, 3), - PIN_FIELD_BASE(26, 26, 3, 0x20, 0x10, 6, 3), - PIN_FIELD_BASE(27, 27, 3, 0x10, 0x10, 24, 3), - PIN_FIELD_BASE(28, 28, 3, 0x20, 0x10, 15, 3), - PIN_FIELD_BASE(29, 29, 3, 0x20, 0x10, 18, 3), - PIN_FIELD_BASE(30, 30, 3, 0x20, 0x10, 21, 3), - PIN_FIELD_BASE(31, 31, 3, 0x20, 0x10, 12, 3), - PIN_FIELD_BASE(32, 32, 3, 0x20, 0x10, 24, 3), - PIN_FIELD_BASE(33, 33, 3, 0x30, 0x10, 6, 3), - PIN_FIELD_BASE(34, 34, 3, 0x30, 0x10, 3, 3), - PIN_FIELD_BASE(35, 35, 3, 0x20, 0x10, 27, 3), - PIN_FIELD_BASE(36, 36, 3, 0x30, 0x10, 0, 3), - PIN_FIELD_BASE(37, 37, 3, 0x30, 0x10, 9, 3), - PIN_FIELD_BASE(38, 38, 3, 0x10, 0x10, 3, 3), - PIN_FIELD_BASE(39, 39, 3, 0x10, 0x10, 0, 3), - PIN_FIELD_BASE(40, 40, 3, 0x00, 0x10, 0, 3), - PIN_FIELD_BASE(41, 41, 3, 0x00, 0x10, 3, 3), - PIN_FIELD_BASE(42, 42, 3, 0x00, 0x10, 27, 3), - PIN_FIELD_BASE(43, 43, 3, 0x00, 0x10, 24, 3), - PIN_FIELD_BASE(44, 44, 3, 0x00, 0x10, 21, 3), - PIN_FIELD_BASE(45, 45, 3, 0x00, 0x10, 18, 3), - PIN_FIELD_BASE(46, 46, 3, 0x00, 0x10, 15, 3), - PIN_FIELD_BASE(47, 47, 3, 0x00, 0x10, 12, 3), - PIN_FIELD_BASE(48, 48, 3, 0x00, 0x10, 9, 3), - PIN_FIELD_BASE(49, 49, 3, 0x00, 0x10, 6, 3), - PIN_FIELD_BASE(50, 50, 3, 0x10, 0x10, 15, 3), - PIN_FIELD_BASE(51, 51, 3, 0x10, 0x10, 6, 3), - PIN_FIELD_BASE(52, 52, 3, 0x10, 0x10, 9, 3), - PIN_FIELD_BASE(53, 53, 3, 0x10, 0x10, 12, 3), - PIN_FIELD_BASE(54, 54, 3, 0x10, 0x10, 18, 3), - - PIN_FIELD_BASE(55, 55, 1, 0x10, 0x10, 12, 3), - PIN_FIELD_BASE(56, 56, 1, 0x10, 0x10, 15, 3), - PIN_FIELD_BASE(57, 57, 1, 0x10, 0x10, 9, 3), - PIN_FIELD_BASE(58, 58, 1, 0x00, 0x10, 12, 3), - PIN_FIELD_BASE(59, 59, 1, 0x00, 0x10, 15, 3), - PIN_FIELD_BASE(60, 60, 1, 0x00, 0x10, 18, 3), - PIN_FIELD_BASE(61, 61, 1, 0x00, 0x10, 9, 3), - PIN_FIELD_BASE(62, 62, 1, 0x00, 0x10, 21, 3), - PIN_FIELD_BASE(63, 63, 1, 0x20, 0x10, 0, 3), - PIN_FIELD_BASE(64, 64, 1, 0x00, 0x10, 24, 3), - PIN_FIELD_BASE(65, 65, 1, 0x00, 0x10, 27, 3), - PIN_FIELD_BASE(66, 66, 1, 0x10, 0x10, 0, 3), - PIN_FIELD_BASE(67, 67, 1, 0x10, 0x10, 3, 3), - PIN_FIELD_BASE(68, 68, 1, 0x10, 0x10, 6, 3), - - PIN_FIELD_BASE(69, 69, 5, 0x00, 0x10, 3, 3), - PIN_FIELD_BASE(70, 70, 5, 0x00, 0x10, 6, 3), - - PIN_FIELD_BASE(73, 73, 4, 0x10, 0x10, 0, 3), - PIN_FIELD_BASE(74, 74, 4, 0x00, 0x10, 3, 3), - PIN_FIELD_BASE(75, 75, 4, 0x10, 0x10, 3, 3), - PIN_FIELD_BASE(76, 76, 4, 0x00, 0x10, 27, 3), - PIN_FIELD_BASE(77, 77, 4, 0x00, 0x10, 6, 3), - PIN_FIELD_BASE(78, 78, 4, 0x00, 0x10, 0, 3), - PIN_FIELD_BASE(79, 79, 4, 0x10, 0x10, 6, 3), - - PIN_FIELD_BASE(80, 80, 1, 0x10, 0x10, 24, 3), - PIN_FIELD_BASE(81, 81, 1, 0x10, 0x10, 27, 3), - PIN_FIELD_BASE(82, 82, 1, 0x10, 0x10, 18, 3), - PIN_FIELD_BASE(83, 83, 1, 0x10, 0x10, 21, 3), -}; - -static const struct mtk_pin_field_calc mt7988_pin_pupd_range[] = { - PIN_FIELD_BASE(0, 0, 5, 0x50, 0x10, 7, 1), - PIN_FIELD_BASE(1, 1, 5, 0x50, 0x10, 8, 1), - PIN_FIELD_BASE(2, 2, 5, 0x50, 0x10, 5, 1), - PIN_FIELD_BASE(3, 3, 5, 0x50, 0x10, 6, 1), - PIN_FIELD_BASE(4, 4, 5, 0x50, 0x10, 0, 1), - PIN_FIELD_BASE(5, 5, 5, 0x50, 0x10, 3, 1), - PIN_FIELD_BASE(6, 6, 5, 0x50, 0x10, 4, 1), - - PIN_FIELD_BASE(11, 11, 1, 0x60, 0x10, 0, 1), - PIN_FIELD_BASE(12, 12, 1, 0x60, 0x10, 18, 1), - - PIN_FIELD_BASE(19, 19, 4, 0x50, 0x10, 2, 1), - PIN_FIELD_BASE(20, 20, 4, 0x50, 0x10, 1, 1), - - PIN_FIELD_BASE(21, 21, 3, 0x70, 0x10, 17, 1), - PIN_FIELD_BASE(22, 22, 3, 0x70, 0x10, 23, 1), - PIN_FIELD_BASE(23, 23, 3, 0x70, 0x10, 20, 1), - PIN_FIELD_BASE(24, 24, 3, 0x70, 0x10, 19, 1), - PIN_FIELD_BASE(25, 25, 3, 0x70, 0x10, 21, 1), - PIN_FIELD_BASE(26, 26, 3, 0x70, 0x10, 22, 1), - PIN_FIELD_BASE(27, 27, 3, 0x70, 0x10, 18, 1), - PIN_FIELD_BASE(28, 28, 3, 0x70, 0x10, 25, 1), - PIN_FIELD_BASE(29, 29, 3, 0x70, 0x10, 26, 1), - PIN_FIELD_BASE(30, 30, 3, 0x70, 0x10, 27, 1), - PIN_FIELD_BASE(31, 31, 3, 0x70, 0x10, 24, 1), - PIN_FIELD_BASE(32, 32, 3, 0x70, 0x10, 28, 1), - PIN_FIELD_BASE(33, 33, 3, 0x80, 0x10, 0, 1), - PIN_FIELD_BASE(34, 34, 3, 0x70, 0x10, 31, 1), - PIN_FIELD_BASE(35, 35, 3, 0x70, 0x10, 29, 1), - PIN_FIELD_BASE(36, 36, 3, 0x70, 0x10, 30, 1), - PIN_FIELD_BASE(37, 37, 3, 0x80, 0x10, 1, 1), - PIN_FIELD_BASE(38, 38, 3, 0x70, 0x10, 11, 1), - PIN_FIELD_BASE(39, 39, 3, 0x70, 0x10, 10, 1), - PIN_FIELD_BASE(40, 40, 3, 0x70, 0x10, 0, 1), - PIN_FIELD_BASE(41, 41, 3, 0x70, 0x10, 1, 1), - PIN_FIELD_BASE(42, 42, 3, 0x70, 0x10, 9, 1), - PIN_FIELD_BASE(43, 43, 3, 0x70, 0x10, 8, 1), - PIN_FIELD_BASE(44, 44, 3, 0x70, 0x10, 7, 1), - PIN_FIELD_BASE(45, 45, 3, 0x70, 0x10, 6, 1), - PIN_FIELD_BASE(46, 46, 3, 0x70, 0x10, 5, 1), - PIN_FIELD_BASE(47, 47, 3, 0x70, 0x10, 4, 1), - PIN_FIELD_BASE(48, 48, 3, 0x70, 0x10, 3, 1), - PIN_FIELD_BASE(49, 49, 3, 0x70, 0x10, 2, 1), - PIN_FIELD_BASE(50, 50, 3, 0x70, 0x10, 15, 1), - PIN_FIELD_BASE(51, 51, 3, 0x70, 0x10, 12, 1), - PIN_FIELD_BASE(52, 52, 3, 0x70, 0x10, 13, 1), - PIN_FIELD_BASE(53, 53, 3, 0x70, 0x10, 14, 1), - PIN_FIELD_BASE(54, 54, 3, 0x70, 0x10, 16, 1), - - PIN_FIELD_BASE(55, 55, 1, 0x60, 0x10, 12, 1), - PIN_FIELD_BASE(56, 56, 1, 0x60, 0x10, 13, 1), - PIN_FIELD_BASE(57, 57, 1, 0x60, 0x10, 11, 1), - PIN_FIELD_BASE(58, 58, 1, 0x60, 0x10, 2, 1), - PIN_FIELD_BASE(59, 59, 1, 0x60, 0x10, 3, 1), - PIN_FIELD_BASE(60, 60, 1, 0x60, 0x10, 4, 1), - PIN_FIELD_BASE(61, 61, 1, 0x60, 0x10, 1, 1), - PIN_FIELD_BASE(62, 62, 1, 0x60, 0x10, 5, 1), - PIN_FIELD_BASE(64, 64, 1, 0x60, 0x10, 6, 1), - PIN_FIELD_BASE(65, 65, 1, 0x60, 0x10, 7, 1), - PIN_FIELD_BASE(66, 66, 1, 0x60, 0x10, 8, 1), - PIN_FIELD_BASE(67, 67, 1, 0x60, 0x10, 9, 1), - PIN_FIELD_BASE(68, 68, 1, 0x60, 0x10, 10, 1), - - PIN_FIELD_BASE(69, 69, 5, 0x50, 0x10, 1, 1), - PIN_FIELD_BASE(70, 70, 5, 0x50, 0x10, 2, 1), - - PIN_FIELD_BASE(73, 73, 4, 0x50, 0x10, 3, 1), - PIN_FIELD_BASE(74, 74, 4, 0x50, 0x10, 0, 1), - - PIN_FIELD_BASE(80, 80, 1, 0x60, 0x10, 16, 1), - PIN_FIELD_BASE(81, 81, 1, 0x60, 0x10, 17, 1), - PIN_FIELD_BASE(82, 82, 1, 0x60, 0x10, 14, 1), - PIN_FIELD_BASE(83, 83, 1, 0x60, 0x10, 15, 1), -}; - -static const struct mtk_pin_field_calc mt7988_pin_r0_range[] = { - PIN_FIELD_BASE(0, 0, 5, 0x60, 0x10, 7, 1), - PIN_FIELD_BASE(1, 1, 5, 0x60, 0x10, 8, 1), - PIN_FIELD_BASE(2, 2, 5, 0x60, 0x10, 5, 1), - PIN_FIELD_BASE(3, 3, 5, 0x60, 0x10, 6, 1), - PIN_FIELD_BASE(4, 4, 5, 0x60, 0x10, 0, 1), - PIN_FIELD_BASE(5, 5, 5, 0x60, 0x10, 3, 1), - PIN_FIELD_BASE(6, 6, 5, 0x60, 0x10, 4, 1), - - PIN_FIELD_BASE(11, 11, 1, 0x80, 0x10, 0, 1), - PIN_FIELD_BASE(12, 12, 1, 0x80, 0x10, 18, 1), - - PIN_FIELD_BASE(19, 19, 4, 0x70, 0x10, 2, 1), - PIN_FIELD_BASE(20, 20, 4, 0x70, 0x10, 1, 1), - - PIN_FIELD_BASE(21, 21, 3, 0x90, 0x10, 17, 1), - PIN_FIELD_BASE(22, 22, 3, 0x90, 0x10, 23, 1), - PIN_FIELD_BASE(23, 23, 3, 0x90, 0x10, 20, 1), - PIN_FIELD_BASE(24, 24, 3, 0x90, 0x10, 19, 1), - PIN_FIELD_BASE(25, 25, 3, 0x90, 0x10, 21, 1), - PIN_FIELD_BASE(26, 26, 3, 0x90, 0x10, 22, 1), - PIN_FIELD_BASE(27, 27, 3, 0x90, 0x10, 18, 1), - PIN_FIELD_BASE(28, 28, 3, 0x90, 0x10, 25, 1), - PIN_FIELD_BASE(29, 29, 3, 0x90, 0x10, 26, 1), - PIN_FIELD_BASE(30, 30, 3, 0x90, 0x10, 27, 1), - PIN_FIELD_BASE(31, 31, 3, 0x90, 0x10, 24, 1), - PIN_FIELD_BASE(32, 32, 3, 0x90, 0x10, 28, 1), - PIN_FIELD_BASE(33, 33, 3, 0xa0, 0x10, 0, 1), - PIN_FIELD_BASE(34, 34, 3, 0x90, 0x10, 31, 1), - PIN_FIELD_BASE(35, 35, 3, 0x90, 0x10, 29, 1), - PIN_FIELD_BASE(36, 36, 3, 0x90, 0x10, 30, 1), - PIN_FIELD_BASE(37, 37, 3, 0xa0, 0x10, 1, 1), - PIN_FIELD_BASE(38, 38, 3, 0x90, 0x10, 11, 1), - PIN_FIELD_BASE(39, 39, 3, 0x90, 0x10, 10, 1), - PIN_FIELD_BASE(40, 40, 3, 0x90, 0x10, 0, 1), - PIN_FIELD_BASE(41, 41, 3, 0x90, 0x10, 1, 1), - PIN_FIELD_BASE(42, 42, 3, 0x90, 0x10, 9, 1), - PIN_FIELD_BASE(43, 43, 3, 0x90, 0x10, 8, 1), - PIN_FIELD_BASE(44, 44, 3, 0x90, 0x10, 7, 1), - PIN_FIELD_BASE(45, 45, 3, 0x90, 0x10, 6, 1), - PIN_FIELD_BASE(46, 46, 3, 0x90, 0x10, 5, 1), - PIN_FIELD_BASE(47, 47, 3, 0x90, 0x10, 4, 1), - PIN_FIELD_BASE(48, 48, 3, 0x90, 0x10, 3, 1), - PIN_FIELD_BASE(49, 49, 3, 0x90, 0x10, 2, 1), - PIN_FIELD_BASE(50, 50, 3, 0x90, 0x10, 15, 1), - PIN_FIELD_BASE(51, 51, 3, 0x90, 0x10, 12, 1), - PIN_FIELD_BASE(52, 52, 3, 0x90, 0x10, 13, 1), - PIN_FIELD_BASE(53, 53, 3, 0x90, 0x10, 14, 1), - PIN_FIELD_BASE(54, 54, 3, 0x90, 0x10, 16, 1), - - PIN_FIELD_BASE(55, 55, 1, 0x80, 0x10, 12, 1), - PIN_FIELD_BASE(56, 56, 1, 0x80, 0x10, 13, 1), - PIN_FIELD_BASE(57, 57, 1, 0x80, 0x10, 11, 1), - PIN_FIELD_BASE(58, 58, 1, 0x80, 0x10, 2, 1), - PIN_FIELD_BASE(59, 59, 1, 0x80, 0x10, 3, 1), - PIN_FIELD_BASE(60, 60, 1, 0x80, 0x10, 4, 1), - PIN_FIELD_BASE(61, 61, 1, 0x80, 0x10, 1, 1), - PIN_FIELD_BASE(62, 62, 1, 0x80, 0x10, 5, 1), - PIN_FIELD_BASE(64, 64, 1, 0x80, 0x10, 6, 1), - PIN_FIELD_BASE(65, 65, 1, 0x80, 0x10, 7, 1), - PIN_FIELD_BASE(66, 66, 1, 0x80, 0x10, 8, 1), - PIN_FIELD_BASE(67, 67, 1, 0x80, 0x10, 9, 1), - PIN_FIELD_BASE(68, 68, 1, 0x80, 0x10, 10, 1), - - PIN_FIELD_BASE(69, 69, 5, 0x60, 0x10, 1, 1), - PIN_FIELD_BASE(70, 70, 5, 0x60, 0x10, 2, 1), - - PIN_FIELD_BASE(73, 73, 4, 0x70, 0x10, 3, 1), - PIN_FIELD_BASE(74, 74, 4, 0x70, 0x10, 0, 1), - - PIN_FIELD_BASE(80, 80, 1, 0x80, 0x10, 16, 1), - PIN_FIELD_BASE(81, 81, 1, 0x80, 0x10, 17, 1), - PIN_FIELD_BASE(82, 82, 1, 0x80, 0x10, 14, 1), - PIN_FIELD_BASE(83, 83, 1, 0x80, 0x10, 15, 1), -}; - -static const struct mtk_pin_field_calc mt7988_pin_r1_range[] = { - PIN_FIELD_BASE(0, 0, 5, 0x70, 0x10, 7, 1), - PIN_FIELD_BASE(1, 1, 5, 0x70, 0x10, 8, 1), - PIN_FIELD_BASE(2, 2, 5, 0x70, 0x10, 5, 1), - PIN_FIELD_BASE(3, 3, 5, 0x70, 0x10, 6, 1), - PIN_FIELD_BASE(4, 4, 5, 0x70, 0x10, 0, 1), - PIN_FIELD_BASE(5, 5, 5, 0x70, 0x10, 3, 1), - PIN_FIELD_BASE(6, 6, 5, 0x70, 0x10, 4, 1), - - PIN_FIELD_BASE(11, 11, 1, 0x90, 0x10, 0, 1), - PIN_FIELD_BASE(12, 12, 1, 0x90, 0x10, 18, 1), - - PIN_FIELD_BASE(19, 19, 4, 0x80, 0x10, 2, 1), - PIN_FIELD_BASE(20, 20, 4, 0x80, 0x10, 1, 1), - - PIN_FIELD_BASE(21, 21, 3, 0xb0, 0x10, 17, 1), - PIN_FIELD_BASE(22, 22, 3, 0xb0, 0x10, 23, 1), - PIN_FIELD_BASE(23, 23, 3, 0xb0, 0x10, 20, 1), - PIN_FIELD_BASE(24, 24, 3, 0xb0, 0x10, 19, 1), - PIN_FIELD_BASE(25, 25, 3, 0xb0, 0x10, 21, 1), - PIN_FIELD_BASE(26, 26, 3, 0xb0, 0x10, 22, 1), - PIN_FIELD_BASE(27, 27, 3, 0xb0, 0x10, 18, 1), - PIN_FIELD_BASE(28, 28, 3, 0xb0, 0x10, 25, 1), - PIN_FIELD_BASE(29, 29, 3, 0xb0, 0x10, 26, 1), - PIN_FIELD_BASE(30, 30, 3, 0xb0, 0x10, 27, 1), - PIN_FIELD_BASE(31, 31, 3, 0xb0, 0x10, 24, 1), - PIN_FIELD_BASE(32, 32, 3, 0xb0, 0x10, 28, 1), - PIN_FIELD_BASE(33, 33, 3, 0xc0, 0x10, 0, 1), - PIN_FIELD_BASE(34, 34, 3, 0xb0, 0x10, 31, 1), - PIN_FIELD_BASE(35, 35, 3, 0xb0, 0x10, 29, 1), - PIN_FIELD_BASE(36, 36, 3, 0xb0, 0x10, 30, 1), - PIN_FIELD_BASE(37, 37, 3, 0xc0, 0x10, 1, 1), - PIN_FIELD_BASE(38, 38, 3, 0xb0, 0x10, 11, 1), - PIN_FIELD_BASE(39, 39, 3, 0xb0, 0x10, 10, 1), - PIN_FIELD_BASE(40, 40, 3, 0xb0, 0x10, 0, 1), - PIN_FIELD_BASE(41, 41, 3, 0xb0, 0x10, 1, 1), - PIN_FIELD_BASE(42, 42, 3, 0xb0, 0x10, 9, 1), - PIN_FIELD_BASE(43, 43, 3, 0xb0, 0x10, 8, 1), - PIN_FIELD_BASE(44, 44, 3, 0xb0, 0x10, 7, 1), - PIN_FIELD_BASE(45, 45, 3, 0xb0, 0x10, 6, 1), - PIN_FIELD_BASE(46, 46, 3, 0xb0, 0x10, 5, 1), - PIN_FIELD_BASE(47, 47, 3, 0xb0, 0x10, 4, 1), - PIN_FIELD_BASE(48, 48, 3, 0xb0, 0x10, 3, 1), - PIN_FIELD_BASE(49, 49, 3, 0xb0, 0x10, 2, 1), - PIN_FIELD_BASE(50, 50, 3, 0xb0, 0x10, 15, 1), - PIN_FIELD_BASE(51, 51, 3, 0xb0, 0x10, 12, 1), - PIN_FIELD_BASE(52, 52, 3, 0xb0, 0x10, 13, 1), - PIN_FIELD_BASE(53, 53, 3, 0xb0, 0x10, 14, 1), - PIN_FIELD_BASE(54, 54, 3, 0xb0, 0x10, 16, 1), - - PIN_FIELD_BASE(55, 55, 1, 0x90, 0x10, 12, 1), - PIN_FIELD_BASE(56, 56, 1, 0x90, 0x10, 13, 1), - PIN_FIELD_BASE(57, 57, 1, 0x90, 0x10, 11, 1), - PIN_FIELD_BASE(58, 58, 1, 0x90, 0x10, 2, 1), - PIN_FIELD_BASE(59, 59, 1, 0x90, 0x10, 3, 1), - PIN_FIELD_BASE(60, 60, 1, 0x90, 0x10, 4, 1), - PIN_FIELD_BASE(61, 61, 1, 0x90, 0x10, 1, 1), - PIN_FIELD_BASE(62, 62, 1, 0x90, 0x10, 5, 1), - PIN_FIELD_BASE(64, 64, 1, 0x90, 0x10, 6, 1), - PIN_FIELD_BASE(65, 65, 1, 0x90, 0x10, 7, 1), - PIN_FIELD_BASE(66, 66, 1, 0x90, 0x10, 8, 1), - PIN_FIELD_BASE(67, 67, 1, 0x90, 0x10, 9, 1), - PIN_FIELD_BASE(68, 68, 1, 0x90, 0x10, 10, 1), - - PIN_FIELD_BASE(69, 69, 5, 0x70, 0x10, 1, 1), - PIN_FIELD_BASE(70, 70, 5, 0x70, 0x10, 2, 1), - - PIN_FIELD_BASE(73, 73, 4, 0x80, 0x10, 3, 1), - PIN_FIELD_BASE(74, 74, 4, 0x80, 0x10, 0, 1), - - PIN_FIELD_BASE(80, 80, 1, 0x90, 0x10, 16, 1), - PIN_FIELD_BASE(81, 81, 1, 0x90, 0x10, 17, 1), - PIN_FIELD_BASE(82, 82, 1, 0x90, 0x10, 14, 1), - PIN_FIELD_BASE(83, 83, 1, 0x90, 0x10, 15, 1), -}; - -static const struct mtk_pin_reg_calc mt7988_reg_cals[] = { - [PINCTRL_PIN_REG_MODE] = MTK_RANGE(mt7988_pin_mode_range), - [PINCTRL_PIN_REG_DIR] = MTK_RANGE(mt7988_pin_dir_range), - [PINCTRL_PIN_REG_DI] = MTK_RANGE(mt7988_pin_di_range), - [PINCTRL_PIN_REG_DO] = MTK_RANGE(mt7988_pin_do_range), - [PINCTRL_PIN_REG_SMT] = MTK_RANGE(mt7988_pin_smt_range), - [PINCTRL_PIN_REG_IES] = MTK_RANGE(mt7988_pin_ies_range), - [PINCTRL_PIN_REG_PU] = MTK_RANGE(mt7988_pin_pu_range), - [PINCTRL_PIN_REG_PD] = MTK_RANGE(mt7988_pin_pd_range), - [PINCTRL_PIN_REG_DRV] = MTK_RANGE(mt7988_pin_drv_range), - [PINCTRL_PIN_REG_PUPD] = MTK_RANGE(mt7988_pin_pupd_range), - [PINCTRL_PIN_REG_R0] = MTK_RANGE(mt7988_pin_r0_range), - [PINCTRL_PIN_REG_R1] = MTK_RANGE(mt7988_pin_r1_range), -}; - -static const struct mtk_pin_desc mt7988_pins[] = { - MT7988_PIN(0, "UART2_RXD"), - MT7988_PIN(1, "UART2_TXD"), - MT7988_PIN(2, "UART2_CTS"), - MT7988_PIN(3, "UART2_RTS"), - MT7988_PIN(4, "GPIO_A"), - MT7988_PIN(5, "SMI_0_MDC"), - MT7988_PIN(6, "SMI_0_MDIO"), - MT7988_PIN(7, "PCIE30_2L_0_WAKE_N"), - MT7988_PIN(8, "PCIE30_2L_0_CLKREQ_N"), - MT7988_PIN(9, "PCIE30_1L_1_WAKE_N"), - MT7988_PIN(10, "PCIE30_1L_1_CLKREQ_N"), - MT7988_PIN(11, "GPIO_P"), - MT7988_PIN(12, "WATCHDOG"), - MT7988_PIN(13, "GPIO_RESET"), - MT7988_PIN(14, "GPIO_WPS"), - MT7988_PIN(15, "PMIC_I2C_SCL"), - MT7988_PIN(16, "PMIC_I2C_SDA"), - MT7988_PIN(17, "I2C_1_SCL"), - MT7988_PIN(18, "I2C_1_SDA"), - MT7988_PIN(19, "PCIE30_2L_0_PRESET_N"), - MT7988_PIN(20, "PCIE30_1L_1_PRESET_N"), - MT7988_PIN(21, "PWMD1"), - MT7988_PIN(22, "SPI0_WP"), - MT7988_PIN(23, "SPI0_HOLD"), - MT7988_PIN(24, "SPI0_CSB"), - MT7988_PIN(25, "SPI0_MISO"), - MT7988_PIN(26, "SPI0_MOSI"), - MT7988_PIN(27, "SPI0_CLK"), - MT7988_PIN(28, "SPI1_CSB"), - MT7988_PIN(29, "SPI1_MISO"), - MT7988_PIN(30, "SPI1_MOSI"), - MT7988_PIN(31, "SPI1_CLK"), - MT7988_PIN(32, "SPI2_CLK"), - MT7988_PIN(33, "SPI2_MOSI"), - MT7988_PIN(34, "SPI2_MISO"), - MT7988_PIN(35, "SPI2_CSB"), - MT7988_PIN(36, "SPI2_HOLD"), - MT7988_PIN(37, "SPI2_WP"), - MT7988_PIN(38, "EMMC_RSTB"), - MT7988_PIN(39, "EMMC_DSL"), - MT7988_PIN(40, "EMMC_CK"), - MT7988_PIN(41, "EMMC_CMD"), - MT7988_PIN(42, "EMMC_DATA_7"), - MT7988_PIN(43, "EMMC_DATA_6"), - MT7988_PIN(44, "EMMC_DATA_5"), - MT7988_PIN(45, "EMMC_DATA_4"), - MT7988_PIN(46, "EMMC_DATA_3"), - MT7988_PIN(47, "EMMC_DATA_2"), - MT7988_PIN(48, "EMMC_DATA_1"), - MT7988_PIN(49, "EMMC_DATA_0"), - MT7988_PIN(50, "PCM_FS_I2S_LRCK"), - MT7988_PIN(51, "PCM_CLK_I2S_BCLK"), - MT7988_PIN(52, "PCM_DRX_I2S_DIN"), - MT7988_PIN(53, "PCM_DTX_I2S_DOUT"), - MT7988_PIN(54, "PCM_MCK_I2S_MCLK"), - MT7988_PIN(55, "UART0_RXD"), - MT7988_PIN(56, "UART0_TXD"), - MT7988_PIN(57, "PWMD0"), - MT7988_PIN(58, "JTAG_JTDI"), - MT7988_PIN(59, "JTAG_JTDO"), - MT7988_PIN(60, "JTAG_JTMS"), - MT7988_PIN(61, "JTAG_JTCLK"), - MT7988_PIN(62, "JTAG_JTRST_N"), - MT7988_PIN(63, "USB_DRV_VBUS_P1"), - MT7988_PIN(64, "LED_A"), - MT7988_PIN(65, "LED_B"), - MT7988_PIN(66, "LED_C"), - MT7988_PIN(67, "LED_D"), - MT7988_PIN(68, "LED_E"), - MT7988_PIN(69, "GPIO_B"), - MT7988_PIN(70, "GPIO_C"), - MT7988_PIN(71, "I2C_2_SCL"), - MT7988_PIN(72, "I2C_2_SDA"), - MT7988_PIN(73, "PCIE30_2L_1_PRESET_N"), - MT7988_PIN(74, "PCIE30_1L_0_PRESET_N"), - MT7988_PIN(75, "PCIE30_2L_1_WAKE_N"), - MT7988_PIN(76, "PCIE30_2L_1_CLKREQ_N"), - MT7988_PIN(77, "PCIE30_1L_0_WAKE_N"), - MT7988_PIN(78, "PCIE30_1L_0_CLKREQ_N"), - MT7988_PIN(79, "USB_DRV_VBUS_P0"), - MT7988_PIN(80, "UART1_RXD"), - MT7988_PIN(81, "UART1_TXD"), - MT7988_PIN(82, "UART1_CTS"), - MT7988_PIN(83, "UART1_RTS"), -}; - -/* jtag */ -static int mt7988_tops_jtag0_0_pins[] = { 0, 1, 2, 3, 4 }; -static int mt7988_tops_jtag0_0_funcs[] = { 2, 2, 2, 2, 2 }; - -static int mt7988_wo0_jtag_pins[] = { 50, 51, 52, 53, 54 }; -static int mt7988_wo0_jtag_funcs[] = { 3, 3, 3, 3, 3 }; - -static int mt7988_wo1_jtag_pins[] = { 50, 51, 52, 53, 54 }; -static int mt7988_wo1_jtag_funcs[] = { 4, 4, 4, 4, 4 }; - -static int mt7988_wo2_jtag_pins[] = { 50, 51, 52, 53, 54 }; -static int mt7988_wo2_jtag_funcs[] = { 5, 5, 5, 5, 5 }; - -static int mt7988_jtag_pins[] = { 58, 59, 60, 61, 62 }; -static int mt7988_jtag_funcs[] = { 1, 1, 1, 1, 1 }; - -static int mt7988_tops_jtag0_1_pins[] = { 58, 59, 60, 61, 62 }; -static int mt7988_tops_jtag0_1_funcs[] = { 4, 4, 4, 4, 4 }; - -/* int_usxgmii */ -static int mt7988_int_usxgmii_pins[] = { 2, 3 }; -static int mt7988_int_usxgmii_funcs[] = { 3, 3 }; - -/* pwm */ -static int mt7988_pwm0_pins[] = { 57 }; -static int mt7988_pwm0_funcs[] = { 1 }; - -static int mt7988_pwm1_pins[] = { 21 }; -static int mt7988_pwm1_funcs[] = { 1 }; - -static int mt7988_pwm2_pins[] = { 80 }; -static int mt7988_pwm2_funcs[] = { 2 }; - -static int mt7988_pwm3_pins[] = { 81 }; -static int mt7988_pwm3_funcs[] = { 2 }; - -static int mt7988_pwm4_pins[] = { 82 }; -static int mt7988_pwm4_funcs[] = { 2 }; - -static int mt7988_pwm5_pins[] = { 83 }; -static int mt7988_pwm5_funcs[] = { 2 }; - -static int mt7988_pwm6_pins[] = { 69 }; -static int mt7988_pwm6_funcs[] = { 3 }; - -static int mt7988_pwm7_pins[] = { 70 }; -static int mt7988_pwm7_funcs[] = { 3 }; - -/* dfd */ -static int mt7988_dfd_pins[] = { 0, 1, 2, 3, 4 }; -static int mt7988_dfd_funcs[] = { 4, 4, 4, 4, 4 }; - -/* i2c */ -static int mt7988_xfi_phy0_i2c0_pins[] = { 0, 1 }; -static int mt7988_xfi_phy0_i2c0_funcs[] = { 5, 5 }; - -static int mt7988_xfi_phy1_i2c0_pins[] = { 0, 1 }; -static int mt7988_xfi_phy1_i2c0_funcs[] = { 6, 6 }; - -static int mt7988_xfi_phy_pll_i2c0_pins[] = { 3, 4 }; -static int mt7988_xfi_phy_pll_i2c0_funcs[] = { 5, 5 }; - -static int mt7988_xfi_phy_pll_i2c1_pins[] = { 3, 4 }; -static int mt7988_xfi_phy_pll_i2c1_funcs[] = { 6, 6 }; - -static int mt7988_i2c0_0_pins[] = { 5, 6 }; -static int mt7988_i2c0_0_funcs[] = { 2, 2 }; - -static int mt7988_i2c1_sfp_pins[] = { 5, 6 }; -static int mt7988_i2c1_sfp_funcs[] = { 4, 4 }; - -static int mt7988_xfi_pextp_phy0_i2c_pins[] = { 5, 6 }; -static int mt7988_xfi_pextp_phy0_i2c_funcs[] = { 5, 5 }; - -static int mt7988_xfi_pextp_phy1_i2c_pins[] = { 5, 6 }; -static int mt7988_xfi_pextp_phy1_i2c_funcs[] = { 6, 6 }; - -static int mt7988_i2c0_1_pins[] = { 15, 16 }; -static int mt7988_i2c0_1_funcs[] = { 1, 1 }; - -static int mt7988_u30_phy_i2c0_pins[] = { 15, 16 }; -static int mt7988_u30_phy_i2c0_funcs[] = { 2, 2 }; - -static int mt7988_u32_phy_i2c0_pins[] = { 15, 16 }; -static int mt7988_u32_phy_i2c0_funcs[] = { 3, 3 }; - -static int mt7988_xfi_phy0_i2c1_pins[] = { 15, 16 }; -static int mt7988_xfi_phy0_i2c1_funcs[] = { 5, 5 }; - -static int mt7988_xfi_phy1_i2c1_pins[] = { 15, 16 }; -static int mt7988_xfi_phy1_i2c1_funcs[] = { 6, 6 }; - -static int mt7988_xfi_phy_pll_i2c2_pins[] = { 15, 16 }; -static int mt7988_xfi_phy_pll_i2c2_funcs[] = { 7, 7 }; - -static int mt7988_i2c1_0_pins[] = { 17, 18 }; -static int mt7988_i2c1_0_funcs[] = { 1, 1 }; - -static int mt7988_u30_phy_i2c1_pins[] = { 17, 18 }; -static int mt7988_u30_phy_i2c1_funcs[] = { 2, 2 }; - -static int mt7988_u32_phy_i2c1_pins[] = { 17, 18 }; -static int mt7988_u32_phy_i2c1_funcs[] = { 3, 3 }; - -static int mt7988_xfi_phy_pll_i2c3_pins[] = { 17, 18 }; -static int mt7988_xfi_phy_pll_i2c3_funcs[] = { 4, 4 }; - -static int mt7988_sgmii0_i2c_pins[] = { 17, 18 }; -static int mt7988_sgmii0_i2c_funcs[] = { 5, 5 }; - -static int mt7988_sgmii1_i2c_pins[] = { 17, 18 }; -static int mt7988_sgmii1_i2c_funcs[] = { 6, 6 }; - -static int mt7988_i2c1_2_pins[] = { 69, 70 }; -static int mt7988_i2c1_2_funcs[] = { 2, 2 }; - -static int mt7988_i2c2_0_pins[] = { 69, 70 }; -static int mt7988_i2c2_0_funcs[] = { 4, 4 }; - -static int mt7988_i2c2_1_pins[] = { 71, 72 }; -static int mt7988_i2c2_1_funcs[] = { 1, 1 }; - -/* eth */ -static int mt7988_mdc_mdio0_pins[] = { 5, 6 }; -static int mt7988_mdc_mdio0_funcs[] = { 1, 1 }; - -static int mt7988_2p5g_ext_mdio_pins[] = { 28, 29 }; -static int mt7988_2p5g_ext_mdio_funcs[] = { 6, 6 }; - -static int mt7988_gbe_ext_mdio_pins[] = { 30, 31 }; -static int mt7988_gbe_ext_mdio_funcs[] = { 6, 6 }; - -static int mt7988_mdc_mdio1_pins[] = { 69, 70 }; -static int mt7988_mdc_mdio1_funcs[] = { 1, 1 }; - -/* pcie */ -static int mt7988_pcie_wake_n0_0_pins[] = { 7 }; -static int mt7988_pcie_wake_n0_0_funcs[] = { 1 }; - -static int mt7988_pcie_clk_req_n0_0_pins[] = { 8 }; -static int mt7988_pcie_clk_req_n0_0_funcs[] = { 1 }; - -static int mt7988_pcie_wake_n3_0_pins[] = { 9 }; -static int mt7988_pcie_wake_n3_0_funcs[] = { 1 }; - -static int mt7988_pcie_clk_req_n3_pins[] = { 10 }; -static int mt7988_pcie_clk_req_n3_funcs[] = { 1 }; - -static int mt7988_pcie_clk_req_n0_1_pins[] = { 10 }; -static int mt7988_pcie_clk_req_n0_1_funcs[] = { 2 }; - -static int mt7988_pcie_p0_phy_i2c_pins[] = { 7, 8 }; -static int mt7988_pcie_p0_phy_i2c_funcs[] = { 3, 3 }; - -static int mt7988_pcie_p1_phy_i2c_pins[] = { 7, 8 }; -static int mt7988_pcie_p1_phy_i2c_funcs[] = { 4, 4 }; - -static int mt7988_pcie_p3_phy_i2c_pins[] = { 9, 10 }; -static int mt7988_pcie_p3_phy_i2c_funcs[] = { 4, 4 }; - -static int mt7988_pcie_p2_phy_i2c_pins[] = { 7, 8 }; -static int mt7988_pcie_p2_phy_i2c_funcs[] = { 5, 5 }; - -static int mt7988_ckm_phy_i2c_pins[] = { 9, 10 }; -static int mt7988_ckm_phy_i2c_funcs[] = { 5, 5 }; - -static int mt7988_pcie_wake_n0_1_pins[] = { 13 }; -static int mt7988_pcie_wake_n0_1_funcs[] = { 2 }; - -static int mt7988_pcie_wake_n3_1_pins[] = { 14 }; -static int mt7988_pcie_wake_n3_1_funcs[] = { 2 }; - -static int mt7988_pcie_2l_0_pereset_pins[] = { 19 }; -static int mt7988_pcie_2l_0_pereset_funcs[] = { 1 }; - -static int mt7988_pcie_1l_1_pereset_pins[] = { 20 }; -static int mt7988_pcie_1l_1_pereset_funcs[] = { 1 }; - -static int mt7988_pcie_clk_req_n2_1_pins[] = { 63 }; -static int mt7988_pcie_clk_req_n2_1_funcs[] = { 2 }; - -static int mt7988_pcie_2l_1_pereset_pins[] = { 73 }; -static int mt7988_pcie_2l_1_pereset_funcs[] = { 1 }; - -static int mt7988_pcie_1l_0_pereset_pins[] = { 74 }; -static int mt7988_pcie_1l_0_pereset_funcs[] = { 1 }; - -static int mt7988_pcie_wake_n1_0_pins[] = { 75 }; -static int mt7988_pcie_wake_n1_0_funcs[] = { 1 }; - -static int mt7988_pcie_clk_req_n1_pins[] = { 76 }; -static int mt7988_pcie_clk_req_n1_funcs[] = { 1 }; - -static int mt7988_pcie_wake_n2_0_pins[] = { 77 }; -static int mt7988_pcie_wake_n2_0_funcs[] = { 1 }; - -static int mt7988_pcie_clk_req_n2_0_pins[] = { 78 }; -static int mt7988_pcie_clk_req_n2_0_funcs[] = { 1 }; - -static int mt7988_pcie_wake_n2_1_pins[] = { 79 }; -static int mt7988_pcie_wake_n2_1_funcs[] = { 2 }; - -/* pmic */ -static int mt7988_pmic_pins[] = { 11 }; -static int mt7988_pmic_funcs[] = { 1 }; - -/* watchdog */ -static int mt7988_watchdog_pins[] = { 12 }; -static int mt7988_watchdog_funcs[] = { 1 }; - -/* spi */ -static int mt7988_spi0_wp_hold_pins[] = { 22, 23 }; -static int mt7988_spi0_wp_hold_funcs[] = { 1, 1 }; - -static int mt7988_spi0_pins[] = { 24, 25, 26, 27 }; -static int mt7988_spi0_funcs[] = { 1, 1, 1, 1 }; - -static int mt7988_spi1_pins[] = { 28, 29, 30, 31 }; -static int mt7988_spi1_funcs[] = { 1, 1, 1, 1 }; - -static int mt7988_spi2_pins[] = { 32, 33, 34, 35 }; -static int mt7988_spi2_funcs[] = { 1, 1, 1, 1 }; - -static int mt7988_spi2_wp_hold_pins[] = { 36, 37 }; -static int mt7988_spi2_wp_hold_funcs[] = { 1, 1 }; - -/* flash */ -static int mt7988_snfi_pins[] = { 22, 23, 24, 25, 26, 27 }; -static int mt7988_snfi_funcs[] = { 2, 2, 2, 2, 2, 2 }; - -static int mt7988_emmc_45_pins[] = { - 21, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37 -}; -static int mt7988_emmc_45_funcs[] = { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 }; - -static int mt7988_sdcard_pins[] = { 32, 33, 34, 35, 36, 37 }; -static int mt7988_sdcard_funcs[] = { 5, 5, 5, 5, 5, 5 }; - -static int mt7988_emmc_51_pins[] = { 38, 39, 40, 41, 42, 43, - 44, 45, 46, 47, 48, 49 }; -static int mt7988_emmc_51_funcs[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; - -/* uart */ -static int mt7988_uart2_pins[] = { 0, 1, 2, 3 }; -static int mt7988_uart2_funcs[] = { 1, 1, 1, 1 }; - -static int mt7988_tops_uart0_0_pins[] = { 22, 23 }; -static int mt7988_tops_uart0_0_funcs[] = { 3, 3 }; - -static int mt7988_uart2_0_pins[] = { 28, 29, 30, 31 }; -static int mt7988_uart2_0_funcs[] = { 2, 2, 2, 2 }; - -static int mt7988_uart1_0_pins[] = { 32, 33, 34, 35 }; -static int mt7988_uart1_0_funcs[] = { 2, 2, 2, 2 }; - -static int mt7988_uart2_1_pins[] = { 32, 33, 34, 35 }; -static int mt7988_uart2_1_funcs[] = { 3, 3, 3, 3 }; - -static int mt7988_net_wo0_uart_txd_0_pins[] = { 28 }; -static int mt7988_net_wo0_uart_txd_0_funcs[] = { 3 }; - -static int mt7988_net_wo1_uart_txd_0_pins[] = { 29 }; -static int mt7988_net_wo1_uart_txd_0_funcs[] = { 3 }; - -static int mt7988_net_wo2_uart_txd_0_pins[] = { 30 }; -static int mt7988_net_wo2_uart_txd_0_funcs[] = { 3 }; - -static int mt7988_tops_uart1_0_pins[] = { 28, 29 }; -static int mt7988_tops_uart1_0_funcs[] = { 4, 4 }; - -static int mt7988_tops_uart0_1_pins[] = { 30, 31 }; -static int mt7988_tops_uart0_1_funcs[] = { 4, 4 }; - -static int mt7988_tops_uart1_1_pins[] = { 36, 37 }; -static int mt7988_tops_uart1_1_funcs[] = { 3, 3 }; - -static int mt7988_uart0_pins[] = { 55, 56 }; -static int mt7988_uart0_funcs[] = { 1, 1 }; - -static int mt7988_tops_uart0_2_pins[] = { 55, 56 }; -static int mt7988_tops_uart0_2_funcs[] = { 2, 2 }; - -static int mt7988_uart2_2_pins[] = { 50, 51, 52, 53 }; -static int mt7988_uart2_2_funcs[] = { 2, 2, 2, 2 }; - -static int mt7988_uart1_1_pins[] = { 58, 59, 60, 61 }; -static int mt7988_uart1_1_funcs[] = { 2, 2, 2, 2 }; - -static int mt7988_uart2_3_pins[] = { 58, 59, 60, 61 }; -static int mt7988_uart2_3_funcs[] = { 3, 3, 3, 3 }; - -static int mt7988_uart1_2_pins[] = { 80, 81, 82, 83 }; -static int mt7988_uart1_2_funcs[] = { 1, 1, 1, 1 }; - -static int mt7988_tops_uart1_2_pins[] = { 80, 81 }; -static int mt7988_tops_uart1_2_funcs[] = { - 4, - 4, -}; - -static int mt7988_net_wo0_uart_txd_1_pins[] = { 80 }; -static int mt7988_net_wo0_uart_txd_1_funcs[] = { 3 }; - -static int mt7988_net_wo1_uart_txd_1_pins[] = { 81 }; -static int mt7988_net_wo1_uart_txd_1_funcs[] = { 3 }; - -static int mt7988_net_wo2_uart_txd_1_pins[] = { 82 }; -static int mt7988_net_wo2_uart_txd_1_funcs[] = { 3 }; - -/* udi */ -static int mt7988_udi_pins[] = { 32, 33, 34, 35, 36 }; -static int mt7988_udi_funcs[] = { 4, 4, 4, 4, 4 }; - -/* i2s */ -static int mt7988_i2s_pins[] = { 50, 51, 52, 53, 54 }; -static int mt7988_i2s_funcs[] = { 1, 1, 1, 1, 1 }; - -/* pcm */ -static int mt7988_pcm_pins[] = { 50, 51, 52, 53 }; -static int mt7988_pcm_funcs[] = { 1, 1, 1, 1 }; - -/* led */ -static int mt7988_gbe0_led1_pins[] = { 58 }; -static int mt7988_gbe0_led1_funcs[] = { 6 }; -static int mt7988_gbe1_led1_pins[] = { 59 }; -static int mt7988_gbe1_led1_funcs[] = { 6 }; -static int mt7988_gbe2_led1_pins[] = { 60 }; -static int mt7988_gbe2_led1_funcs[] = { 6 }; -static int mt7988_gbe3_led1_pins[] = { 61 }; -static int mt7988_gbe3_led1_funcs[] = { 6 }; - -static int mt7988_2p5gbe_led1_pins[] = { 62 }; -static int mt7988_2p5gbe_led1_funcs[] = { 6 }; - -static int mt7988_gbe0_led0_pins[] = { 64 }; -static int mt7988_gbe0_led0_funcs[] = { 1 }; -static int mt7988_gbe1_led0_pins[] = { 65 }; -static int mt7988_gbe1_led0_funcs[] = { 1 }; -static int mt7988_gbe2_led0_pins[] = { 66 }; -static int mt7988_gbe2_led0_funcs[] = { 1 }; -static int mt7988_gbe3_led0_pins[] = { 67 }; -static int mt7988_gbe3_led0_funcs[] = { 1 }; - -static int mt7988_2p5gbe_led0_pins[] = { 68 }; -static int mt7988_2p5gbe_led0_funcs[] = { 1 }; - -/* usb */ -static int mt7988_drv_vbus_p1_pins[] = { 63 }; -static int mt7988_drv_vbus_p1_funcs[] = { 1 }; - -static int mt7988_drv_vbus_pins[] = { 79 }; -static int mt7988_drv_vbus_funcs[] = { 1 }; - -static const struct group_desc mt7988_groups[] = { - /* @GPIO(0,1,2,3): uart2 */ - PINCTRL_PIN_GROUP("uart2", mt7988_uart2), - /* @GPIO(0,1,2,3,4): tops_jtag0_0 */ - PINCTRL_PIN_GROUP("tops_jtag0_0", mt7988_tops_jtag0_0), - /* @GPIO(2,3): int_usxgmii */ - PINCTRL_PIN_GROUP("int_usxgmii", mt7988_int_usxgmii), - /* @GPIO(0,1,2,3,4): dfd */ - PINCTRL_PIN_GROUP("dfd", mt7988_dfd), - /* @GPIO(0,1): xfi_phy0_i2c0 */ - PINCTRL_PIN_GROUP("xfi_phy0_i2c0", mt7988_xfi_phy0_i2c0), - /* @GPIO(0,1): xfi_phy1_i2c0 */ - PINCTRL_PIN_GROUP("xfi_phy1_i2c0", mt7988_xfi_phy1_i2c0), - /* @GPIO(3,4): xfi_phy_pll_i2c0 */ - PINCTRL_PIN_GROUP("xfi_phy_pll_i2c0", mt7988_xfi_phy_pll_i2c0), - /* @GPIO(3,4): xfi_phy_pll_i2c1 */ - PINCTRL_PIN_GROUP("xfi_phy_pll_i2c1", mt7988_xfi_phy_pll_i2c1), - /* @GPIO(5,6) i2c0_0 */ - PINCTRL_PIN_GROUP("i2c0_0", mt7988_i2c0_0), - /* @GPIO(5,6) i2c1_sfp */ - PINCTRL_PIN_GROUP("i2c1_sfp", mt7988_i2c1_sfp), - /* @GPIO(5,6) xfi_pextp_phy0_i2c */ - PINCTRL_PIN_GROUP("xfi_pextp_phy0_i2c", mt7988_xfi_pextp_phy0_i2c), - /* @GPIO(5,6) xfi_pextp_phy1_i2c */ - PINCTRL_PIN_GROUP("xfi_pextp_phy1_i2c", mt7988_xfi_pextp_phy1_i2c), - /* @GPIO(5,6) mdc_mdio0 */ - PINCTRL_PIN_GROUP("mdc_mdio0", mt7988_mdc_mdio0), - /* @GPIO(7): pcie_wake_n0_0 */ - PINCTRL_PIN_GROUP("pcie_wake_n0_0", mt7988_pcie_wake_n0_0), - /* @GPIO(8): pcie_clk_req_n0_0 */ - PINCTRL_PIN_GROUP("pcie_clk_req_n0_0", mt7988_pcie_clk_req_n0_0), - /* @GPIO(9): pcie_wake_n3_0 */ - PINCTRL_PIN_GROUP("pcie_wake_n3_0", mt7988_pcie_wake_n3_0), - /* @GPIO(10): pcie_clk_req_n3 */ - PINCTRL_PIN_GROUP("pcie_clk_req_n3", mt7988_pcie_clk_req_n3), - /* @GPIO(10): pcie_clk_req_n0_1 */ - PINCTRL_PIN_GROUP("pcie_clk_req_n0_1", mt7988_pcie_clk_req_n0_1), - /* @GPIO(7,8) pcie_p0_phy_i2c */ - PINCTRL_PIN_GROUP("pcie_p0_phy_i2c", mt7988_pcie_p0_phy_i2c), - /* @GPIO(7,8) pcie_p1_phy_i2c */ - PINCTRL_PIN_GROUP("pcie_p1_phy_i2c", mt7988_pcie_p1_phy_i2c), - /* @GPIO(7,8) pcie_p2_phy_i2c */ - PINCTRL_PIN_GROUP("pcie_p2_phy_i2c", mt7988_pcie_p2_phy_i2c), - /* @GPIO(9,10) pcie_p3_phy_i2c */ - PINCTRL_PIN_GROUP("pcie_p3_phy_i2c", mt7988_pcie_p3_phy_i2c), - /* @GPIO(9,10) ckm_phy_i2c */ - PINCTRL_PIN_GROUP("ckm_phy_i2c", mt7988_ckm_phy_i2c), - /* @GPIO(11): pmic */ - PINCTRL_PIN_GROUP("pcie_pmic", mt7988_pmic), - /* @GPIO(12): watchdog */ - PINCTRL_PIN_GROUP("watchdog", mt7988_watchdog), - /* @GPIO(13): pcie_wake_n0_1 */ - PINCTRL_PIN_GROUP("pcie_wake_n0_1", mt7988_pcie_wake_n0_1), - /* @GPIO(14): pcie_wake_n3_1 */ - PINCTRL_PIN_GROUP("pcie_wake_n3_1", mt7988_pcie_wake_n3_1), - /* @GPIO(15,16) i2c0_1 */ - PINCTRL_PIN_GROUP("i2c0_1", mt7988_i2c0_1), - /* @GPIO(15,16) u30_phy_i2c0 */ - PINCTRL_PIN_GROUP("u30_phy_i2c0", mt7988_u30_phy_i2c0), - /* @GPIO(15,16) u32_phy_i2c0 */ - PINCTRL_PIN_GROUP("u32_phy_i2c0", mt7988_u32_phy_i2c0), - /* @GPIO(15,16) xfi_phy0_i2c1 */ - PINCTRL_PIN_GROUP("xfi_phy0_i2c1", mt7988_xfi_phy0_i2c1), - /* @GPIO(15,16) xfi_phy1_i2c1 */ - PINCTRL_PIN_GROUP("xfi_phy1_i2c1", mt7988_xfi_phy1_i2c1), - /* @GPIO(15,16) xfi_phy_pll_i2c2 */ - PINCTRL_PIN_GROUP("xfi_phy_pll_i2c2", mt7988_xfi_phy_pll_i2c2), - /* @GPIO(17,18) i2c1_0 */ - PINCTRL_PIN_GROUP("i2c1_0", mt7988_i2c1_0), - /* @GPIO(17,18) u30_phy_i2c1 */ - PINCTRL_PIN_GROUP("u30_phy_i2c1", mt7988_u30_phy_i2c1), - /* @GPIO(17,18) u32_phy_i2c1 */ - PINCTRL_PIN_GROUP("u32_phy_i2c1", mt7988_u32_phy_i2c1), - /* @GPIO(17,18) xfi_phy_pll_i2c3 */ - PINCTRL_PIN_GROUP("xfi_phy_pll_i2c3", mt7988_xfi_phy_pll_i2c3), - /* @GPIO(17,18) sgmii0_i2c */ - PINCTRL_PIN_GROUP("sgmii0_i2c", mt7988_sgmii0_i2c), - /* @GPIO(17,18) sgmii1_i2c */ - PINCTRL_PIN_GROUP("sgmii1_i2c", mt7988_sgmii1_i2c), - /* @GPIO(19): pcie_2l_0_pereset */ - PINCTRL_PIN_GROUP("pcie_2l_0_pereset", mt7988_pcie_2l_0_pereset), - /* @GPIO(20): pcie_1l_1_pereset */ - PINCTRL_PIN_GROUP("pcie_1l_1_pereset", mt7988_pcie_1l_1_pereset), - /* @GPIO(21): pwm1 */ - PINCTRL_PIN_GROUP("pwm1", mt7988_pwm1), - /* @GPIO(22,23) spi0_wp_hold */ - PINCTRL_PIN_GROUP("spi0_wp_hold", mt7988_spi0_wp_hold), - /* @GPIO(24,25,26,27) spi0 */ - PINCTRL_PIN_GROUP("spi0", mt7988_spi0), - /* @GPIO(28,29,30,31) spi1 */ - PINCTRL_PIN_GROUP("spi1", mt7988_spi1), - /* @GPIO(32,33,34,35) spi2 */ - PINCTRL_PIN_GROUP("spi2", mt7988_spi2), - /* @GPIO(36,37) spi2_wp_hold */ - PINCTRL_PIN_GROUP("spi2_wp_hold", mt7988_spi2_wp_hold), - /* @GPIO(22,23,24,25,26,27) snfi */ - PINCTRL_PIN_GROUP("snfi", mt7988_snfi), - /* @GPIO(22,23) tops_uart0_0 */ - PINCTRL_PIN_GROUP("tops_uart0_0", mt7988_tops_uart0_0), - /* @GPIO(28,29,30,31) uart2_0 */ - PINCTRL_PIN_GROUP("uart2_0", mt7988_uart2_0), - /* @GPIO(32,33,34,35) uart1_0 */ - PINCTRL_PIN_GROUP("uart1_0", mt7988_uart1_0), - /* @GPIO(32,33,34,35) uart2_1 */ - PINCTRL_PIN_GROUP("uart2_1", mt7988_uart2_1), - /* @GPIO(28) net_wo0_uart_txd_0 */ - PINCTRL_PIN_GROUP("net_wo0_uart_txd_0", mt7988_net_wo0_uart_txd_0), - /* @GPIO(29) net_wo1_uart_txd_0 */ - PINCTRL_PIN_GROUP("net_wo1_uart_txd_0", mt7988_net_wo1_uart_txd_0), - /* @GPIO(30) net_wo2_uart_txd_0 */ - PINCTRL_PIN_GROUP("net_wo2_uart_txd_0", mt7988_net_wo2_uart_txd_0), - /* @GPIO(28,29) tops_uart1_0 */ - PINCTRL_PIN_GROUP("tops_uart0_0", mt7988_tops_uart1_0), - /* @GPIO(30,31) tops_uart0_1 */ - PINCTRL_PIN_GROUP("tops_uart0_1", mt7988_tops_uart0_1), - /* @GPIO(36,37) tops_uart1_1 */ - PINCTRL_PIN_GROUP("tops_uart1_1", mt7988_tops_uart1_1), - /* @GPIO(32,33,34,35,36) udi */ - PINCTRL_PIN_GROUP("udi", mt7988_udi), - /* @GPIO(21,28,29,30,31,32,33,34,35,36,37) emmc_45 */ - PINCTRL_PIN_GROUP("emmc_45", mt7988_emmc_45), - /* @GPIO(32,33,34,35,36,37) sdcard */ - PINCTRL_PIN_GROUP("sdcard", mt7988_sdcard), - /* @GPIO(38,39,40,41,42,43,44,45,46,47,48,49) emmc_51 */ - PINCTRL_PIN_GROUP("emmc_51", mt7988_emmc_51), - /* @GPIO(28,29) 2p5g_ext_mdio */ - PINCTRL_PIN_GROUP("2p5g_ext_mdio", mt7988_2p5g_ext_mdio), - /* @GPIO(30,31) gbe_ext_mdio */ - PINCTRL_PIN_GROUP("gbe_ext_mdio", mt7988_gbe_ext_mdio), - /* @GPIO(50,51,52,53,54) i2s */ - PINCTRL_PIN_GROUP("i2s", mt7988_i2s), - /* @GPIO(50,51,52,53) pcm */ - PINCTRL_PIN_GROUP("pcm", mt7988_pcm), - /* @GPIO(55,56) uart0 */ - PINCTRL_PIN_GROUP("uart0", mt7988_uart0), - /* @GPIO(55,56) tops_uart0_2 */ - PINCTRL_PIN_GROUP("tops_uart0_2", mt7988_tops_uart0_2), - /* @GPIO(50,51,52,53) uart2_2 */ - PINCTRL_PIN_GROUP("uart2_2", mt7988_uart2_2), - /* @GPIO(50,51,52,53,54) wo0_jtag */ - PINCTRL_PIN_GROUP("wo0_jtag", mt7988_wo0_jtag), - /* @GPIO(50,51,52,53,54) wo1-wo1_jtag */ - PINCTRL_PIN_GROUP("wo1_jtag", mt7988_wo1_jtag), - /* @GPIO(50,51,52,53,54) wo2_jtag */ - PINCTRL_PIN_GROUP("wo2_jtag", mt7988_wo2_jtag), - /* @GPIO(57) pwm0 */ - PINCTRL_PIN_GROUP("pwm0", mt7988_pwm0), - /* @GPIO(58,59,60,61,62) jtag */ - PINCTRL_PIN_GROUP("jtag", mt7988_jtag), - /* @GPIO(58,59,60,61,62) tops_jtag0_1 */ - PINCTRL_PIN_GROUP("tops_jtag0_1", mt7988_tops_jtag0_1), - /* @GPIO(58,59,60,61) uart2_3 */ - PINCTRL_PIN_GROUP("uart2_3", mt7988_uart2_3), - /* @GPIO(58,59,60,61) uart1_1 */ - PINCTRL_PIN_GROUP("uart1_1", mt7988_uart1_1), - /* @GPIO(58,59,60,61) gbe_led1 */ - PINCTRL_PIN_GROUP("gbe0_led1", mt7988_gbe0_led1), - PINCTRL_PIN_GROUP("gbe1_led1", mt7988_gbe1_led1), - PINCTRL_PIN_GROUP("gbe2_led1", mt7988_gbe2_led1), - PINCTRL_PIN_GROUP("gbe3_led1", mt7988_gbe3_led1), - /* @GPIO(62) 2p5gbe_led1 */ - PINCTRL_PIN_GROUP("2p5gbe_led1", mt7988_2p5gbe_led1), - /* @GPIO(64,65,66,67) gbe_led0 */ - PINCTRL_PIN_GROUP("gbe0_led0", mt7988_gbe0_led0), - PINCTRL_PIN_GROUP("gbe1_led0", mt7988_gbe1_led0), - PINCTRL_PIN_GROUP("gbe2_led0", mt7988_gbe2_led0), - PINCTRL_PIN_GROUP("gbe3_led0", mt7988_gbe3_led0), - /* @GPIO(68) 2p5gbe_led0 */ - PINCTRL_PIN_GROUP("2p5gbe_led0", mt7988_2p5gbe_led0), - /* @GPIO(63) drv_vbus_p1 */ - PINCTRL_PIN_GROUP("drv_vbus_p1", mt7988_drv_vbus_p1), - /* @GPIO(63) pcie_clk_req_n2_1 */ - PINCTRL_PIN_GROUP("pcie_clk_req_n2_1", mt7988_pcie_clk_req_n2_1), - /* @GPIO(69, 70) mdc_mdio1 */ - PINCTRL_PIN_GROUP("mdc_mdio1", mt7988_mdc_mdio1), - /* @GPIO(69, 70) i2c1_2 */ - PINCTRL_PIN_GROUP("i2c1_2", mt7988_i2c1_2), - /* @GPIO(69) pwm6 */ - PINCTRL_PIN_GROUP("pwm6", mt7988_pwm6), - /* @GPIO(70) pwm7 */ - PINCTRL_PIN_GROUP("pwm7", mt7988_pwm7), - /* @GPIO(69,70) i2c2_0 */ - PINCTRL_PIN_GROUP("i2c2_0", mt7988_i2c2_0), - /* @GPIO(71,72) i2c2_1 */ - PINCTRL_PIN_GROUP("i2c2_1", mt7988_i2c2_1), - /* @GPIO(73) pcie_2l_1_pereset */ - PINCTRL_PIN_GROUP("pcie_2l_1_pereset", mt7988_pcie_2l_1_pereset), - /* @GPIO(74) pcie_1l_0_pereset */ - PINCTRL_PIN_GROUP("pcie_1l_0_pereset", mt7988_pcie_1l_0_pereset), - /* @GPIO(75) pcie_wake_n1_0 */ - PINCTRL_PIN_GROUP("pcie_wake_n1_0", mt7988_pcie_wake_n1_0), - /* @GPIO(76) pcie_clk_req_n1 */ - PINCTRL_PIN_GROUP("pcie_clk_req_n1", mt7988_pcie_clk_req_n1), - /* @GPIO(77) pcie_wake_n2_0 */ - PINCTRL_PIN_GROUP("pcie_wake_n2_0", mt7988_pcie_wake_n2_0), - /* @GPIO(78) pcie_clk_req_n2_0 */ - PINCTRL_PIN_GROUP("pcie_clk_req_n2_0", mt7988_pcie_clk_req_n2_0), - /* @GPIO(79) drv_vbus */ - PINCTRL_PIN_GROUP("drv_vbus", mt7988_drv_vbus), - /* @GPIO(79) pcie_wake_n2_1 */ - PINCTRL_PIN_GROUP("pcie_wake_n2_1", mt7988_pcie_wake_n2_1), - /* @GPIO(80,81,82,83) uart1_2 */ - PINCTRL_PIN_GROUP("uart1_2", mt7988_uart1_2), - /* @GPIO(80) pwm2 */ - PINCTRL_PIN_GROUP("pwm2", mt7988_pwm2), - /* @GPIO(81) pwm3 */ - PINCTRL_PIN_GROUP("pwm3", mt7988_pwm3), - /* @GPIO(82) pwm4 */ - PINCTRL_PIN_GROUP("pwm4", mt7988_pwm4), - /* @GPIO(83) pwm5 */ - PINCTRL_PIN_GROUP("pwm5", mt7988_pwm5), - /* @GPIO(80) net_wo0_uart_txd_0 */ - PINCTRL_PIN_GROUP("net_wo0_uart_txd_0", mt7988_net_wo0_uart_txd_0), - /* @GPIO(81) net_wo1_uart_txd_0 */ - PINCTRL_PIN_GROUP("net_wo1_uart_txd_0", mt7988_net_wo1_uart_txd_0), - /* @GPIO(82) net_wo2_uart_txd_0 */ - PINCTRL_PIN_GROUP("net_wo2_uart_txd_0", mt7988_net_wo2_uart_txd_0), - /* @GPIO(80,81) tops_uart1_2 */ - PINCTRL_PIN_GROUP("tops_uart1_2", mt7988_tops_uart1_2), - /* @GPIO(80) net_wo0_uart_txd_1 */ - PINCTRL_PIN_GROUP("net_wo0_uart_txd_1", mt7988_net_wo0_uart_txd_1), - /* @GPIO(81) net_wo1_uart_txd_1 */ - PINCTRL_PIN_GROUP("net_wo1_uart_txd_1", mt7988_net_wo1_uart_txd_1), - /* @GPIO(82) net_wo2_uart_txd_1 */ - PINCTRL_PIN_GROUP("net_wo2_uart_txd_1", mt7988_net_wo2_uart_txd_1), -}; - -/* Joint those groups owning the same capability in user point of view which - * allows that people tend to use through the device tree. - */ -static const char * const mt7988_jtag_groups[] = { - "tops_jtag0_0", "wo0_jtag", "wo1_jtag", - "wo2_jtag", "jtag", "tops_jtag0_1", -}; -static const char * const mt7988_int_usxgmii_groups[] = { - "int_usxgmii", -}; -static const char * const mt7988_pwm_groups[] = { - "pwm0", "pwm1", "pwm2", "pwm3", "pwm4", "pwm5", "pwm6", "pwm7" -}; -static const char * const mt7988_dfd_groups[] = { - "dfd", -}; -static const char * const mt7988_i2c_groups[] = { - "xfi_phy0_i2c0", - "xfi_phy1_i2c0", - "xfi_phy_pll_i2c0", - "xfi_phy_pll_i2c1", - "i2c0_0", - "i2c1_sfp", - "xfi_pextp_phy0_i2c", - "xfi_pextp_phy1_i2c", - "i2c0_1", - "u30_phy_i2c0", - "u32_phy_i2c0", - "xfi_phy0_i2c1", - "xfi_phy1_i2c1", - "xfi_phy_pll_i2c2", - "i2c1_0", - "u30_phy_i2c1", - "u32_phy_i2c1", - "xfi_phy_pll_i2c3", - "sgmii0_i2c", - "sgmii1_i2c", - "i2c1_2", - "i2c2_0", - "i2c2_1", -}; -static const char * const mt7988_ethernet_groups[] = { - "mdc_mdio0", - "2p5g_ext_mdio", - "gbe_ext_mdio", - "mdc_mdio1", -}; -static const char * const mt7988_pcie_groups[] = { - "pcie_wake_n0_0", "pcie_clk_req_n0_0", "pcie_wake_n3_0", - "pcie_clk_req_n3", "pcie_p0_phy_i2c", "pcie_p1_phy_i2c", - "pcie_p3_phy_i2c", "pcie_p2_phy_i2c", "ckm_phy_i2c", - "pcie_wake_n0_1", "pcie_wake_n3_1", "pcie_2l_0_pereset", - "pcie_1l_1_pereset", "pcie_clk_req_n2_1", "pcie_2l_1_pereset", - "pcie_1l_0_pereset", "pcie_wake_n1_0", "pcie_clk_req_n1", - "pcie_wake_n2_0", "pcie_clk_req_n2_0", "pcie_wake_n2_1", - "pcie_clk_req_n0_1" -}; -static const char * const mt7988_pmic_groups[] = { - "pmic", -}; -static const char * const mt7988_wdt_groups[] = { - "watchdog", -}; -static const char * const mt7988_spi_groups[] = { - "spi0", "spi0_wp_hold", "spi1", "spi2", "spi2_wp_hold", -}; -static const char * const mt7988_flash_groups[] = { "emmc_45", "sdcard", "snfi", - "emmc_51" }; -static const char * const mt7988_uart_groups[] = { - "uart2", - "tops_uart0_0", - "uart2_0", - "uart1_0", - "uart2_1", - "net_wo0_uart_txd_0", - "net_wo1_uart_txd_0", - "net_wo2_uart_txd_0", - "tops_uart1_0", - "ops_uart0_1", - "ops_uart1_1", - "uart0", - "tops_uart0_2", - "uart1_1", - "uart2_3", - "uart1_2", - "tops_uart1_2", - "net_wo0_uart_txd_1", - "net_wo1_uart_txd_1", - "net_wo2_uart_txd_1", -}; -static const char * const mt7988_udi_groups[] = { - "udi", -}; -static const char * const mt7988_audio_groups[] = { - "i2s", "pcm", -}; -static const char * const mt7988_led_groups[] = { - "gbe0_led1", "gbe1_led1", "gbe2_led1", "gbe3_led1", "2p5gbe_led1", - "gbe0_led0", "gbe1_led0", "gbe2_led0", "gbe3_led0", "2p5gbe_led0", - "wf5g_led0", "wf5g_led1", -}; -static const char * const mt7988_usb_groups[] = { - "drv_vbus", - "drv_vbus_p1", -}; - -static const struct function_desc mt7988_functions[] = { - { "audio", mt7988_audio_groups, ARRAY_SIZE(mt7988_audio_groups) }, - { "jtag", mt7988_jtag_groups, ARRAY_SIZE(mt7988_jtag_groups) }, - { "int_usxgmii", mt7988_int_usxgmii_groups, - ARRAY_SIZE(mt7988_int_usxgmii_groups) }, - { "pwm", mt7988_pwm_groups, ARRAY_SIZE(mt7988_pwm_groups) }, - { "dfd", mt7988_dfd_groups, ARRAY_SIZE(mt7988_dfd_groups) }, - { "i2c", mt7988_i2c_groups, ARRAY_SIZE(mt7988_i2c_groups) }, - { "eth", mt7988_ethernet_groups, ARRAY_SIZE(mt7988_ethernet_groups) }, - { "pcie", mt7988_pcie_groups, ARRAY_SIZE(mt7988_pcie_groups) }, - { "pmic", mt7988_pmic_groups, ARRAY_SIZE(mt7988_pmic_groups) }, - { "watchdog", mt7988_wdt_groups, ARRAY_SIZE(mt7988_wdt_groups) }, - { "spi", mt7988_spi_groups, ARRAY_SIZE(mt7988_spi_groups) }, - { "flash", mt7988_flash_groups, ARRAY_SIZE(mt7988_flash_groups) }, - { "uart", mt7988_uart_groups, ARRAY_SIZE(mt7988_uart_groups) }, - { "udi", mt7988_udi_groups, ARRAY_SIZE(mt7988_udi_groups) }, - { "usb", mt7988_usb_groups, ARRAY_SIZE(mt7988_usb_groups) }, - { "led", mt7988_led_groups, ARRAY_SIZE(mt7988_led_groups) }, -}; - -static const struct mtk_eint_hw mt7988_eint_hw = { - .port_mask = 7, - .ports = 7, - .ap_num = ARRAY_SIZE(mt7988_pins), - .db_cnt = 16, -}; - -static const char * const mt7988_pinctrl_register_base_names[] = { - "gpio_base", "iocfg_tr_base", "iocfg_br_base", - "iocfg_rb_base", "iocfg_lb_base", "iocfg_tl_base", -}; - -static struct mtk_pin_soc mt7988_data = { - .reg_cal = mt7988_reg_cals, - .pins = mt7988_pins, - .npins = ARRAY_SIZE(mt7988_pins), - .grps = mt7988_groups, - .ngrps = ARRAY_SIZE(mt7988_groups), - .funcs = mt7988_functions, - .nfuncs = ARRAY_SIZE(mt7988_functions), - .eint_hw = &mt7988_eint_hw, - .gpio_m = 0, - .ies_present = false, - .base_names = mt7988_pinctrl_register_base_names, - .nbase_names = ARRAY_SIZE(mt7988_pinctrl_register_base_names), - .bias_disable_set = mtk_pinconf_bias_disable_set, - .bias_disable_get = mtk_pinconf_bias_disable_get, - .bias_set = mtk_pinconf_bias_set, - .bias_get = mtk_pinconf_bias_get, - .drive_set = mtk_pinconf_drive_set_rev1, - .drive_get = mtk_pinconf_drive_get_rev1, - .adv_pull_get = mtk_pinconf_adv_pull_get, - .adv_pull_set = mtk_pinconf_adv_pull_set, -}; - -static const struct of_device_id mt7988_pinctrl_of_match[] = { - { - .compatible = "mediatek,mt7988-pinctrl", - }, - {} -}; - -static int mt7988_pinctrl_probe(struct platform_device *pdev) -{ - return mtk_moore_pinctrl_probe(pdev, &mt7988_data); -} - -static struct platform_driver mt7988_pinctrl_driver = { - .driver = { - .name = "mt7988-pinctrl", - .of_match_table = mt7988_pinctrl_of_match, - }, - .probe = mt7988_pinctrl_probe, -}; - -static int __init mt7988_pinctrl_init(void) -{ - return platform_driver_register(&mt7988_pinctrl_driver); -} -arch_initcall(mt7988_pinctrl_init); diff --git a/target/linux/mediatek/files-6.1/include/dt-bindings/clock/mediatek,mt7988-clk.h b/target/linux/mediatek/files-6.1/include/dt-bindings/clock/mediatek,mt7988-clk.h deleted file mode 100644 index 77cfea4a8..000000000 --- a/target/linux/mediatek/files-6.1/include/dt-bindings/clock/mediatek,mt7988-clk.h +++ /dev/null @@ -1,276 +0,0 @@ -/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ -/* - * Copyright (c) 2023 MediaTek Inc. - * Author: Sam Shih - * Author: Xiufeng Li - */ - -#ifndef _DT_BINDINGS_CLK_MT7988_H -#define _DT_BINDINGS_CLK_MT7988_H - -/* APMIXEDSYS */ - -#define CLK_APMIXED_NETSYSPLL 0 -#define CLK_APMIXED_MPLL 1 -#define CLK_APMIXED_MMPLL 2 -#define CLK_APMIXED_APLL2 3 -#define CLK_APMIXED_NET1PLL 4 -#define CLK_APMIXED_NET2PLL 5 -#define CLK_APMIXED_WEDMCUPLL 6 -#define CLK_APMIXED_SGMPLL 7 -#define CLK_APMIXED_ARM_B 8 -#define CLK_APMIXED_CCIPLL2_B 9 -#define CLK_APMIXED_USXGMIIPLL 10 -#define CLK_APMIXED_MSDCPLL 11 - -/* TOPCKGEN */ - -#define CLK_TOP_XTAL 0 -#define CLK_TOP_XTAL_D2 1 -#define CLK_TOP_RTC_32K 2 -#define CLK_TOP_RTC_32P7K 3 -#define CLK_TOP_MPLL_D2 4 -#define CLK_TOP_MPLL_D3_D2 5 -#define CLK_TOP_MPLL_D4 6 -#define CLK_TOP_MPLL_D8 7 -#define CLK_TOP_MPLL_D8_D2 8 -#define CLK_TOP_MMPLL_D2 9 -#define CLK_TOP_MMPLL_D3_D5 10 -#define CLK_TOP_MMPLL_D4 11 -#define CLK_TOP_MMPLL_D6_D2 12 -#define CLK_TOP_MMPLL_D8 13 -#define CLK_TOP_APLL2_D4 14 -#define CLK_TOP_NET1PLL_D4 15 -#define CLK_TOP_NET1PLL_D5 16 -#define CLK_TOP_NET1PLL_D5_D2 17 -#define CLK_TOP_NET1PLL_D5_D4 18 -#define CLK_TOP_NET1PLL_D8 19 -#define CLK_TOP_NET1PLL_D8_D2 20 -#define CLK_TOP_NET1PLL_D8_D4 21 -#define CLK_TOP_NET1PLL_D8_D8 22 -#define CLK_TOP_NET1PLL_D8_D16 23 -#define CLK_TOP_NET2PLL_D2 24 -#define CLK_TOP_NET2PLL_D4 25 -#define CLK_TOP_NET2PLL_D4_D4 26 -#define CLK_TOP_NET2PLL_D4_D8 27 -#define CLK_TOP_NET2PLL_D6 28 -#define CLK_TOP_NET2PLL_D8 29 -#define CLK_TOP_NETSYS_SEL 30 -#define CLK_TOP_NETSYS_500M_SEL 31 -#define CLK_TOP_NETSYS_2X_SEL 32 -#define CLK_TOP_NETSYS_GSW_SEL 33 -#define CLK_TOP_ETH_GMII_SEL 34 -#define CLK_TOP_NETSYS_MCU_SEL 35 -#define CLK_TOP_NETSYS_PAO_2X_SEL 36 -#define CLK_TOP_EIP197_SEL 37 -#define CLK_TOP_AXI_INFRA_SEL 38 -#define CLK_TOP_UART_SEL 39 -#define CLK_TOP_EMMC_250M_SEL 40 -#define CLK_TOP_EMMC_400M_SEL 41 -#define CLK_TOP_SPI_SEL 42 -#define CLK_TOP_SPIM_MST_SEL 43 -#define CLK_TOP_NFI1X_SEL 44 -#define CLK_TOP_SPINFI_SEL 45 -#define CLK_TOP_PWM_SEL 46 -#define CLK_TOP_I2C_SEL 47 -#define CLK_TOP_PCIE_MBIST_250M_SEL 48 -#define CLK_TOP_PEXTP_TL_SEL 49 -#define CLK_TOP_PEXTP_TL_P1_SEL 50 -#define CLK_TOP_PEXTP_TL_P2_SEL 51 -#define CLK_TOP_PEXTP_TL_P3_SEL 52 -#define CLK_TOP_USB_SYS_SEL 53 -#define CLK_TOP_USB_SYS_P1_SEL 54 -#define CLK_TOP_USB_XHCI_SEL 55 -#define CLK_TOP_USB_XHCI_P1_SEL 56 -#define CLK_TOP_USB_FRMCNT_SEL 57 -#define CLK_TOP_USB_FRMCNT_P1_SEL 58 -#define CLK_TOP_AUD_SEL 59 -#define CLK_TOP_A1SYS_SEL 60 -#define CLK_TOP_AUD_L_SEL 61 -#define CLK_TOP_A_TUNER_SEL 62 -#define CLK_TOP_SSPXTP_SEL 63 -#define CLK_TOP_USB_PHY_SEL 64 -#define CLK_TOP_USXGMII_SBUS_0_SEL 65 -#define CLK_TOP_USXGMII_SBUS_1_SEL 66 -#define CLK_TOP_SGM_0_SEL 67 -#define CLK_TOP_SGM_SBUS_0_SEL 68 -#define CLK_TOP_SGM_1_SEL 69 -#define CLK_TOP_SGM_SBUS_1_SEL 70 -#define CLK_TOP_XFI_PHY_0_XTAL_SEL 71 -#define CLK_TOP_XFI_PHY_1_XTAL_SEL 72 -#define CLK_TOP_SYSAXI_SEL 73 -#define CLK_TOP_SYSAPB_SEL 74 -#define CLK_TOP_ETH_REFCK_50M_SEL 75 -#define CLK_TOP_ETH_SYS_200M_SEL 76 -#define CLK_TOP_ETH_SYS_SEL 77 -#define CLK_TOP_ETH_XGMII_SEL 78 -#define CLK_TOP_BUS_TOPS_SEL 79 -#define CLK_TOP_NPU_TOPS_SEL 80 -#define CLK_TOP_DRAMC_SEL 81 -#define CLK_TOP_DRAMC_MD32_SEL 82 -#define CLK_TOP_INFRA_F26M_SEL 83 -#define CLK_TOP_PEXTP_P0_SEL 84 -#define CLK_TOP_PEXTP_P1_SEL 85 -#define CLK_TOP_PEXTP_P2_SEL 86 -#define CLK_TOP_PEXTP_P3_SEL 87 -#define CLK_TOP_DA_XTP_GLB_P0_SEL 88 -#define CLK_TOP_DA_XTP_GLB_P1_SEL 89 -#define CLK_TOP_DA_XTP_GLB_P2_SEL 90 -#define CLK_TOP_DA_XTP_GLB_P3_SEL 91 -#define CLK_TOP_CKM_SEL 92 -#define CLK_TOP_DA_SEL 93 -#define CLK_TOP_PEXTP_SEL 94 -#define CLK_TOP_TOPS_P2_26M_SEL 95 -#define CLK_TOP_MCUSYS_BACKUP_625M_SEL 96 -#define CLK_TOP_NETSYS_SYNC_250M_SEL 97 -#define CLK_TOP_MACSEC_SEL 98 -#define CLK_TOP_NETSYS_TOPS_400M_SEL 99 -#define CLK_TOP_NETSYS_PPEFB_250M_SEL 100 -#define CLK_TOP_NETSYS_WARP_SEL 101 -#define CLK_TOP_ETH_MII_SEL 102 -#define CLK_TOP_NPU_SEL 103 -#define CLK_TOP_AUD_I2S_M 104 - -/* MCUSYS */ - -#define CLK_MCU_BUS_DIV_SEL 0 -#define CLK_MCU_ARM_DIV_SEL 1 - -/* INFRACFG_AO */ - -#define CLK_INFRA_MUX_UART0_SEL 0 -#define CLK_INFRA_MUX_UART1_SEL 1 -#define CLK_INFRA_MUX_UART2_SEL 2 -#define CLK_INFRA_MUX_SPI0_SEL 3 -#define CLK_INFRA_MUX_SPI1_SEL 4 -#define CLK_INFRA_MUX_SPI2_SEL 5 -#define CLK_INFRA_PWM_SEL 6 -#define CLK_INFRA_PWM_CK1_SEL 7 -#define CLK_INFRA_PWM_CK2_SEL 8 -#define CLK_INFRA_PWM_CK3_SEL 9 -#define CLK_INFRA_PWM_CK4_SEL 10 -#define CLK_INFRA_PWM_CK5_SEL 11 -#define CLK_INFRA_PWM_CK6_SEL 12 -#define CLK_INFRA_PWM_CK7_SEL 13 -#define CLK_INFRA_PWM_CK8_SEL 14 -#define CLK_INFRA_PCIE_GFMUX_TL_O_P0_SEL 15 -#define CLK_INFRA_PCIE_GFMUX_TL_O_P1_SEL 16 -#define CLK_INFRA_PCIE_GFMUX_TL_O_P2_SEL 17 -#define CLK_INFRA_PCIE_GFMUX_TL_O_P3_SEL 18 - -/* INFRACFG */ - -#define CLK_INFRA_PCIE_PERI_26M_CK_P0 19 -#define CLK_INFRA_PCIE_PERI_26M_CK_P1 20 -#define CLK_INFRA_PCIE_PERI_26M_CK_P2 21 -#define CLK_INFRA_PCIE_PERI_26M_CK_P3 22 -#define CLK_INFRA_66M_GPT_BCK 23 -#define CLK_INFRA_66M_PWM_HCK 24 -#define CLK_INFRA_66M_PWM_BCK 25 -#define CLK_INFRA_66M_PWM_CK1 26 -#define CLK_INFRA_66M_PWM_CK2 27 -#define CLK_INFRA_66M_PWM_CK3 28 -#define CLK_INFRA_66M_PWM_CK4 29 -#define CLK_INFRA_66M_PWM_CK5 30 -#define CLK_INFRA_66M_PWM_CK6 31 -#define CLK_INFRA_66M_PWM_CK7 32 -#define CLK_INFRA_66M_PWM_CK8 33 -#define CLK_INFRA_133M_CQDMA_BCK 34 -#define CLK_INFRA_66M_AUD_SLV_BCK 35 -#define CLK_INFRA_AUD_26M 36 -#define CLK_INFRA_AUD_L 37 -#define CLK_INFRA_AUD_AUD 38 -#define CLK_INFRA_AUD_EG2 39 -#define CLK_INFRA_DRAMC_F26M 40 -#define CLK_INFRA_133M_DBG_ACKM 41 -#define CLK_INFRA_66M_AP_DMA_BCK 42 -#define CLK_INFRA_66M_SEJ_BCK 43 -#define CLK_INFRA_PRE_CK_SEJ_F13M 44 -#define CLK_INFRA_26M_THERM_SYSTEM 45 -#define CLK_INFRA_I2C_BCK 46 -#define CLK_INFRA_52M_UART0_CK 47 -#define CLK_INFRA_52M_UART1_CK 48 -#define CLK_INFRA_52M_UART2_CK 49 -#define CLK_INFRA_NFI 50 -#define CLK_INFRA_SPINFI 51 -#define CLK_INFRA_66M_NFI_HCK 52 -#define CLK_INFRA_104M_SPI0 53 -#define CLK_INFRA_104M_SPI1 54 -#define CLK_INFRA_104M_SPI2_BCK 55 -#define CLK_INFRA_66M_SPI0_HCK 56 -#define CLK_INFRA_66M_SPI1_HCK 57 -#define CLK_INFRA_66M_SPI2_HCK 58 -#define CLK_INFRA_66M_FLASHIF_AXI 59 -#define CLK_INFRA_RTC 60 -#define CLK_INFRA_26M_ADC_BCK 61 -#define CLK_INFRA_RC_ADC 62 -#define CLK_INFRA_MSDC400 63 -#define CLK_INFRA_MSDC2_HCK 64 -#define CLK_INFRA_133M_MSDC_0_HCK 65 -#define CLK_INFRA_66M_MSDC_0_HCK 66 -#define CLK_INFRA_133M_CPUM_BCK 67 -#define CLK_INFRA_BIST2FPC 68 -#define CLK_INFRA_I2C_X16W_MCK_CK_P1 69 -#define CLK_INFRA_I2C_X16W_PCK_CK_P1 70 -#define CLK_INFRA_133M_USB_HCK 71 -#define CLK_INFRA_133M_USB_HCK_CK_P1 72 -#define CLK_INFRA_66M_USB_HCK 73 -#define CLK_INFRA_66M_USB_HCK_CK_P1 74 -#define CLK_INFRA_USB_SYS 75 -#define CLK_INFRA_USB_SYS_CK_P1 76 -#define CLK_INFRA_USB_REF 77 -#define CLK_INFRA_USB_CK_P1 78 -#define CLK_INFRA_USB_FRMCNT 79 -#define CLK_INFRA_USB_FRMCNT_CK_P1 80 -#define CLK_INFRA_USB_PIPE 81 -#define CLK_INFRA_USB_PIPE_CK_P1 82 -#define CLK_INFRA_USB_UTMI 83 -#define CLK_INFRA_USB_UTMI_CK_P1 84 -#define CLK_INFRA_USB_XHCI 85 -#define CLK_INFRA_USB_XHCI_CK_P1 86 -#define CLK_INFRA_PCIE_GFMUX_TL_P0 87 -#define CLK_INFRA_PCIE_GFMUX_TL_P1 88 -#define CLK_INFRA_PCIE_GFMUX_TL_P2 89 -#define CLK_INFRA_PCIE_GFMUX_TL_P3 90 -#define CLK_INFRA_PCIE_PIPE_P0 91 -#define CLK_INFRA_PCIE_PIPE_P1 92 -#define CLK_INFRA_PCIE_PIPE_P2 93 -#define CLK_INFRA_PCIE_PIPE_P3 94 -#define CLK_INFRA_133M_PCIE_CK_P0 95 -#define CLK_INFRA_133M_PCIE_CK_P1 96 -#define CLK_INFRA_133M_PCIE_CK_P2 97 -#define CLK_INFRA_133M_PCIE_CK_P3 98 - -/* ETHDMA */ - -#define CLK_ETHDMA_XGP1_EN 0 -#define CLK_ETHDMA_XGP2_EN 1 -#define CLK_ETHDMA_XGP3_EN 2 -#define CLK_ETHDMA_FE_EN 3 -#define CLK_ETHDMA_GP2_EN 4 -#define CLK_ETHDMA_GP1_EN 5 -#define CLK_ETHDMA_GP3_EN 6 -#define CLK_ETHDMA_ESW_EN 7 -#define CLK_ETHDMA_CRYPT0_EN 8 -#define CLK_ETHDMA_NR_CLK 9 - -/* SGMIISYS_0 */ - -#define CLK_SGM0_TX_EN 0 -#define CLK_SGM0_RX_EN 1 -#define CLK_SGMII0_NR_CLK 2 - -/* SGMIISYS_1 */ - -#define CLK_SGM1_TX_EN 0 -#define CLK_SGM1_RX_EN 1 -#define CLK_SGMII1_NR_CLK 2 - -/* ETHWARP */ - -#define CLK_ETHWARP_WOCPU2_EN 0 -#define CLK_ETHWARP_WOCPU1_EN 1 -#define CLK_ETHWARP_WOCPU0_EN 2 -#define CLK_ETHWARP_NR_CLK 3 - -#endif /* _DT_BINDINGS_CLK_MT7988_H */ diff --git a/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7988a.dtsi b/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7988a.dtsi index 9ad068fe0..3d85936c1 100644 --- a/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7988a.dtsi +++ b/target/linux/mediatek/files-6.6/arch/arm64/boot/dts/mediatek/mt7988a.dtsi @@ -92,26 +92,32 @@ cluster0_opp: opp_table0 { compatible = "operating-points-v2"; opp-shared; - opp00 { opp-hz = /bits/ 64 <800000000>; opp-microvolt = <850000>; }; - opp01 { opp-hz = /bits/ 64 <1100000000>; opp-microvolt = <850000>; }; - opp02 { opp-hz = /bits/ 64 <1500000000>; opp-microvolt = <850000>; }; - opp03 { opp-hz = /bits/ 64 <1800000000>; opp-microvolt = <900000>; }; + + opp04 { + opp-hz = /bits/ 64 <2100000000>; + opp-microvolt = <1000000>; + }; + + opp05 { + opp-hz = /bits/ 64 <2300000000>; + opp-microvolt = <1150000>; + }; }; }; diff --git a/target/linux/mediatek/files/block/partitions/fit.c b/target/linux/mediatek/files/block/partitions/fit.c index 463cd4e9a..01b0f42c7 100644 --- a/target/linux/mediatek/files/block/partitions/fit.c +++ b/target/linux/mediatek/files/block/partitions/fit.c @@ -161,7 +161,7 @@ int parse_fit_partitions(struct parsed_partitions *state, u64 fit_start_sector, config = fdt_path_offset(fit, FIT_CONFS_PATH); if (config < 0) { - printk(KERN_ERR "FIT: Cannot find %s node: %d\n", FIT_CONFS_PATH, images); + printk(KERN_ERR "FIT: Cannot find %s node: %d\n", FIT_CONFS_PATH, config); ret = -ENOENT; goto ret_out; } diff --git a/target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/Kconfig b/target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/Kconfig deleted file mode 100644 index d9e0230cf..000000000 --- a/target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/Kconfig +++ /dev/null @@ -1,3 +0,0 @@ - -config MT753X_GSW - tristate "Driver for the MediaTek MT753x switch" diff --git a/target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/Makefile b/target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/Makefile deleted file mode 100644 index 7aae451cd..000000000 --- a/target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -# -# Makefile for MediaTek MT753x gigabit switch -# - -obj-$(CONFIG_MT753X_GSW) += mt753x.o - -mt753x-$(CONFIG_SWCONFIG) += mt753x_swconfig.o - -mt753x-y += mt753x_mdio.o mt7530.o mt7531.o \ - mt753x_common.o mt753x_vlan.o \ - mt753x_nl.o diff --git a/target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt7530.c b/target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt7530.c deleted file mode 100644 index 6a94d0d2f..000000000 --- a/target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt7530.c +++ /dev/null @@ -1,631 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2018 MediaTek Inc. - * Author: Weijie Gao - */ - -#include -#include - -#include "mt753x.h" -#include "mt753x_regs.h" - -/* MT7530 registers */ - -/* Unique fields of PMCR for MT7530 */ -#define FORCE_MODE BIT(15) - -/* Unique fields of GMACCR for MT7530 */ -#define VLAN_SUPT_NO_S 14 -#define VLAN_SUPT_NO_M 0x1c000 -#define LATE_COL_DROP BIT(13) - -/* Unique fields of (M)HWSTRAP for MT7530 */ -#define BOND_OPTION BIT(24) -#define P5_PHY0_SEL BIT(20) -#define CHG_TRAP BIT(16) -#define LOOPDET_DIS BIT(14) -#define P5_INTF_SEL_GMAC5 BIT(13) -#define SMI_ADDR_S 11 -#define SMI_ADDR_M 0x1800 -#define XTAL_FSEL_S 9 -#define XTAL_FSEL_M 0x600 -#define P6_INTF_DIS BIT(8) -#define P5_INTF_MODE_RGMII BIT(7) -#define P5_INTF_DIS_S BIT(6) -#define C_MDIO_BPS_S BIT(5) -#define EEPROM_EN_S BIT(4) - -/* PHY EEE Register bitmap of define */ -#define PHY_DEV07 0x07 -#define PHY_DEV07_REG_03C 0x3c - -/* PHY Extend Register 0x14 bitmap of define */ -#define PHY_EXT_REG_14 0x14 - -/* Fields of PHY_EXT_REG_14 */ -#define PHY_EN_DOWN_SHFIT BIT(4) - -/* PHY Token Ring Register 0x10 bitmap of define */ -#define PHY_TR_REG_10 0x10 - -/* PHY Token Ring Register 0x12 bitmap of define */ -#define PHY_TR_REG_12 0x12 - -/* PHY LPI PCS/DSP Control Register bitmap of define */ -#define PHY_LPI_REG_11 0x11 - -/* PHY DEV 0x1e Register bitmap of define */ -#define PHY_DEV1E 0x1e -#define PHY_DEV1E_REG_123 0x123 -#define PHY_DEV1E_REG_A6 0xa6 - -/* Values of XTAL_FSEL */ -#define XTAL_20MHZ 1 -#define XTAL_40MHZ 2 -#define XTAL_25MHZ 3 - -#define P6ECR 0x7830 -#define P6_INTF_MODE_TRGMII BIT(0) - -#define TRGMII_TXCTRL 0x7a40 -#define TRAIN_TXEN BIT(31) -#define TXC_INV BIT(30) -#define TX_DOEO BIT(29) -#define TX_RST BIT(28) - -#define TRGMII_TD0_CTRL 0x7a50 -#define TRGMII_TD1_CTRL 0x7a58 -#define TRGMII_TD2_CTRL 0x7a60 -#define TRGMII_TD3_CTRL 0x7a68 -#define TRGMII_TXCTL_CTRL 0x7a70 -#define TRGMII_TCK_CTRL 0x7a78 -#define TRGMII_TD_CTRL(n) (0x7a50 + (n) * 8) -#define NUM_TRGMII_CTRL 6 -#define TX_DMPEDRV BIT(31) -#define TX_DM_SR BIT(15) -#define TX_DMERODT BIT(14) -#define TX_DMOECTL BIT(13) -#define TX_TAP_S 8 -#define TX_TAP_M 0xf00 -#define TX_TRAIN_WD_S 0 -#define TX_TRAIN_WD_M 0xff - -#define TRGMII_TD0_ODT 0x7a54 -#define TRGMII_TD1_ODT 0x7a5c -#define TRGMII_TD2_ODT 0x7a64 -#define TRGMII_TD3_ODT 0x7a6c -#define TRGMII_TXCTL_ODT 0x7574 -#define TRGMII_TCK_ODT 0x757c -#define TRGMII_TD_ODT(n) (0x7a54 + (n) * 8) -#define NUM_TRGMII_ODT 6 -#define TX_DM_DRVN_PRE_S 30 -#define TX_DM_DRVN_PRE_M 0xc0000000 -#define TX_DM_DRVP_PRE_S 28 -#define TX_DM_DRVP_PRE_M 0x30000000 -#define TX_DM_TDSEL_S 24 -#define TX_DM_TDSEL_M 0xf000000 -#define TX_ODTEN BIT(23) -#define TX_DME_PRE BIT(20) -#define TX_DM_DRVNT0 BIT(19) -#define TX_DM_DRVPT0 BIT(18) -#define TX_DM_DRVNTE BIT(17) -#define TX_DM_DRVPTE BIT(16) -#define TX_DM_ODTN_S 12 -#define TX_DM_ODTN_M 0x7000 -#define TX_DM_ODTP_S 8 -#define TX_DM_ODTP_M 0x700 -#define TX_DM_DRVN_S 4 -#define TX_DM_DRVN_M 0xf0 -#define TX_DM_DRVP_S 0 -#define TX_DM_DRVP_M 0x0f - -#define P5RGMIIRXCR 0x7b00 -#define CSR_RGMII_RCTL_CFG_S 24 -#define CSR_RGMII_RCTL_CFG_M 0x7000000 -#define CSR_RGMII_RXD_CFG_S 16 -#define CSR_RGMII_RXD_CFG_M 0x70000 -#define CSR_RGMII_EDGE_ALIGN BIT(8) -#define CSR_RGMII_RXC_90DEG_CFG_S 4 -#define CSR_RGMII_RXC_90DEG_CFG_M 0xf0 -#define CSR_RGMII_RXC_0DEG_CFG_S 0 -#define CSR_RGMII_RXC_0DEG_CFG_M 0x0f - -#define P5RGMIITXCR 0x7b04 -#define CSR_RGMII_TXEN_CFG_S 16 -#define CSR_RGMII_TXEN_CFG_M 0x70000 -#define CSR_RGMII_TXD_CFG_S 8 -#define CSR_RGMII_TXD_CFG_M 0x700 -#define CSR_RGMII_TXC_CFG_S 0 -#define CSR_RGMII_TXC_CFG_M 0x1f - -#define CHIP_REV 0x7ffc -#define CHIP_NAME_S 16 -#define CHIP_NAME_M 0xffff0000 -#define CHIP_REV_S 0 -#define CHIP_REV_M 0x0f - -/* MMD registers */ -#define CORE_PLL_GROUP2 0x401 -#define RG_SYSPLL_EN_NORMAL BIT(15) -#define RG_SYSPLL_VODEN BIT(14) -#define RG_SYSPLL_POSDIV_S 5 -#define RG_SYSPLL_POSDIV_M 0x60 - -#define CORE_PLL_GROUP4 0x403 -#define RG_SYSPLL_DDSFBK_EN BIT(12) -#define RG_SYSPLL_BIAS_EN BIT(11) -#define RG_SYSPLL_BIAS_LPF_EN BIT(10) - -#define CORE_PLL_GROUP5 0x404 -#define RG_LCDDS_PCW_NCPO1_S 0 -#define RG_LCDDS_PCW_NCPO1_M 0xffff - -#define CORE_PLL_GROUP6 0x405 -#define RG_LCDDS_PCW_NCPO0_S 0 -#define RG_LCDDS_PCW_NCPO0_M 0xffff - -#define CORE_PLL_GROUP7 0x406 -#define RG_LCDDS_PWDB BIT(15) -#define RG_LCDDS_ISO_EN BIT(13) -#define RG_LCCDS_C_S 4 -#define RG_LCCDS_C_M 0x70 -#define RG_LCDDS_PCW_NCPO_CHG BIT(3) - -#define CORE_PLL_GROUP10 0x409 -#define RG_LCDDS_SSC_DELTA_S 0 -#define RG_LCDDS_SSC_DELTA_M 0xfff - -#define CORE_PLL_GROUP11 0x40a -#define RG_LCDDS_SSC_DELTA1_S 0 -#define RG_LCDDS_SSC_DELTA1_M 0xfff - -#define CORE_GSWPLL_GCR_1 0x040d -#define GSWPLL_PREDIV_S 14 -#define GSWPLL_PREDIV_M 0xc000 -#define GSWPLL_POSTDIV_200M_S 12 -#define GSWPLL_POSTDIV_200M_M 0x3000 -#define GSWPLL_EN_PRE BIT(11) -#define GSWPLL_FBKSEL BIT(10) -#define GSWPLL_BP BIT(9) -#define GSWPLL_BR BIT(8) -#define GSWPLL_FBKDIV_200M_S 0 -#define GSWPLL_FBKDIV_200M_M 0xff - -#define CORE_GSWPLL_GCR_2 0x040e -#define GSWPLL_POSTDIV_500M_S 8 -#define GSWPLL_POSTDIV_500M_M 0x300 -#define GSWPLL_FBKDIV_500M_S 0 -#define GSWPLL_FBKDIV_500M_M 0xff - -#define TRGMII_GSW_CLK_CG 0x0410 -#define TRGMIICK_EN BIT(1) -#define GSWCK_EN BIT(0) - -static int mt7530_mii_read(struct gsw_mt753x *gsw, int phy, int reg) -{ - if (phy < MT753X_NUM_PHYS) - phy = (gsw->phy_base + phy) & MT753X_SMI_ADDR_MASK; - - return mdiobus_read(gsw->host_bus, phy, reg); -} - -static void mt7530_mii_write(struct gsw_mt753x *gsw, int phy, int reg, u16 val) -{ - if (phy < MT753X_NUM_PHYS) - phy = (gsw->phy_base + phy) & MT753X_SMI_ADDR_MASK; - - mdiobus_write(gsw->host_bus, phy, reg, val); -} - -static int mt7530_mmd_read(struct gsw_mt753x *gsw, int addr, int devad, u16 reg) -{ - u16 val; - - if (addr < MT753X_NUM_PHYS) - addr = (gsw->phy_base + addr) & MT753X_SMI_ADDR_MASK; - - mutex_lock(&gsw->host_bus->mdio_lock); - - gsw->host_bus->write(gsw->host_bus, addr, MII_MMD_ACC_CTL_REG, - (MMD_ADDR << MMD_CMD_S) | - ((devad << MMD_DEVAD_S) & MMD_DEVAD_M)); - - gsw->host_bus->write(gsw->host_bus, addr, MII_MMD_ADDR_DATA_REG, reg); - - gsw->host_bus->write(gsw->host_bus, addr, MII_MMD_ACC_CTL_REG, - (MMD_DATA << MMD_CMD_S) | - ((devad << MMD_DEVAD_S) & MMD_DEVAD_M)); - - val = gsw->host_bus->read(gsw->host_bus, addr, MII_MMD_ADDR_DATA_REG); - - mutex_unlock(&gsw->host_bus->mdio_lock); - - return val; -} - -static void mt7530_mmd_write(struct gsw_mt753x *gsw, int addr, int devad, - u16 reg, u16 val) -{ - if (addr < MT753X_NUM_PHYS) - addr = (gsw->phy_base + addr) & MT753X_SMI_ADDR_MASK; - - mutex_lock(&gsw->host_bus->mdio_lock); - - gsw->host_bus->write(gsw->host_bus, addr, MII_MMD_ACC_CTL_REG, - (MMD_ADDR << MMD_CMD_S) | - ((devad << MMD_DEVAD_S) & MMD_DEVAD_M)); - - gsw->host_bus->write(gsw->host_bus, addr, MII_MMD_ADDR_DATA_REG, reg); - - gsw->host_bus->write(gsw->host_bus, addr, MII_MMD_ACC_CTL_REG, - (MMD_DATA << MMD_CMD_S) | - ((devad << MMD_DEVAD_S) & MMD_DEVAD_M)); - - gsw->host_bus->write(gsw->host_bus, addr, MII_MMD_ADDR_DATA_REG, val); - - mutex_unlock(&gsw->host_bus->mdio_lock); -} - -static void mt7530_core_reg_write(struct gsw_mt753x *gsw, u32 reg, u32 val) -{ - gsw->mmd_write(gsw, 0, 0x1f, reg, val); -} - -static void mt7530_trgmii_setting(struct gsw_mt753x *gsw) -{ - u16 i; - - mt7530_core_reg_write(gsw, CORE_PLL_GROUP5, 0x0780); - mdelay(1); - mt7530_core_reg_write(gsw, CORE_PLL_GROUP6, 0); - mt7530_core_reg_write(gsw, CORE_PLL_GROUP10, 0x87); - mdelay(1); - mt7530_core_reg_write(gsw, CORE_PLL_GROUP11, 0x87); - - /* PLL BIAS enable */ - mt7530_core_reg_write(gsw, CORE_PLL_GROUP4, - RG_SYSPLL_DDSFBK_EN | RG_SYSPLL_BIAS_EN); - mdelay(1); - - /* PLL LPF enable */ - mt7530_core_reg_write(gsw, CORE_PLL_GROUP4, - RG_SYSPLL_DDSFBK_EN | - RG_SYSPLL_BIAS_EN | RG_SYSPLL_BIAS_LPF_EN); - - /* sys PLL enable */ - mt7530_core_reg_write(gsw, CORE_PLL_GROUP2, - RG_SYSPLL_EN_NORMAL | RG_SYSPLL_VODEN | - (1 << RG_SYSPLL_POSDIV_S)); - - /* LCDDDS PWDS */ - mt7530_core_reg_write(gsw, CORE_PLL_GROUP7, - (3 << RG_LCCDS_C_S) | - RG_LCDDS_PWDB | RG_LCDDS_ISO_EN); - mdelay(1); - - /* Enable MT7530 TRGMII clock */ - mt7530_core_reg_write(gsw, TRGMII_GSW_CLK_CG, GSWCK_EN | TRGMIICK_EN); - - /* lower Tx Driving */ - for (i = 0 ; i < NUM_TRGMII_ODT; i++) - mt753x_reg_write(gsw, TRGMII_TD_ODT(i), - (4 << TX_DM_DRVP_S) | (4 << TX_DM_DRVN_S)); -} - -static void mt7530_rgmii_setting(struct gsw_mt753x *gsw) -{ - u32 val; - - mt7530_core_reg_write(gsw, CORE_PLL_GROUP5, 0x0c80); - mdelay(1); - mt7530_core_reg_write(gsw, CORE_PLL_GROUP6, 0); - mt7530_core_reg_write(gsw, CORE_PLL_GROUP10, 0x87); - mdelay(1); - mt7530_core_reg_write(gsw, CORE_PLL_GROUP11, 0x87); - - val = mt753x_reg_read(gsw, TRGMII_TXCTRL); - val &= ~TXC_INV; - mt753x_reg_write(gsw, TRGMII_TXCTRL, val); - - mt753x_reg_write(gsw, TRGMII_TCK_CTRL, - (8 << TX_TAP_S) | (0x55 << TX_TRAIN_WD_S)); -} - -static int mt7530_mac_port_setup(struct gsw_mt753x *gsw) -{ - u32 hwstrap, p6ecr = 0, p5mcr, p6mcr, phyad; - - hwstrap = mt753x_reg_read(gsw, MHWSTRAP); - hwstrap &= ~(P6_INTF_DIS | P5_INTF_MODE_RGMII | P5_INTF_DIS_S); - hwstrap |= P5_INTF_SEL_GMAC5; - if (!gsw->port5_cfg.enabled) { - p5mcr = FORCE_MODE; - hwstrap |= P5_INTF_DIS_S; - } else { - p5mcr = (IPG_96BIT_WITH_SHORT_IPG << IPG_CFG_S) | - MAC_MODE | MAC_TX_EN | MAC_RX_EN | - BKOFF_EN | BACKPR_EN; - - if (gsw->port5_cfg.force_link) { - p5mcr |= FORCE_MODE | FORCE_LINK | FORCE_RX_FC | - FORCE_TX_FC; - p5mcr |= gsw->port5_cfg.speed << FORCE_SPD_S; - - if (gsw->port5_cfg.duplex) - p5mcr |= FORCE_DPX; - } - - switch (gsw->port5_cfg.phy_mode) { - case PHY_INTERFACE_MODE_MII: - case PHY_INTERFACE_MODE_GMII: - break; - case PHY_INTERFACE_MODE_RGMII: - hwstrap |= P5_INTF_MODE_RGMII; - break; - default: - dev_info(gsw->dev, "%s is not supported by port5\n", - phy_modes(gsw->port5_cfg.phy_mode)); - p5mcr = FORCE_MODE; - hwstrap |= P5_INTF_DIS_S; - } - - /* Port5 to PHY direct mode */ - if (of_property_read_u32(gsw->port5_cfg.np, "phy-address", - &phyad)) - goto parse_p6; - - if (phyad != 0 && phyad != 4) { - dev_info(gsw->dev, - "Only PHY 0/4 can be connected to Port 5\n"); - goto parse_p6; - } - - hwstrap &= ~P5_INTF_SEL_GMAC5; - if (phyad == 0) - hwstrap |= P5_PHY0_SEL; - else - hwstrap &= ~P5_PHY0_SEL; - } - -parse_p6: - if (!gsw->port6_cfg.enabled) { - p6mcr = FORCE_MODE; - hwstrap |= P6_INTF_DIS; - } else { - p6mcr = (IPG_96BIT_WITH_SHORT_IPG << IPG_CFG_S) | - MAC_MODE | MAC_TX_EN | MAC_RX_EN | - BKOFF_EN | BACKPR_EN; - - if (gsw->port6_cfg.force_link) { - p6mcr |= FORCE_MODE | FORCE_LINK | FORCE_RX_FC | - FORCE_TX_FC; - p6mcr |= gsw->port6_cfg.speed << FORCE_SPD_S; - - if (gsw->port6_cfg.duplex) - p6mcr |= FORCE_DPX; - } - - switch (gsw->port6_cfg.phy_mode) { - case PHY_INTERFACE_MODE_RGMII: - p6ecr = BIT(1); - break; - case PHY_INTERFACE_MODE_TRGMII: - /* set MT7530 central align */ - p6ecr = BIT(0); - break; - default: - dev_info(gsw->dev, "%s is not supported by port6\n", - phy_modes(gsw->port6_cfg.phy_mode)); - p6mcr = FORCE_MODE; - hwstrap |= P6_INTF_DIS; - } - } - - mt753x_reg_write(gsw, MHWSTRAP, hwstrap); - mt753x_reg_write(gsw, P6ECR, p6ecr); - - mt753x_reg_write(gsw, PMCR(5), p5mcr); - mt753x_reg_write(gsw, PMCR(6), p6mcr); - - return 0; -} - -static void mt7530_core_pll_setup(struct gsw_mt753x *gsw) -{ - u32 hwstrap; - - hwstrap = mt753x_reg_read(gsw, HWSTRAP); - - switch ((hwstrap & XTAL_FSEL_M) >> XTAL_FSEL_S) { - case XTAL_40MHZ: - /* Disable MT7530 core clock */ - mt7530_core_reg_write(gsw, TRGMII_GSW_CLK_CG, 0); - - /* disable MT7530 PLL */ - mt7530_core_reg_write(gsw, CORE_GSWPLL_GCR_1, - (2 << GSWPLL_POSTDIV_200M_S) | - (32 << GSWPLL_FBKDIV_200M_S)); - - /* For MT7530 core clock = 500Mhz */ - mt7530_core_reg_write(gsw, CORE_GSWPLL_GCR_2, - (1 << GSWPLL_POSTDIV_500M_S) | - (25 << GSWPLL_FBKDIV_500M_S)); - - /* Enable MT7530 PLL */ - mt7530_core_reg_write(gsw, CORE_GSWPLL_GCR_1, - (2 << GSWPLL_POSTDIV_200M_S) | - (32 << GSWPLL_FBKDIV_200M_S) | - GSWPLL_EN_PRE); - - usleep_range(20, 40); - - /* Enable MT7530 core clock */ - mt7530_core_reg_write(gsw, TRGMII_GSW_CLK_CG, GSWCK_EN); - break; - default: - /* TODO: PLL settings for 20/25MHz */ - break; - } - - hwstrap = mt753x_reg_read(gsw, HWSTRAP); - hwstrap |= CHG_TRAP; - if (gsw->direct_phy_access) - hwstrap &= ~C_MDIO_BPS_S; - else - hwstrap |= C_MDIO_BPS_S; - - mt753x_reg_write(gsw, MHWSTRAP, hwstrap); - - if (gsw->port6_cfg.enabled && - gsw->port6_cfg.phy_mode == PHY_INTERFACE_MODE_TRGMII) { - mt7530_trgmii_setting(gsw); - } else { - /* RGMII */ - mt7530_rgmii_setting(gsw); - } - - /* delay setting for 10/1000M */ - mt753x_reg_write(gsw, P5RGMIIRXCR, - CSR_RGMII_EDGE_ALIGN | - (2 << CSR_RGMII_RXC_0DEG_CFG_S)); - mt753x_reg_write(gsw, P5RGMIITXCR, 0x14 << CSR_RGMII_TXC_CFG_S); -} - -static int mt7530_sw_detect(struct gsw_mt753x *gsw, struct chip_rev *crev) -{ - u32 rev; - - rev = mt753x_reg_read(gsw, CHIP_REV); - - if (((rev & CHIP_NAME_M) >> CHIP_NAME_S) == MT7530) { - if (crev) { - crev->rev = rev & CHIP_REV_M; - crev->name = "MT7530"; - } - - return 0; - } - - return -ENODEV; -} - -static void mt7530_phy_setting(struct gsw_mt753x *gsw) -{ - int i; - u32 val; - - for (i = 0; i < MT753X_NUM_PHYS; i++) { - /* Disable EEE */ - gsw->mmd_write(gsw, i, PHY_DEV07, PHY_DEV07_REG_03C, 0); - - /* Enable HW auto downshift */ - gsw->mii_write(gsw, i, 0x1f, 0x1); - val = gsw->mii_read(gsw, i, PHY_EXT_REG_14); - val |= PHY_EN_DOWN_SHFIT; - gsw->mii_write(gsw, i, PHY_EXT_REG_14, val); - - /* Increase SlvDPSready time */ - gsw->mii_write(gsw, i, 0x1f, 0x52b5); - gsw->mii_write(gsw, i, PHY_TR_REG_10, 0xafae); - gsw->mii_write(gsw, i, PHY_TR_REG_12, 0x2f); - gsw->mii_write(gsw, i, PHY_TR_REG_10, 0x8fae); - - /* Increase post_update_timer */ - gsw->mii_write(gsw, i, 0x1f, 0x3); - gsw->mii_write(gsw, i, PHY_LPI_REG_11, 0x4b); - gsw->mii_write(gsw, i, 0x1f, 0); - - /* Adjust 100_mse_threshold */ - gsw->mmd_write(gsw, i, PHY_DEV1E, PHY_DEV1E_REG_123, 0xffff); - - /* Disable mcc */ - gsw->mmd_write(gsw, i, PHY_DEV1E, PHY_DEV1E_REG_A6, 0x300); - } -} - -static inline bool get_phy_access_mode(const struct device_node *np) -{ - return of_property_read_bool(np, "mt7530,direct-phy-access"); -} - -static int mt7530_sw_init(struct gsw_mt753x *gsw) -{ - int i; - u32 val; - - gsw->direct_phy_access = get_phy_access_mode(gsw->dev->of_node); - - /* Force MT7530 to use (in)direct PHY access */ - val = mt753x_reg_read(gsw, HWSTRAP); - val |= CHG_TRAP; - if (gsw->direct_phy_access) - val &= ~C_MDIO_BPS_S; - else - val |= C_MDIO_BPS_S; - mt753x_reg_write(gsw, MHWSTRAP, val); - - /* Read PHY address base from HWSTRAP */ - gsw->phy_base = (((val & SMI_ADDR_M) >> SMI_ADDR_S) << 3) + 8; - gsw->phy_base &= MT753X_SMI_ADDR_MASK; - - if (gsw->direct_phy_access) { - gsw->mii_read = mt7530_mii_read; - gsw->mii_write = mt7530_mii_write; - gsw->mmd_read = mt7530_mmd_read; - gsw->mmd_write = mt7530_mmd_write; - } else { - gsw->mii_read = mt753x_mii_read; - gsw->mii_write = mt753x_mii_write; - gsw->mmd_read = mt753x_mmd_ind_read; - gsw->mmd_write = mt753x_mmd_ind_write; - } - - for (i = 0; i < MT753X_NUM_PHYS; i++) { - val = gsw->mii_read(gsw, i, MII_BMCR); - val |= BMCR_PDOWN; - gsw->mii_write(gsw, i, MII_BMCR, val); - } - - /* Force MAC link down before reset */ - mt753x_reg_write(gsw, PMCR(5), FORCE_MODE); - mt753x_reg_write(gsw, PMCR(6), FORCE_MODE); - - /* Switch soft reset */ - /* BUG: sw reset causes gsw int flooding */ - mt753x_reg_write(gsw, SYS_CTRL, SW_PHY_RST | SW_SYS_RST | SW_REG_RST); - usleep_range(10, 20); - - /* global mac control settings configuration */ - mt753x_reg_write(gsw, GMACCR, - LATE_COL_DROP | (15 << MTCC_LMT_S) | - (2 << MAX_RX_JUMBO_S) | RX_PKT_LEN_MAX_JUMBO); - - mt7530_core_pll_setup(gsw); - mt7530_mac_port_setup(gsw); - - return 0; -} - -static int mt7530_sw_post_init(struct gsw_mt753x *gsw) -{ - int i; - u32 val; - - mt7530_phy_setting(gsw); - - for (i = 0; i < MT753X_NUM_PHYS; i++) { - val = gsw->mii_read(gsw, i, MII_BMCR); - val &= ~BMCR_PDOWN; - gsw->mii_write(gsw, i, MII_BMCR, val); - } - - return 0; -} - -struct mt753x_sw_id mt7530_id = { - .model = MT7530, - .detect = mt7530_sw_detect, - .init = mt7530_sw_init, - .post_init = mt7530_sw_post_init -}; diff --git a/target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt7530.h b/target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt7530.h deleted file mode 100644 index 40243d4e5..000000000 --- a/target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt7530.h +++ /dev/null @@ -1,13 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (c) 2018 MediaTek Inc. - */ - -#ifndef _MT7530_H_ -#define _MT7530_H_ - -#include "mt753x.h" - -extern struct mt753x_sw_id mt7530_id; - -#endif /* _MT7530_H_ */ diff --git a/target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt7531.c b/target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt7531.c deleted file mode 100644 index 7ebf09c10..000000000 --- a/target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt7531.c +++ /dev/null @@ -1,918 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2018 MediaTek Inc. - * Author: Zhanguo Ju - */ - -#include -#include -#include - -#include "mt753x.h" -#include "mt753x_regs.h" - -/* MT7531 registers */ -#define SGMII_REG_BASE 0x5000 -#define SGMII_REG_PORT_BASE 0x1000 -#define SGMII_REG(p, r) (SGMII_REG_BASE + \ - (p) * SGMII_REG_PORT_BASE + (r)) -#define PCS_CONTROL_1(p) SGMII_REG(p, 0x00) -#define SGMII_MODE(p) SGMII_REG(p, 0x20) -#define QPHY_PWR_STATE_CTRL(p) SGMII_REG(p, 0xe8) -#define PHYA_CTRL_SIGNAL3(p) SGMII_REG(p, 0x128) - -/* Fields of PCS_CONTROL_1 */ -#define SGMII_LINK_STATUS BIT(18) -#define SGMII_AN_ENABLE BIT(12) -#define SGMII_AN_RESTART BIT(9) - -/* Fields of SGMII_MODE */ -#define SGMII_REMOTE_FAULT_DIS BIT(8) -#define SGMII_IF_MODE_FORCE_DUPLEX BIT(4) -#define SGMII_IF_MODE_FORCE_SPEED_S 0x2 -#define SGMII_IF_MODE_FORCE_SPEED_M 0x0c -#define SGMII_IF_MODE_ADVERT_AN BIT(1) - -/* Values of SGMII_IF_MODE_FORCE_SPEED */ -#define SGMII_IF_MODE_FORCE_SPEED_10 0 -#define SGMII_IF_MODE_FORCE_SPEED_100 1 -#define SGMII_IF_MODE_FORCE_SPEED_1000 2 - -/* Fields of QPHY_PWR_STATE_CTRL */ -#define PHYA_PWD BIT(4) - -/* Fields of PHYA_CTRL_SIGNAL3 */ -#define RG_TPHY_SPEED_S 2 -#define RG_TPHY_SPEED_M 0x0c - -/* Values of RG_TPHY_SPEED */ -#define RG_TPHY_SPEED_1000 0 -#define RG_TPHY_SPEED_2500 1 - -/* Unique fields of (M)HWSTRAP for MT7531 */ -#define XTAL_FSEL_S 7 -#define XTAL_FSEL_M BIT(7) -#define PHY_EN BIT(6) -#define CHG_STRAP BIT(8) - -/* Efuse Register Define */ -#define GBE_EFUSE 0x7bc8 -#define GBE_SEL_EFUSE_EN BIT(0) - -/* PHY ENABLE Register bitmap define */ -#define PHY_DEV1F 0x1f -#define PHY_DEV1F_REG_44 0x44 -#define PHY_DEV1F_REG_104 0x104 -#define PHY_DEV1F_REG_10A 0x10a -#define PHY_DEV1F_REG_10B 0x10b -#define PHY_DEV1F_REG_10C 0x10c -#define PHY_DEV1F_REG_10D 0x10d -#define PHY_DEV1F_REG_268 0x268 -#define PHY_DEV1F_REG_269 0x269 -#define PHY_DEV1F_REG_403 0x403 - -/* Fields of PHY_DEV1F_REG_403 */ -#define GBE_EFUSE_SETTING BIT(3) -#define PHY_EN_BYPASS_MODE BIT(4) -#define POWER_ON_OFF BIT(5) -#define PHY_PLL_M GENMASK(9, 8) -#define PHY_PLL_SEL(x) (((x) << 8) & GENMASK(9, 8)) - -/* PHY EEE Register bitmap of define */ -#define PHY_DEV07 0x07 -#define PHY_DEV07_REG_03C 0x3c - -/* PHY Extend Register 0x14 bitmap of define */ -#define PHY_EXT_REG_14 0x14 - -/* Fields of PHY_EXT_REG_14 */ -#define PHY_EN_DOWN_SHFIT BIT(4) - -/* PHY Extend Register 0x17 bitmap of define */ -#define PHY_EXT_REG_17 0x17 - -/* Fields of PHY_EXT_REG_17 */ -#define PHY_LINKDOWN_POWER_SAVING_EN BIT(4) - -/* PHY Token Ring Register 0x10 bitmap of define */ -#define PHY_TR_REG_10 0x10 - -/* PHY Token Ring Register 0x12 bitmap of define */ -#define PHY_TR_REG_12 0x12 - -/* PHY DEV 0x1e Register bitmap of define */ -#define PHY_DEV1E 0x1e -#define PHY_DEV1E_REG_13 0x13 -#define PHY_DEV1E_REG_14 0x14 -#define PHY_DEV1E_REG_41 0x41 -#define PHY_DEV1E_REG_A6 0xa6 -#define PHY_DEV1E_REG_0C6 0x0c6 -#define PHY_DEV1E_REG_0FE 0x0fe -#define PHY_DEV1E_REG_123 0x123 -#define PHY_DEV1E_REG_189 0x189 - -/* Fields of PHY_DEV1E_REG_0C6 */ -#define PHY_POWER_SAVING_S 8 -#define PHY_POWER_SAVING_M 0x300 -#define PHY_POWER_SAVING_TX 0x0 - -/* Fields of PHY_DEV1E_REG_189 */ -#define DESCRAMBLER_CLEAR_EN 0x1 - -/* Values of XTAL_FSEL_S */ -#define XTAL_40MHZ 0 -#define XTAL_25MHZ 1 - -#define PLLGP_EN 0x7820 -#define EN_COREPLL BIT(2) -#define SW_CLKSW BIT(1) -#define SW_PLLGP BIT(0) - -#define PLLGP_CR0 0x78a8 -#define RG_COREPLL_EN BIT(22) -#define RG_COREPLL_POSDIV_S 23 -#define RG_COREPLL_POSDIV_M 0x3800000 -#define RG_COREPLL_SDM_PCW_S 1 -#define RG_COREPLL_SDM_PCW_M 0x3ffffe -#define RG_COREPLL_SDM_PCW_CHG BIT(0) - -/* TOP Signals Status Register */ -#define TOP_SIG_SR 0x780c -#define PAD_DUAL_SGMII_EN BIT(1) - -/* RGMII and SGMII PLL clock */ -#define ANA_PLLGP_CR2 0x78b0 -#define ANA_PLLGP_CR5 0x78bc - -/* GPIO mode define */ -#define GPIO_MODE_REGS(x) (0x7c0c + (((x) / 8) * 4)) -#define GPIO_MODE_S 4 - -/* GPIO GROUP IOLB SMT0 Control */ -#define SMT0_IOLB 0x7f04 -#define SMT_IOLB_5_SMI_MDC_EN BIT(5) - -/* Unique fields of PMCR for MT7531 */ -#define FORCE_MODE_EEE1G BIT(25) -#define FORCE_MODE_EEE100 BIT(26) -#define FORCE_MODE_TX_FC BIT(27) -#define FORCE_MODE_RX_FC BIT(28) -#define FORCE_MODE_DPX BIT(29) -#define FORCE_MODE_SPD BIT(30) -#define FORCE_MODE_LNK BIT(31) -#define FORCE_MODE BIT(15) - -#define CHIP_REV 0x781C -#define CHIP_NAME_S 16 -#define CHIP_NAME_M 0xffff0000 -#define CHIP_REV_S 0 -#define CHIP_REV_M 0x0f -#define CHIP_REV_E1 0x0 - -#define CLKGEN_CTRL 0x7500 -#define CLK_SKEW_OUT_S 8 -#define CLK_SKEW_OUT_M 0x300 -#define CLK_SKEW_IN_S 6 -#define CLK_SKEW_IN_M 0xc0 -#define RXCLK_NO_DELAY BIT(5) -#define TXCLK_NO_REVERSE BIT(4) -#define GP_MODE_S 1 -#define GP_MODE_M 0x06 -#define GP_CLK_EN BIT(0) - -/* Values of GP_MODE */ -#define GP_MODE_RGMII 0 -#define GP_MODE_MII 1 -#define GP_MODE_REV_MII 2 - -/* Values of CLK_SKEW_IN */ -#define CLK_SKEW_IN_NO_CHANGE 0 -#define CLK_SKEW_IN_DELAY_100PPS 1 -#define CLK_SKEW_IN_DELAY_200PPS 2 -#define CLK_SKEW_IN_REVERSE 3 - -/* Values of CLK_SKEW_OUT */ -#define CLK_SKEW_OUT_NO_CHANGE 0 -#define CLK_SKEW_OUT_DELAY_100PPS 1 -#define CLK_SKEW_OUT_DELAY_200PPS 2 -#define CLK_SKEW_OUT_REVERSE 3 - -/* Proprietory Control Register of Internal Phy device 0x1e */ -#define RXADC_CONTROL_3 0xc2 -#define RXADC_LDO_CONTROL_2 0xd3 - -/* Proprietory Control Register of Internal Phy device 0x1f */ -#define TXVLD_DA_271 0x271 -#define TXVLD_DA_272 0x272 -#define TXVLD_DA_273 0x273 - -/* DSP Channel and NOD_ADDR*/ -#define DSP_CH 0x2 -#define DSP_NOD_ADDR 0xD - -/* gpio pinmux pins and functions define */ -static int gpio_int_pins[] = {0}; -static int gpio_int_funcs[] = {1}; -static int gpio_mdc_pins[] = {11, 20}; -static int gpio_mdc_funcs[] = {2, 2}; -static int gpio_mdio_pins[] = {12, 21}; -static int gpio_mdio_funcs[] = {2, 2}; - -static int mt7531_set_port_sgmii_force_mode(struct gsw_mt753x *gsw, u32 port, - struct mt753x_port_cfg *port_cfg) -{ - u32 speed, port_base, val; - ktime_t timeout; - u32 timeout_us; - - if (port < 5 || port >= MT753X_NUM_PORTS) { - dev_info(gsw->dev, "port %d is not a SGMII port\n", port); - return -EINVAL; - } - - port_base = port - 5; - - switch (port_cfg->speed) { - case MAC_SPD_1000: - speed = RG_TPHY_SPEED_1000; - break; - case MAC_SPD_2500: - speed = RG_TPHY_SPEED_2500; - break; - default: - dev_info(gsw->dev, "invalid SGMII speed idx %d for port %d\n", - port_cfg->speed, port); - - speed = RG_TPHY_SPEED_1000; - } - - /* Step 1: Speed select register setting */ - val = mt753x_reg_read(gsw, PHYA_CTRL_SIGNAL3(port_base)); - val &= ~RG_TPHY_SPEED_M; - val |= speed << RG_TPHY_SPEED_S; - mt753x_reg_write(gsw, PHYA_CTRL_SIGNAL3(port_base), val); - - /* Step 2 : Disable AN */ - val = mt753x_reg_read(gsw, PCS_CONTROL_1(port_base)); - val &= ~SGMII_AN_ENABLE; - mt753x_reg_write(gsw, PCS_CONTROL_1(port_base), val); - - /* Step 3: SGMII force mode setting */ - val = mt753x_reg_read(gsw, SGMII_MODE(port_base)); - val &= ~SGMII_IF_MODE_ADVERT_AN; - val &= ~SGMII_IF_MODE_FORCE_SPEED_M; - val |= SGMII_IF_MODE_FORCE_SPEED_1000 << SGMII_IF_MODE_FORCE_SPEED_S; - val |= SGMII_IF_MODE_FORCE_DUPLEX; - /* For sgmii force mode, 0 is full duplex and 1 is half duplex */ - if (port_cfg->duplex) - val &= ~SGMII_IF_MODE_FORCE_DUPLEX; - - mt753x_reg_write(gsw, SGMII_MODE(port_base), val); - - /* Step 4: XXX: Disable Link partner's AN and set force mode */ - - /* Step 5: XXX: Special setting for PHYA ==> reserved for flexible */ - - /* Step 6 : Release PHYA power down state */ - val = mt753x_reg_read(gsw, QPHY_PWR_STATE_CTRL(port_base)); - val &= ~PHYA_PWD; - mt753x_reg_write(gsw, QPHY_PWR_STATE_CTRL(port_base), val); - - /* Step 7 : Polling SGMII_LINK_STATUS */ - timeout_us = 2000000; - timeout = ktime_add_us(ktime_get(), timeout_us); - while (1) { - val = mt753x_reg_read(gsw, PCS_CONTROL_1(port_base)); - val &= SGMII_LINK_STATUS; - - if (val) - break; - - if (ktime_compare(ktime_get(), timeout) > 0) - return -ETIMEDOUT; - } - - return 0; -} - -static int mt7531_set_port_sgmii_an_mode(struct gsw_mt753x *gsw, u32 port, - struct mt753x_port_cfg *port_cfg) -{ - u32 speed, port_base, val; - ktime_t timeout; - u32 timeout_us; - - if (port < 5 || port >= MT753X_NUM_PORTS) { - dev_info(gsw->dev, "port %d is not a SGMII port\n", port); - return -EINVAL; - } - - port_base = port - 5; - - switch (port_cfg->speed) { - case MAC_SPD_1000: - speed = RG_TPHY_SPEED_1000; - break; - case MAC_SPD_2500: - speed = RG_TPHY_SPEED_2500; - break; - default: - dev_info(gsw->dev, "invalid SGMII speed idx %d for port %d\n", - port_cfg->speed, port); - - speed = RG_TPHY_SPEED_1000; - } - - /* Step 1: Speed select register setting */ - val = mt753x_reg_read(gsw, PHYA_CTRL_SIGNAL3(port_base)); - val &= ~RG_TPHY_SPEED_M; - val |= speed << RG_TPHY_SPEED_S; - mt753x_reg_write(gsw, PHYA_CTRL_SIGNAL3(port_base), val); - - /* Step 2: Remote fault disable */ - val = mt753x_reg_read(gsw, SGMII_MODE(port)); - val |= SGMII_REMOTE_FAULT_DIS; - mt753x_reg_write(gsw, SGMII_MODE(port), val); - - /* Step 3: Setting Link partner's AN enable = 1 */ - - /* Step 4: Setting Link partner's device ability for speed/duplex */ - - /* Step 5: AN re-start */ - val = mt753x_reg_read(gsw, PCS_CONTROL_1(port)); - val |= SGMII_AN_RESTART; - mt753x_reg_write(gsw, PCS_CONTROL_1(port), val); - - /* Step 6: Special setting for PHYA ==> reserved for flexible */ - - /* Step 7 : Polling SGMII_LINK_STATUS */ - timeout_us = 2000000; - timeout = ktime_add_us(ktime_get(), timeout_us); - while (1) { - val = mt753x_reg_read(gsw, PCS_CONTROL_1(port_base)); - val &= SGMII_LINK_STATUS; - - if (val) - break; - - if (ktime_compare(ktime_get(), timeout) > 0) - return -ETIMEDOUT; - } - - return 0; -} - -static int mt7531_set_port_rgmii(struct gsw_mt753x *gsw, u32 port) -{ - u32 val; - - if (port != 5) { - dev_info(gsw->dev, "RGMII mode is not available for port %d\n", - port); - return -EINVAL; - } - - val = mt753x_reg_read(gsw, CLKGEN_CTRL); - val |= GP_CLK_EN; - val &= ~GP_MODE_M; - val |= GP_MODE_RGMII << GP_MODE_S; - val |= TXCLK_NO_REVERSE; - val |= RXCLK_NO_DELAY; - val &= ~CLK_SKEW_IN_M; - val |= CLK_SKEW_IN_NO_CHANGE << CLK_SKEW_IN_S; - val &= ~CLK_SKEW_OUT_M; - val |= CLK_SKEW_OUT_NO_CHANGE << CLK_SKEW_OUT_S; - mt753x_reg_write(gsw, CLKGEN_CTRL, val); - - return 0; -} - -static int mt7531_mac_port_setup(struct gsw_mt753x *gsw, u32 port, - struct mt753x_port_cfg *port_cfg) -{ - u32 pmcr; - u32 speed; - - if (port < 5 || port >= MT753X_NUM_PORTS) { - dev_info(gsw->dev, "port %d is not a MAC port\n", port); - return -EINVAL; - } - - if (port_cfg->enabled) { - pmcr = (IPG_96BIT_WITH_SHORT_IPG << IPG_CFG_S) | - MAC_MODE | MAC_TX_EN | MAC_RX_EN | - BKOFF_EN | BACKPR_EN; - - if (port_cfg->force_link) { - /* PMCR's speed field 0x11 is reserved, - * sw should set 0x10 - */ - speed = port_cfg->speed; - if (port_cfg->speed == MAC_SPD_2500) - speed = MAC_SPD_1000; - - pmcr |= FORCE_MODE_LNK | FORCE_LINK | - FORCE_MODE_SPD | FORCE_MODE_DPX | - FORCE_MODE_RX_FC | FORCE_MODE_TX_FC | - FORCE_RX_FC | FORCE_TX_FC | - (speed << FORCE_SPD_S); - - if (port_cfg->duplex) - pmcr |= FORCE_DPX; - } - } else { - pmcr = FORCE_MODE_LNK; - } - - switch (port_cfg->phy_mode) { - case PHY_INTERFACE_MODE_RGMII: - mt7531_set_port_rgmii(gsw, port); - break; - case PHY_INTERFACE_MODE_SGMII: - if (port_cfg->force_link) - mt7531_set_port_sgmii_force_mode(gsw, port, port_cfg); - else - mt7531_set_port_sgmii_an_mode(gsw, port, port_cfg); - break; - default: - if (port_cfg->enabled) - dev_info(gsw->dev, "%s is not supported by port %d\n", - phy_modes(port_cfg->phy_mode), port); - - pmcr = FORCE_MODE_LNK; - } - - mt753x_reg_write(gsw, PMCR(port), pmcr); - - return 0; -} - -static void mt7531_core_pll_setup(struct gsw_mt753x *gsw) -{ - u32 hwstrap; - u32 val; - - val = mt753x_reg_read(gsw, TOP_SIG_SR); - if (val & PAD_DUAL_SGMII_EN) - return; - - hwstrap = mt753x_reg_read(gsw, HWSTRAP); - - switch ((hwstrap & XTAL_FSEL_M) >> XTAL_FSEL_S) { - case XTAL_25MHZ: - /* Step 1 : Disable MT7531 COREPLL */ - val = mt753x_reg_read(gsw, PLLGP_EN); - val &= ~EN_COREPLL; - mt753x_reg_write(gsw, PLLGP_EN, val); - - /* Step 2: switch to XTAL output */ - val = mt753x_reg_read(gsw, PLLGP_EN); - val |= SW_CLKSW; - mt753x_reg_write(gsw, PLLGP_EN, val); - - val = mt753x_reg_read(gsw, PLLGP_CR0); - val &= ~RG_COREPLL_EN; - mt753x_reg_write(gsw, PLLGP_CR0, val); - - /* Step 3: disable PLLGP and enable program PLLGP */ - val = mt753x_reg_read(gsw, PLLGP_EN); - val |= SW_PLLGP; - mt753x_reg_write(gsw, PLLGP_EN, val); - - /* Step 4: program COREPLL output frequency to 500MHz */ - val = mt753x_reg_read(gsw, PLLGP_CR0); - val &= ~RG_COREPLL_POSDIV_M; - val |= 2 << RG_COREPLL_POSDIV_S; - mt753x_reg_write(gsw, PLLGP_CR0, val); - usleep_range(25, 35); - - val = mt753x_reg_read(gsw, PLLGP_CR0); - val &= ~RG_COREPLL_SDM_PCW_M; - val |= 0x140000 << RG_COREPLL_SDM_PCW_S; - mt753x_reg_write(gsw, PLLGP_CR0, val); - - /* Set feedback divide ratio update signal to high */ - val = mt753x_reg_read(gsw, PLLGP_CR0); - val |= RG_COREPLL_SDM_PCW_CHG; - mt753x_reg_write(gsw, PLLGP_CR0, val); - /* Wait for at least 16 XTAL clocks */ - usleep_range(10, 20); - - /* Step 5: set feedback divide ratio update signal to low */ - val = mt753x_reg_read(gsw, PLLGP_CR0); - val &= ~RG_COREPLL_SDM_PCW_CHG; - mt753x_reg_write(gsw, PLLGP_CR0, val); - - /* Enable 325M clock for SGMII */ - mt753x_reg_write(gsw, ANA_PLLGP_CR5, 0xad0000); - - /* Enable 250SSC clock for RGMII */ - mt753x_reg_write(gsw, ANA_PLLGP_CR2, 0x4f40000); - - /* Step 6: Enable MT7531 PLL */ - val = mt753x_reg_read(gsw, PLLGP_CR0); - val |= RG_COREPLL_EN; - mt753x_reg_write(gsw, PLLGP_CR0, val); - - val = mt753x_reg_read(gsw, PLLGP_EN); - val |= EN_COREPLL; - mt753x_reg_write(gsw, PLLGP_EN, val); - usleep_range(25, 35); - - break; - case XTAL_40MHZ: - /* Step 1 : Disable MT7531 COREPLL */ - val = mt753x_reg_read(gsw, PLLGP_EN); - val &= ~EN_COREPLL; - mt753x_reg_write(gsw, PLLGP_EN, val); - - /* Step 2: switch to XTAL output */ - val = mt753x_reg_read(gsw, PLLGP_EN); - val |= SW_CLKSW; - mt753x_reg_write(gsw, PLLGP_EN, val); - - val = mt753x_reg_read(gsw, PLLGP_CR0); - val &= ~RG_COREPLL_EN; - mt753x_reg_write(gsw, PLLGP_CR0, val); - - /* Step 3: disable PLLGP and enable program PLLGP */ - val = mt753x_reg_read(gsw, PLLGP_EN); - val |= SW_PLLGP; - mt753x_reg_write(gsw, PLLGP_EN, val); - - /* Step 4: program COREPLL output frequency to 500MHz */ - val = mt753x_reg_read(gsw, PLLGP_CR0); - val &= ~RG_COREPLL_POSDIV_M; - val |= 2 << RG_COREPLL_POSDIV_S; - mt753x_reg_write(gsw, PLLGP_CR0, val); - usleep_range(25, 35); - - val = mt753x_reg_read(gsw, PLLGP_CR0); - val &= ~RG_COREPLL_SDM_PCW_M; - val |= 0x190000 << RG_COREPLL_SDM_PCW_S; - mt753x_reg_write(gsw, PLLGP_CR0, val); - - /* Set feedback divide ratio update signal to high */ - val = mt753x_reg_read(gsw, PLLGP_CR0); - val |= RG_COREPLL_SDM_PCW_CHG; - mt753x_reg_write(gsw, PLLGP_CR0, val); - /* Wait for at least 16 XTAL clocks */ - usleep_range(10, 20); - - /* Step 5: set feedback divide ratio update signal to low */ - val = mt753x_reg_read(gsw, PLLGP_CR0); - val &= ~RG_COREPLL_SDM_PCW_CHG; - mt753x_reg_write(gsw, PLLGP_CR0, val); - - /* Enable 325M clock for SGMII */ - mt753x_reg_write(gsw, ANA_PLLGP_CR5, 0xad0000); - - /* Enable 250SSC clock for RGMII */ - mt753x_reg_write(gsw, ANA_PLLGP_CR2, 0x4f40000); - - /* Step 6: Enable MT7531 PLL */ - val = mt753x_reg_read(gsw, PLLGP_CR0); - val |= RG_COREPLL_EN; - mt753x_reg_write(gsw, PLLGP_CR0, val); - - val = mt753x_reg_read(gsw, PLLGP_EN); - val |= EN_COREPLL; - mt753x_reg_write(gsw, PLLGP_EN, val); - usleep_range(25, 35); - break; - } -} - -static int mt7531_internal_phy_calibration(struct gsw_mt753x *gsw) -{ - return 0; -} - -static int mt7531_sw_detect(struct gsw_mt753x *gsw, struct chip_rev *crev) -{ - u32 rev, topsig; - - rev = mt753x_reg_read(gsw, CHIP_REV); - - if (((rev & CHIP_NAME_M) >> CHIP_NAME_S) == MT7531) { - if (crev) { - topsig = mt753x_reg_read(gsw, TOP_SIG_SR); - - crev->rev = rev & CHIP_REV_M; - crev->name = topsig & PAD_DUAL_SGMII_EN ? - "MT7531AE" : "MT7531BE"; - } - - return 0; - } - - return -ENODEV; -} - -static void pinmux_set_mux_7531(struct gsw_mt753x *gsw, u32 pin, u32 mode) -{ - u32 val; - - val = mt753x_reg_read(gsw, GPIO_MODE_REGS(pin)); - val &= ~(0xf << (pin & 7) * GPIO_MODE_S); - val |= mode << (pin & 7) * GPIO_MODE_S; - mt753x_reg_write(gsw, GPIO_MODE_REGS(pin), val); -} - -static int mt7531_set_gpio_pinmux(struct gsw_mt753x *gsw) -{ - u32 group = 0; - struct device_node *np = gsw->dev->of_node; - - /* Set GPIO 0 interrupt mode */ - pinmux_set_mux_7531(gsw, gpio_int_pins[0], gpio_int_funcs[0]); - - of_property_read_u32(np, "mediatek,mdio_master_pinmux", &group); - - /* group = 0: do nothing, 1: 1st group (AE), 2: 2nd group (BE) */ - if (group > 0 && group <= 2) { - group--; - pinmux_set_mux_7531(gsw, gpio_mdc_pins[group], - gpio_mdc_funcs[group]); - pinmux_set_mux_7531(gsw, gpio_mdio_pins[group], - gpio_mdio_funcs[group]); - } - - return 0; -} - -static void mt7531_phy_pll_setup(struct gsw_mt753x *gsw) -{ - u32 hwstrap; - u32 val; - - hwstrap = mt753x_reg_read(gsw, HWSTRAP); - - switch ((hwstrap & XTAL_FSEL_M) >> XTAL_FSEL_S) { - case XTAL_25MHZ: - /* disable pll auto calibration */ - gsw->mmd_write(gsw, 0, PHY_DEV1F, PHY_DEV1F_REG_104, 0x608); - - /* change pll sel */ - val = gsw->mmd_read(gsw, 0, PHY_DEV1F, - PHY_DEV1F_REG_403); - val &= ~(PHY_PLL_M); - val |= PHY_PLL_SEL(3); - gsw->mmd_write(gsw, 0, PHY_DEV1F, PHY_DEV1F_REG_403, val); - - /* set divider ratio */ - gsw->mmd_write(gsw, 0, PHY_DEV1F, - PHY_DEV1F_REG_10A, 0x1009); - - /* set divider ratio */ - gsw->mmd_write(gsw, 0, PHY_DEV1F, PHY_DEV1F_REG_10B, 0x7c6); - - /* capacitance and resistance adjustment */ - gsw->mmd_write(gsw, 0, PHY_DEV1F, - PHY_DEV1F_REG_10C, 0xa8be); - - break; - case XTAL_40MHZ: - /* disable pll auto calibration */ - gsw->mmd_write(gsw, 0, PHY_DEV1F, PHY_DEV1F_REG_104, 0x608); - - /* change pll sel */ - val = gsw->mmd_read(gsw, 0, PHY_DEV1F, - PHY_DEV1F_REG_403); - val &= ~(PHY_PLL_M); - val |= PHY_PLL_SEL(3); - gsw->mmd_write(gsw, 0, PHY_DEV1F, PHY_DEV1F_REG_403, val); - - /* set divider ratio */ - gsw->mmd_write(gsw, 0, PHY_DEV1F, - PHY_DEV1F_REG_10A, 0x1018); - - /* set divider ratio */ - gsw->mmd_write(gsw, 0, PHY_DEV1F, PHY_DEV1F_REG_10B, 0xc676); - - /* capacitance and resistance adjustment */ - gsw->mmd_write(gsw, 0, PHY_DEV1F, - PHY_DEV1F_REG_10C, 0xd8be); - break; - } - - /* power down pll. additional delay is not required via mdio access */ - gsw->mmd_write(gsw, 0, PHY_DEV1F, PHY_DEV1F_REG_10D, 0x10); - - /* power up pll */ - gsw->mmd_write(gsw, 0, PHY_DEV1F, PHY_DEV1F_REG_10D, 0x14); -} - -static void mt7531_phy_setting(struct gsw_mt753x *gsw) -{ - int i; - u32 val; - - /* Adjust DAC TX Delay */ - gsw->mmd_write(gsw, 0, PHY_DEV1F, PHY_DEV1F_REG_44, 0xc0); - - for (i = 0; i < MT753X_NUM_PHYS; i++) { - /* Disable EEE */ - gsw->mmd_write(gsw, i, PHY_DEV07, PHY_DEV07_REG_03C, 0); - - /* Enable HW auto downshift */ - gsw->mii_write(gsw, i, 0x1f, 0x1); - val = gsw->mii_read(gsw, i, PHY_EXT_REG_14); - val |= PHY_EN_DOWN_SHFIT; - gsw->mii_write(gsw, i, PHY_EXT_REG_14, val); - - /* Increase SlvDPSready time */ - gsw->mii_write(gsw, i, 0x1f, 0x52b5); - gsw->mii_write(gsw, i, PHY_TR_REG_10, 0xafae); - gsw->mii_write(gsw, i, PHY_TR_REG_12, 0x2f); - gsw->mii_write(gsw, i, PHY_TR_REG_10, 0x8fae); - gsw->mii_write(gsw, i, 0x1f, 0); - - /* Adjust 100_mse_threshold */ - gsw->mmd_write(gsw, i, PHY_DEV1E, PHY_DEV1E_REG_123, 0xffff); - - /* Disable mcc */ - gsw->mmd_write(gsw, i, PHY_DEV1E, PHY_DEV1E_REG_A6, 0x300); - - /* PHY link down power saving enable */ - val = gsw->mii_read(gsw, i, PHY_EXT_REG_17); - val |= PHY_LINKDOWN_POWER_SAVING_EN; - gsw->mii_write(gsw, i, PHY_EXT_REG_17, val); - - val = gsw->mmd_read(gsw, i, PHY_DEV1E, PHY_DEV1E_REG_0C6); - val &= ~PHY_POWER_SAVING_M; - val |= PHY_POWER_SAVING_TX << PHY_POWER_SAVING_S; - gsw->mmd_write(gsw, i, PHY_DEV1E, PHY_DEV1E_REG_0C6, val); - - /* Set TX Pair delay selection */ - gsw->mmd_write(gsw, i, PHY_DEV1E, PHY_DEV1E_REG_13, 0x404); - gsw->mmd_write(gsw, i, PHY_DEV1E, PHY_DEV1E_REG_14, 0x404); - } -} - -static void mt7531_adjust_line_driving(struct gsw_mt753x *gsw, u32 port) -{ - /* For ADC timing margin window for LDO calibration */ - gsw->mmd_write(gsw, port, PHY_DEV1E, RXADC_LDO_CONTROL_2, 0x2222); - - /* Adjust AD sample timing */ - gsw->mmd_write(gsw, port, PHY_DEV1E, RXADC_CONTROL_3, 0x4444); - - /* Adjust Line driver current for different mode */ - gsw->mmd_write(gsw, port, PHY_DEV1F, TXVLD_DA_271, 0x2ca5); - - /* Adjust Line driver current for different mode */ - gsw->mmd_write(gsw, port, PHY_DEV1F, TXVLD_DA_272, 0xc6b); - - /* Adjust Line driver amplitude for 10BT */ - gsw->mmd_write(gsw, port, PHY_DEV1F, TXVLD_DA_273, 0x3000); - - /* Adjust RX Echo path filter */ - gsw->mmd_write(gsw, port, PHY_DEV1E, PHY_DEV1E_REG_0FE, 0x2); - - /* Adjust RX HVGA bias current */ - gsw->mmd_write(gsw, port, PHY_DEV1E, PHY_DEV1E_REG_41, 0x3333); - - /* Adjust TX class AB driver 1 */ - gsw->mmd_write(gsw, port, PHY_DEV1F, PHY_DEV1F_REG_268, 0x388); - - /* Adjust TX class AB driver 2 */ - gsw->mmd_write(gsw, port, PHY_DEV1F, PHY_DEV1F_REG_269, 0x4448); -} - -static void mt7531_eee_setting(struct gsw_mt753x *gsw, u32 port) -{ - u32 tr_reg_control; - u32 val; - - /* Disable generate signal to clear the scramble_lock when lpi mode */ - val = gsw->mmd_read(gsw, port, PHY_DEV1E, PHY_DEV1E_REG_189); - val &= ~DESCRAMBLER_CLEAR_EN; - gsw->mmd_write(gsw, port, PHY_DEV1E, PHY_DEV1E_REG_189, val); - - /* roll back CR*/ - gsw->mii_write(gsw, port, 0x1f, 0x52b5); - gsw->mmd_write(gsw, port, 0x1e, 0x2d1, 0); - tr_reg_control = (1 << 15) | (0 << 13) | (DSP_CH << 11) | - (DSP_NOD_ADDR << 7) | (0x8 << 1); - gsw->mii_write(gsw, port, 17, 0x1b); - gsw->mii_write(gsw, port, 18, 0); - gsw->mii_write(gsw, port, 16, tr_reg_control); - tr_reg_control = (1 << 15) | (0 << 13) | (DSP_CH << 11) | - (DSP_NOD_ADDR << 7) | (0xf << 1); - gsw->mii_write(gsw, port, 17, 0); - gsw->mii_write(gsw, port, 18, 0); - gsw->mii_write(gsw, port, 16, tr_reg_control); - - tr_reg_control = (1 << 15) | (0 << 13) | (DSP_CH << 11) | - (DSP_NOD_ADDR << 7) | (0x10 << 1); - gsw->mii_write(gsw, port, 17, 0x500); - gsw->mii_write(gsw, port, 18, 0); - gsw->mii_write(gsw, port, 16, tr_reg_control); - gsw->mii_write(gsw, port, 0x1f, 0); -} - -static int mt7531_sw_init(struct gsw_mt753x *gsw) -{ - int i; - u32 val; - - gsw->phy_base = (gsw->smi_addr + 1) & MT753X_SMI_ADDR_MASK; - - gsw->mii_read = mt753x_mii_read; - gsw->mii_write = mt753x_mii_write; - gsw->mmd_read = mt753x_mmd_read; - gsw->mmd_write = mt753x_mmd_write; - - for (i = 0; i < MT753X_NUM_PHYS; i++) { - val = gsw->mii_read(gsw, i, MII_BMCR); - val |= BMCR_ISOLATE; - gsw->mii_write(gsw, i, MII_BMCR, val); - } - - /* Force MAC link down before reset */ - mt753x_reg_write(gsw, PMCR(5), FORCE_MODE_LNK); - mt753x_reg_write(gsw, PMCR(6), FORCE_MODE_LNK); - - /* Switch soft reset */ - mt753x_reg_write(gsw, SYS_CTRL, SW_SYS_RST | SW_REG_RST); - usleep_range(10, 20); - - /* Enable MDC input Schmitt Trigger */ - val = mt753x_reg_read(gsw, SMT0_IOLB); - mt753x_reg_write(gsw, SMT0_IOLB, val | SMT_IOLB_5_SMI_MDC_EN); - - /* Set 7531 gpio pinmux */ - mt7531_set_gpio_pinmux(gsw); - - /* Global mac control settings */ - mt753x_reg_write(gsw, GMACCR, - (15 << MTCC_LMT_S) | (11 << MAX_RX_JUMBO_S) | - RX_PKT_LEN_MAX_JUMBO); - - mt7531_core_pll_setup(gsw); - mt7531_mac_port_setup(gsw, 5, &gsw->port5_cfg); - mt7531_mac_port_setup(gsw, 6, &gsw->port6_cfg); - - return 0; -} - -static int mt7531_sw_post_init(struct gsw_mt753x *gsw) -{ - int i; - u32 val; - - mt7531_phy_pll_setup(gsw); - - /* Internal PHYs are disabled by default. SW should enable them. - * Note that this may already be enabled in bootloader stage. - */ - val = gsw->mmd_read(gsw, 0, PHY_DEV1F, PHY_DEV1F_REG_403); - val |= PHY_EN_BYPASS_MODE; - val &= ~POWER_ON_OFF; - gsw->mmd_write(gsw, 0, PHY_DEV1F, PHY_DEV1F_REG_403, val); - - mt7531_phy_setting(gsw); - - for (i = 0; i < MT753X_NUM_PHYS; i++) { - val = gsw->mii_read(gsw, i, MII_BMCR); - val &= ~BMCR_ISOLATE; - gsw->mii_write(gsw, i, MII_BMCR, val); - } - - for (i = 0; i < MT753X_NUM_PHYS; i++) - mt7531_adjust_line_driving(gsw, i); - - for (i = 0; i < MT753X_NUM_PHYS; i++) - mt7531_eee_setting(gsw, i); - - val = mt753x_reg_read(gsw, CHIP_REV); - val &= CHIP_REV_M; - if (val == CHIP_REV_E1) { - mt7531_internal_phy_calibration(gsw); - } else { - val = mt753x_reg_read(gsw, GBE_EFUSE); - if (val & GBE_SEL_EFUSE_EN) { - val = gsw->mmd_read(gsw, 0, PHY_DEV1F, - PHY_DEV1F_REG_403); - val &= ~GBE_EFUSE_SETTING; - gsw->mmd_write(gsw, 0, PHY_DEV1F, PHY_DEV1F_REG_403, - val); - } else { - mt7531_internal_phy_calibration(gsw); - } - } - - return 0; -} - -struct mt753x_sw_id mt7531_id = { - .model = MT7531, - .detect = mt7531_sw_detect, - .init = mt7531_sw_init, - .post_init = mt7531_sw_post_init -}; - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Zhanguo Ju "); -MODULE_DESCRIPTION("Driver for MediaTek MT753x Gigabit Switch"); diff --git a/target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt7531.h b/target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt7531.h deleted file mode 100644 index 52c8a49fd..000000000 --- a/target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt7531.h +++ /dev/null @@ -1,13 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (c) 2018 MediaTek Inc. - */ - -#ifndef _MT7531_H_ -#define _MT7531_H_ - -#include "mt753x.h" - -extern struct mt753x_sw_id mt7531_id; - -#endif /* _MT7531_H_ */ diff --git a/target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt753x.h b/target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt753x.h deleted file mode 100644 index 27cd6f4f1..000000000 --- a/target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt753x.h +++ /dev/null @@ -1,213 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (c) 2018 MediaTek Inc. - * Author: Weijie Gao - */ - -#ifndef _MT753X_H_ -#define _MT753X_H_ - -#include -#include -#include -#include -#include -#include - -#ifdef CONFIG_SWCONFIG -#include -#endif - -#include "mt753x_vlan.h" - -#define MT753X_DFL_CPU_PORT 6 -#define MT753X_NUM_PHYS 5 - -#define MT753X_DFL_SMI_ADDR 0x1f -#define MT753X_SMI_ADDR_MASK 0x1f - -struct gsw_mt753x; - -enum mt753x_model { - MT7530 = 0x7530, - MT7531 = 0x7531 -}; - -struct mt753x_port_cfg { - struct device_node *np; - phy_interface_t phy_mode; - u32 enabled: 1; - u32 force_link: 1; - u32 speed: 2; - u32 duplex: 1; -}; - -struct mt753x_phy { - struct gsw_mt753x *gsw; - struct net_device netdev; - struct phy_device *phydev; -}; - -struct gsw_mt753x { - u32 id; - - struct device *dev; - struct mii_bus *host_bus; - struct mii_bus *gphy_bus; - struct mutex mii_lock; /* MII access lock */ - u32 smi_addr; - u32 phy_base; - int direct_phy_access; - - enum mt753x_model model; - const char *name; - - struct mt753x_port_cfg port5_cfg; - struct mt753x_port_cfg port6_cfg; - - int phy_status_poll; - struct mt753x_phy phys[MT753X_NUM_PHYS]; - - int phy_link_sts; - - int irq; - int reset_pin; - struct work_struct irq_worker; - -#ifdef CONFIG_SWCONFIG - struct switch_dev swdev; - u32 cpu_port; -#endif - - int global_vlan_enable; - struct mt753x_vlan_entry vlan_entries[MT753X_NUM_VLANS]; - struct mt753x_port_entry port_entries[MT753X_NUM_PORTS]; - - int (*mii_read)(struct gsw_mt753x *gsw, int phy, int reg); - void (*mii_write)(struct gsw_mt753x *gsw, int phy, int reg, u16 val); - - int (*mmd_read)(struct gsw_mt753x *gsw, int addr, int devad, u16 reg); - void (*mmd_write)(struct gsw_mt753x *gsw, int addr, int devad, u16 reg, - u16 val); - - struct list_head list; -}; - -struct chip_rev { - const char *name; - u32 rev; -}; - -struct mt753x_sw_id { - enum mt753x_model model; - int (*detect)(struct gsw_mt753x *gsw, struct chip_rev *crev); - int (*init)(struct gsw_mt753x *gsw); - int (*post_init)(struct gsw_mt753x *gsw); -}; - -extern struct list_head mt753x_devs; - -struct gsw_mt753x *mt753x_get_gsw(u32 id); -struct gsw_mt753x *mt753x_get_first_gsw(void); -void mt753x_put_gsw(void); -void mt753x_lock_gsw(void); - -u32 mt753x_reg_read(struct gsw_mt753x *gsw, u32 reg); -void mt753x_reg_write(struct gsw_mt753x *gsw, u32 reg, u32 val); - -int mt753x_mii_read(struct gsw_mt753x *gsw, int phy, int reg); -void mt753x_mii_write(struct gsw_mt753x *gsw, int phy, int reg, u16 val); - -int mt753x_mmd_read(struct gsw_mt753x *gsw, int addr, int devad, u16 reg); -void mt753x_mmd_write(struct gsw_mt753x *gsw, int addr, int devad, u16 reg, - u16 val); - -int mt753x_mmd_ind_read(struct gsw_mt753x *gsw, int addr, int devad, u16 reg); -void mt753x_mmd_ind_write(struct gsw_mt753x *gsw, int addr, int devad, u16 reg, - u16 val); - -void mt753x_irq_worker(struct work_struct *work); -void mt753x_irq_enable(struct gsw_mt753x *gsw); - -/* MDIO Indirect Access Registers */ -#define MII_MMD_ACC_CTL_REG 0x0d -#define MMD_CMD_S 14 -#define MMD_CMD_M 0xc000 -#define MMD_DEVAD_S 0 -#define MMD_DEVAD_M 0x1f - -/* MMD_CMD: MMD commands */ -#define MMD_ADDR 0 -#define MMD_DATA 1 - -#define MII_MMD_ADDR_DATA_REG 0x0e - -/* Procedure of MT753x Internal Register Access - * - * 1. Internal Register Address - * - * The MT753x has a 16-bit register address and each register is 32-bit. - * This means the lowest two bits are not used as the register address is - * 4-byte aligned. - * - * Rest of the valid bits are divided into two parts: - * Bit 15..6 is the Page address - * Bit 5..2 is the low address - * - * ------------------------------------------------------------------- - * | 15 14 13 12 11 10 9 8 7 6 | 5 4 3 2 | 1 0 | - * |----------------------------------------|---------------|--------| - * | Page Address | Address | Unused | - * ------------------------------------------------------------------- - * - * 2. MDIO access timing - * - * The MT753x uses the following MDIO timing for a single register read - * - * Phase 1: Write Page Address - * ------------------------------------------------------------------- - * | ST | OP | PHY_ADDR | TYPE | RSVD | TA | RSVD | PAGE_ADDR | - * ------------------------------------------------------------------- - * | 01 | 01 | 11111 | 1 | 1111 | xx | 00000 | REG_ADDR[15..6] | - * ------------------------------------------------------------------- - * - * Phase 2: Write low Address & Read low word - * ------------------------------------------------------------------- - * | ST | OP | PHY_ADDR | TYPE | LOW_ADDR | TA | DATA | - * ------------------------------------------------------------------- - * | 01 | 10 | 11111 | 0 | REG_ADDR[5..2] | xx | DATA[15..0] | - * ------------------------------------------------------------------- - * - * Phase 3: Read high word - * ------------------------------------------------------------------- - * | ST | OP | PHY_ADDR | TYPE | RSVD | TA | DATA | - * ------------------------------------------------------------------- - * | 01 | 10 | 11111 | 1 | 0000 | xx | DATA[31..16] | - * ------------------------------------------------------------------- - * - * The MT753x uses the following MDIO timing for a single register write - * - * Phase 1: Write Page Address (The same as read) - * - * Phase 2: Write low Address and low word - * ------------------------------------------------------------------- - * | ST | OP | PHY_ADDR | TYPE | LOW_ADDR | TA | DATA | - * ------------------------------------------------------------------- - * | 01 | 01 | 11111 | 0 | REG_ADDR[5..2] | xx | DATA[15..0] | - * ------------------------------------------------------------------- - * - * Phase 3: write high word - * ------------------------------------------------------------------- - * | ST | OP | PHY_ADDR | TYPE | RSVD | TA | DATA | - * ------------------------------------------------------------------- - * | 01 | 01 | 11111 | 1 | 0000 | xx | DATA[31..16] | - * ------------------------------------------------------------------- - * - */ - -/* Internal Register Address fields */ -#define MT753X_REG_PAGE_ADDR_S 6 -#define MT753X_REG_PAGE_ADDR_M 0xffc0 -#define MT753X_REG_ADDR_S 2 -#define MT753X_REG_ADDR_M 0x3c -#endif /* _MT753X_H_ */ diff --git a/target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt753x_common.c b/target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt753x_common.c deleted file mode 100644 index 4015ddf12..000000000 --- a/target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt753x_common.c +++ /dev/null @@ -1,90 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2018 MediaTek Inc. - * Author: Weijie Gao - */ - -#include -#include - -#include "mt753x.h" -#include "mt753x_regs.h" - -void mt753x_irq_enable(struct gsw_mt753x *gsw) -{ - u32 val; - int i; - - /* Record initial PHY link status */ - for (i = 0; i < MT753X_NUM_PHYS; i++) { - val = gsw->mii_read(gsw, i, MII_BMSR); - if (val & BMSR_LSTATUS) - gsw->phy_link_sts |= BIT(i); - } - - val = BIT(MT753X_NUM_PHYS) - 1; - - mt753x_reg_write(gsw, SYS_INT_EN, val); -} - -static void display_port_link_status(struct gsw_mt753x *gsw, u32 port) -{ - u32 pmsr, speed_bits; - const char *speed; - - pmsr = mt753x_reg_read(gsw, PMSR(port)); - - speed_bits = (pmsr & MAC_SPD_STS_M) >> MAC_SPD_STS_S; - - switch (speed_bits) { - case MAC_SPD_10: - speed = "10Mbps"; - break; - case MAC_SPD_100: - speed = "100Mbps"; - break; - case MAC_SPD_1000: - speed = "1Gbps"; - break; - case MAC_SPD_2500: - speed = "2.5Gbps"; - break; - } - - if (pmsr & MAC_LNK_STS) { - dev_info(gsw->dev, "Port %d Link is Up - %s/%s\n", - port, speed, (pmsr & MAC_DPX_STS) ? "Full" : "Half"); - } else { - dev_info(gsw->dev, "Port %d Link is Down\n", port); - } -} - -void mt753x_irq_worker(struct work_struct *work) -{ - struct gsw_mt753x *gsw; - u32 sts, physts, laststs; - int i; - - gsw = container_of(work, struct gsw_mt753x, irq_worker); - - sts = mt753x_reg_read(gsw, SYS_INT_STS); - - /* Check for changed PHY link status */ - for (i = 0; i < MT753X_NUM_PHYS; i++) { - if (!(sts & PHY_LC_INT(i))) - continue; - - laststs = gsw->phy_link_sts & BIT(i); - physts = !!(gsw->mii_read(gsw, i, MII_BMSR) & BMSR_LSTATUS); - physts <<= i; - - if (physts ^ laststs) { - gsw->phy_link_sts ^= BIT(i); - display_port_link_status(gsw, i); - } - } - - mt753x_reg_write(gsw, SYS_INT_STS, sts); - - enable_irq(gsw->irq); -} diff --git a/target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt753x_mdio.c b/target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt753x_mdio.c deleted file mode 100644 index 3e2e6d68a..000000000 --- a/target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt753x_mdio.c +++ /dev/null @@ -1,597 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2018 MediaTek Inc. - * Author: Weijie Gao - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "mt753x.h" -#include "mt753x_swconfig.h" -#include "mt753x_regs.h" -#include "mt753x_nl.h" -#include "mt7530.h" -#include "mt7531.h" - -static u32 mt753x_id; -struct list_head mt753x_devs; -static DEFINE_MUTEX(mt753x_devs_lock); - -static struct mt753x_sw_id *mt753x_sw_ids[] = { - &mt7530_id, - &mt7531_id, -}; - -u32 mt753x_reg_read(struct gsw_mt753x *gsw, u32 reg) -{ - u32 high, low; - - mutex_lock(&gsw->host_bus->mdio_lock); - - gsw->host_bus->write(gsw->host_bus, gsw->smi_addr, 0x1f, - (reg & MT753X_REG_PAGE_ADDR_M) >> MT753X_REG_PAGE_ADDR_S); - - low = gsw->host_bus->read(gsw->host_bus, gsw->smi_addr, - (reg & MT753X_REG_ADDR_M) >> MT753X_REG_ADDR_S); - - high = gsw->host_bus->read(gsw->host_bus, gsw->smi_addr, 0x10); - - mutex_unlock(&gsw->host_bus->mdio_lock); - - return (high << 16) | (low & 0xffff); -} - -void mt753x_reg_write(struct gsw_mt753x *gsw, u32 reg, u32 val) -{ - mutex_lock(&gsw->host_bus->mdio_lock); - - gsw->host_bus->write(gsw->host_bus, gsw->smi_addr, 0x1f, - (reg & MT753X_REG_PAGE_ADDR_M) >> MT753X_REG_PAGE_ADDR_S); - - gsw->host_bus->write(gsw->host_bus, gsw->smi_addr, - (reg & MT753X_REG_ADDR_M) >> MT753X_REG_ADDR_S, val & 0xffff); - - gsw->host_bus->write(gsw->host_bus, gsw->smi_addr, 0x10, val >> 16); - - mutex_unlock(&gsw->host_bus->mdio_lock); -} - -/* Indirect MDIO clause 22/45 access */ -static int mt753x_mii_rw(struct gsw_mt753x *gsw, int phy, int reg, u16 data, - u32 cmd, u32 st) -{ - ktime_t timeout; - u32 val, timeout_us; - int ret = 0; - - timeout_us = 100000; - timeout = ktime_add_us(ktime_get(), timeout_us); - while (1) { - val = mt753x_reg_read(gsw, PHY_IAC); - - if ((val & PHY_ACS_ST) == 0) - break; - - if (ktime_compare(ktime_get(), timeout) > 0) - return -ETIMEDOUT; - } - - val = (st << MDIO_ST_S) | - ((cmd << MDIO_CMD_S) & MDIO_CMD_M) | - ((phy << MDIO_PHY_ADDR_S) & MDIO_PHY_ADDR_M) | - ((reg << MDIO_REG_ADDR_S) & MDIO_REG_ADDR_M); - - if (cmd == MDIO_CMD_WRITE || cmd == MDIO_CMD_ADDR) - val |= data & MDIO_RW_DATA_M; - - mt753x_reg_write(gsw, PHY_IAC, val | PHY_ACS_ST); - - timeout_us = 100000; - timeout = ktime_add_us(ktime_get(), timeout_us); - while (1) { - val = mt753x_reg_read(gsw, PHY_IAC); - - if ((val & PHY_ACS_ST) == 0) - break; - - if (ktime_compare(ktime_get(), timeout) > 0) - return -ETIMEDOUT; - } - - if (cmd == MDIO_CMD_READ || cmd == MDIO_CMD_READ_C45) { - val = mt753x_reg_read(gsw, PHY_IAC); - ret = val & MDIO_RW_DATA_M; - } - - return ret; -} - -int mt753x_mii_read(struct gsw_mt753x *gsw, int phy, int reg) -{ - int val; - - if (phy < MT753X_NUM_PHYS) - phy = (gsw->phy_base + phy) & MT753X_SMI_ADDR_MASK; - - mutex_lock(&gsw->mii_lock); - val = mt753x_mii_rw(gsw, phy, reg, 0, MDIO_CMD_READ, MDIO_ST_C22); - mutex_unlock(&gsw->mii_lock); - - return val; -} - -void mt753x_mii_write(struct gsw_mt753x *gsw, int phy, int reg, u16 val) -{ - if (phy < MT753X_NUM_PHYS) - phy = (gsw->phy_base + phy) & MT753X_SMI_ADDR_MASK; - - mutex_lock(&gsw->mii_lock); - mt753x_mii_rw(gsw, phy, reg, val, MDIO_CMD_WRITE, MDIO_ST_C22); - mutex_unlock(&gsw->mii_lock); -} - -int mt753x_mmd_read(struct gsw_mt753x *gsw, int addr, int devad, u16 reg) -{ - int val; - - if (addr < MT753X_NUM_PHYS) - addr = (gsw->phy_base + addr) & MT753X_SMI_ADDR_MASK; - - mutex_lock(&gsw->mii_lock); - mt753x_mii_rw(gsw, addr, devad, reg, MDIO_CMD_ADDR, MDIO_ST_C45); - val = mt753x_mii_rw(gsw, addr, devad, 0, MDIO_CMD_READ_C45, - MDIO_ST_C45); - mutex_unlock(&gsw->mii_lock); - - return val; -} - -void mt753x_mmd_write(struct gsw_mt753x *gsw, int addr, int devad, u16 reg, - u16 val) -{ - if (addr < MT753X_NUM_PHYS) - addr = (gsw->phy_base + addr) & MT753X_SMI_ADDR_MASK; - - mutex_lock(&gsw->mii_lock); - mt753x_mii_rw(gsw, addr, devad, reg, MDIO_CMD_ADDR, MDIO_ST_C45); - mt753x_mii_rw(gsw, addr, devad, val, MDIO_CMD_WRITE, MDIO_ST_C45); - mutex_unlock(&gsw->mii_lock); -} - -int mt753x_mmd_ind_read(struct gsw_mt753x *gsw, int addr, int devad, u16 reg) -{ - u16 val; - - if (addr < MT753X_NUM_PHYS) - addr = (gsw->phy_base + addr) & MT753X_SMI_ADDR_MASK; - - mutex_lock(&gsw->mii_lock); - - mt753x_mii_rw(gsw, addr, MII_MMD_ACC_CTL_REG, - (MMD_ADDR << MMD_CMD_S) | - ((devad << MMD_DEVAD_S) & MMD_DEVAD_M), - MDIO_CMD_WRITE, MDIO_ST_C22); - - mt753x_mii_rw(gsw, addr, MII_MMD_ADDR_DATA_REG, reg, - MDIO_CMD_WRITE, MDIO_ST_C22); - - mt753x_mii_rw(gsw, addr, MII_MMD_ACC_CTL_REG, - (MMD_DATA << MMD_CMD_S) | - ((devad << MMD_DEVAD_S) & MMD_DEVAD_M), - MDIO_CMD_WRITE, MDIO_ST_C22); - - val = mt753x_mii_rw(gsw, addr, MII_MMD_ADDR_DATA_REG, 0, - MDIO_CMD_READ, MDIO_ST_C22); - - mutex_unlock(&gsw->mii_lock); - - return val; -} - -void mt753x_mmd_ind_write(struct gsw_mt753x *gsw, int addr, int devad, u16 reg, - u16 val) -{ - if (addr < MT753X_NUM_PHYS) - addr = (gsw->phy_base + addr) & MT753X_SMI_ADDR_MASK; - - mutex_lock(&gsw->mii_lock); - - mt753x_mii_rw(gsw, addr, MII_MMD_ACC_CTL_REG, - (MMD_ADDR << MMD_CMD_S) | - ((devad << MMD_DEVAD_S) & MMD_DEVAD_M), - MDIO_CMD_WRITE, MDIO_ST_C22); - - mt753x_mii_rw(gsw, addr, MII_MMD_ADDR_DATA_REG, reg, - MDIO_CMD_WRITE, MDIO_ST_C22); - - mt753x_mii_rw(gsw, addr, MII_MMD_ACC_CTL_REG, - (MMD_DATA << MMD_CMD_S) | - ((devad << MMD_DEVAD_S) & MMD_DEVAD_M), - MDIO_CMD_WRITE, MDIO_ST_C22); - - mt753x_mii_rw(gsw, addr, MII_MMD_ADDR_DATA_REG, val, - MDIO_CMD_WRITE, MDIO_ST_C22); - - mutex_unlock(&gsw->mii_lock); -} - -static inline int mt753x_get_duplex(const struct device_node *np) -{ - return of_property_read_bool(np, "full-duplex"); -} - -static void mt753x_load_port_cfg(struct gsw_mt753x *gsw) -{ - struct device_node *port_np; - struct device_node *fixed_link_node; - struct mt753x_port_cfg *port_cfg; - u32 port; - - for_each_child_of_node(gsw->dev->of_node, port_np) { - if (!of_device_is_compatible(port_np, "mediatek,mt753x-port")) - continue; - - if (!of_device_is_available(port_np)) - continue; - - if (of_property_read_u32(port_np, "reg", &port)) - continue; - - switch (port) { - case 5: - port_cfg = &gsw->port5_cfg; - break; - case 6: - port_cfg = &gsw->port6_cfg; - break; - default: - continue; - } - - if (port_cfg->enabled) { - dev_info(gsw->dev, "duplicated node for port%d\n", - port_cfg->phy_mode); - continue; - } - - port_cfg->np = port_np; - - if (of_get_phy_mode(port_np, &port_cfg->phy_mode) < 0) { - dev_info(gsw->dev, "incorrect phy-mode %d\n", port); - continue; - } - - fixed_link_node = of_get_child_by_name(port_np, "fixed-link"); - if (fixed_link_node) { - u32 speed; - - port_cfg->force_link = 1; - port_cfg->duplex = mt753x_get_duplex(fixed_link_node); - - if (of_property_read_u32(fixed_link_node, "speed", - &speed)) { - speed = 0; - continue; - } - - of_node_put(fixed_link_node); - - switch (speed) { - case 10: - port_cfg->speed = MAC_SPD_10; - break; - case 100: - port_cfg->speed = MAC_SPD_100; - break; - case 1000: - port_cfg->speed = MAC_SPD_1000; - break; - case 2500: - port_cfg->speed = MAC_SPD_2500; - break; - default: - dev_info(gsw->dev, "incorrect speed %d\n", - speed); - continue; - } - } - - port_cfg->enabled = 1; - } -} - -static void mt753x_add_gsw(struct gsw_mt753x *gsw) -{ - mutex_lock(&mt753x_devs_lock); - gsw->id = mt753x_id++; - INIT_LIST_HEAD(&gsw->list); - list_add_tail(&gsw->list, &mt753x_devs); - mutex_unlock(&mt753x_devs_lock); -} - -static void mt753x_remove_gsw(struct gsw_mt753x *gsw) -{ - mutex_lock(&mt753x_devs_lock); - list_del(&gsw->list); - mutex_unlock(&mt753x_devs_lock); -} - - -struct gsw_mt753x *mt753x_get_gsw(u32 id) -{ - struct gsw_mt753x *dev; - - mutex_lock(&mt753x_devs_lock); - - list_for_each_entry(dev, &mt753x_devs, list) { - if (dev->id == id) - return dev; - } - - mutex_unlock(&mt753x_devs_lock); - - return NULL; -} - -struct gsw_mt753x *mt753x_get_first_gsw(void) -{ - struct gsw_mt753x *dev; - - mutex_lock(&mt753x_devs_lock); - - list_for_each_entry(dev, &mt753x_devs, list) - return dev; - - mutex_unlock(&mt753x_devs_lock); - - return NULL; -} - -void mt753x_put_gsw(void) -{ - mutex_unlock(&mt753x_devs_lock); -} - -void mt753x_lock_gsw(void) -{ - mutex_lock(&mt753x_devs_lock); -} - -static int mt753x_hw_reset(struct gsw_mt753x *gsw) -{ - struct device_node *np = gsw->dev->of_node; - struct reset_control *rstc; - int mcm; - int ret = -EINVAL; - - mcm = of_property_read_bool(np, "mediatek,mcm"); - if (mcm) { - rstc = devm_reset_control_get(gsw->dev, "mcm"); - ret = IS_ERR(rstc); - if (IS_ERR(rstc)) { - dev_err(gsw->dev, "Missing reset ctrl of switch\n"); - return ret; - } - - reset_control_assert(rstc); - msleep(30); - reset_control_deassert(rstc); - - gsw->reset_pin = -1; - return 0; - } - - gsw->reset_pin = of_get_named_gpio(np, "reset-gpios", 0); - if (gsw->reset_pin < 0) { - dev_err(gsw->dev, "Missing reset pin of switch\n"); - return ret; - } - - ret = devm_gpio_request(gsw->dev, gsw->reset_pin, "mt753x-reset"); - if (ret) { - dev_info(gsw->dev, "Failed to request gpio %d\n", - gsw->reset_pin); - return ret; - } - - gpio_direction_output(gsw->reset_pin, 0); - msleep(30); - gpio_set_value(gsw->reset_pin, 1); - msleep(500); - - return 0; -} - -static irqreturn_t mt753x_irq_handler(int irq, void *dev) -{ - struct gsw_mt753x *gsw = dev; - - disable_irq_nosync(gsw->irq); - - schedule_work(&gsw->irq_worker); - - return IRQ_HANDLED; -} - -static int mt753x_probe(struct platform_device *pdev) -{ - struct gsw_mt753x *gsw; - struct mt753x_sw_id *sw; - struct device_node *np = pdev->dev.of_node; - struct device_node *mdio; - struct mii_bus *mdio_bus; - int ret = -EINVAL; - struct chip_rev rev; - struct mt753x_mapping *map; - int i; - - mdio = of_parse_phandle(np, "mediatek,mdio", 0); - if (!mdio) - return -EINVAL; - - mdio_bus = of_mdio_find_bus(mdio); - if (!mdio_bus) - return -EPROBE_DEFER; - - gsw = devm_kzalloc(&pdev->dev, sizeof(struct gsw_mt753x), GFP_KERNEL); - if (!gsw) - return -ENOMEM; - - gsw->host_bus = mdio_bus; - gsw->dev = &pdev->dev; - mutex_init(&gsw->mii_lock); - - /* Switch hard reset */ - if (mt753x_hw_reset(gsw)) - goto fail; - - /* Fetch the SMI address dirst */ - if (of_property_read_u32(np, "mediatek,smi-addr", &gsw->smi_addr)) - gsw->smi_addr = MT753X_DFL_SMI_ADDR; - - /* Get LAN/WAN port mapping */ - map = mt753x_find_mapping(np); - if (map) { - mt753x_apply_mapping(gsw, map); - gsw->global_vlan_enable = 1; - dev_info(gsw->dev, "LAN/WAN VLAN setting=%s\n", map->name); - } - - /* Load MAC port configurations */ - mt753x_load_port_cfg(gsw); - - /* Check for valid switch and then initialize */ - for (i = 0; i < ARRAY_SIZE(mt753x_sw_ids); i++) { - if (!mt753x_sw_ids[i]->detect(gsw, &rev)) { - sw = mt753x_sw_ids[i]; - - gsw->name = rev.name; - gsw->model = sw->model; - - dev_info(gsw->dev, "Switch is MediaTek %s rev %d", - gsw->name, rev.rev); - - /* Initialize the switch */ - ret = sw->init(gsw); - if (ret) - goto fail; - - break; - } - } - - if (i >= ARRAY_SIZE(mt753x_sw_ids)) { - dev_err(gsw->dev, "No mt753x switch found\n"); - goto fail; - } - - gsw->irq = platform_get_irq(pdev, 0); - if (gsw->irq >= 0) { - ret = devm_request_irq(gsw->dev, gsw->irq, mt753x_irq_handler, - 0, dev_name(gsw->dev), gsw); - if (ret) { - dev_err(gsw->dev, "Failed to request irq %d\n", - gsw->irq); - goto fail; - } - - INIT_WORK(&gsw->irq_worker, mt753x_irq_worker); - } - - platform_set_drvdata(pdev, gsw); - - gsw->phy_status_poll = of_property_read_bool(gsw->dev->of_node, - "mediatek,phy-poll"); - - mt753x_add_gsw(gsw); - - mt753x_swconfig_init(gsw); - - if (sw->post_init) - sw->post_init(gsw); - - if (gsw->irq >= 0) - mt753x_irq_enable(gsw); - - return 0; - -fail: - devm_kfree(&pdev->dev, gsw); - - return ret; -} - -static int mt753x_remove(struct platform_device *pdev) -{ - struct gsw_mt753x *gsw = platform_get_drvdata(pdev); - - if (gsw->irq >= 0) - cancel_work_sync(&gsw->irq_worker); - - if (gsw->reset_pin >= 0) - devm_gpio_free(&pdev->dev, gsw->reset_pin); - -#ifdef CONFIG_SWCONFIG - mt753x_swconfig_destroy(gsw); -#endif - - mt753x_remove_gsw(gsw); - - platform_set_drvdata(pdev, NULL); - - return 0; -} - -static const struct of_device_id mt753x_ids[] = { - { .compatible = "mediatek,mt753x" }, - { }, -}; - -MODULE_DEVICE_TABLE(of, mt753x_ids); - -static struct platform_driver mt753x_driver = { - .probe = mt753x_probe, - .remove = mt753x_remove, - .driver = { - .name = "mt753x", - .of_match_table = mt753x_ids, - }, -}; - -static int __init mt753x_init(void) -{ - int ret; - - INIT_LIST_HEAD(&mt753x_devs); - ret = platform_driver_register(&mt753x_driver); - - mt753x_nl_init(); - - return ret; -} -module_init(mt753x_init); - -static void __exit mt753x_exit(void) -{ - mt753x_nl_exit(); - - platform_driver_unregister(&mt753x_driver); -} -module_exit(mt753x_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Weijie Gao "); -MODULE_DESCRIPTION("Driver for MediaTek MT753x Gigabit Switch"); diff --git a/target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt753x_nl.c b/target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt753x_nl.c deleted file mode 100644 index ccde2c920..000000000 --- a/target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt753x_nl.c +++ /dev/null @@ -1,382 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2018 MediaTek Inc. - * Author: Sirui Zhao - */ - -#include -#include -#include -#include -#include - -#include "mt753x.h" -#include "mt753x_nl.h" - -struct mt753x_nl_cmd_item { - enum mt753x_cmd cmd; - bool require_dev; - int (*process)(struct genl_info *info, struct gsw_mt753x *gsw); - u32 nr_required_attrs; - const enum mt753x_attr *required_attrs; -}; - -static int mt753x_nl_response(struct sk_buff *skb, struct genl_info *info); - -/* -static const struct nla_policy mt753x_nl_cmd_policy[] = { - [MT753X_ATTR_TYPE_MESG] = { .type = NLA_STRING }, - [MT753X_ATTR_TYPE_PHY] = { .type = NLA_S32 }, - [MT753X_ATTR_TYPE_REG] = { .type = NLA_S32 }, - [MT753X_ATTR_TYPE_VAL] = { .type = NLA_S32 }, - [MT753X_ATTR_TYPE_DEV_NAME] = { .type = NLA_S32 }, - [MT753X_ATTR_TYPE_DEV_ID] = { .type = NLA_S32 }, - [MT753X_ATTR_TYPE_DEVAD] = { .type = NLA_S32 }, -}; -*/ - -static const struct genl_ops mt753x_nl_ops[] = { - { - .cmd = MT753X_CMD_REQUEST, - .doit = mt753x_nl_response, -// .policy = mt753x_nl_cmd_policy, - .flags = GENL_ADMIN_PERM, - }, { - .cmd = MT753X_CMD_READ, - .doit = mt753x_nl_response, -// .policy = mt753x_nl_cmd_policy, - .flags = GENL_ADMIN_PERM, - }, { - .cmd = MT753X_CMD_WRITE, - .doit = mt753x_nl_response, -// .policy = mt753x_nl_cmd_policy, - .flags = GENL_ADMIN_PERM, - }, -}; - -static struct genl_family mt753x_nl_family = { - .name = MT753X_GENL_NAME, - .version = MT753X_GENL_VERSION, - .maxattr = MT753X_NR_ATTR_TYPE, - .ops = mt753x_nl_ops, - .n_ops = ARRAY_SIZE(mt753x_nl_ops), -}; - -static int mt753x_nl_list_devs(char *buff, int size) -{ - struct gsw_mt753x *gsw; - int len, total = 0; - char buf[80]; - - memset(buff, 0, size); - - mt753x_lock_gsw(); - - list_for_each_entry(gsw, &mt753x_devs, list) { - len = snprintf(buf, sizeof(buf), - "id: %d, model: %s, node: %s\n", - gsw->id, gsw->name, gsw->dev->of_node->name); - strncat(buff, buf, size - total); - total += len; - } - - mt753x_put_gsw(); - - return total; -} - -static int mt753x_nl_prepare_reply(struct genl_info *info, u8 cmd, - struct sk_buff **skbp) -{ - struct sk_buff *msg; - void *reply; - - if (!info) - return -EINVAL; - - msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); - if (!msg) - return -ENOMEM; - - /* Construct send-back message header */ - reply = genlmsg_put(msg, info->snd_portid, info->snd_seq, - &mt753x_nl_family, 0, cmd); - if (!reply) { - nlmsg_free(msg); - return -EINVAL; - } - - *skbp = msg; - return 0; -} - -static int mt753x_nl_send_reply(struct sk_buff *skb, struct genl_info *info) -{ - struct genlmsghdr *genlhdr = nlmsg_data(nlmsg_hdr(skb)); - void *reply = genlmsg_data(genlhdr); - - /* Finalize a generic netlink message (update message header) */ - genlmsg_end(skb, reply); - - /* reply to a request */ - return genlmsg_reply(skb, info); -} - -static s32 mt753x_nl_get_s32(struct genl_info *info, enum mt753x_attr attr, - s32 defval) -{ - struct nlattr *na; - - na = info->attrs[attr]; - if (na) - return nla_get_s32(na); - - return defval; -} - -static int mt753x_nl_get_u32(struct genl_info *info, enum mt753x_attr attr, - u32 *val) -{ - struct nlattr *na; - - na = info->attrs[attr]; - if (na) { - *val = nla_get_u32(na); - return 0; - } - - return -1; -} - -static struct gsw_mt753x *mt753x_nl_parse_find_gsw(struct genl_info *info) -{ - struct gsw_mt753x *gsw; - struct nlattr *na; - int gsw_id; - - na = info->attrs[MT753X_ATTR_TYPE_DEV_ID]; - if (na) { - gsw_id = nla_get_s32(na); - if (gsw_id >= 0) - gsw = mt753x_get_gsw(gsw_id); - else - gsw = mt753x_get_first_gsw(); - } else { - gsw = mt753x_get_first_gsw(); - } - - return gsw; -} - -static int mt753x_nl_get_swdevs(struct genl_info *info, struct gsw_mt753x *gsw) -{ - struct sk_buff *rep_skb = NULL; - char dev_info[512]; - int ret; - - ret = mt753x_nl_list_devs(dev_info, sizeof(dev_info)); - if (!ret) { - pr_info("No switch registered\n"); - return -EINVAL; - } - - ret = mt753x_nl_prepare_reply(info, MT753X_CMD_REPLY, &rep_skb); - if (ret < 0) - goto err; - - ret = nla_put_string(rep_skb, MT753X_ATTR_TYPE_MESG, dev_info); - if (ret < 0) - goto err; - - return mt753x_nl_send_reply(rep_skb, info); - -err: - if (rep_skb) - nlmsg_free(rep_skb); - - return ret; -} - -static int mt753x_nl_reply_read(struct genl_info *info, struct gsw_mt753x *gsw) -{ - struct sk_buff *rep_skb = NULL; - s32 phy, devad, reg; - int value; - int ret = 0; - - phy = mt753x_nl_get_s32(info, MT753X_ATTR_TYPE_PHY, -1); - devad = mt753x_nl_get_s32(info, MT753X_ATTR_TYPE_DEVAD, -1); - reg = mt753x_nl_get_s32(info, MT753X_ATTR_TYPE_REG, -1); - - if (reg < 0) - goto err; - - ret = mt753x_nl_prepare_reply(info, MT753X_CMD_READ, &rep_skb); - if (ret < 0) - goto err; - - if (phy >= 0) { - if (devad < 0) - value = gsw->mii_read(gsw, phy, reg); - else - value = gsw->mmd_read(gsw, phy, devad, reg); - } else { - value = mt753x_reg_read(gsw, reg); - } - - ret = nla_put_s32(rep_skb, MT753X_ATTR_TYPE_REG, reg); - if (ret < 0) - goto err; - - ret = nla_put_s32(rep_skb, MT753X_ATTR_TYPE_VAL, value); - if (ret < 0) - goto err; - - return mt753x_nl_send_reply(rep_skb, info); - -err: - if (rep_skb) - nlmsg_free(rep_skb); - - return ret; -} - -static int mt753x_nl_reply_write(struct genl_info *info, struct gsw_mt753x *gsw) -{ - struct sk_buff *rep_skb = NULL; - s32 phy, devad, reg; - u32 value; - int ret = 0; - - phy = mt753x_nl_get_s32(info, MT753X_ATTR_TYPE_PHY, -1); - devad = mt753x_nl_get_s32(info, MT753X_ATTR_TYPE_DEVAD, -1); - reg = mt753x_nl_get_s32(info, MT753X_ATTR_TYPE_REG, -1); - - if (mt753x_nl_get_u32(info, MT753X_ATTR_TYPE_VAL, &value)) - goto err; - - if (reg < 0) - goto err; - - ret = mt753x_nl_prepare_reply(info, MT753X_CMD_WRITE, &rep_skb); - if (ret < 0) - goto err; - - if (phy >= 0) { - if (devad < 0) - gsw->mii_write(gsw, phy, reg, value); - else - gsw->mmd_write(gsw, phy, devad, reg, value); - } else { - mt753x_reg_write(gsw, reg, value); - } - - ret = nla_put_s32(rep_skb, MT753X_ATTR_TYPE_REG, reg); - if (ret < 0) - goto err; - - ret = nla_put_s32(rep_skb, MT753X_ATTR_TYPE_VAL, value); - if (ret < 0) - goto err; - - return mt753x_nl_send_reply(rep_skb, info); - -err: - if (rep_skb) - nlmsg_free(rep_skb); - - return ret; -} - -static const enum mt753x_attr mt753x_nl_cmd_read_attrs[] = { - MT753X_ATTR_TYPE_REG -}; - -static const enum mt753x_attr mt753x_nl_cmd_write_attrs[] = { - MT753X_ATTR_TYPE_REG, - MT753X_ATTR_TYPE_VAL -}; - -static const struct mt753x_nl_cmd_item mt753x_nl_cmds[] = { - { - .cmd = MT753X_CMD_REQUEST, - .require_dev = false, - .process = mt753x_nl_get_swdevs - }, { - .cmd = MT753X_CMD_READ, - .require_dev = true, - .process = mt753x_nl_reply_read, - .required_attrs = mt753x_nl_cmd_read_attrs, - .nr_required_attrs = ARRAY_SIZE(mt753x_nl_cmd_read_attrs), - }, { - .cmd = MT753X_CMD_WRITE, - .require_dev = true, - .process = mt753x_nl_reply_write, - .required_attrs = mt753x_nl_cmd_write_attrs, - .nr_required_attrs = ARRAY_SIZE(mt753x_nl_cmd_write_attrs), - } -}; - -static int mt753x_nl_response(struct sk_buff *skb, struct genl_info *info) -{ - struct genlmsghdr *hdr = nlmsg_data(info->nlhdr); - const struct mt753x_nl_cmd_item *cmditem = NULL; - struct gsw_mt753x *gsw = NULL; - u32 sat_req_attrs = 0; - int i, ret; - - for (i = 0; i < ARRAY_SIZE(mt753x_nl_cmds); i++) { - if (hdr->cmd == mt753x_nl_cmds[i].cmd) { - cmditem = &mt753x_nl_cmds[i]; - break; - } - } - - if (!cmditem) { - pr_info("mt753x-nl: unknown cmd %u\n", hdr->cmd); - return -EINVAL; - } - - for (i = 0; i < cmditem->nr_required_attrs; i++) { - if (info->attrs[cmditem->required_attrs[i]]) - sat_req_attrs++; - } - - if (sat_req_attrs != cmditem->nr_required_attrs) { - pr_info("mt753x-nl: missing required attr(s) for cmd %u\n", - hdr->cmd); - return -EINVAL; - } - - if (cmditem->require_dev) { - gsw = mt753x_nl_parse_find_gsw(info); - if (!gsw) { - pr_info("mt753x-nl: failed to find switch dev\n"); - return -EINVAL; - } - } - - ret = cmditem->process(info, gsw); - - mt753x_put_gsw(); - - return ret; -} - -int __init mt753x_nl_init(void) -{ - int ret; - - ret = genl_register_family(&mt753x_nl_family); - if (ret) { - pr_info("mt753x-nl: genl_register_family_with_ops failed\n"); - return ret; - } - - return 0; -} - -void __exit mt753x_nl_exit(void) -{ - genl_unregister_family(&mt753x_nl_family); -} diff --git a/target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt753x_nl.h b/target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt753x_nl.h deleted file mode 100644 index 85dc9e791..000000000 --- a/target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt753x_nl.h +++ /dev/null @@ -1,43 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (c) 2018 MediaTek Inc. - * Author: Sirui Zhao - */ - -#ifndef _MT753X_NL_H_ -#define _MT753X_NL_H_ - -#define MT753X_GENL_NAME "mt753x" -#define MT753X_GENL_VERSION 0x1 - -enum mt753x_cmd { - MT753X_CMD_UNSPEC = 0, - MT753X_CMD_REQUEST, - MT753X_CMD_REPLY, - MT753X_CMD_READ, - MT753X_CMD_WRITE, - - __MT753X_CMD_MAX, -}; - -enum mt753x_attr { - MT753X_ATTR_TYPE_UNSPEC = 0, - MT753X_ATTR_TYPE_MESG, - MT753X_ATTR_TYPE_PHY, - MT753X_ATTR_TYPE_DEVAD, - MT753X_ATTR_TYPE_REG, - MT753X_ATTR_TYPE_VAL, - MT753X_ATTR_TYPE_DEV_NAME, - MT753X_ATTR_TYPE_DEV_ID, - - __MT753X_ATTR_TYPE_MAX, -}; - -#define MT753X_NR_ATTR_TYPE (__MT753X_ATTR_TYPE_MAX - 1) - -#ifdef __KERNEL__ -int __init mt753x_nl_init(void); -void __exit mt753x_nl_exit(void); -#endif /* __KERNEL__ */ - -#endif /* _MT753X_NL_H_ */ diff --git a/target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt753x_regs.h b/target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt753x_regs.h deleted file mode 100644 index 3f23ae200..000000000 --- a/target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt753x_regs.h +++ /dev/null @@ -1,294 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (c) 2018 MediaTek Inc. - * Author: Weijie Gao - */ - -#ifndef _MT753X_REGS_H_ -#define _MT753X_REGS_H_ - -#include - -/* Values of Egress TAG Control */ -#define ETAG_CTRL_UNTAG 0 -#define ETAG_CTRL_TAG 2 -#define ETAG_CTRL_SWAP 1 -#define ETAG_CTRL_STACK 3 - -#define VTCR 0x90 -#define VAWD1 0x94 -#define VAWD2 0x98 - -/* Fields of VTCR */ -#define VTCR_BUSY BIT(31) -#define IDX_INVLD BIT(16) -#define VTCR_FUNC_S 12 -#define VTCR_FUNC_M 0xf000 -#define VTCR_VID_S 0 -#define VTCR_VID_M 0xfff - -/* Values of VTCR_FUNC */ -#define VTCR_READ_VLAN_ENTRY 0 -#define VTCR_WRITE_VLAN_ENTRY 1 -#define VTCR_INVD_VLAN_ENTRY 2 -#define VTCR_ENABLE_VLAN_ENTRY 3 -#define VTCR_READ_ACL_ENTRY 4 -#define VTCR_WRITE_ACL_ENTRY 5 -#define VTCR_READ_TRTCM_TABLE 6 -#define VTCR_WRITE_TRTCM_TABLE 7 -#define VTCR_READ_ACL_MASK_ENTRY 8 -#define VTCR_WRITE_ACL_MASK_ENTRY 9 -#define VTCR_READ_ACL_RULE_ENTRY 10 -#define VTCR_WRITE_ACL_RULE_ENTRY 11 -#define VTCR_READ_ACL_RATE_ENTRY 12 -#define VTCR_WRITE_ACL_RATE_ENTRY 13 - -/* VLAN entry fields */ -/* VAWD1 */ -#define PORT_STAG BIT(31) -#define IVL_MAC BIT(30) -#define EG_CON BIT(29) -#define VTAG_EN BIT(28) -#define COPY_PRI BIT(27) -#define USER_PRI_S 24 -#define USER_PRI_M 0x7000000 -#define PORT_MEM_S 16 -#define PORT_MEM_M 0xff0000 -#define S_TAG1_S 4 -#define S_TAG1_M 0xfff0 -#define FID_S 1 -#define FID_M 0x0e -#define VENTRY_VALID BIT(0) - -/* VAWD2 */ -#define S_TAG2_S 16 -#define S_TAG2_M 0xffff0000 -#define PORT_ETAG_S(p) ((p) * 2) -#define PORT_ETAG_M 0x03 - -#define PORT_CTRL_BASE 0x2000 -#define PORT_CTRL_PORT_OFFSET 0x100 -#define PORT_CTRL_REG(p, r) (PORT_CTRL_BASE + \ - (p) * PORT_CTRL_PORT_OFFSET + (r)) -#define CKGCR(p) PORT_CTRL_REG(p, 0x00) -#define PCR(p) PORT_CTRL_REG(p, 0x04) -#define PIC(p) PORT_CTRL_REG(p, 0x08) -#define PSC(p) PORT_CTRL_REG(p, 0x0c) -#define PVC(p) PORT_CTRL_REG(p, 0x10) -#define PPBV1(p) PORT_CTRL_REG(p, 0x14) -#define PPBV2(p) PORT_CTRL_REG(p, 0x18) -#define BSR(p) PORT_CTRL_REG(p, 0x1c) -#define STAG01 PORT_CTRL_REG(p, 0x20) -#define STAG23 PORT_CTRL_REG(p, 0x24) -#define STAG45 PORT_CTRL_REG(p, 0x28) -#define STAG67 PORT_CTRL_REG(p, 0x2c) - -#define PPBV(p, g) (PPBV1(p) + ((g) / 2) * 4) - -/* Fields of PCR */ -#define MLDV2_EN BIT(30) -#define EG_TAG_S 28 -#define EG_TAG_M 0x30000000 -#define PORT_PRI_S 24 -#define PORT_PRI_M 0x7000000 -#define PORT_MATRIX_S 16 -#define PORT_MATRIX_M 0xff0000 -#define UP2DSCP_EN BIT(12) -#define UP2TAG_EN BIT(11) -#define ACL_EN BIT(10) -#define PORT_TX_MIR BIT(9) -#define PORT_RX_MIR BIT(8) -#define ACL_MIR BIT(7) -#define MIS_PORT_FW_S 4 -#define MIS_PORT_FW_M 0x70 -#define VLAN_MIS BIT(2) -#define PORT_VLAN_S 0 -#define PORT_VLAN_M 0x03 - -/* Values of PORT_VLAN */ -#define PORT_MATRIX_MODE 0 -#define FALLBACK_MODE 1 -#define CHECK_MODE 2 -#define SECURITY_MODE 3 - -/* Fields of PVC */ -#define STAG_VPID_S 16 -#define STAG_VPID_M 0xffff0000 -#define DIS_PVID BIT(15) -#define FORCE_PVID BIT(14) -#define PT_VPM BIT(12) -#define PT_OPTION BIT(11) -#define PVC_EG_TAG_S 8 -#define PVC_EG_TAG_M 0x700 -#define VLAN_ATTR_S 6 -#define VLAN_ATTR_M 0xc0 -#define PVC_PORT_STAG BIT(5) -#define BC_LKYV_EN BIT(4) -#define MC_LKYV_EN BIT(3) -#define UC_LKYV_EN BIT(2) -#define ACC_FRM_S 0 -#define ACC_FRM_M 0x03 - -/* Values of VLAN_ATTR */ -#define VA_USER_PORT 0 -#define VA_STACK_PORT 1 -#define VA_TRANSLATION_PORT 2 -#define VA_TRANSPARENT_PORT 3 - -/* Fields of PPBV */ -#define GRP_PORT_PRI_S(g) (((g) % 2) * 16 + 13) -#define GRP_PORT_PRI_M 0x07 -#define GRP_PORT_VID_S(g) (((g) % 2) * 16) -#define GRP_PORT_VID_M 0xfff - -#define PORT_MAC_CTRL_BASE 0x3000 -#define PORT_MAC_CTRL_PORT_OFFSET 0x100 -#define PORT_MAC_CTRL_REG(p, r) (PORT_MAC_CTRL_BASE + \ - (p) * PORT_MAC_CTRL_PORT_OFFSET + (r)) -#define PMCR(p) PORT_MAC_CTRL_REG(p, 0x00) -#define PMEEECR(p) PORT_MAC_CTRL_REG(p, 0x04) -#define PMSR(p) PORT_MAC_CTRL_REG(p, 0x08) -#define PINT_EN(p) PORT_MAC_CTRL_REG(p, 0x10) -#define PINT_STS(p) PORT_MAC_CTRL_REG(p, 0x14) - -#define GMACCR (PORT_MAC_CTRL_BASE + 0xe0) -#define TXCRC_EN BIT(19) -#define RXCRC_EN BIT(18) -#define PRMBL_LMT_EN BIT(17) -#define MTCC_LMT_S 9 -#define MTCC_LMT_M 0x1e00 -#define MAX_RX_JUMBO_S 2 -#define MAX_RX_JUMBO_M 0x3c -#define MAX_RX_PKT_LEN_S 0 -#define MAX_RX_PKT_LEN_M 0x3 - -/* Values of MAX_RX_PKT_LEN */ -#define RX_PKT_LEN_1518 0 -#define RX_PKT_LEN_1536 1 -#define RX_PKT_LEN_1522 2 -#define RX_PKT_LEN_MAX_JUMBO 3 - -/* Fields of PMCR */ -#define IPG_CFG_S 18 -#define IPG_CFG_M 0xc0000 -#define EXT_PHY BIT(17) -#define MAC_MODE BIT(16) -#define MAC_TX_EN BIT(14) -#define MAC_RX_EN BIT(13) -#define MAC_PRE BIT(11) -#define BKOFF_EN BIT(9) -#define BACKPR_EN BIT(8) -#define FORCE_EEE1G BIT(7) -#define FORCE_EEE1000 BIT(6) -#define FORCE_RX_FC BIT(5) -#define FORCE_TX_FC BIT(4) -#define FORCE_SPD_S 2 -#define FORCE_SPD_M 0x0c -#define FORCE_DPX BIT(1) -#define FORCE_LINK BIT(0) - -/* Fields of PMSR */ -#define EEE1G_STS BIT(7) -#define EEE100_STS BIT(6) -#define RX_FC_STS BIT(5) -#define TX_FC_STS BIT(4) -#define MAC_SPD_STS_S 2 -#define MAC_SPD_STS_M 0x0c -#define MAC_DPX_STS BIT(1) -#define MAC_LNK_STS BIT(0) - -/* Values of MAC_SPD_STS */ -#define MAC_SPD_10 0 -#define MAC_SPD_100 1 -#define MAC_SPD_1000 2 -#define MAC_SPD_2500 3 - -/* Values of IPG_CFG */ -#define IPG_96BIT 0 -#define IPG_96BIT_WITH_SHORT_IPG 1 -#define IPG_64BIT 2 - -#define MIB_COUNTER_BASE 0x4000 -#define MIB_COUNTER_PORT_OFFSET 0x100 -#define MIB_COUNTER_REG(p, r) (MIB_COUNTER_BASE + \ - (p) * MIB_COUNTER_PORT_OFFSET + (r)) -#define STATS_TDPC 0x00 -#define STATS_TCRC 0x04 -#define STATS_TUPC 0x08 -#define STATS_TMPC 0x0C -#define STATS_TBPC 0x10 -#define STATS_TCEC 0x14 -#define STATS_TSCEC 0x18 -#define STATS_TMCEC 0x1C -#define STATS_TDEC 0x20 -#define STATS_TLCEC 0x24 -#define STATS_TXCEC 0x28 -#define STATS_TPPC 0x2C -#define STATS_TL64PC 0x30 -#define STATS_TL65PC 0x34 -#define STATS_TL128PC 0x38 -#define STATS_TL256PC 0x3C -#define STATS_TL512PC 0x40 -#define STATS_TL1024PC 0x44 -#define STATS_TOC 0x48 -#define STATS_RDPC 0x60 -#define STATS_RFPC 0x64 -#define STATS_RUPC 0x68 -#define STATS_RMPC 0x6C -#define STATS_RBPC 0x70 -#define STATS_RAEPC 0x74 -#define STATS_RCEPC 0x78 -#define STATS_RUSPC 0x7C -#define STATS_RFEPC 0x80 -#define STATS_ROSPC 0x84 -#define STATS_RJEPC 0x88 -#define STATS_RPPC 0x8C -#define STATS_RL64PC 0x90 -#define STATS_RL65PC 0x94 -#define STATS_RL128PC 0x98 -#define STATS_RL256PC 0x9C -#define STATS_RL512PC 0xA0 -#define STATS_RL1024PC 0xA4 -#define STATS_ROC 0xA8 -#define STATS_RDPC_CTRL 0xB0 -#define STATS_RDPC_ING 0xB4 -#define STATS_RDPC_ARL 0xB8 - -#define SYS_CTRL 0x7000 -#define SW_PHY_RST BIT(2) -#define SW_SYS_RST BIT(1) -#define SW_REG_RST BIT(0) - -#define SYS_INT_EN 0x7008 -#define SYS_INT_STS 0x700c -#define MAC_PC_INT BIT(16) -#define PHY_INT(p) BIT((p) + 8) -#define PHY_LC_INT(p) BIT(p) - -#define PHY_IAC 0x701c -#define PHY_ACS_ST BIT(31) -#define MDIO_REG_ADDR_S 25 -#define MDIO_REG_ADDR_M 0x3e000000 -#define MDIO_PHY_ADDR_S 20 -#define MDIO_PHY_ADDR_M 0x1f00000 -#define MDIO_CMD_S 18 -#define MDIO_CMD_M 0xc0000 -#define MDIO_ST_S 16 -#define MDIO_ST_M 0x30000 -#define MDIO_RW_DATA_S 0 -#define MDIO_RW_DATA_M 0xffff - -/* MDIO_CMD: MDIO commands */ -#define MDIO_CMD_ADDR 0 -#define MDIO_CMD_WRITE 1 -#define MDIO_CMD_READ 2 -#define MDIO_CMD_READ_C45 3 - -/* MDIO_ST: MDIO start field */ -#define MDIO_ST_C45 0 -#define MDIO_ST_C22 1 - -#define HWSTRAP 0x7800 -#define MHWSTRAP 0x7804 - -#endif /* _MT753X_REGS_H_ */ diff --git a/target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt753x_swconfig.c b/target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt753x_swconfig.c deleted file mode 100644 index 342ad576b..000000000 --- a/target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt753x_swconfig.c +++ /dev/null @@ -1,510 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2018 MediaTek Inc. - * Author: Weijie Gao - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "mt753x.h" -#include "mt753x_swconfig.h" -#include "mt753x_regs.h" - -#define MT753X_PORT_MIB_TXB_ID 18 /* TxByte */ -#define MT753X_PORT_MIB_RXB_ID 37 /* RxByte */ - -#define MIB_DESC(_s, _o, _n) \ - { \ - .size = (_s), \ - .offset = (_o), \ - .name = (_n), \ - } - -struct mt753x_mib_desc { - unsigned int size; - unsigned int offset; - const char *name; -}; - -static const struct mt753x_mib_desc mt753x_mibs[] = { - MIB_DESC(1, STATS_TDPC, "TxDrop"), - MIB_DESC(1, STATS_TCRC, "TxCRC"), - MIB_DESC(1, STATS_TUPC, "TxUni"), - MIB_DESC(1, STATS_TMPC, "TxMulti"), - MIB_DESC(1, STATS_TBPC, "TxBroad"), - MIB_DESC(1, STATS_TCEC, "TxCollision"), - MIB_DESC(1, STATS_TSCEC, "TxSingleCol"), - MIB_DESC(1, STATS_TMCEC, "TxMultiCol"), - MIB_DESC(1, STATS_TDEC, "TxDefer"), - MIB_DESC(1, STATS_TLCEC, "TxLateCol"), - MIB_DESC(1, STATS_TXCEC, "TxExcCol"), - MIB_DESC(1, STATS_TPPC, "TxPause"), - MIB_DESC(1, STATS_TL64PC, "Tx64Byte"), - MIB_DESC(1, STATS_TL65PC, "Tx65Byte"), - MIB_DESC(1, STATS_TL128PC, "Tx128Byte"), - MIB_DESC(1, STATS_TL256PC, "Tx256Byte"), - MIB_DESC(1, STATS_TL512PC, "Tx512Byte"), - MIB_DESC(1, STATS_TL1024PC, "Tx1024Byte"), - MIB_DESC(2, STATS_TOC, "TxByte"), - MIB_DESC(1, STATS_RDPC, "RxDrop"), - MIB_DESC(1, STATS_RFPC, "RxFiltered"), - MIB_DESC(1, STATS_RUPC, "RxUni"), - MIB_DESC(1, STATS_RMPC, "RxMulti"), - MIB_DESC(1, STATS_RBPC, "RxBroad"), - MIB_DESC(1, STATS_RAEPC, "RxAlignErr"), - MIB_DESC(1, STATS_RCEPC, "RxCRC"), - MIB_DESC(1, STATS_RUSPC, "RxUnderSize"), - MIB_DESC(1, STATS_RFEPC, "RxFragment"), - MIB_DESC(1, STATS_ROSPC, "RxOverSize"), - MIB_DESC(1, STATS_RJEPC, "RxJabber"), - MIB_DESC(1, STATS_RPPC, "RxPause"), - MIB_DESC(1, STATS_RL64PC, "Rx64Byte"), - MIB_DESC(1, STATS_RL65PC, "Rx65Byte"), - MIB_DESC(1, STATS_RL128PC, "Rx128Byte"), - MIB_DESC(1, STATS_RL256PC, "Rx256Byte"), - MIB_DESC(1, STATS_RL512PC, "Rx512Byte"), - MIB_DESC(1, STATS_RL1024PC, "Rx1024Byte"), - MIB_DESC(2, STATS_ROC, "RxByte"), - MIB_DESC(1, STATS_RDPC_CTRL, "RxCtrlDrop"), - MIB_DESC(1, STATS_RDPC_ING, "RxIngDrop"), - MIB_DESC(1, STATS_RDPC_ARL, "RxARLDrop") -}; - -enum { - /* Global attributes. */ - MT753X_ATTR_ENABLE_VLAN, -}; - -static int mt753x_get_vlan_enable(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct gsw_mt753x *gsw = container_of(dev, struct gsw_mt753x, swdev); - - val->value.i = gsw->global_vlan_enable; - - return 0; -} - -static int mt753x_set_vlan_enable(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct gsw_mt753x *gsw = container_of(dev, struct gsw_mt753x, swdev); - - gsw->global_vlan_enable = val->value.i != 0; - - return 0; -} - -static int mt753x_get_port_pvid(struct switch_dev *dev, int port, int *val) -{ - struct gsw_mt753x *gsw = container_of(dev, struct gsw_mt753x, swdev); - - if (port >= MT753X_NUM_PORTS) - return -EINVAL; - - *val = mt753x_reg_read(gsw, PPBV1(port)); - *val &= GRP_PORT_VID_M; - - return 0; -} - -static int mt753x_set_port_pvid(struct switch_dev *dev, int port, int pvid) -{ - struct gsw_mt753x *gsw = container_of(dev, struct gsw_mt753x, swdev); - - if (port >= MT753X_NUM_PORTS) - return -EINVAL; - - if (pvid < MT753X_MIN_VID || pvid > MT753X_MAX_VID) - return -EINVAL; - - gsw->port_entries[port].pvid = pvid; - - return 0; -} - -static int mt753x_get_vlan_ports(struct switch_dev *dev, struct switch_val *val) -{ - struct gsw_mt753x *gsw = container_of(dev, struct gsw_mt753x, swdev); - u32 member; - u32 etags; - int i; - - val->len = 0; - - if (val->port_vlan < 0 || val->port_vlan >= MT753X_NUM_VLANS) - return -EINVAL; - - mt753x_vlan_ctrl(gsw, VTCR_READ_VLAN_ENTRY, val->port_vlan); - - member = mt753x_reg_read(gsw, VAWD1); - member &= PORT_MEM_M; - member >>= PORT_MEM_S; - - etags = mt753x_reg_read(gsw, VAWD2); - - for (i = 0; i < MT753X_NUM_PORTS; i++) { - struct switch_port *p; - int etag; - - if (!(member & BIT(i))) - continue; - - p = &val->value.ports[val->len++]; - p->id = i; - - etag = (etags >> PORT_ETAG_S(i)) & PORT_ETAG_M; - - if (etag == ETAG_CTRL_TAG) - p->flags |= BIT(SWITCH_PORT_FLAG_TAGGED); - else if (etag != ETAG_CTRL_UNTAG) - dev_info(gsw->dev, - "vlan egress tag control neither untag nor tag.\n"); - } - - return 0; -} - -static int mt753x_set_vlan_ports(struct switch_dev *dev, struct switch_val *val) -{ - struct gsw_mt753x *gsw = container_of(dev, struct gsw_mt753x, swdev); - u8 member = 0; - u8 etags = 0; - int i; - - if (val->port_vlan < 0 || val->port_vlan >= MT753X_NUM_VLANS || - val->len > MT753X_NUM_PORTS) - return -EINVAL; - - for (i = 0; i < val->len; i++) { - struct switch_port *p = &val->value.ports[i]; - - if (p->id >= MT753X_NUM_PORTS) - return -EINVAL; - - member |= BIT(p->id); - - if (p->flags & BIT(SWITCH_PORT_FLAG_TAGGED)) - etags |= BIT(p->id); - } - - gsw->vlan_entries[val->port_vlan].member = member; - gsw->vlan_entries[val->port_vlan].etags = etags; - - return 0; -} - -static int mt753x_set_vid(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct gsw_mt753x *gsw = container_of(dev, struct gsw_mt753x, swdev); - int vlan; - u16 vid; - - vlan = val->port_vlan; - vid = (u16)val->value.i; - - if (vlan < 0 || vlan >= MT753X_NUM_VLANS) - return -EINVAL; - - if (vid < MT753X_MIN_VID || vid > MT753X_MAX_VID) - return -EINVAL; - - gsw->vlan_entries[vlan].vid = vid; - return 0; -} - -static int mt753x_get_vid(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - val->value.i = val->port_vlan; - return 0; -} - -static int mt753x_get_port_link(struct switch_dev *dev, int port, - struct switch_port_link *link) -{ - struct gsw_mt753x *gsw = container_of(dev, struct gsw_mt753x, swdev); - u32 speed, pmsr; - - if (port < 0 || port >= MT753X_NUM_PORTS) - return -EINVAL; - - pmsr = mt753x_reg_read(gsw, PMSR(port)); - - link->link = pmsr & MAC_LNK_STS; - link->duplex = pmsr & MAC_DPX_STS; - speed = (pmsr & MAC_SPD_STS_M) >> MAC_SPD_STS_S; - - switch (speed) { - case MAC_SPD_10: - link->speed = SWITCH_PORT_SPEED_10; - break; - case MAC_SPD_100: - link->speed = SWITCH_PORT_SPEED_100; - break; - case MAC_SPD_1000: - link->speed = SWITCH_PORT_SPEED_1000; - break; - case MAC_SPD_2500: - /* TODO: swconfig has no support for 2500 now */ - link->speed = SWITCH_PORT_SPEED_UNKNOWN; - break; - } - - return 0; -} - -static int mt753x_set_port_link(struct switch_dev *dev, int port, - struct switch_port_link *link) -{ -#ifndef MODULE - if (port >= MT753X_NUM_PHYS) - return -EINVAL; - - return switch_generic_set_link(dev, port, link); -#else - return -ENOTSUPP; -#endif -} - -static u64 get_mib_counter(struct gsw_mt753x *gsw, int i, int port) -{ - unsigned int offset; - u64 lo, hi, hi2; - - offset = mt753x_mibs[i].offset; - - if (mt753x_mibs[i].size == 1) - return mt753x_reg_read(gsw, MIB_COUNTER_REG(port, offset)); - - do { - hi = mt753x_reg_read(gsw, MIB_COUNTER_REG(port, offset + 4)); - lo = mt753x_reg_read(gsw, MIB_COUNTER_REG(port, offset)); - hi2 = mt753x_reg_read(gsw, MIB_COUNTER_REG(port, offset + 4)); - } while (hi2 != hi); - - return (hi << 32) | lo; -} - -static int mt753x_get_port_mib(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - static char buf[4096]; - struct gsw_mt753x *gsw = container_of(dev, struct gsw_mt753x, swdev); - int i, len = 0; - - if (val->port_vlan >= MT753X_NUM_PORTS) - return -EINVAL; - - len += snprintf(buf + len, sizeof(buf) - len, - "Port %d MIB counters\n", val->port_vlan); - - for (i = 0; i < ARRAY_SIZE(mt753x_mibs); ++i) { - u64 counter; - - len += snprintf(buf + len, sizeof(buf) - len, - "%-11s: ", mt753x_mibs[i].name); - counter = get_mib_counter(gsw, i, val->port_vlan); - len += snprintf(buf + len, sizeof(buf) - len, "%llu\n", - counter); - } - - val->value.s = buf; - val->len = len; - return 0; -} - -static int mt753x_get_port_stats(struct switch_dev *dev, int port, - struct switch_port_stats *stats) -{ - struct gsw_mt753x *gsw = container_of(dev, struct gsw_mt753x, swdev); - - if (port < 0 || port >= MT753X_NUM_PORTS) - return -EINVAL; - - stats->tx_bytes = get_mib_counter(gsw, MT753X_PORT_MIB_TXB_ID, port); - stats->rx_bytes = get_mib_counter(gsw, MT753X_PORT_MIB_RXB_ID, port); - - return 0; -} - -static void mt753x_port_isolation(struct gsw_mt753x *gsw) -{ - int i; - - for (i = 0; i < MT753X_NUM_PORTS; i++) - mt753x_reg_write(gsw, PCR(i), - BIT(gsw->cpu_port) << PORT_MATRIX_S); - - mt753x_reg_write(gsw, PCR(gsw->cpu_port), PORT_MATRIX_M); - - for (i = 0; i < MT753X_NUM_PORTS; i++) - mt753x_reg_write(gsw, PVC(i), - (0x8100 << STAG_VPID_S) | - (VA_TRANSPARENT_PORT << VLAN_ATTR_S)); -} - -static int mt753x_apply_config(struct switch_dev *dev) -{ - struct gsw_mt753x *gsw = container_of(dev, struct gsw_mt753x, swdev); - - if (!gsw->global_vlan_enable) { - mt753x_port_isolation(gsw); - return 0; - } - - mt753x_apply_vlan_config(gsw); - - return 0; -} - -static int mt753x_reset_switch(struct switch_dev *dev) -{ - struct gsw_mt753x *gsw = container_of(dev, struct gsw_mt753x, swdev); - int i; - - memset(gsw->port_entries, 0, sizeof(gsw->port_entries)); - memset(gsw->vlan_entries, 0, sizeof(gsw->vlan_entries)); - - /* set default vid of each vlan to the same number of vlan, so the vid - * won't need be set explicitly. - */ - for (i = 0; i < MT753X_NUM_VLANS; i++) - gsw->vlan_entries[i].vid = i; - - return 0; -} - -static int mt753x_phy_read16(struct switch_dev *dev, int addr, u8 reg, - u16 *value) -{ - struct gsw_mt753x *gsw = container_of(dev, struct gsw_mt753x, swdev); - - *value = gsw->mii_read(gsw, addr, reg); - - return 0; -} - -static int mt753x_phy_write16(struct switch_dev *dev, int addr, u8 reg, - u16 value) -{ - struct gsw_mt753x *gsw = container_of(dev, struct gsw_mt753x, swdev); - - gsw->mii_write(gsw, addr, reg, value); - - return 0; -} - -static const struct switch_attr mt753x_global[] = { - { - .type = SWITCH_TYPE_INT, - .name = "enable_vlan", - .description = "VLAN mode (1:enabled)", - .max = 1, - .id = MT753X_ATTR_ENABLE_VLAN, - .get = mt753x_get_vlan_enable, - .set = mt753x_set_vlan_enable, - } -}; - -static const struct switch_attr mt753x_port[] = { - { - .type = SWITCH_TYPE_STRING, - .name = "mib", - .description = "Get MIB counters for port", - .get = mt753x_get_port_mib, - .set = NULL, - }, -}; - -static const struct switch_attr mt753x_vlan[] = { - { - .type = SWITCH_TYPE_INT, - .name = "vid", - .description = "VLAN ID (0-4094)", - .set = mt753x_set_vid, - .get = mt753x_get_vid, - .max = 4094, - }, -}; - -static const struct switch_dev_ops mt753x_swdev_ops = { - .attr_global = { - .attr = mt753x_global, - .n_attr = ARRAY_SIZE(mt753x_global), - }, - .attr_port = { - .attr = mt753x_port, - .n_attr = ARRAY_SIZE(mt753x_port), - }, - .attr_vlan = { - .attr = mt753x_vlan, - .n_attr = ARRAY_SIZE(mt753x_vlan), - }, - .get_vlan_ports = mt753x_get_vlan_ports, - .set_vlan_ports = mt753x_set_vlan_ports, - .get_port_pvid = mt753x_get_port_pvid, - .set_port_pvid = mt753x_set_port_pvid, - .get_port_link = mt753x_get_port_link, - .set_port_link = mt753x_set_port_link, - .get_port_stats = mt753x_get_port_stats, - .apply_config = mt753x_apply_config, - .reset_switch = mt753x_reset_switch, - .phy_read16 = mt753x_phy_read16, - .phy_write16 = mt753x_phy_write16, -}; - -int mt753x_swconfig_init(struct gsw_mt753x *gsw) -{ - struct device_node *np = gsw->dev->of_node; - struct switch_dev *swdev; - int ret; - - if (of_property_read_u32(np, "mediatek,cpuport", &gsw->cpu_port)) - gsw->cpu_port = MT753X_DFL_CPU_PORT; - - swdev = &gsw->swdev; - - swdev->name = gsw->name; - swdev->alias = gsw->name; - swdev->cpu_port = gsw->cpu_port; - swdev->ports = MT753X_NUM_PORTS; - swdev->vlans = MT753X_NUM_VLANS; - swdev->ops = &mt753x_swdev_ops; - - ret = register_switch(swdev, NULL); - if (ret) { - dev_notice(gsw->dev, "Failed to register switch %s\n", - swdev->name); - return ret; - } - - mt753x_apply_config(swdev); - - return 0; -} - -void mt753x_swconfig_destroy(struct gsw_mt753x *gsw) -{ - unregister_switch(&gsw->swdev); -} diff --git a/target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt753x_swconfig.h b/target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt753x_swconfig.h deleted file mode 100644 index f000364ee..000000000 --- a/target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt753x_swconfig.h +++ /dev/null @@ -1,29 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (c) 2018 MediaTek Inc. - * Author: Weijie Gao - */ - -#ifndef _MT753X_SWCONFIG_H_ -#define _MT753X_SWCONFIG_H_ - -#ifdef CONFIG_SWCONFIG -#include -#include "mt753x.h" - -int mt753x_swconfig_init(struct gsw_mt753x *gsw); -void mt753x_swconfig_destroy(struct gsw_mt753x *gsw); -#else -static inline int mt753x_swconfig_init(struct gsw_mt753x *gsw) -{ - mt753x_apply_vlan_config(gsw); - - return 0; -} - -static inline void mt753x_swconfig_destroy(struct gsw_mt753x *gsw) -{ -} -#endif - -#endif /* _MT753X_SWCONFIG_H_ */ diff --git a/target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt753x_vlan.c b/target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt753x_vlan.c deleted file mode 100644 index 4d88eee8d..000000000 --- a/target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt753x_vlan.c +++ /dev/null @@ -1,183 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2018 MediaTek Inc. - */ - -#include "mt753x.h" -#include "mt753x_regs.h" - -struct mt753x_mapping mt753x_def_mapping[] = { - { - .name = "llllw", - .pvids = { 1, 1, 1, 1, 2, 2, 1 }, - .members = { 0, 0x4f, 0x30 }, - .etags = { 0, 0, 0 }, - .vids = { 0, 1, 2 }, - }, { - .name = "wllll", - .pvids = { 2, 1, 1, 1, 1, 2, 1 }, - .members = { 0, 0x5e, 0x21 }, - .etags = { 0, 0, 0 }, - .vids = { 0, 1, 2 }, - }, { - .name = "lwlll", - .pvids = { 1, 2, 1, 1, 1, 2, 1 }, - .members = { 0, 0x5d, 0x22 }, - .etags = { 0, 0, 0 }, - .vids = { 0, 1, 2 }, - }, -}; - -void mt753x_vlan_ctrl(struct gsw_mt753x *gsw, u32 cmd, u32 val) -{ - int i; - - mt753x_reg_write(gsw, VTCR, - VTCR_BUSY | ((cmd << VTCR_FUNC_S) & VTCR_FUNC_M) | - (val & VTCR_VID_M)); - - for (i = 0; i < 300; i++) { - u32 val = mt753x_reg_read(gsw, VTCR); - - if ((val & VTCR_BUSY) == 0) - break; - - usleep_range(1000, 1100); - } - - if (i == 300) - dev_info(gsw->dev, "vtcr timeout\n"); -} - -static void mt753x_write_vlan_entry(struct gsw_mt753x *gsw, int vlan, u16 vid, - u8 ports, u8 etags) -{ - int port; - u32 val; - - /* vlan port membership */ - if (ports) - mt753x_reg_write(gsw, VAWD1, - IVL_MAC | VTAG_EN | VENTRY_VALID | - ((ports << PORT_MEM_S) & PORT_MEM_M)); - else - mt753x_reg_write(gsw, VAWD1, 0); - - /* egress mode */ - val = 0; - for (port = 0; port < MT753X_NUM_PORTS; port++) { - if (etags & BIT(port)) - val |= ETAG_CTRL_TAG << PORT_ETAG_S(port); - else - val |= ETAG_CTRL_UNTAG << PORT_ETAG_S(port); - } - mt753x_reg_write(gsw, VAWD2, val); - - /* write to vlan table */ - mt753x_vlan_ctrl(gsw, VTCR_WRITE_VLAN_ENTRY, vid); -} - -void mt753x_apply_vlan_config(struct gsw_mt753x *gsw) -{ - int i, j; - u8 tag_ports; - u8 untag_ports; - - /* set all ports as security mode */ - for (i = 0; i < MT753X_NUM_PORTS; i++) - mt753x_reg_write(gsw, PCR(i), - PORT_MATRIX_M | SECURITY_MODE); - - /* check if a port is used in tag/untag vlan egress mode */ - tag_ports = 0; - untag_ports = 0; - - for (i = 0; i < MT753X_NUM_VLANS; i++) { - u8 member = gsw->vlan_entries[i].member; - u8 etags = gsw->vlan_entries[i].etags; - - if (!member) - continue; - - for (j = 0; j < MT753X_NUM_PORTS; j++) { - if (!(member & BIT(j))) - continue; - - if (etags & BIT(j)) - tag_ports |= 1u << j; - else - untag_ports |= 1u << j; - } - } - - /* set all untag-only ports as transparent and the rest as user port */ - for (i = 0; i < MT753X_NUM_PORTS; i++) { - u32 pvc_mode = 0x8100 << STAG_VPID_S; - - if (untag_ports & BIT(i) && !(tag_ports & BIT(i))) - pvc_mode = (0x8100 << STAG_VPID_S) | - (VA_TRANSPARENT_PORT << VLAN_ATTR_S); - - mt753x_reg_write(gsw, PVC(i), pvc_mode); - } - - /* first clear the switch vlan table */ - for (i = 0; i < MT753X_NUM_VLANS; i++) - mt753x_write_vlan_entry(gsw, i, i, 0, 0); - - /* now program only vlans with members to avoid - * clobbering remapped entries in later iterations - */ - for (i = 0; i < MT753X_NUM_VLANS; i++) { - u16 vid = gsw->vlan_entries[i].vid; - u8 member = gsw->vlan_entries[i].member; - u8 etags = gsw->vlan_entries[i].etags; - - if (member) - mt753x_write_vlan_entry(gsw, i, vid, member, etags); - } - - /* Port Default PVID */ - for (i = 0; i < MT753X_NUM_PORTS; i++) { - int vlan = gsw->port_entries[i].pvid; - u16 pvid = 0; - u32 val; - - if (vlan < MT753X_NUM_VLANS && gsw->vlan_entries[vlan].member) - pvid = gsw->vlan_entries[vlan].vid; - - val = mt753x_reg_read(gsw, PPBV1(i)); - val &= ~GRP_PORT_VID_M; - val |= pvid; - mt753x_reg_write(gsw, PPBV1(i), val); - } -} - -struct mt753x_mapping *mt753x_find_mapping(struct device_node *np) -{ - const char *map; - int i; - - if (of_property_read_string(np, "mediatek,portmap", &map)) - return NULL; - - for (i = 0; i < ARRAY_SIZE(mt753x_def_mapping); i++) - if (!strcmp(map, mt753x_def_mapping[i].name)) - return &mt753x_def_mapping[i]; - - return NULL; -} - -void mt753x_apply_mapping(struct gsw_mt753x *gsw, struct mt753x_mapping *map) -{ - int i = 0; - - for (i = 0; i < MT753X_NUM_PORTS; i++) - gsw->port_entries[i].pvid = map->pvids[i]; - - for (i = 0; i < MT753X_NUM_VLANS; i++) { - gsw->vlan_entries[i].member = map->members[i]; - gsw->vlan_entries[i].etags = map->etags[i]; - gsw->vlan_entries[i].vid = map->vids[i]; - } -} diff --git a/target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt753x_vlan.h b/target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt753x_vlan.h deleted file mode 100644 index c726b8eac..000000000 --- a/target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt753x_vlan.h +++ /dev/null @@ -1,40 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (c) 2018 MediaTek Inc. - */ - -#ifndef _MT753X_VLAN_H_ -#define _MT753X_VLAN_H_ - -#define MT753X_NUM_PORTS 7 -#define MT753X_NUM_VLANS 4095 -#define MT753X_MAX_VID 4095 -#define MT753X_MIN_VID 0 - -struct gsw_mt753x; - -struct mt753x_port_entry { - u16 pvid; -}; - -struct mt753x_vlan_entry { - u16 vid; - u8 member; - u8 etags; -}; - -struct mt753x_mapping { - char *name; - u16 pvids[MT753X_NUM_PORTS]; - u8 members[MT753X_NUM_VLANS]; - u8 etags[MT753X_NUM_VLANS]; - u16 vids[MT753X_NUM_VLANS]; -}; - -extern struct mt753x_mapping mt753x_defaults[]; - -void mt753x_vlan_ctrl(struct gsw_mt753x *gsw, u32 cmd, u32 val); -void mt753x_apply_vlan_config(struct gsw_mt753x *gsw); -struct mt753x_mapping *mt753x_find_mapping(struct device_node *np); -void mt753x_apply_mapping(struct gsw_mt753x *gsw, struct mt753x_mapping *map); -#endif /* _MT753X_VLAN_H_ */ diff --git a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/acl.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/acl.c index 75e5a5e74..85c12b000 100644 --- a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/acl.c +++ b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/acl.c @@ -144,7 +144,7 @@ static rtk_api_ret_t _rtk_filter_igrAcl_writeDataField(rtl8367c_aclrule *aclRule * RT_ERR_SMI - SMI access error * RT_ERR_NULL_POINTER - Pointer pFilter_field or pFilter_cfg point to NULL. * Note: - * This function enable and intialize ACL function + * This function enable and initialize ACL function */ rtk_api_ret_t rtk_filter_igrAcl_init(void) { @@ -204,7 +204,7 @@ rtk_api_ret_t rtk_filter_igrAcl_init(void) * This function add a comparison rule (*pFilter_field) to an ACL configuration (*pFilter_cfg). * Pointer pFilter_cfg points to an ACL configuration structure, this structure keeps multiple ACL * comparison rules by means of linked list. Pointer pFilter_field will be added to linked - * list keeped by structure that pFilter_cfg points to. + * list kept by structure that pFilter_cfg points to. */ rtk_api_ret_t rtk_filter_igrAcl_field_add(rtk_filter_cfg_t* pFilter_cfg, rtk_filter_field_t* pFilter_field) { @@ -348,7 +348,7 @@ static rtk_api_ret_t _rtk_filter_igrAcl_writeDataField(rtl8367c_aclrule *aclRule } else { - /*default acl template for ipv6 address supports MSB 32-bits and LSB 32-bits only*/ + /*default ACL template for ipv6 address supports MSB 32-bits and LSB 32-bits only*/ aclRule[tempIdx].data_bits.field[fieldIdx] = ((ip6addr[3] & (0xFFFF << ((i&1) * 16))) >> ((i&1) * 16)); aclRule[tempIdx].care_bits.field[fieldIdx] = ((ip6mask[3] & (0xFFFF << ((i&1) * 16))) >> ((i&1) * 16)); } @@ -557,7 +557,7 @@ static rtk_api_ret_t _rtk_filter_igrAcl_writeDataField(rtl8367c_aclrule *aclRule * pFilter_cfg - The ACL configuration that this function will add comparison rule * pFilter_action - Action(s) of ACL configuration. * Output: - * ruleNum - number of rules written in acl table + * ruleNum - number of rules written in ACL table * Return: * RT_ERR_OK - OK * RT_ERR_FAILED - Failed @@ -1140,12 +1140,12 @@ rtk_api_ret_t rtk_filter_igrAcl_cfg_delAll(void) /* Function Name: * rtk_filter_igrAcl_cfg_get * Description: - * Get one ingress acl configuration from ASIC. + * Get one ingress ACL configuration from ASIC. * Input: * filter_id - Start index of ACL configuration. * Output: - * pFilter_cfg - buffer pointer of ingress acl data - * pFilter_action - buffer pointer of ingress acl action + * pFilter_cfg - buffer pointer of ingress ACL data + * pFilter_action - buffer pointer of ingress ACL action * Return: * RT_ERR_OK - OK * RT_ERR_FAILED - Failed @@ -1462,7 +1462,7 @@ rtk_api_ret_t rtk_filter_igrAcl_cfg_get(rtk_filter_id_t filter_id, rtk_filter_cf * RT_ERR_PORT_ID - Invalid port id. * RT_ERR_INPUT - Invalid input parameters. * Note: - * This function sets action of packets when no ACL configruation matches. + * This function sets action of packets when no ACL configuration matches. */ rtk_api_ret_t rtk_filter_igrAcl_unmatchAction_set(rtk_port_t port, rtk_filter_unmatch_action_t action) { @@ -1535,7 +1535,7 @@ rtk_api_ret_t rtk_filter_igrAcl_unmatchAction_get(rtk_port_t port, rtk_filter_un * RT_ERR_PORT_ID - Invalid port id. * RT_ERR_INPUT - Invalid input parameters. * Note: - * This function gets action of packets when no ACL configruation matches. + * This function gets action of packets when no ACL configuration matches. */ rtk_api_ret_t rtk_filter_igrAcl_state_set(rtk_port_t port, rtk_filter_state_t state) { @@ -1571,7 +1571,7 @@ rtk_api_ret_t rtk_filter_igrAcl_state_set(rtk_port_t port, rtk_filter_state_t st * RT_ERR_PORT_ID - Invalid port id. * RT_ERR_INPUT - Invalid input parameters. * Note: - * This function gets action of packets when no ACL configruation matches. + * This function gets action of packets when no ACL configuration matches. */ rtk_api_ret_t rtk_filter_igrAcl_state_get(rtk_port_t port, rtk_filter_state_t* pState) { @@ -1699,7 +1699,7 @@ rtk_api_ret_t rtk_filter_igrAcl_template_get(rtk_filter_template_t *aclTemplate) * RT_ERR_FAILED - Failed * RT_ERR_SMI - SMI access error * Note: - * System support 16 user defined field selctors. + * System support 16 user defined field selectors. * Each selector can be enabled or disable. * User can defined retrieving 16-bits in many predefiend * standard l2/l3/l4 payload. @@ -1928,7 +1928,7 @@ rtk_api_ret_t rtk_filter_vidrange_get(rtk_uint32 index, rtk_filter_vidrange_t *p * Set Port Range check * Input: * index - index of Port Range 0-15 - * type - IP Range check type, 0:Delete a entry, 1: Source Port, 2: Destnation Port + * type - IP Range check type, 0:Delete a entry, 1: Source Port, 2: Destination Port * upperPort - The upper bound of Port range * lowerPort - The lower Bound of Port range * Output: @@ -1977,7 +1977,7 @@ rtk_api_ret_t rtk_filter_portrange_set(rtk_uint32 index, rtk_filter_portrange_t * Input: * index - index of Port Range 0-15 * Output: - * pType - IP Range check type, 0:Delete a entry, 1: Source Port, 2: Destnation Port + * pType - IP Range check type, 0:Delete a entry, 1: Source Port, 2: Destination Port * pUpperPort - The upper bound of Port range * pLowerPort - The lower Bound of Port range * Return: @@ -2011,7 +2011,7 @@ rtk_api_ret_t rtk_filter_portrange_get(rtk_uint32 index, rtk_filter_portrange_t /* Function Name: * rtk_filter_igrAclPolarity_set * Description: - * Set ACL Goip control palarity + * Set ACL Goip control polarity * Input: * polarity - 1: High, 0: Low * Output: @@ -2034,7 +2034,7 @@ rtk_api_ret_t rtk_filter_igrAclPolarity_set(rtk_uint32 polarity) /* Function Name: * rtk_filter_igrAclPolarity_get * Description: - * Get ACL Goip control palarity + * Get ACL Goip control polarity * Input: * pPolarity - 1: High, 0: Low * Output: diff --git a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/cpu.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/cpu.c index d1cd95b37..b031cbe92 100644 --- a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/cpu.c +++ b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/cpu.c @@ -113,7 +113,7 @@ rtk_api_ret_t rtk_cpu_enable_get(rtk_enable_t *pEnable) * Note: * The API can set CPU port and inserting proprietary CPU tag mode (Length/Type 0x8899) * to the frame that transmitting to CPU port. - * The inset cpu tag mode is as following: + * The insert CPU tag mode is as following: * - CPU_INSERT_TO_ALL * - CPU_INSERT_TO_TRAPPING * - CPU_INSERT_TO_NONE @@ -160,7 +160,7 @@ rtk_api_ret_t rtk_cpu_tagPort_set(rtk_port_t port, rtk_cpu_insert_t mode) * RT_ERR_L2_NO_CPU_PORT - CPU port is not exist * Note: * The API can get configured CPU port and its setting. - * The inset cpu tag mode is as following: + * The insert CPU tag mode is as following: * - CPU_INSERT_TO_ALL * - CPU_INSERT_TO_TRAPPING * - CPU_INSERT_TO_NONE diff --git a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/igmp.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/igmp.c index 170cbdaaf..18e145a21 100644 --- a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/igmp.c +++ b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/igmp.c @@ -233,7 +233,7 @@ rtk_api_ret_t rtk_igmp_static_router_port_get(rtk_portmask_t *pPortmask) * Input: * port - Port ID * protocol - IGMP/MLD protocol - * action - Per-port and per-protocol IGMP action seeting + * action - Per-port and per-protocol IGMP action setting * Output: * None. * Return: @@ -321,7 +321,7 @@ rtk_api_ret_t rtk_igmp_protocol_set(rtk_port_t port, rtk_igmp_protocol_t protoco * Input: * port - Port ID * protocol - IGMP/MLD protocol - * action - Per-port and per-protocol IGMP action seeting + * action - Per-port and per-protocol IGMP action setting * Output: * None. * Return: @@ -1217,7 +1217,7 @@ rtk_api_ret_t rtk_igmp_portRxPktEnable_get(rtk_port_t port, rtk_igmp_rxPktEnable * Description: * Get IGMP/MLD Group database * Input: - * indes - Index (0~255) + * index - Index (0~255) * Output: * pGroup - Group database information. * Return: @@ -1418,7 +1418,7 @@ rtk_api_ret_t rtk_igmp_ReportLeaveFwdAction_get(rtk_igmp_ReportLeaveFwdAct_t *pA /* Function Name: * rtk_igmp_dropLeaveZeroEnable_set * Description: - * Set the function of droppping Leave packet with group IP = 0.0.0.0 + * Set the function of dropping Leave packet with group IP = 0.0.0.0 * Input: * enabled - Action 1: drop, 0:pass * Output: @@ -1451,7 +1451,7 @@ rtk_api_ret_t rtk_igmp_dropLeaveZeroEnable_set(rtk_enable_t enabled) /* Function Name: * rtk_igmp_dropLeaveZeroEnable_get * Description: - * Get the function of droppping Leave packet with group IP = 0.0.0.0 + * Get the function of dropping Leave packet with group IP = 0.0.0.0 * Input: * None * Output: diff --git a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/acl.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/acl.h index 6308da8d4..634e7325d 100644 --- a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/acl.h +++ b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/acl.h @@ -9,7 +9,7 @@ * * Purpose : RTL8367/RTL8367C switch high-level API * - * Feature : The file includes ACL module high-layer API defination + * Feature : The file includes ACL module high-layer API definition * */ @@ -566,7 +566,7 @@ typedef enum rtk_filter_portrange_e * RT_ERR_SMI - SMI access error * RT_ERR_NULL_POINTER - Pointer pFilter_field or pFilter_cfg point to NULL. * Note: - * This function enable and intialize ACL function + * This function enable and initialize ACL function */ extern rtk_api_ret_t rtk_filter_igrAcl_init(void); @@ -589,7 +589,7 @@ extern rtk_api_ret_t rtk_filter_igrAcl_init(void); * This function add a comparison rule (*pFilter_field) to an ACL configuration (*pFilter_cfg). * Pointer pFilter_cfg points to an ACL configuration structure, this structure keeps multiple ACL * comparison rules by means of linked list. Pointer pFilter_field will be added to linked - * list keeped by structure that pFilter_cfg points to. + * list kept by structure that pFilter_cfg points to. */ extern rtk_api_ret_t rtk_filter_igrAcl_field_add(rtk_filter_cfg_t *pFilter_cfg, rtk_filter_field_t *pFilter_field); @@ -602,7 +602,7 @@ extern rtk_api_ret_t rtk_filter_igrAcl_field_add(rtk_filter_cfg_t *pFilter_cfg, * pFilter_cfg - The ACL configuration that this function will add comparison rule * pFilter_action - Action(s) of ACL configuration. * Output: - * ruleNum - number of rules written in acl table + * ruleNum - number of rules written in ACL table * Return: * RT_ERR_OK - OK * RT_ERR_FAILED - Failed @@ -657,12 +657,12 @@ extern rtk_api_ret_t rtk_filter_igrAcl_cfg_delAll(void); /* Function Name: * rtk_filter_igrAcl_cfg_get * Description: - * Get one ingress acl configuration from ASIC. + * Get one ingress ACL configuration from ASIC. * Input: * filter_id - Start index of ACL configuration. * Output: - * pFilter_cfg - buffer pointer of ingress acl data - * pFilter_action - buffer pointer of ingress acl action + * pFilter_cfg - buffer pointer of ingress ACL data + * pFilter_action - buffer pointer of ingress ACL action * Return: * RT_ERR_OK - OK * RT_ERR_FAILED - Failed @@ -690,7 +690,7 @@ extern rtk_api_ret_t rtk_filter_igrAcl_cfg_get(rtk_filter_id_t filter_id, rtk_fi * RT_ERR_PORT_ID - Invalid port id. * RT_ERR_INPUT - Invalid input parameters. * Note: - * This function sets action of packets when no ACL configruation matches. + * This function sets action of packets when no ACL configuration matches. */ extern rtk_api_ret_t rtk_filter_igrAcl_unmatchAction_set(rtk_port_t port, rtk_filter_unmatch_action_t action); @@ -709,7 +709,7 @@ extern rtk_api_ret_t rtk_filter_igrAcl_unmatchAction_set(rtk_port_t port, rtk_fi * RT_ERR_PORT_ID - Invalid port id. * RT_ERR_INPUT - Invalid input parameters. * Note: - * This function gets action of packets when no ACL configruation matches. + * This function gets action of packets when no ACL configuration matches. */ extern rtk_api_ret_t rtk_filter_igrAcl_unmatchAction_get(rtk_port_t port, rtk_filter_unmatch_action_t* action); @@ -729,7 +729,7 @@ extern rtk_api_ret_t rtk_filter_igrAcl_unmatchAction_get(rtk_port_t port, rtk_fi * RT_ERR_PORT_ID - Invalid port id. * RT_ERR_INPUT - Invalid input parameters. * Note: - * This function gets action of packets when no ACL configruation matches. + * This function gets action of packets when no ACL configuration matches. */ extern rtk_api_ret_t rtk_filter_igrAcl_state_set(rtk_port_t port, rtk_filter_state_t state); @@ -748,7 +748,7 @@ extern rtk_api_ret_t rtk_filter_igrAcl_state_set(rtk_port_t port, rtk_filter_sta * RT_ERR_PORT_ID - Invalid port id. * RT_ERR_INPUT - Invalid input parameters. * Note: - * This function gets action of packets when no ACL configruation matches. + * This function gets action of packets when no ACL configuration matches. */ extern rtk_api_ret_t rtk_filter_igrAcl_state_get(rtk_port_t port, rtk_filter_state_t* state); @@ -802,7 +802,7 @@ extern rtk_api_ret_t rtk_filter_igrAcl_template_get(rtk_filter_template_t *aclTe * RT_ERR_FAILED - Failed * RT_ERR_SMI - SMI access error * Note: - * System support 16 user defined field selctors. + * System support 16 user defined field selectors. * Each selector can be enabled or disable. * User can defined retrieving 16-bits in many predefiend * standard l2/l3/l4 payload. @@ -917,7 +917,7 @@ extern rtk_api_ret_t rtk_filter_vidrange_get(rtk_uint32 index, rtk_filter_vidran * Set Port Range check * Input: * index - index of Port Range 0-15 - * type - IP Range check type, 0:Delete a entry, 1: Source Port, 2: Destnation Port + * type - IP Range check type, 0:Delete a entry, 1: Source Port, 2: Destination Port * upperPort - The upper bound of Port range * lowerPort - The lower Bound of Port range * Output: @@ -940,7 +940,7 @@ extern rtk_api_ret_t rtk_filter_portrange_set(rtk_uint32 index, rtk_filter_portr * Input: * index - index of Port Range 0-15 * Output: - * pType - IP Range check type, 0:Delete a entry, 1: Source Port, 2: Destnation Port + * pType - IP Range check type, 0:Delete a entry, 1: Source Port, 2: Destination Port * pUpperPort - The upper bound of Port range * pLowerPort - The lower Bound of Port range * Return: @@ -957,7 +957,7 @@ extern rtk_api_ret_t rtk_filter_portrange_get(rtk_uint32 index, rtk_filter_portr /* Function Name: * rtk_filter_igrAclPolarity_set * Description: - * Set ACL Goip control palarity + * Set ACL Goip control polarity * Input: * polarity - 1: High, 0: Low * Output: @@ -973,7 +973,7 @@ extern rtk_api_ret_t rtk_filter_igrAclPolarity_set(rtk_uint32 polarity); /* Function Name: * rtk_filter_igrAclPolarity_get * Description: - * Get ACL Goip control palarity + * Get ACL Goip control polarity * Input: * pPolarity - 1: High, 0: Low * Output: diff --git a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/cpu.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/cpu.h index 5544aca7b..67aa1e3d8 100644 --- a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/cpu.h +++ b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/cpu.h @@ -9,7 +9,7 @@ * * Purpose : RTL8367/RTL8367C switch high-level API * - * Feature : The file includes CPU module high-layer API defination + * Feature : The file includes CPU module high-layer API definition * */ @@ -107,7 +107,7 @@ extern rtk_api_ret_t rtk_cpu_enable_get(rtk_enable_t *pEnable); * Note: * The API can set CPU port and inserting proprietary CPU tag mode (Length/Type 0x8899) * to the frame that transmitting to CPU port. - * The inset cpu tag mode is as following: + * The insert CPU tag mode is as following: * - CPU_INSERT_TO_ALL * - CPU_INSERT_TO_TRAPPING * - CPU_INSERT_TO_NONE @@ -131,7 +131,7 @@ extern rtk_api_ret_t rtk_cpu_tagPort_set(rtk_port_t port, rtk_cpu_insert_t mode) * RT_ERR_L2_NO_CPU_PORT - CPU port is not exist * Note: * The API can get configured CPU port and its setting. - * The inset cpu tag mode is as following: + * The insert CPU tag mode is as following: * - CPU_INSERT_TO_ALL * - CPU_INSERT_TO_TRAPPING * - CPU_INSERT_TO_NONE diff --git a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/dot1x.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/dot1x.h index ef0a05a04..082ee2569 100644 --- a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/dot1x.h +++ b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/dot1x.h @@ -9,7 +9,7 @@ * * Purpose : RTL8367/RTL8367C switch high-level API * - * Feature : The file includes 1X module high-layer API defination + * Feature : The file includes 1X module high-layer API definition * */ diff --git a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/eee.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/eee.h index b670998c8..e3920363d 100644 --- a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/eee.h +++ b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/eee.h @@ -9,7 +9,7 @@ * * Purpose : RTL8367/RTL8367C switch high-level API * - * Feature : The file includes EEE module high-layer API defination + * Feature : The file includes EEE module high-layer API definition * */ diff --git a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/i2c.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/i2c.h index 2c7f0756a..110f41e81 100644 --- a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/i2c.h +++ b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/i2c.h @@ -9,7 +9,7 @@ * * Purpose : RTL8367/RTL8367C switch high-level API * - * Feature : The file includes I2C module high-layer API defination + * Feature : The file includes I2C module high-layer API definition * */ diff --git a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/igmp.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/igmp.h index f088b0ccd..b36db43d8 100644 --- a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/igmp.h +++ b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/igmp.h @@ -9,7 +9,7 @@ * * Purpose : RTL8367/RTL8367C switch high-level API * - * Feature : The file includes IGMP module high-layer API defination + * Feature : The file includes IGMP module high-layer API definition * */ @@ -205,7 +205,7 @@ extern rtk_api_ret_t rtk_igmp_static_router_port_get(rtk_portmask_t *pPortmask); * Input: * port - Port ID * protocol - IGMP/MLD protocol - * action - Per-port and per-protocol IGMP action seeting + * action - Per-port and per-protocol IGMP action setting * Output: * None. * Return: @@ -225,7 +225,7 @@ extern rtk_api_ret_t rtk_igmp_protocol_set(rtk_port_t port, rtk_igmp_protocol_t * Input: * port - Port ID * protocol - IGMP/MLD protocol - * action - Per-port and per-protocol IGMP action seeting + * action - Per-port and per-protocol IGMP action setting * Output: * None. * Return: @@ -640,7 +640,7 @@ extern rtk_api_ret_t rtk_igmp_portRxPktEnable_get(rtk_port_t port, rtk_igmp_rxPk * Description: * Get IGMP/MLD Group database * Input: - * indes - Index (0~255) + * index - Index (0~255) * Output: * pGroup - Group database information. * Return: @@ -694,7 +694,7 @@ extern rtk_api_ret_t rtk_igmp_ReportLeaveFwdAction_get(rtk_igmp_ReportLeaveFwdAc /* Function Name: * rtk_igmp_dropLeaveZeroEnable_set * Description: - * Set the function of droppping Leave packet with group IP = 0.0.0.0 + * Set the function of dropping Leave packet with group IP = 0.0.0.0 * Input: * enabled - Action 1: drop, 0:pass * Output: @@ -712,7 +712,7 @@ extern rtk_api_ret_t rtk_igmp_dropLeaveZeroEnable_set(rtk_enable_t enabled); /* Function Name: * rtk_igmp_dropLeaveZeroEnable_get * Description: - * Get the function of droppping Leave packet with group IP = 0.0.0.0 + * Get the function of dropping Leave packet with group IP = 0.0.0.0 * Input: * None * Output: diff --git a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/interrupt.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/interrupt.h index f2689ebc7..20625fff5 100644 --- a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/interrupt.h +++ b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/interrupt.h @@ -9,7 +9,7 @@ * * Purpose : RTL8367/RTL8367C switch high-level API * - * Feature : The file includes Interrupt module high-layer API defination + * Feature : The file includes Interrupt module high-layer API definition * */ diff --git a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/l2.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/l2.h index e0ccdbe3d..ec5aad2e3 100644 --- a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/l2.h +++ b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/l2.h @@ -9,7 +9,7 @@ * * Purpose : RTL8367/RTL8367C switch high-level API * - * Feature : The file includes L2 module high-layer API defination + * Feature : The file includes L2 module high-layer API definition * */ @@ -209,7 +209,7 @@ extern rtk_api_ret_t rtk_l2_init(void); * RT_ERR_L2_INDEXTBL_FULL - hashed index is full of entries. * RT_ERR_INPUT - Invalid input parameters. * Note: - * If the unicast mac address already existed in LUT, it will udpate the status of the entry. + * If the unicast mac address already existed in LUT, it will update the status of the entry. * Otherwise, it will find an empty or asic auto learned entry to write. If all the entries * with the same hash value can't be replaced, ASIC will return a RT_ERR_L2_INDEXTBL_FULL error. */ @@ -307,7 +307,7 @@ extern rtk_api_ret_t rtk_l2_addr_del(rtk_mac_t *pMac, rtk_l2_ucastAddr_t *pL2_da * RT_ERR_PORT_MASK - Invalid portmask. * RT_ERR_INPUT - Invalid input parameters. * Note: - * If the multicast mac address already existed in the LUT, it will udpate the + * If the multicast mac address already existed in the LUT, it will update the * port mask of the entry. Otherwise, it will find an empty or asic auto learned * entry to write. If all the entries with the same hash value can't be replaced, * ASIC will return a RT_ERR_L2_INDEXTBL_FULL error. @@ -383,7 +383,7 @@ extern rtk_api_ret_t rtk_l2_mcastAddr_del(rtk_l2_mcastAddr_t *pMcastAddr); /* Function Name: * rtk_l2_ipMcastAddr_add * Description: - * Add Lut IP multicast entry + * Add LUT IP multicast entry * Input: * pIpMcastAddr - IP Multicast entry * Output: @@ -418,7 +418,7 @@ extern rtk_api_ret_t rtk_l2_ipMcastAddr_add(rtk_l2_ipMcastAddr_t *pIpMcastAddr); * RT_ERR_L2_ENTRY_NOTFOUND - No such LUT entry. * RT_ERR_INPUT - Invalid input parameters. * Note: - * The API can get Lut table of IP multicast entry. + * The API can get LUT table of IP multicast entry. */ extern rtk_api_ret_t rtk_l2_ipMcastAddr_get(rtk_l2_ipMcastAddr_t *pIpMcastAddr); @@ -465,7 +465,7 @@ extern rtk_api_ret_t rtk_l2_ipMcastAddr_del(rtk_l2_ipMcastAddr_t *pIpMcastAddr); /* Function Name: * rtk_l2_ipVidMcastAddr_add * Description: - * Add Lut IP multicast+VID entry + * Add LUT IP multicast+VID entry * Input: * pIpVidMcastAddr - IP & VID multicast Entry * Output: @@ -913,7 +913,7 @@ extern rtk_api_ret_t rtk_l2_learningCnt_get(rtk_port_t port, rtk_mac_cnt_t *pMac * Set flooding portmask * Input: * type - flooding type. - * pFlood_portmask - flooding porkmask + * pFlood_portmask - flooding portmask * Output: * None * Return: @@ -938,7 +938,7 @@ extern rtk_api_ret_t rtk_l2_floodPortMask_set(rtk_l2_flood_type_t floood_type, r * Input: * type - flooding type. * Output: - * pFlood_portmask - flooding porkmask + * pFlood_portmask - flooding portmask * Return: * RT_ERR_OK - OK * RT_ERR_FAILED - Failed @@ -956,10 +956,10 @@ extern rtk_api_ret_t rtk_l2_floodPortMask_get(rtk_l2_flood_type_t floood_type, r /* Function Name: * rtk_l2_localPktPermit_set * Description: - * Set permittion of frames if source port and destination port are the same. + * Set permission of frames if source port and destination port are the same. * Input: * port - Port id. - * permit - permittion status + * permit - permission status * Output: * None * Return: @@ -969,34 +969,34 @@ extern rtk_api_ret_t rtk_l2_floodPortMask_get(rtk_l2_flood_type_t floood_type, r * RT_ERR_PORT_ID - Invalid port number. * RT_ERR_ENABLE - Invalid permit value. * Note: - * This API is setted to permit frame if its source port is equal to destination port. + * This API is set to permit frame if its source port is equal to destination port. */ extern rtk_api_ret_t rtk_l2_localPktPermit_set(rtk_port_t port, rtk_enable_t permit); /* Function Name: * rtk_l2_localPktPermit_get * Description: - * Get permittion of frames if source port and destination port are the same. + * Get permission of frames if source port and destination port are the same. * Input: * port - Port id. * Output: - * pPermit - permittion status + * pPermit - permission status * Return: * RT_ERR_OK - OK * RT_ERR_FAILED - Failed * RT_ERR_SMI - SMI access error * RT_ERR_PORT_ID - Invalid port number. * Note: - * This API is to get permittion status for frames if its source port is equal to destination port. + * This API is to get permission status for frames if its source port is equal to destination port. */ extern rtk_api_ret_t rtk_l2_localPktPermit_get(rtk_port_t port, rtk_enable_t *pPermit); /* Function Name: * rtk_l2_aging_set * Description: - * Set LUT agging out speed + * Set LUT ageing out speed * Input: - * aging_time - Agging out time. + * aging_time - Ageing out time. * Output: * None * Return: @@ -1005,14 +1005,14 @@ extern rtk_api_ret_t rtk_l2_localPktPermit_get(rtk_port_t port, rtk_enable_t *pP * RT_ERR_SMI - SMI access error * RT_ERR_OUT_OF_RANGE - input out of range. * Note: - * The API can set LUT agging out period for each entry and the range is from 14s to 800s. + * The API can set LUT ageing out period for each entry and the range is from 14s to 800s. */ extern rtk_api_ret_t rtk_l2_aging_set(rtk_l2_age_time_t aging_time); /* Function Name: * rtk_l2_aging_get * Description: - * Get LUT agging out time + * Get LUT ageing out time * Input: * None * Output: @@ -1023,14 +1023,14 @@ extern rtk_api_ret_t rtk_l2_aging_set(rtk_l2_age_time_t aging_time); * RT_ERR_SMI - SMI access error * RT_ERR_PORT_ID - Invalid port number. * Note: - * The API can get LUT agging out period for each entry. + * The API can get LUT ageing out period for each entry. */ extern rtk_api_ret_t rtk_l2_aging_get(rtk_l2_age_time_t *pAging_time); /* Function Name: * rtk_l2_ipMcastAddrLookup_set * Description: - * Set Lut IP multicast lookup function + * Set LUT IP multicast lookup function * Input: * type - Lookup type for IPMC packet. * Output: @@ -1051,7 +1051,7 @@ extern rtk_api_ret_t rtk_l2_ipMcastAddrLookup_set(rtk_l2_ipmc_lookup_type_t type /* Function Name: * rtk_l2_ipMcastAddrLookup_get * Description: - * Get Lut IP multicast lookup function + * Get LUT IP multicast lookup function * Input: * None. * Output: @@ -1068,9 +1068,9 @@ extern rtk_api_ret_t rtk_l2_ipMcastAddrLookup_get(rtk_l2_ipmc_lookup_type_t *pTy /* Function Name: * rtk_l2_ipMcastForwardRouterPort_set * Description: - * Set IPMC packet forward to rounter port also or not + * Set IPMC packet forward to router port also or not * Input: - * enabled - 1: Inlcude router port, 0, exclude router port + * enabled - 1: Include router port, 0, exclude router port * Output: * None. * Return: @@ -1085,11 +1085,11 @@ extern rtk_api_ret_t rtk_l2_ipMcastForwardRouterPort_set(rtk_enable_t enabled); /* Function Name: * rtk_l2_ipMcastForwardRouterPort_get * Description: - * Get IPMC packet forward to rounter port also or not + * Get IPMC packet forward to router port also or not * Input: * None. * Output: - * pEnabled - 1: Inlcude router port, 0, exclude router port + * pEnabled - 1: Include router port, 0, exclude router port * Return: * RT_ERR_OK - OK * RT_ERR_FAILED - Failed diff --git a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/leaky.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/leaky.h index 13ef60df8..e5b22e287 100644 --- a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/leaky.h +++ b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/leaky.h @@ -9,7 +9,7 @@ * * Purpose : RTL8367/RTL8367C switch high-level API * - * Feature : The file includes Leaky module high-layer API defination + * Feature : The file includes Leaky module high-layer API definition * */ diff --git a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/led.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/led.h index 71acc7c92..7706107ef 100644 --- a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/led.h +++ b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/led.h @@ -9,7 +9,7 @@ * * Purpose : RTL8367/RTL8367C switch high-level API * - * Feature : The file includes LED module high-layer API defination + * Feature : The file includes LED module high-layer API definition * */ @@ -107,7 +107,7 @@ typedef enum rtk_led_serialOutput_e /* Function Name: * rtk_led_enable_set * Description: - * Set Led enable congiuration + * Set Led enable configuration * Input: * group - LED group id. * pPortmask - LED enable port mask. @@ -126,7 +126,7 @@ extern rtk_api_ret_t rtk_led_enable_set(rtk_led_group_t group, rtk_portmask_t *p /* Function Name: * rtk_led_enable_get * Description: - * Get Led enable congiuration + * Get Led enable configuration * Input: * group - LED group id. * Output: @@ -188,7 +188,7 @@ extern rtk_api_ret_t rtk_led_operation_get(rtk_led_operation_t *pMode); /* Function Name: * rtk_led_modeForce_set * Description: - * Set Led group to congiuration force mode + * Set Led group to configuration force mode * Input: * port - port ID * group - Support LED group id. @@ -214,7 +214,7 @@ extern rtk_api_ret_t rtk_led_modeForce_set(rtk_port_t port, rtk_led_group_t grou /* Function Name: * rtk_led_modeForce_get * Description: - * Get Led group to congiuration force mode + * Get Led group to configuration force mode * Input: * port - port ID * group - Support LED group id. @@ -276,7 +276,7 @@ extern rtk_api_ret_t rtk_led_blinkRate_get(rtk_led_blink_rate_t *pBlinkRate); /* Function Name: * rtk_led_groupConfig_set * Description: - * Set per group Led to congiuration mode + * Set per group Led to configuration mode * Input: * group - LED group. * config - LED configuration @@ -312,7 +312,7 @@ extern rtk_api_ret_t rtk_led_groupConfig_set(rtk_led_group_t group, rtk_led_cong /* Function Name: * rtk_led_groupConfig_get * Description: - * Get Led group congiuration mode + * Get Led group configuration mode * Input: * group - LED group. * Output: @@ -370,7 +370,7 @@ extern rtk_api_ret_t rtk_led_groupAbility_get(rtk_led_group_t group, rtk_led_abi /* Function Name: * rtk_led_serialMode_set * Description: - * Set Led serial mode active congiuration + * Set Led serial mode active configuration * Input: * active - LED group. * Output: @@ -381,14 +381,14 @@ extern rtk_api_ret_t rtk_led_groupAbility_get(rtk_led_group_t group, rtk_led_abi * RT_ERR_SMI - SMI access error * RT_ERR_INPUT - Invalid input parameters. * Note: - * The API can set LED serial mode active congiuration. + * The API can set LED serial mode active configuration. */ extern rtk_api_ret_t rtk_led_serialMode_set(rtk_led_active_t active); /* Function Name: * rtk_led_serialMode_get * Description: - * Get Led group congiuration mode + * Get Led group configuration mode * Input: * group - LED group. * Output: diff --git a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/mirror.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/mirror.h index 1e984b7d8..8d179ce2d 100644 --- a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/mirror.h +++ b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/mirror.h @@ -9,7 +9,7 @@ * * Purpose : RTL8367/RTL8367C switch high-level API * - * Feature : The file includes Mirror module high-layer API defination + * Feature : The file includes Mirror module high-layer API definition * */ @@ -81,7 +81,7 @@ extern rtk_api_ret_t rtk_mirror_portBased_get(rtk_port_t* pMirroring_port, rtk_p * RT_ERR_SMI - SMI access error * RT_ERR_ENABLE - Invalid enable input * Note: - * The API is to set mirror isolation function that prevent normal forwarding packets to miror port. + * The API is to set mirror isolation function that prevent normal forwarding packets to mirror port. */ extern rtk_api_ret_t rtk_mirror_portIso_set(rtk_enable_t enable); @@ -118,7 +118,7 @@ extern rtk_api_ret_t rtk_mirror_portIso_get(rtk_enable_t *pEnable); * RT_ERR_SMI - SMI access error * RT_ERR_ENABLE - Invalid enable input * Note: - * The API is to set mirror VLAN leaky function forwarding packets to miror port. + * The API is to set mirror VLAN leaky function forwarding packets to mirror port. */ extern rtk_api_ret_t rtk_mirror_vlanLeaky_set(rtk_enable_t txenable, rtk_enable_t rxenable); @@ -157,7 +157,7 @@ extern rtk_api_ret_t rtk_mirror_vlanLeaky_get(rtk_enable_t *pTxenable, rtk_enabl * RT_ERR_SMI - SMI access error * RT_ERR_ENABLE - Invalid enable input * Note: - * The API is to set mirror VLAN leaky function forwarding packets to miror port. + * The API is to set mirror VLAN leaky function forwarding packets to mirror port. */ extern rtk_api_ret_t rtk_mirror_isolationLeaky_set(rtk_enable_t txenable, rtk_enable_t rxenable); diff --git a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/port.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/port.h index fcac1bcb8..458f16bf6 100644 --- a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/port.h +++ b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/port.h @@ -9,7 +9,7 @@ * * Purpose : RTL8367/RTL8367C switch high-level API * - * Feature : The file includes port module high-layer API defination + * Feature : The file includes port module high-layer API definition * */ @@ -222,7 +222,7 @@ typedef struct rtk_rtctResult_s /* Function Name: * rtk_port_phyAutoNegoAbility_set * Description: - * Set ethernet PHY auto-negotiation desired ability. + * Set Ethernet PHY auto-negotiation desired ability. * Input: * port - port id. * pAbility - Ability structure @@ -259,7 +259,7 @@ extern rtk_api_ret_t rtk_port_phyAutoNegoAbility_set(rtk_port_t port, rtk_port_p * RT_ERR_INPUT - Invalid input parameters. * RT_ERR_BUSYWAIT_TIMEOUT - PHY access busy * Note: - * Get the capablity of specified PHY. + * Get the capability of specified PHY. */ extern rtk_api_ret_t rtk_port_phyAutoNegoAbility_get(rtk_port_t port, rtk_port_phy_ability_t *pAbility); @@ -303,14 +303,14 @@ extern rtk_api_ret_t rtk_port_phyForceModeAbility_set(rtk_port_t port, rtk_port_ * RT_ERR_INPUT - Invalid input parameters. * RT_ERR_BUSYWAIT_TIMEOUT - PHY access busy * Note: - * Get the capablity of specified PHY. + * Get the capability of specified PHY. */ extern rtk_api_ret_t rtk_port_phyForceModeAbility_get(rtk_port_t port, rtk_port_phy_ability_t *pAbility); /* Function Name: * rtk_port_phyStatus_get * Description: - * Get ethernet PHY linking status + * Get Ethernet PHY linking status * Input: * port - Port id. * Output: @@ -459,7 +459,7 @@ extern rtk_api_ret_t rtk_port_macStatus_get(rtk_port_t port, rtk_port_mac_abilit * For UTP port, This API will also enable the digital * loopback bit in PHY register for sync of speed between * PHY and MAC. For EXT port, users need to force the - * link state by themself. + * link state by themselves. */ extern rtk_api_ret_t rtk_port_macLocalLoopbackEnable_set(rtk_port_t port, rtk_enable_t enable); @@ -527,7 +527,7 @@ extern rtk_api_ret_t rtk_port_phyReg_get(rtk_port_t port, rtk_port_phy_reg_t reg /* Function Name: * rtk_port_backpressureEnable_set * Description: - * Set the half duplex backpressure enable status of the specific port. + * Set the half duplex back-pressure enable status of the specific port. * Input: * port - port id. * enable - Back pressure status. @@ -540,8 +540,8 @@ extern rtk_api_ret_t rtk_port_phyReg_get(rtk_port_t port, rtk_port_phy_reg_t reg * RT_ERR_PORT_ID - Invalid port number. * RT_ERR_ENABLE - Invalid enable input. * Note: - * This API can set the half duplex backpressure enable status of the specific port. - * The half duplex backpressure enable status of the port is as following: + * This API can set the half duplex back-pressure enable status of the specific port. + * The half duplex back-pressure enable status of the port is as following: * - DISABLE * - ENABLE */ @@ -550,7 +550,7 @@ extern rtk_api_ret_t rtk_port_backpressureEnable_set(rtk_port_t port, rtk_enable /* Function Name: * rtk_port_backpressureEnable_get * Description: - * Get the half duplex backpressure enable status of the specific port. + * Get the half duplex back-pressure enable status of the specific port. * Input: * port - Port id. * Output: @@ -561,8 +561,8 @@ extern rtk_api_ret_t rtk_port_backpressureEnable_set(rtk_port_t port, rtk_enable * RT_ERR_SMI - SMI access error * RT_ERR_PORT_ID - Invalid port number. * Note: - * This API can get the half duplex backpressure enable status of the specific port. - * The half duplex backpressure enable status of the port is as following: + * This API can get the half duplex back-pressure enable status of the specific port. + * The half duplex back-pressure enable status of the port is as following: * - DISABLE * - ENABLE */ @@ -594,7 +594,7 @@ extern rtk_api_ret_t rtk_port_adminEnable_set(rtk_port_t port, rtk_enable_t enab /* Function Name: * rtk_port_adminEnable_get * Description: - * Get port admin configurationof the specific port. + * Get port admin configuration of the specific port. * Input: * port - Port id. * Output: @@ -628,7 +628,7 @@ extern rtk_api_ret_t rtk_port_adminEnable_get(rtk_port_t port, rtk_enable_t *pEn * RT_ERR_PORT_ID - Invalid port number. * RT_ERR_PORT_MASK - Invalid portmask. * Note: - * This API set the port mask that a port can trasmit packet to of each port + * This API set the port mask that a port can transmit packet to of each port * A port can only transmit packet to ports included in permitted portmask */ extern rtk_api_ret_t rtk_port_isolation_set(rtk_port_t port, rtk_portmask_t *pPortmask); @@ -647,7 +647,7 @@ extern rtk_api_ret_t rtk_port_isolation_set(rtk_port_t port, rtk_portmask_t *pPo * RT_ERR_SMI - SMI access error * RT_ERR_PORT_ID - Invalid port number. * Note: - * This API get the port mask that a port can trasmit packet to of each port + * This API get the port mask that a port can transmit packet to of each port * A port can only transmit packet to ports included in permitted portmask */ extern rtk_api_ret_t rtk_port_isolation_get(rtk_port_t port, rtk_portmask_t *pPortmask); @@ -669,7 +669,7 @@ extern rtk_api_ret_t rtk_port_isolation_get(rtk_port_t port, rtk_portmask_t *pPo * Note: * This API can set external interface 2 RGMII delay. * In TX delay, there are 2 selection: no-delay and 2ns delay. - * In RX dekay, there are 8 steps for delay tunning. 0 for no-delay, and 7 for maximum delay. + * In RX delay, there are 8 steps for delay tuning. 0 for no-delay, and 7 for maximum delay. */ extern rtk_api_ret_t rtk_port_rgmiiDelayExt_set(rtk_port_t port, rtk_data_t txDelay, rtk_data_t rxDelay); @@ -690,7 +690,7 @@ extern rtk_api_ret_t rtk_port_rgmiiDelayExt_set(rtk_port_t port, rtk_data_t txDe * Note: * This API can set external interface 2 RGMII delay. * In TX delay, there are 2 selection: no-delay and 2ns delay. - * In RX dekay, there are 8 steps for delay tunning. 0 for n0-delay, and 7 for maximum delay. + * In RX delay, there are 8 steps for delay tuning. 0 for n0-delay, and 7 for maximum delay. */ extern rtk_api_ret_t rtk_port_rgmiiDelayExt_get(rtk_port_t port, rtk_data_t *pTxDelay, rtk_data_t *pRxDelay); diff --git a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/ptp.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/ptp.h index 6c4aca5a5..d18c4a01e 100644 --- a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/ptp.h +++ b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/ptp.h @@ -9,7 +9,7 @@ * * Purpose : RTL8367/RTL8367C switch high-level API * - * Feature : The file includes time module high-layer API defination + * Feature : The file includes time module high-layer API definition * */ @@ -310,7 +310,7 @@ extern rtk_api_ret_t rtk_ptp_portEnable_get(rtk_port_t port, rtk_enable_t *pEnab /* Function Name: * rtk_ptp_portTimestamp_get * Description: - * Get PTP timstamp according to the PTP identifier on the dedicated port from the specified device. + * Get PTP timestamp according to the PTP identifier on the dedicated port from the specified device. * Input: * unit - unit id * port - port id diff --git a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/qos.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/qos.h index 4be417486..d2d8fac24 100644 --- a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/qos.h +++ b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/qos.h @@ -9,7 +9,7 @@ * * Purpose : RTL8367/RTL8367C switch high-level API * - * Feature : The file includes QoS module high-layer API defination + * Feature : The file includes QoS module high-layer API definition * */ @@ -123,7 +123,7 @@ typedef rtk_uint32 rtk_queue_num_t; /* queue number*/ /* Function Name: * rtk_qos_init * Description: - * Configure Qos default settings with queue number assigment to each port. + * Configure QoS default settings with queue number assignment to each port. * Input: * queueNum - Queue number of each port. * Output: @@ -135,7 +135,7 @@ typedef rtk_uint32 rtk_queue_num_t; /* queue number*/ * RT_ERR_QUEUE_NUM - Invalid queue number. * RT_ERR_INPUT - Invalid input parameters. * Note: - * This API will initialize related Qos setting with queue number assigment. + * This API will initialize related QoS setting with queue number assignment. * The queue number is from 1 to 8. */ extern rtk_api_ret_t rtk_qos_init(rtk_queue_num_t queueNum); @@ -235,7 +235,7 @@ extern rtk_api_ret_t rtk_qos_1pPriRemap_set(rtk_pri_t dot1p_pri, rtk_pri_t int_p * RT_ERR_VLAN_PRIORITY - Invalid priority. * RT_ERR_QOS_INT_PRIORITY - Invalid priority. * Note: - * Priority of 802.1Q assigment for internal asic priority, and it is uesed for queue usage and packet scheduling. + * Priority of 802.1Q assignment for internal asic priority, and it is used for queue usage and packet scheduling. */ extern rtk_api_ret_t rtk_qos_1pPriRemap_get(rtk_pri_t dot1p_pri, rtk_pri_t *pInt_pri); diff --git a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rate.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rate.h index 231ed01bb..b3cdf432f 100644 --- a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rate.h +++ b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rate.h @@ -9,7 +9,7 @@ * * Purpose : RTL8367/RTL8367C switch high-level API * - * Feature : The file includes rate module high-layer API defination + * Feature : The file includes rate module high-layer API definition * */ diff --git a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtk_error.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtk_error.h index dc9c0bed3..54d1a13f3 100644 --- a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtk_error.h +++ b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtk_error.h @@ -40,7 +40,7 @@ typedef enum rt_error_code_e RT_ERR_NULL_POINTER, /* 0x00000007, input parameter is null pointer */ RT_ERR_QUEUE_ID, /* 0x00000008, invalid queue id */ RT_ERR_QUEUE_NUM, /* 0x00000009, invalid queue number */ - RT_ERR_BUSYWAIT_TIMEOUT, /* 0x0000000a, busy watting time out */ + RT_ERR_BUSYWAIT_TIMEOUT, /* 0x0000000a, busy waiting time out */ RT_ERR_MAC, /* 0x0000000b, invalid mac address */ RT_ERR_OUT_OF_RANGE, /* 0x0000000c, input parameter out of range */ RT_ERR_CHIP_NOT_SUPPORTED, /* 0x0000000d, functions not supported by this chip model */ @@ -57,7 +57,7 @@ typedef enum rt_error_code_e /* 0x0001xxxx for vlan */ RT_ERR_VLAN_VID = 0x00010000, /* 0x00010000, invalid vid */ RT_ERR_VLAN_PRIORITY, /* 0x00010001, invalid 1p priority */ - RT_ERR_VLAN_EMPTY_ENTRY, /* 0x00010002, emtpy entry of vlan table */ + RT_ERR_VLAN_EMPTY_ENTRY, /* 0x00010002, empty entry of vlan table */ RT_ERR_VLAN_ACCEPT_FRAME_TYPE, /* 0x00010003, invalid accept frame type */ RT_ERR_VLAN_EXIST, /* 0x00010004, vlan is exist */ RT_ERR_VLAN_ENTRY_NOT_FOUND, /* 0x00010005, specified vlan entry not found */ @@ -165,7 +165,7 @@ typedef enum rt_error_code_e RT_ERR_INBW_TOKEN_AMOUNT, /* 0x000c0001, invalid amount of token for input bandwidth control */ RT_ERR_INBW_FCON_VALUE, /* 0x000c0002, invalid flow control ON threshold value for input bandwidth control */ RT_ERR_INBW_FCOFF_VALUE, /* 0x000c0003, invalid flow control OFF threshold value for input bandwidth control */ - RT_ERR_INBW_FC_ALLOWANCE, /* 0x000c0004, invalid allowance of incomming packet for input bandwidth control */ + RT_ERR_INBW_FC_ALLOWANCE, /* 0x000c0004, invalid allowance of incoming packet for input bandwidth control */ RT_ERR_INBW_RATE, /* 0x000c0005, invalid input bandwidth */ /* 0x000dxxxx for QoS */ @@ -220,7 +220,7 @@ typedef enum rt_error_code_e RT_ERR_DOT1X_PROC, /* 0x00110006, unauthorized behavior error */ RT_ERR_DOT1X_GVLANIDX, /* 0x00110007, guest vlan index error */ RT_ERR_DOT1X_GVLANTALK, /* 0x00110008, guest vlan OPDIR error */ - RT_ERR_DOT1X_MAC_PORT_MISMATCH, /* 0x00110009, Auth MAC and port mismatch eror */ + RT_ERR_DOT1X_MAC_PORT_MISMATCH, /* 0x00110009, Auth MAC and port mismatch error */ RT_ERR_END /* The symbol is the latest symbol */ } rt_error_code_t; diff --git a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtk_switch.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtk_switch.h index b0ca13682..0a43c0dbd 100644 --- a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtk_switch.h +++ b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtk_switch.h @@ -185,10 +185,10 @@ typedef enum rtk_switch_maxPktLen_linkSpeed_e { #define RTK_SCAN_ALL_LOG_PORT(__port__) for(__port__ = 0; __port__ < RTK_SWITCH_PORT_NUM; __port__++) if( rtk_switch_logicalPortCheck(__port__) == RT_ERR_OK) #define RTK_SCAN_ALL_LOG_PORTMASK(__portmask__) for((__portmask__).bits[0] = 0; (__portmask__).bits[0] < 0x7FFFF; (__portmask__).bits[0]++) if( rtk_switch_isPortMaskValid(&__portmask__) == RT_ERR_OK) -/* Port mask defination */ +/* Port mask definition */ #define RTK_PHY_PORTMASK_ALL (rtk_switch_phyPortMask_get()) -/* Port defination*/ +/* Port definition*/ #define RTK_MAX_LOGICAL_PORT_ID (rtk_switch_maxLogicalPort_get()) /* Function Name: @@ -477,7 +477,7 @@ extern rtk_api_ret_t rtk_switch_isPortMaskExt(rtk_portmask_t *pPmask); /* Function Name: * rtk_switch_portmask_L2P_get * Description: - * Get physicl portmask from logical portmask + * Get physical portmask from logical portmask * Input: * pLogicalPmask - logical port mask * Output: @@ -546,7 +546,7 @@ rtk_api_ret_t rtk_switch_logPortMask_get(rtk_portmask_t *pPortmask); /* Function Name: * rtk_switch_init * Description: - * Set chip to default configuration enviroment + * Set chip to default configuration environment * Input: * None * Output: diff --git a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtk_types.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtk_types.h index 589ecb781..cafc7ff9d 100644 --- a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtk_types.h +++ b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtk_types.h @@ -56,13 +56,13 @@ typedef enum rtk_enable_e #define ETHER_ADDR_LEN 6 #endif -/* ethernet address type */ +/* Ethernet address type */ typedef struct rtk_mac_s { rtk_uint8 octet[ETHER_ADDR_LEN]; } rtk_mac_t; -typedef rtk_uint32 rtk_pri_t; /* priority vlaue */ +typedef rtk_uint32 rtk_pri_t; /* priority value */ typedef rtk_uint32 rtk_qid_t; /* queue id type */ typedef rtk_uint32 rtk_data_t; typedef rtk_uint32 rtk_dscp_t; /* dscp vlaue */ diff --git a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_cputag.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_cputag.h index f7a460145..982e2c4bf 100644 --- a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_cputag.h +++ b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_cputag.h @@ -38,7 +38,7 @@ extern ret_t rtl8367c_setAsicCputagInsertMode(rtk_uint32 mode); extern ret_t rtl8367c_getAsicCputagInsertMode(rtk_uint32 *pMode); extern ret_t rtl8367c_setAsicCputagPriorityRemapping(rtk_uint32 srcPri, rtk_uint32 newPri); extern ret_t rtl8367c_getAsicCputagPriorityRemapping(rtk_uint32 srcPri, rtk_uint32 *pNewPri); -extern ret_t rtl8367c_setAsicCputagPosition(rtk_uint32 postion); +extern ret_t rtl8367c_setAsicCputagPosition(rtk_uint32 position); extern ret_t rtl8367c_getAsicCputagPosition(rtk_uint32* pPostion); extern ret_t rtl8367c_setAsicCputagMode(rtk_uint32 mode); extern ret_t rtl8367c_getAsicCputagMode(rtk_uint32 *pMode); diff --git a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_green.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_green.h index 38fd085d0..95c1b20bd 100644 --- a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_green.h +++ b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_green.h @@ -11,7 +11,7 @@ * $Date: 2017-03-08 15:13:58 +0800 (gT, 08 T 2017) $ * * Purpose : RTL8367C switch high-level API for RTL8367C - * Feature : Green ethernet related functions + * Feature : Green Ethernet related functions * */ diff --git a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_qos.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_qos.h index 26042bfa1..d0a899587 100644 --- a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_qos.h +++ b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_qos.h @@ -11,7 +11,7 @@ * $Date: 2017-03-08 15:13:58 +0800 (gT, 08 T 2017) $ * * Purpose : RTL8367C switch high-level API for RTL8367C - * Feature : Qos related functions + * Feature : QoS related functions * */ diff --git a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_unknownMulticast.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_unknownMulticast.h index d142d25cf..e492e715b 100644 --- a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_unknownMulticast.h +++ b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_asicdrv_unknownMulticast.h @@ -11,7 +11,7 @@ * $Date: 2017-03-08 15:13:58 +0800 (gT, 08 T 2017) $ * * Purpose : RTL8367C switch high-level API for RTL8367C - * Feature : Unkown multicast related functions + * Feature : Unknown multicast related functions * */ diff --git a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_base.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_base.h index 676ca8ed7..7a70e158f 100644 --- a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_base.h +++ b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_base.h @@ -11,7 +11,7 @@ * $Date: 2017-03-08 15:13:58 +0800 (gT, 08 T 2017) $ * * Purpose : RTL8367C switch high-level API for RTL8367C - * Feature : Regsiter MACRO related definition + * Feature : Register MACRO related definition * */ diff --git a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_reg.h b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_reg.h index eb4f48b83..f973c7bcb 100644 --- a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_reg.h +++ b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/include/rtl8367c_reg.h @@ -20357,8 +20357,8 @@ auto-generated register address and field data #define RTL8367C_IGMP_MLD_DISCARD_STORM_FILTER_MASK 0x2000 #define RTL8367C_REPORT_FORWARD_OFFSET 12 #define RTL8367C_REPORT_FORWARD_MASK 0x1000 -#define RTL8367C_ROBURSTNESS_VAR_OFFSET 9 -#define RTL8367C_ROBURSTNESS_VAR_MASK 0xE00 +#define RTL8367C_ROBUSTNESS_VAR_OFFSET 9 +#define RTL8367C_ROBUSTNESS_VAR_MASK 0xE00 #define RTL8367C_LEAVE_SUPPRESSION_OFFSET 8 #define RTL8367C_LEAVE_SUPPRESSION_MASK 0x100 #define RTL8367C_REPORT_SUPPRESSION_OFFSET 7 diff --git a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/l2.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/l2.c index feff0b240..e73199a4e 100644 --- a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/l2.c +++ b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/l2.c @@ -86,7 +86,7 @@ rtk_api_ret_t rtk_l2_init(void) * RT_ERR_L2_INDEXTBL_FULL - hashed index is full of entries. * RT_ERR_INPUT - Invalid input parameters. * Note: - * If the unicast mac address already existed in LUT, it will udpate the status of the entry. + * If the unicast mac address already existed in LUT, it will update the status of the entry. * Otherwise, it will find an empty or asic auto learned entry to write. If all the entries * with the same hash value can't be replaced, ASIC will return a RT_ERR_L2_INDEXTBL_FULL error. */ @@ -453,7 +453,7 @@ rtk_api_ret_t rtk_l2_addr_del(rtk_mac_t *pMac, rtk_l2_ucastAddr_t *pL2_data) * RT_ERR_PORT_MASK - Invalid portmask. * RT_ERR_INPUT - Invalid input parameters. * Note: - * If the multicast mac address already existed in the LUT, it will udpate the + * If the multicast mac address already existed in the LUT, it will update the * port mask of the entry. Otherwise, it will find an empty or asic auto learned * entry to write. If all the entries with the same hash value can't be replaced, * ASIC will return a RT_ERR_L2_INDEXTBL_FULL error. @@ -800,7 +800,7 @@ rtk_api_ret_t rtk_l2_mcastAddr_del(rtk_l2_mcastAddr_t *pMcastAddr) /* Function Name: * rtk_l2_ipMcastAddr_add * Description: - * Add Lut IP multicast entry + * Add LUT IP multicast entry * Input: * pIpMcastAddr - IP Multicast entry * Output: @@ -914,7 +914,7 @@ rtk_api_ret_t rtk_l2_ipMcastAddr_add(rtk_l2_ipMcastAddr_t *pIpMcastAddr) * RT_ERR_L2_ENTRY_NOTFOUND - No such LUT entry. * RT_ERR_INPUT - Invalid input parameters. * Note: - * The API can get Lut table of IP multicast entry. + * The API can get LUT table of IP multicast entry. */ rtk_api_ret_t rtk_l2_ipMcastAddr_get(rtk_l2_ipMcastAddr_t *pIpMcastAddr) { @@ -1080,7 +1080,7 @@ rtk_api_ret_t rtk_l2_ipMcastAddr_del(rtk_l2_ipMcastAddr_t *pIpMcastAddr) /* Function Name: * rtk_l2_ipVidMcastAddr_add * Description: - * Add Lut IP multicast+VID entry + * Add LUT IP multicast+VID entry * Input: * pIpVidMcastAddr - IP & VID multicast Entry * Output: @@ -2143,7 +2143,7 @@ rtk_api_ret_t rtk_l2_learningCnt_get(rtk_port_t port, rtk_mac_cnt_t *pMac_cnt) * Set flooding portmask * Input: * type - flooding type. - * pFlood_portmask - flooding porkmask + * pFlood_portmask - flooding portmask * Output: * None * Return: @@ -2204,7 +2204,7 @@ rtk_api_ret_t rtk_l2_floodPortMask_set(rtk_l2_flood_type_t floood_type, rtk_port * Input: * type - flooding type. * Output: - * pFlood_portmask - flooding porkmask + * pFlood_portmask - flooding portmask * Return: * RT_ERR_OK - OK * RT_ERR_FAILED - Failed @@ -2259,10 +2259,10 @@ rtk_api_ret_t rtk_l2_floodPortMask_get(rtk_l2_flood_type_t floood_type, rtk_port /* Function Name: * rtk_l2_localPktPermit_set * Description: - * Set permittion of frames if source port and destination port are the same. + * Set permission of frames if source port and destination port are the same. * Input: * port - Port id. - * permit - permittion status + * permit - permission status * Output: * None * Return: @@ -2272,7 +2272,7 @@ rtk_api_ret_t rtk_l2_floodPortMask_get(rtk_l2_flood_type_t floood_type, rtk_port * RT_ERR_PORT_ID - Invalid port number. * RT_ERR_ENABLE - Invalid permit value. * Note: - * This API is setted to permit frame if its source port is equal to destination port. + * This API is set to permit frame if its source port is equal to destination port. */ rtk_api_ret_t rtk_l2_localPktPermit_set(rtk_port_t port, rtk_enable_t permit) { @@ -2296,18 +2296,18 @@ rtk_api_ret_t rtk_l2_localPktPermit_set(rtk_port_t port, rtk_enable_t permit) /* Function Name: * rtk_l2_localPktPermit_get * Description: - * Get permittion of frames if source port and destination port are the same. + * Get permission of frames if source port and destination port are the same. * Input: * port - Port id. * Output: - * pPermit - permittion status + * pPermit - permission status * Return: * RT_ERR_OK - OK * RT_ERR_FAILED - Failed * RT_ERR_SMI - SMI access error * RT_ERR_PORT_ID - Invalid port number. * Note: - * This API is to get permittion status for frames if its source port is equal to destination port. + * This API is to get permission status for frames if its source port is equal to destination port. */ rtk_api_ret_t rtk_l2_localPktPermit_get(rtk_port_t port, rtk_enable_t *pPermit) { @@ -2331,9 +2331,9 @@ rtk_api_ret_t rtk_l2_localPktPermit_get(rtk_port_t port, rtk_enable_t *pPermit) /* Function Name: * rtk_l2_aging_set * Description: - * Set LUT agging out speed + * Set LUT ageing out speed * Input: - * aging_time - Agging out time. + * aging_time - Ageing out time. * Output: * None * Return: @@ -2342,7 +2342,7 @@ rtk_api_ret_t rtk_l2_localPktPermit_get(rtk_port_t port, rtk_enable_t *pPermit) * RT_ERR_SMI - SMI access error * RT_ERR_OUT_OF_RANGE - input out of range. * Note: - * The API can set LUT agging out period for each entry and the range is from 45s to 458s. + * The API can set LUT ageing out period for each entry and the range is from 45s to 458s. */ rtk_api_ret_t rtk_l2_aging_set(rtk_l2_age_time_t aging_time) { @@ -2371,7 +2371,7 @@ rtk_api_ret_t rtk_l2_aging_set(rtk_l2_age_time_t aging_time) /* Function Name: * rtk_l2_aging_get * Description: - * Get LUT agging out time + * Get LUT ageing out time * Input: * None * Output: @@ -2382,7 +2382,7 @@ rtk_api_ret_t rtk_l2_aging_set(rtk_l2_age_time_t aging_time) * RT_ERR_SMI - SMI access error * RT_ERR_PORT_ID - Invalid port number. * Note: - * The API can get LUT agging out period for each entry. + * The API can get LUT ageing out period for each entry. */ rtk_api_ret_t rtk_l2_aging_get(rtk_l2_age_time_t *pAging_time) { @@ -2416,7 +2416,7 @@ rtk_api_ret_t rtk_l2_aging_get(rtk_l2_age_time_t *pAging_time) /* Function Name: * rtk_l2_ipMcastAddrLookup_set * Description: - * Set Lut IP multicast lookup function + * Set LUT IP multicast lookup function * Input: * type - Lookup type for IPMC packet. * Output: @@ -2473,7 +2473,7 @@ rtk_api_ret_t rtk_l2_ipMcastAddrLookup_set(rtk_l2_ipmc_lookup_type_t type) /* Function Name: * rtk_l2_ipMcastAddrLookup_get * Description: - * Get Lut IP multicast lookup function + * Get LUT IP multicast lookup function * Input: * None. * Output: @@ -2518,9 +2518,9 @@ rtk_api_ret_t rtk_l2_ipMcastAddrLookup_get(rtk_l2_ipmc_lookup_type_t *pType) /* Function Name: * rtk_l2_ipMcastForwardRouterPort_set * Description: - * Set IPMC packet forward to rounter port also or not + * Set IPMC packet forward to router port also or not * Input: - * enabled - 1: Inlcude router port, 0, exclude router port + * enabled - 1: Include router port, 0, exclude router port * Output: * None. * Return: @@ -2549,11 +2549,11 @@ rtk_api_ret_t rtk_l2_ipMcastForwardRouterPort_set(rtk_enable_t enabled) /* Function Name: * rtk_l2_ipMcastForwardRouterPort_get * Description: - * Get IPMC packet forward to rounter port also or not + * Get IPMC packet forward to router port also or not * Input: * None. * Output: - * pEnabled - 1: Inlcude router port, 0, exclude router port + * pEnabled - 1: Include router port, 0, exclude router port * Return: * RT_ERR_OK - OK * RT_ERR_FAILED - Failed diff --git a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/led.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/led.c index c00c331d8..02e0829dc 100644 --- a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/led.c +++ b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/led.c @@ -27,7 +27,7 @@ /* Function Name: * rtk_led_enable_set * Description: - * Set Led enable congiuration + * Set Led enable configuration * Input: * group - LED group id. * pPortmask - LED enable port mask. @@ -74,7 +74,7 @@ rtk_api_ret_t rtk_led_enable_set(rtk_led_group_t group, rtk_portmask_t *pPortmas /* Function Name: * rtk_led_enable_get * Description: - * Get Led enable congiuration + * Get Led enable configuration * Input: * group - LED group id. * Output: @@ -205,7 +205,7 @@ rtk_api_ret_t rtk_led_operation_get(rtk_led_operation_t *pMode) /* Function Name: * rtk_led_modeForce_set * Description: - * Set Led group to congiuration force mode + * Set Led group to configuration force mode * Input: * port - port ID * group - Support LED group id. @@ -255,7 +255,7 @@ rtk_api_ret_t rtk_led_modeForce_set(rtk_port_t port, rtk_led_group_t group, rtk_ /* Function Name: * rtk_led_modeForce_get * Description: - * Get Led group to congiuration force mode + * Get Led group to configuration force mode * Input: * port - port ID * group - Support LED group id. @@ -369,7 +369,7 @@ rtk_api_ret_t rtk_led_blinkRate_get(rtk_led_blink_rate_t *pBlinkRate) /* Function Name: * rtk_led_groupConfig_set * Description: - * Set per group Led to congiuration mode + * Set per group Led to configuration mode * Input: * group - LED group. * config - LED configuration @@ -422,7 +422,7 @@ rtk_api_ret_t rtk_led_groupConfig_set(rtk_led_group_t group, rtk_led_congig_t co /* Function Name: * rtk_led_groupConfig_get * Description: - * Get Led group congiuration mode + * Get Led group configuration mode * Input: * group - LED group. * Output: @@ -583,7 +583,7 @@ rtk_api_ret_t rtk_led_groupAbility_get(rtk_led_group_t group, rtk_led_ability_t /* Function Name: * rtk_led_serialMode_set * Description: - * Set Led serial mode active congiuration + * Set Led serial mode active configuration * Input: * active - LED group. * Output: @@ -594,7 +594,7 @@ rtk_api_ret_t rtk_led_groupAbility_get(rtk_led_group_t group, rtk_led_ability_t * RT_ERR_SMI - SMI access error * RT_ERR_INPUT - Invalid input parameters. * Note: - * The API can set LED serial mode active congiuration. + * The API can set LED serial mode active configuration. */ rtk_api_ret_t rtk_led_serialMode_set(rtk_led_active_t active) { diff --git a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/mirror.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/mirror.c index 1921d1a5a..3bbad8adb 100644 --- a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/mirror.c +++ b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/mirror.c @@ -66,7 +66,7 @@ rtk_api_ret_t rtk_mirror_portBased_set(rtk_port_t mirroring_port, rtk_portmask_t RTK_CHK_PORTMASK_VALID(pMirrored_tx_portmask); - /*Mirror Sorce Port Mask Check*/ + /*Mirror Source Port Mask Check*/ if (pMirrored_tx_portmask->bits[0]!=pMirrored_rx_portmask->bits[0]&&pMirrored_tx_portmask->bits[0]!=0&&pMirrored_rx_portmask->bits[0]!=0) return RT_ERR_PORT_MASK; @@ -353,7 +353,7 @@ rtk_api_ret_t rtk_mirror_vlanLeaky_get(rtk_enable_t *pTxenable, rtk_enable_t *pR * RT_ERR_SMI - SMI access error * RT_ERR_ENABLE - Invalid enable input * Note: - * The API is to set mirror VLAN leaky function forwarding packets to miror port. + * The API is to set mirror VLAN leaky function forwarding packets to mirror port. */ rtk_api_ret_t rtk_mirror_isolationLeaky_set(rtk_enable_t txenable, rtk_enable_t rxenable) { diff --git a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/port.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/port.c index 9f99d1b3d..9c7bcd0e3 100644 --- a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/port.c +++ b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/port.c @@ -410,7 +410,7 @@ static rtk_api_ret_t _rtk_port_FiberModeAbility_get(rtk_port_t port, rtk_port_ph /* Function Name: * rtk_port_phyAutoNegoAbility_set * Description: - * Set ethernet PHY auto-negotiation desired ability. + * Set Ethernet PHY auto-negotiation desired ability. * Input: * port - port id. * pAbility - Ability structure @@ -618,7 +618,7 @@ rtk_api_ret_t rtk_port_phyAutoNegoAbility_set(rtk_port_t port, rtk_port_phy_abil * RT_ERR_INPUT - Invalid input parameters. * RT_ERR_BUSYWAIT_TIMEOUT - PHY access busy * Note: - * Get the capablity of specified PHY. + * Get the capability of specified PHY. */ rtk_api_ret_t rtk_port_phyAutoNegoAbility_get(rtk_port_t port, rtk_port_phy_ability_t *pAbility) { @@ -836,7 +836,7 @@ rtk_api_ret_t rtk_port_phyForceModeAbility_set(rtk_port_t port, rtk_port_phy_abi if (1 == pAbility->AsyFC) { - /*Asymetric flow control in reg 4.11*/ + /*Asymmetric flow control in reg 4.11*/ phyEnMsk4 = phyEnMsk4 | (1 << 11); } if (1 == pAbility->FC) @@ -892,7 +892,7 @@ rtk_api_ret_t rtk_port_phyForceModeAbility_set(rtk_port_t port, rtk_port_phy_abi * RT_ERR_INPUT - Invalid input parameters. * RT_ERR_BUSYWAIT_TIMEOUT - PHY access busy * Note: - * Get the capablity of specified PHY. + * Get the capability of specified PHY. */ rtk_api_ret_t rtk_port_phyForceModeAbility_get(rtk_port_t port, rtk_port_phy_ability_t *pAbility) { @@ -982,7 +982,7 @@ rtk_api_ret_t rtk_port_phyForceModeAbility_get(rtk_port_t port, rtk_port_phy_abi /* Function Name: * rtk_port_phyStatus_get * Description: - * Get ethernet PHY linking status + * Get Ethernet PHY linking status * Input: * port - Port id. * Output: @@ -1363,7 +1363,7 @@ rtk_api_ret_t rtk_port_macStatus_get(rtk_port_t port, rtk_port_mac_ability_t *pP * For UTP port, This API will also enable the digital * loopback bit in PHY register for sync of speed between * PHY and MAC. For EXT port, users need to force the - * link state by themself. + * link state by themselves. */ rtk_api_ret_t rtk_port_macLocalLoopbackEnable_set(rtk_port_t port, rtk_enable_t enable) { @@ -1508,7 +1508,7 @@ rtk_api_ret_t rtk_port_phyReg_get(rtk_port_t port, rtk_port_phy_reg_t reg, rtk_p /* Function Name: * rtk_port_backpressureEnable_set * Description: - * Set the half duplex backpressure enable status of the specific port. + * Set the half duplex back-pressure enable status of the specific port. * Input: * port - port id. * enable - Back pressure status. @@ -1521,10 +1521,10 @@ rtk_api_ret_t rtk_port_phyReg_get(rtk_port_t port, rtk_port_phy_reg_t reg, rtk_p * RT_ERR_PORT_ID - Invalid port number. * RT_ERR_ENABLE - Invalid enable input. * Note: - * This API can set the half duplex backpressure enable status of the specific port. - * The half duplex backpressure enable status of the port is as following: + * This API can set the half duplex back-pressure enable status of the specific port. + * The half duplex back-pressure enable status of the port is as following: * - DISABLE(Defer) - * - ENABLE (Backpressure) + * - ENABLE (Back-pressure) */ rtk_api_ret_t rtk_port_backpressureEnable_set(rtk_port_t port, rtk_enable_t enable) { @@ -1548,7 +1548,7 @@ rtk_api_ret_t rtk_port_backpressureEnable_set(rtk_port_t port, rtk_enable_t enab /* Function Name: * rtk_port_backpressureEnable_get * Description: - * Get the half duplex backpressure enable status of the specific port. + * Get the half duplex back-pressure enable status of the specific port. * Input: * port - Port id. * Output: @@ -1559,10 +1559,10 @@ rtk_api_ret_t rtk_port_backpressureEnable_set(rtk_port_t port, rtk_enable_t enab * RT_ERR_SMI - SMI access error * RT_ERR_PORT_ID - Invalid port number. * Note: - * This API can get the half duplex backpressure enable status of the specific port. - * The half duplex backpressure enable status of the port is as following: + * This API can get the half duplex back-pressure enable status of the specific port. + * The half duplex back-pressure enable status of the port is as following: * - DISABLE(Defer) - * - ENABLE (Backpressure) + * - ENABLE (Back-pressure) */ rtk_api_ret_t rtk_port_backpressureEnable_get(rtk_port_t port, rtk_enable_t *pEnable) { @@ -1643,7 +1643,7 @@ rtk_api_ret_t rtk_port_adminEnable_set(rtk_port_t port, rtk_enable_t enable) /* Function Name: * rtk_port_adminEnable_get * Description: - * Get port admin configurationof the specific port. + * Get port admin configuration of the specific port. * Input: * port - Port id. * Output: @@ -1704,7 +1704,7 @@ rtk_api_ret_t rtk_port_adminEnable_get(rtk_port_t port, rtk_enable_t *pEnable) * RT_ERR_PORT_ID - Invalid port number. * RT_ERR_PORT_MASK - Invalid portmask. * Note: - * This API set the port mask that a port can trasmit packet to of each port + * This API set the port mask that a port can transmit packet to of each port * A port can only transmit packet to ports included in permitted portmask */ rtk_api_ret_t rtk_port_isolation_set(rtk_port_t port, rtk_portmask_t *pPortmask) @@ -1747,7 +1747,7 @@ rtk_api_ret_t rtk_port_isolation_set(rtk_port_t port, rtk_portmask_t *pPortmask) * RT_ERR_SMI - SMI access error * RT_ERR_PORT_ID - Invalid port number. * Note: - * This API get the port mask that a port can trasmit packet to of each port + * This API get the port mask that a port can transmit packet to of each port * A port can only transmit packet to ports included in permitted portmask */ rtk_api_ret_t rtk_port_isolation_get(rtk_port_t port, rtk_portmask_t *pPortmask) @@ -1790,7 +1790,7 @@ rtk_api_ret_t rtk_port_isolation_get(rtk_port_t port, rtk_portmask_t *pPortmask) * Note: * This API can set external interface 2 RGMII delay. * In TX delay, there are 2 selection: no-delay and 2ns delay. - * In RX dekay, there are 8 steps for delay tunning. 0 for no-delay, and 7 for maximum delay. + * In RX delay, there are 8 steps for delay tuning. 0 for no-delay, and 7 for maximum delay. */ rtk_api_ret_t rtk_port_rgmiiDelayExt_set(rtk_port_t port, rtk_data_t txDelay, rtk_data_t rxDelay) { @@ -1841,7 +1841,7 @@ rtk_api_ret_t rtk_port_rgmiiDelayExt_set(rtk_port_t port, rtk_data_t txDelay, rt * Note: * This API can set external interface 2 RGMII delay. * In TX delay, there are 2 selection: no-delay and 2ns delay. - * In RX dekay, there are 8 steps for delay tunning. 0 for n0-delay, and 7 for maximum delay. + * In RX delay, there are 8 steps for delay tuning. 0 for n0-delay, and 7 for maximum delay. */ rtk_api_ret_t rtk_port_rgmiiDelayExt_get(rtk_port_t port, rtk_data_t *pTxDelay, rtk_data_t *pRxDelay) { diff --git a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/ptp.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/ptp.c index 40962a0e6..af8ce3091 100644 --- a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/ptp.c +++ b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/ptp.c @@ -401,7 +401,7 @@ rtk_api_ret_t rtk_ptp_portEnable_get(rtk_port_t port, rtk_enable_t *pEnable) /* Function Name: * rtk_ptp_portTimestamp_get * Description: - * Get PTP timstamp according to the PTP identifier on the dedicated port from the specified device. + * Get PTP timestamp according to the PTP identifier on the dedicated port from the specified device. * Input: * unit - unit id * port - port id diff --git a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/qos.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/qos.c index 70067a301..9bcb49cfb 100644 --- a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/qos.c +++ b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/qos.c @@ -28,7 +28,7 @@ /* Function Name: * rtk_qos_init * Description: - * Configure Qos default settings with queue number assigment to each port. + * Configure QoS default settings with queue number assignment to each port. * Input: * queueNum - Queue number of each port. * Output: @@ -40,7 +40,7 @@ * RT_ERR_QUEUE_NUM - Invalid queue number. * RT_ERR_INPUT - Invalid input parameters. * Note: - * This API will initialize related Qos setting with queue number assigment. + * This API will initialize related QoS setting with queue number assignment. * The queue number is from 1 to 8. */ rtk_api_ret_t rtk_qos_init(rtk_queue_num_t queueNum) @@ -143,7 +143,7 @@ rtk_api_ret_t rtk_qos_init(rtk_queue_num_t queueNum) return retVal; } - /* Finetune B/T value */ + /* Fine-tune B/T value */ if((retVal = rtl8367c_setAsicReg(0x1722, 0x1158)) != RT_ERR_OK) return retVal; @@ -455,7 +455,7 @@ rtk_api_ret_t rtk_qos_1pPriRemap_set(rtk_pri_t dot1p_pri, rtk_pri_t int_pri) * RT_ERR_VLAN_PRIORITY - Invalid priority. * RT_ERR_QOS_INT_PRIORITY - Invalid priority. * Note: - * Priority of 802.1Q assigment for internal asic priority, and it is uesed for queue usage and packet scheduling. + * Priority of 802.1Q assignment for internal asic priority, and it is used for queue usage and packet scheduling. */ rtk_api_ret_t rtk_qos_1pPriRemap_get(rtk_pri_t dot1p_pri, rtk_pri_t *pInt_pri) { diff --git a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rldp.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rldp.c index d3ca02975..0ecc32a6b 100644 --- a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rldp.c +++ b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rldp.c @@ -8,7 +8,7 @@ * available at https://www.gnu.org/licenses/old-licenses/gpl-2.0.txt * * $Revision: 76306 $ - * $Date: 2017-03-08 15:13:58 +0800 (gT, 08 T 2017) $ + * $Date: 2017-03-08 15:13:58 +0800 (週三, 08 三月 2017) $ * * Purpose : Declaration of RLDP and RLPP API * @@ -404,7 +404,7 @@ rtk_api_ret_t rtk_rldp_portStatus_get(rtk_port_t port, rtk_rldp_portStatus_t *pP * RT_ERR_NULL_POINTER * Note: * Clear operation effect loop_enter and loop_leave only, other field in - * the structure are don't care. Loop status cab't be clean. + * the structure are don't care. Loop status can't be clean. */ rtk_api_ret_t rtk_rldp_portStatus_set(rtk_port_t port, rtk_rldp_portStatus_t *pPortStatus) { diff --git a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtk_switch.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtk_switch.c index 0bb0db077..20542f259 100644 --- a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtk_switch.c +++ b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtk_switch.c @@ -152,7 +152,7 @@ static rtk_switch_halCtrl_t rtl8370b_hal_Ctrl = /* Minimum physical port number */ 0, - /* Maxmum physical port number */ + /* Maximum physical port number */ 10, /* Physical port mask */ @@ -221,7 +221,7 @@ static rtk_switch_halCtrl_t rtl8364b_hal_Ctrl = /* Minimum physical port number */ 0, - /* Maxmum physical port number */ + /* Maximum physical port number */ 7, /* Physical port mask */ @@ -290,7 +290,7 @@ static rtk_switch_halCtrl_t rtl8363sc_vb_hal_Ctrl = /* Minimum physical port number */ 0, - /* Maxmum physical port number */ + /* Maximum physical port number */ 7, /* Physical port mask */ @@ -1215,7 +1215,7 @@ rtk_api_ret_t rtk_switch_isPortMaskExt(rtk_portmask_t *pPmask) /* Function Name: * rtk_switch_portmask_L2P_get * Description: - * Get physicl portmask from logical portmask + * Get physical portmask from logical portmask * Input: * pLogicalPmask - logical port mask * Output: @@ -1351,7 +1351,7 @@ rtk_api_ret_t rtk_switch_logPortMask_get(rtk_portmask_t *pPortmask) /* Function Name: * rtk_switch_init * Description: - * Set chip to default configuration enviroment + * Set chip to default configuration environment * Input: * None * Output: diff --git a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_acl.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_acl.c index d9ccd9711..1e4d2961e 100644 --- a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_acl.c +++ b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_acl.c @@ -173,7 +173,7 @@ static void _rtl8367c_aclActStUser2Smi(rtl8367c_acl_act_t *pAclUser, rtk_uint16 /* Function Name: * rtl8367c_setAsicAcl * Description: - * Set port acl function enable/disable + * Set port ACL function enable/disable * Input: * port - Physical port number (0~10) * enabled - 1: enabled, 0: disabled @@ -196,7 +196,7 @@ ret_t rtl8367c_setAsicAcl(rtk_uint32 port, rtk_uint32 enabled) /* Function Name: * rtl8367c_getAsicAcl * Description: - * Get port acl function enable/disable + * Get port ACL function enable/disable * Input: * port - Physical port number (0~10) * enabled - 1: enabled, 0: disabled @@ -219,7 +219,7 @@ ret_t rtl8367c_getAsicAcl(rtk_uint32 port, rtk_uint32* pEnabled) /* Function Name: * rtl8367c_setAsicAclUnmatchedPermit * Description: - * Set port acl function unmatched permit action + * Set port ACL function unmatched permit action * Input: * port - Physical port number (0~10) * enabled - 1: enabled, 0: disabled @@ -242,7 +242,7 @@ ret_t rtl8367c_setAsicAclUnmatchedPermit(rtk_uint32 port, rtk_uint32 enabled) /* Function Name: * rtl8367c_getAsicAclUnmatchedPermit * Description: - * Get port acl function unmatched permit action + * Get port ACL function unmatched permit action * Input: * port - Physical port number (0~10) * enabled - 1: enabled, 0: disabled @@ -266,10 +266,10 @@ ret_t rtl8367c_getAsicAclUnmatchedPermit(rtk_uint32 port, rtk_uint32* pEnabled) /* Function Name: * rtl8367c_setAsicAclRule * Description: - * Set acl rule content + * Set ACL rule content * Input: * index - ACL rule index (0-95) of 96 ACL rules - * pAclRule - ACL rule stucture for setting + * pAclRule - ACL rule structure for setting * Output: * None * Return: @@ -278,8 +278,8 @@ ret_t rtl8367c_getAsicAclUnmatchedPermit(rtk_uint32 port, rtk_uint32* pEnabled) * RT_ERR_OUT_OF_RANGE - Invalid ACL rule index (0-95) * Note: * System supported 95 shared 289-bit ACL ingress rule. Index was available at range 0-95 only. - * If software want to modify ACL rule, the ACL function should be disable at first or unspecify - * acl action will be executed. + * If software want to modify ACL rule, the ACL function should be disabled at first or unspecified + * ACL action will be executed. * One ACL rule structure has three parts setting: * Bit 0-147 Data Bits of this Rule * Bit 148 Valid Bit @@ -410,10 +410,10 @@ ret_t rtl8367c_setAsicAclRule(rtk_uint32 index, rtl8367c_aclrule* pAclRule) /* Function Name: * rtl8367c_getAsicAclRule * Description: - * Get acl rule content + * Get ACL rule content * Input: * index - ACL rule index (0-63) of 64 ACL rules - * pAclRule - ACL rule stucture for setting + * pAclRule - ACL rule structure for setting * Output: * None * Return: @@ -588,7 +588,7 @@ ret_t rtl8367c_getAsicAclNot(rtk_uint32 index, rtk_uint32* pNot) * Set fields of a ACL Template * Input: * index - ACL template index(0~4) - * pAclType - ACL type stucture for setting + * pAclType - ACL type structure for setting * Output: * None * Return: @@ -598,7 +598,7 @@ ret_t rtl8367c_getAsicAclNot(rtk_uint32 index, rtk_uint32* pNot) * Note: * The API can set type field of the 5 ACL rule templates. * Each type has 8 fields. One field means what data in one field of a ACL rule means - * 8 fields of ACL rule 0~95 is descripted by one type in ACL group + * 8 fields of ACL rule 0~95 is described by one type in ACL group */ ret_t rtl8367c_setAsicAclTemplate(rtk_uint32 index, rtl8367c_acltemplate_t* pAclType) { @@ -630,7 +630,7 @@ ret_t rtl8367c_setAsicAclTemplate(rtk_uint32 index, rtl8367c_acltemplate_t* pAcl * Get fields of a ACL Template * Input: * index - ACL template index(0~4) - * pAclType - ACL type stucture for setting + * pAclType - ACL type structure for setting * Output: * None * Return: @@ -669,7 +669,7 @@ ret_t rtl8367c_getAsicAclTemplate(rtk_uint32 index, rtl8367c_acltemplate_t *pAcl * Set ACL rule matched Action * Input: * index - ACL rule index (0-95) of 96 ACL rules - * pAclAct - ACL action stucture for setting + * pAclAct - ACL action structure for setting * Output: * None * Return: @@ -734,7 +734,7 @@ ret_t rtl8367c_setAsicAclAct(rtk_uint32 index, rtl8367c_acl_act_t* pAclAct) * Get ACL rule matched Action * Input: * index - ACL rule index (0-95) of 96 ACL rules - * pAclAct - ACL action stucture for setting + * pAclAct - ACL action structure for setting * Output: * None * Return: @@ -1137,7 +1137,7 @@ ret_t rtl8367c_getAsicAclIpRange(rtk_uint32 index, rtk_uint32* pType, ipaddr_t* /* Function Name: * rtl8367c_setAsicAclGpioPolarity * Description: - * Set ACL Goip control palarity + * Set ACL Goip control polarity * Input: * polarity - 1: High, 0: Low * Output: @@ -1155,7 +1155,7 @@ ret_t rtl8367c_setAsicAclGpioPolarity(rtk_uint32 polarity) /* Function Name: * rtl8367c_getAsicAclGpioPolarity * Description: - * Get ACL Goip control palarity + * Get ACL Goip control polarity * Input: * pPolarity - 1: High, 0: Low * Output: diff --git a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_cputag.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_cputag.c index d22bf65ea..ec9c332e1 100644 --- a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_cputag.c +++ b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_cputag.c @@ -18,7 +18,7 @@ /* Function Name: * rtl8367c_setAsicCputagEnable * Description: - * Set cpu tag function enable/disable + * Set CPU tag function enable/disable * Input: * enabled - 1: enabled, 0: disabled * Output: @@ -41,7 +41,7 @@ ret_t rtl8367c_setAsicCputagEnable(rtk_uint32 enabled) /* Function Name: * rtl8367c_getAsicCputagEnable * Description: - * Get cpu tag function enable/disable + * Get CPU tag function enable/disable * Input: * pEnabled - 1: enabled, 0: disabled * Output: @@ -59,7 +59,7 @@ ret_t rtl8367c_getAsicCputagEnable(rtk_uint32 *pEnabled) /* Function Name: * rtl8367c_setAsicCputagTrapPort * Description: - * Set cpu tag trap port + * Set CPU tag trap port * Input: * port - port number * Output: @@ -91,7 +91,7 @@ ret_t rtl8367c_setAsicCputagTrapPort(rtk_uint32 port) /* Function Name: * rtl8367c_getAsicCputagTrapPort * Description: - * Get cpu tag trap port + * Get CPU tag trap port * Input: * pPort - port number * Output: @@ -248,9 +248,9 @@ ret_t rtl8367c_getAsicCputagPriorityRemapping(rtk_uint32 srcPri, rtk_uint32 *pNe /* Function Name: * rtl8367c_setAsicCputagPosition * Description: - * Set cpu tag insert position + * Set CPU tag insert position * Input: - * postion - 1: After entire packet(before CRC field), 0: After MAC_SA (Default) + * position - 1: After entire packet(before CRC field), 0: After MAC_SA (Default) * Output: * None * Return: @@ -259,14 +259,14 @@ ret_t rtl8367c_getAsicCputagPriorityRemapping(rtk_uint32 srcPri, rtk_uint32 *pNe * Note: * None */ -ret_t rtl8367c_setAsicCputagPosition(rtk_uint32 postion) +ret_t rtl8367c_setAsicCputagPosition(rtk_uint32 position) { - return rtl8367c_setAsicRegBit(RTL8367C_REG_CPU_CTRL, RTL8367C_CPU_TAG_POSITION_OFFSET, postion); + return rtl8367c_setAsicRegBit(RTL8367C_REG_CPU_CTRL, RTL8367C_CPU_TAG_POSITION_OFFSET, position); } /* Function Name: * rtl8367c_getAsicCputagPosition * Description: - * Get cpu tag insert position + * Get CPU tag insert position * Input: * pPostion - 1: After entire packet(before CRC field), 0: After MAC_SA (Default) * Output: @@ -285,7 +285,7 @@ ret_t rtl8367c_getAsicCputagPosition(rtk_uint32* pPostion) /* Function Name: * rtl8367c_setAsicCputagMode * Description: - * Set cpu tag mode + * Set CPU tag mode * Input: * mode - 1: 4bytes mode, 0: 8bytes mode * Output: @@ -308,7 +308,7 @@ ret_t rtl8367c_setAsicCputagMode(rtk_uint32 mode) /* Function Name: * rtl8367c_getAsicCputagMode * Description: - * Get cpu tag mode + * Get CPU tag mode * Input: * pMode - 1: 4bytes mode, 0: 8bytes mode * Output: @@ -326,7 +326,7 @@ ret_t rtl8367c_getAsicCputagMode(rtk_uint32 *pMode) /* Function Name: * rtl8367c_setAsicCputagRxMinLength * Description: - * Set cpu tag mode + * Set CPU tag mode * Input: * mode - 1: 64bytes, 0: 72bytes * Output: @@ -349,7 +349,7 @@ ret_t rtl8367c_setAsicCputagRxMinLength(rtk_uint32 mode) /* Function Name: * rtl8367c_getAsicCputagRxMinLength * Description: - * Get cpu tag mode + * Get CPU tag mode * Input: * pMode - 1: 64bytes, 0: 72bytes * Output: diff --git a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_eav.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_eav.c index 370b7c6f3..811ee4795 100644 --- a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_eav.c +++ b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_eav.c @@ -100,7 +100,7 @@ ret_t rtl8367c_getAsicEavMacAddress(ether_addr_t *pMac) * Description: * Set PTP parser tag TPID. * Input: - * outerTag - outter tag TPID + * outerTag - outer tag TPID * innerTag - inner tag TPID * Output: * None @@ -128,7 +128,7 @@ ret_t rtl8367c_setAsicEavTpid(rtk_uint32 outerTag, rtk_uint32 innerTag) * Input: * None * Output: - * pOuterTag - outter tag TPID + * pOuterTag - outer tag TPID * pInnerTag - inner tag TPID * Return: * RT_ERR_OK - Success @@ -161,7 +161,7 @@ ret_t rtl8367c_getAsicEavTpid(rtk_uint32* pOuterTag, rtk_uint32* pInnerTag) * RT_ERR_OK - Success * RT_ERR_SMI - SMI access error * Note: - * The time granuality is 8 nano seconds. + * The time granularity is 8 nano seconds. */ ret_t rtl8367c_setAsicEavSysTime(rtk_uint32 second, rtk_uint32 nanoSecond) { @@ -218,7 +218,7 @@ ret_t rtl8367c_setAsicEavSysTime(rtk_uint32 second, rtk_uint32 nanoSecond) * RT_ERR_OK - Success * RT_ERR_SMI - SMI access error * Note: - * The time granuality is 8 nano seconds. + * The time granularity is 8 nano seconds. */ ret_t rtl8367c_getAsicEavSysTime(rtk_uint32* pSecond, rtk_uint32* pNanoSecond) { @@ -265,7 +265,7 @@ ret_t rtl8367c_getAsicEavSysTime(rtk_uint32* pSecond, rtk_uint32* pNanoSecond) * Description: * Set PTP system time adjust * Input: - * type - incresae or decrease + * type - increase or decrease * second - seconds * nanoSecond - nano seconds * Output: @@ -481,7 +481,7 @@ ret_t rtl8367c_getAsicEavInterruptStatus(rtk_uint32* pIms) * RT_ERR_OK - Success * RT_ERR_SMI - SMI access error * Note: - * This API can be used to clear ASIC interrupt status and register will be cleared by writting 1. + * This API can be used to clear ASIC interrupt status and register will be cleared by writing 1. * [0]:TX_SYNC, * [1]:TX_DELAY, * [2]:TX_PDELAY_REQ, @@ -570,7 +570,7 @@ ret_t rtl8367c_getAsicEavPortInterruptStatus(rtk_uint32 port, rtk_uint32* pIms) * RT_ERR_SMI - SMI access error * RT_ERR_PORT_ID - Invalid port number * Note: - * If EAV function is enabled, PTP event messgae packet will be attached PTP timestamp for trapping + * If EAV function is enabled, PTP event message packet will be attached PTP timestamp for trapping */ ret_t rtl8367c_setAsicEavPortEnable(rtk_uint32 port, rtk_uint32 enabled) { @@ -646,7 +646,7 @@ ret_t rtl8367c_getAsicEavPortEnable(rtk_uint32 port, rtk_uint32 *pEnabled) * RT_ERR_OK - Success * RT_ERR_SMI - SMI access error * Note: - * The time granuality is 8 nano seconds. + * The time granularity is 8 nano seconds. */ ret_t rtl8367c_getAsicEavPortTimeStamp(rtk_uint32 port, rtk_uint32 type, rtl8367c_ptp_time_stamp_t* timeStamp) { @@ -796,7 +796,7 @@ ret_t rtl8367c_getAsicEavTrap(rtk_uint32 port, rtk_uint32 *pEnabled) * RT_ERR_SMI - SMI access error * RT_ERR_PORT_ID - Invalid port number * Note: - * If EAV function is enabled, PTP event messgae packet will be attached PTP timestamp for trapping + * If EAV function is enabled, PTP event message packet will be attached PTP timestamp for trapping */ ret_t rtl8367c_setAsicEavEnable(rtk_uint32 port, rtk_uint32 enabled) { diff --git a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_fc.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_fc.c index 28f49b1ba..b7b102243 100644 --- a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_fc.c +++ b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_fc.c @@ -55,7 +55,7 @@ ret_t rtl8367c_getAsicFlowControlSelect(rtk_uint32 *pSelect) /* Function Name: * rtl8367c_setAsicFlowControlJumboMode * Description: - * Set Jumbo threhsold for flow control + * Set Jumbo threshold for flow control * Input: * enabled - Jumbo mode flow control 1: Enable 0:Disable * Output: @@ -73,7 +73,7 @@ ret_t rtl8367c_setAsicFlowControlJumboMode(rtk_uint32 enabled) /* Function Name: * rtl8367c_getAsicFlowControlJumboMode * Description: - * Get Jumbo threhsold for flow control + * Get Jumbo threshold for flow control * Input: * pEnabled - Jumbo mode flow control 1: Enable 0:Disable * Output: diff --git a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_green.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_green.c index a38623850..3fb5f57b9 100644 --- a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_green.c +++ b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_green.c @@ -11,7 +11,7 @@ * $Date: 2017-03-08 15:13:58 +0800 (週三, 08 三月 2017) $ * * Purpose : RTL8367C switch high-level API for RTL8367C - * Feature : Green ethernet related functions + * Feature : Green Ethernet related functions * */ #include @@ -22,7 +22,7 @@ * Get per-Port ingress page usage per second * Input: * port - Physical port number (0~7) - * pPage - page number of ingress packet occuping per second + * pPage - page number of ingress packet occurring per second * Output: * None * Return: @@ -30,7 +30,7 @@ * RT_ERR_SMI - SMI access error * RT_ERR_PORT_ID - Invalid port number * Note: - * Ingress traffic occuping page number per second for high layer green feature usage + * Ingress traffic occurring page number per second for high layer green feature usage */ ret_t rtl8367c_getAsicGreenPortPage(rtk_uint32 port, rtk_uint32* pPage) { @@ -134,7 +134,7 @@ ret_t rtl8367c_setAsicGreenHighPriorityTraffic(rtk_uint32 port) * Get indicator which ASIC had received high priority traffic or not * Input: * port - Physical port number (0~7) - * pIndicator - Have received high priority traffic indicator. If 1 means ASCI had received high priority in 1second checking priod + * pIndicator - Have received high priority traffic indicator. If 1 means ASCI had received high priority in 1second checking period * Output: * None * Return: @@ -153,14 +153,14 @@ ret_t rtl8367c_getAsicGreenHighPriorityTraffic(rtk_uint32 port, rtk_uint32* pInd } /* -@func rtk_int32 | rtl8367c_setAsicGreenEthernet | Set green ethernet function. +@func rtk_int32 | rtl8367c_setAsicGreenEthernet | Set green Ethernet function. @parm rtk_uint32 | green | Green feature function usage 1:enable 0:disable. @rvalue RT_ERR_OK | Success. @rvalue RT_ERR_SMI | SMI access error. @comm The API can set Green Ethernet function to reduce power consumption. While green feature is enabled, ASIC will automatic detect the cable length and then select different power mode for best performance with minimums power consumption. Link down - ports will enter power savining mode in 10 seconds after the cable disconnected if power saving function is enabled. + ports will enter power saving mode in 10 seconds after the cable disconnected if power saving function is enabled. */ ret_t rtl8367c_setAsicGreenEthernet(rtk_uint32 port, rtk_uint32 green) { @@ -286,14 +286,14 @@ ret_t rtl8367c_setAsicGreenEthernet(rtk_uint32 port, rtk_uint32 green) } /* -@func rtk_int32 | rtl8367c_getAsicGreenEthernet | Get green ethernet function. +@func rtk_int32 | rtl8367c_getAsicGreenEthernet | Get green Ethernet function. @parm rtk_uint32 | *green | Green feature function usage 1:enable 0:disable. @rvalue RT_ERR_OK | Success. @rvalue RT_ERR_SMI | SMI access error. @comm The API can set Green Ethernet function to reduce power consumption. While green feature is enabled, ASIC will automatic detect the cable length and then select different power mode for best performance with minimums power consumption. Link down - ports will enter power savining mode in 10 seconds after the cable disconnected if power saving function is enabled. + ports will enter power saving mode in 10 seconds after the cable disconnected if power saving function is enabled. */ ret_t rtl8367c_getAsicGreenEthernet(rtk_uint32 port, rtk_uint32* green) { diff --git a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_hsb.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_hsb.c index 435368d51..1b8ef59d9 100644 --- a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_hsb.c +++ b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_hsb.c @@ -30,7 +30,7 @@ * RT_ERR_SMI - SMI access error * RT_ERR_OUT_OF_RANGE - input parameter out of range * Note: - * System support 16 user defined field selctors. + * System support 16 user defined field selectors. * Each selector can be enabled or disable. User can defined retrieving 16-bits in many predefiend * standard l2/l3/l4 payload. */ diff --git a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_igmp.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_igmp.c index e0e734d61..c915d2d61 100644 --- a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_igmp.c +++ b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_igmp.c @@ -429,8 +429,8 @@ ret_t rtl8367c_setAsicIGMPRobVar(rtk_uint32 rob_var) if(rob_var > RTL8367C_MAX_ROB_VAR) return RT_ERR_OUT_OF_RANGE; - /* Bourstness variable */ - retVal = rtl8367c_setAsicRegBits(RTL8367C_REG_IGMP_MLD_CFG0, RTL8367C_ROBURSTNESS_VAR_MASK, rob_var); + /* Robustness variable */ + retVal = rtl8367c_setAsicRegBits(RTL8367C_REG_IGMP_MLD_CFG0, RTL8367C_ROBUSTNESS_VAR_MASK, rob_var); if(retVal != RT_ERR_OK) return retVal; @@ -456,8 +456,8 @@ ret_t rtl8367c_getAsicIGMPRobVar(rtk_uint32 *prob_var) ret_t retVal; rtk_uint32 value; - /* Bourstness variable */ - retVal = rtl8367c_getAsicRegBits(RTL8367C_REG_IGMP_MLD_CFG0, RTL8367C_ROBURSTNESS_VAR_MASK, &value); + /* Robustness variable */ + retVal = rtl8367c_getAsicRegBits(RTL8367C_REG_IGMP_MLD_CFG0, RTL8367C_ROBUSTNESS_VAR_MASK, &value); if(retVal != RT_ERR_OK) return retVal; @@ -1813,7 +1813,7 @@ ret_t rtl8367c_getAsicIGMPReportLeaveFlood(rtk_uint32 *pFlood) /* Function Name: * rtl8367c_setAsicIGMPDropLeaveZero * Description: - * Set the function of droppping Leave packet with group IP = 0.0.0.0 + * Set the function of dropping Leave packet with group IP = 0.0.0.0 * Input: * drop - 1: Drop, 0:Bypass * Output: @@ -1838,7 +1838,7 @@ ret_t rtl8367c_setAsicIGMPDropLeaveZero(rtk_uint32 drop) /* Function Name: * rtl8367c_getAsicIGMPDropLeaveZero * Description: - * Get the function of droppping Leave packet with group IP = 0.0.0.0 + * Get the function of dropping Leave packet with group IP = 0.0.0.0 * Input: * None * Output: @@ -1865,7 +1865,7 @@ ret_t rtl8367c_getAsicIGMPDropLeaveZero(rtk_uint32 *pDrop) /* Function Name: * rtl8367c_setAsicIGMPBypassStormCTRL * Description: - * Set the function of bypass strom control for IGMP/MLD packet + * Set the function of bypass storm control for IGMP/MLD packet * Input: * bypass - 1: Bypass, 0:not bypass * Output: @@ -1890,7 +1890,7 @@ ret_t rtl8367c_setAsicIGMPBypassStormCTRL(rtk_uint32 bypass) /* Function Name: * rtl8367c_getAsicIGMPBypassStormCTRL * Description: - * Set the function of bypass strom control for IGMP/MLD packet + * Set the function of bypass storm control for IGMP/MLD packet * Input: * None * Output: @@ -1944,7 +1944,7 @@ ret_t rtl8367c_setAsicIGMPIsoLeaky(rtk_uint32 leaky) * Description: * Get Port Isolation leaky for IGMP/MLD packet * Input: - * Noen + * None * Output: * pLeaky - 1: Leaky, 0:not leaky * Return: @@ -1996,7 +1996,7 @@ ret_t rtl8367c_setAsicIGMPVLANLeaky(rtk_uint32 leaky) * Description: * Get VLAN leaky for IGMP/MLD packet * Input: - * Noen + * None * Output: * pLeaky - 1: Leaky, 0:not leaky * Return: diff --git a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_inbwctrl.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_inbwctrl.c index abb36bec2..13a7b1424 100644 --- a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_inbwctrl.c +++ b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_inbwctrl.c @@ -128,7 +128,7 @@ ret_t rtl8367c_getAsicPortIngressBandwidth(rtk_uint32 port, rtk_uint32* pBandwid /* Function Name: * rtl8367c_setAsicPortIngressBandwidthBypass * Description: - * Set ingress bandwidth control bypasss 8899, RMA 01-80-C2-00-00-xx and IGMP + * Set ingress bandwidth control bypass 8899, RMA 01-80-C2-00-00-xx and IGMP * Input: * enabled - 1: enabled, 0: disabled * Output: @@ -146,7 +146,7 @@ ret_t rtl8367c_setAsicPortIngressBandwidthBypass(rtk_uint32 enabled) /* Function Name: * rtl8367c_getAsicPortIngressBandwidthBypass * Description: - * Set ingress bandwidth control bypasss 8899, RMA 01-80-C2-00-00-xx and IGMP + * Set ingress bandwidth control bypass 8899, RMA 01-80-C2-00-00-xx and IGMP * Input: * pEnabled - 1: enabled, 0: disabled * Output: diff --git a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_interrupt.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_interrupt.c index fb6cbcdf1..1d5ccfc90 100644 --- a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_interrupt.c +++ b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_interrupt.c @@ -99,10 +99,10 @@ ret_t rtl8367c_getAsicInterruptMask(rtk_uint32* pImr) * RT_ERR_OK - Success * RT_ERR_SMI - SMI access error * Note: - * This API can be used to clear ASIC interrupt status and register will be cleared by writting 1. + * This API can be used to clear ASIC interrupt status and register will be cleared by writing 1. * [0]:Link change, * [1]:Share meter exceed, - * [2]:Learn number overed, + * [2]:Learn number over, * [3]:Speed Change, * [4]:Tx special congestion * [5]:1 second green feature diff --git a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_led.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_led.c index 118902816..6f2617f5a 100644 --- a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_led.c +++ b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_led.c @@ -607,7 +607,7 @@ ret_t rtl8367c_getAsicLedSerialModeConfig(rtk_uint32 *active, rtk_uint32 *serimo /* @func ret_t | rtl8367c_setAsicLedOutputEnable | Set LED output enable -@parm rtk_uint32 | enabled | enable or disalbe. +@parm rtk_uint32 | enabled | enable or disable. @rvalue RT_ERR_OK | Success. @rvalue RT_ERR_SMI | SMI access error. @rvalue RT_ERR_INPUT | Invalid input value. diff --git a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_lut.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_lut.c index 343a6f159..1521467aa 100644 --- a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_lut.c +++ b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_lut.c @@ -207,7 +207,7 @@ static void _rtl8367c_fdbStSmi2User( rtl8367c_luttb *pLutSt, rtk_uint16 *pFdbSmi /* Function Name: * rtl8367c_setAsicLutIpMulticastLookup * Description: - * Set Lut IP multicast lookup function + * Set LUT IP multicast lookup function * Input: * enabled - 1: enabled, 0: disabled * Output: @@ -225,7 +225,7 @@ ret_t rtl8367c_setAsicLutIpMulticastLookup(rtk_uint32 enabled) /* Function Name: * rtl8367c_getAsicLutIpMulticastLookup * Description: - * Get Lut IP multicast lookup function + * Get LUT IP multicast lookup function * Input: * pEnabled - 1: enabled, 0: disabled * Output: @@ -244,7 +244,7 @@ ret_t rtl8367c_getAsicLutIpMulticastLookup(rtk_uint32* pEnabled) /* Function Name: * rtl8367c_setAsicLutIpMulticastLookup * Description: - * Set Lut IP multicast + VID lookup function + * Set LUT IP multicast + VID lookup function * Input: * enabled - 1: enabled, 0: disabled * Output: @@ -263,7 +263,7 @@ ret_t rtl8367c_setAsicLutIpMulticastVidLookup(rtk_uint32 enabled) /* Function Name: * rtl8367c_getAsicLutIpMulticastVidLookup * Description: - * Get Lut IP multicast lookup function + * Get LUT IP multicast lookup function * Input: * pEnabled - 1: enabled, 0: disabled * Output: @@ -282,7 +282,7 @@ ret_t rtl8367c_getAsicLutIpMulticastVidLookup(rtk_uint32* pEnabled) /* Function Name: * rtl8367c_setAsicLutIpLookupMethod * Description: - * Set Lut IP lookup hash with DIP or {DIP,SIP} pair + * Set LUT IP lookup hash with DIP or {DIP,SIP} pair * Input: * type - 1: When DIP can be found in IPMC_GROUP_TABLE, use DIP+SIP Hash, otherwise, use DIP+(SIP=0.0.0.0) Hash. * 0: When DIP can be found in IPMC_GROUP_TABLE, use DIP+(SIP=0.0.0.0) Hash, otherwise use DIP+SIP Hash. @@ -301,7 +301,7 @@ ret_t rtl8367c_setAsicLutIpLookupMethod(rtk_uint32 type) /* Function Name: * rtl8367c_getAsicLutIpLookupMethod * Description: - * Get Lut IP lookup hash with DIP or {DIP,SIP} pair + * Get LUT IP lookup hash with DIP or {DIP,SIP} pair * Input: * pType - 1: When DIP can be found in IPMC_GROUP_TABLE, use DIP+SIP Hash, otherwise, use DIP+(SIP=0.0.0.0) Hash. * 0: When DIP can be found in IPMC_GROUP_TABLE, use DIP+(SIP=0.0.0.0) Hash, otherwise use DIP+SIP Hash. @@ -320,10 +320,10 @@ ret_t rtl8367c_getAsicLutIpLookupMethod(rtk_uint32* pType) /* Function Name: * rtl8367c_setAsicLutAgeTimerSpeed * Description: - * Set LUT agging out speed + * Set LUT ageing out speed * Input: - * timer - Agging out timer 0:Has been aged out - * speed - Agging out speed 0-fastest 3-slowest + * timer - Ageing out timer 0:Has been aged out + * speed - Ageing out speed 0-fastest 3-slowest * Output: * None * Return: @@ -346,10 +346,10 @@ ret_t rtl8367c_setAsicLutAgeTimerSpeed(rtk_uint32 timer, rtk_uint32 speed) /* Function Name: * rtl8367c_getAsicLutAgeTimerSpeed * Description: - * Get LUT agging out speed + * Get LUT ageing out speed * Input: - * pTimer - Agging out timer 0:Has been aged out - * pSpeed - Agging out speed 0-fastest 3-slowest + * pTimer - Ageing out timer 0:Has been aged out + * pSpeed - Ageing out speed 0-fastest 3-slowest * Output: * None * Return: @@ -378,7 +378,7 @@ ret_t rtl8367c_getAsicLutAgeTimerSpeed(rtk_uint32* pTimer, rtk_uint32* pSpeed) /* Function Name: * rtl8367c_setAsicLutCamTbUsage * Description: - * Configure Lut CAM table usage + * Configure LUT CAM table usage * Input: * enabled - L2 CAM table usage 1: enabled, 0: disabled * Output: @@ -400,7 +400,7 @@ ret_t rtl8367c_setAsicLutCamTbUsage(rtk_uint32 enabled) /* Function Name: * rtl8367c_getAsicLutCamTbUsage * Description: - * Get Lut CAM table usage + * Get LUT CAM table usage * Input: * pEnabled - L2 CAM table usage 1: enabled, 0: disabled * Output: @@ -439,7 +439,7 @@ ret_t rtl8367c_getAsicLutCamTbUsage(rtk_uint32* pEnabled) * Note: * None */ - /*޸: RTL8367C_PORTIDMAX, RTL8367C_LUT_LEARNLIMITMAX, RTL8367C_LUT_PORT_LEARN_LIMITNO_REG*/ + /*modification: RTL8367C_PORTIDMAX, RTL8367C_LUT_LEARNLIMITMAX, RTL8367C_LUT_PORT_LEARN_LIMITNO_REG*/ ret_t rtl8367c_setAsicLutLearnLimitNo(rtk_uint32 port, rtk_uint32 number) { if(port > RTL8367C_PORTIDMAX) @@ -470,7 +470,7 @@ ret_t rtl8367c_setAsicLutLearnLimitNo(rtk_uint32 port, rtk_uint32 number) * Note: * None */ - /*޸: RTL8367C_PORTIDMAX, RTL8367C_LUT_PORT_LEARN_LIMITNO_REG*/ + /*modification: RTL8367C_PORTIDMAX, RTL8367C_LUT_PORT_LEARN_LIMITNO_REG*/ ret_t rtl8367c_getAsicLutLearnLimitNo(rtk_uint32 port, rtk_uint32* pNumber) { if(port > RTL8367C_PORTIDMAX) @@ -498,7 +498,7 @@ ret_t rtl8367c_getAsicLutLearnLimitNo(rtk_uint32 port, rtk_uint32* pNumber) * Note: * None */ - /*޸: RTL8367C_LUT_LEARNLIMITMAX*/ + /*modification: RTL8367C_LUT_LEARNLIMITMAX*/ ret_t rtl8367c_setAsicSystemLutLearnLimitNo(rtk_uint32 number) { if(number > RTL8367C_LUT_LEARNLIMITMAX) @@ -632,7 +632,7 @@ ret_t rtl8367c_getAsicSystemLutLearnOverAct(rtk_uint32 *pAction) * Note: * None */ - /*޸: RTL8367C_LUT_SYSTEM_LEARN_PMASK_MASK*/ + /*modification: RTL8367C_LUT_SYSTEM_LEARN_PMASK_MASK*/ ret_t rtl8367c_setAsicSystemLutLearnPortMask(rtk_uint32 portmask) { ret_t retVal; @@ -666,7 +666,7 @@ ret_t rtl8367c_setAsicSystemLutLearnPortMask(rtk_uint32 portmask) * Note: * None */ - /*޸: RTL8367C_LUT_SYSTEM_LEARN_PMASK_MASK*/ + /*modification: RTL8367C_LUT_SYSTEM_LEARN_PMASK_MASK*/ ret_t rtl8367c_getAsicSystemLutLearnPortMask(rtk_uint32 *pPortmask) { rtk_uint32 tmpmask; @@ -966,7 +966,7 @@ ret_t rtl8367c_getAsicL2LookupTb(rtk_uint32 method, rtl8367c_luttb *pL2Table) * Note: * None */ - /*޸RTL8367C_PORTIDMAX, RTL8367C_REG_L2_LRN_CNT_REG, port10 reg is not contnious, wait for updating of base.h*/ + /*modification:RTL8367C_PORTIDMAX, RTL8367C_REG_L2_LRN_CNT_REG, port10 reg is not continuous, wait for updating of base.h*/ ret_t rtl8367c_getAsicLutLearnNo(rtk_uint32 port, rtk_uint32* pNumber) { ret_t retVal; @@ -1047,7 +1047,7 @@ ret_t rtl8367c_getAsicLutFlushAllStatus(rtk_uint32 *pBusyStatus) * Note: * None */ - /*port8~port10һregister, wait for updating of base.h, reg.h*/ + /*port8~port10 setup is done in a separate register, wait for updating of base.h, reg.h*/ ret_t rtl8367c_setAsicLutForceFlush(rtk_uint32 portmask) { ret_t retVal; @@ -1079,7 +1079,7 @@ ret_t rtl8367c_setAsicLutForceFlush(rtk_uint32 portmask) * Note: * None */ - /*port8~port10һregister, wait for updating of base.h, reg.h*/ + /*port8~port10 setup is done in a separate register, wait for updating of base.h, reg.h*/ ret_t rtl8367c_getAsicLutForceFlushStatus(rtk_uint32 *pPortmask) { rtk_uint32 tmpMask; @@ -1142,7 +1142,7 @@ ret_t rtl8367c_getAsicLutFlushMode(rtk_uint32* pMode) * Description: * Get L2 LUT flush type * Input: - * type - 0: dynamice unicast; 1: both dynamic and static unicast entry + * type - 0: dynamic unicast; 1: both dynamic and static unicast entry * Output: * None * Return: @@ -1160,7 +1160,7 @@ ret_t rtl8367c_setAsicLutFlushType(rtk_uint32 type) * Description: * Set L2 LUT flush type * Input: - * pType - 0: dynamice unicast; 1: both dynamic and static unicast entry + * pType - 0: dynamic unicast; 1: both dynamic and static unicast entry * Output: * None * Return: @@ -1271,7 +1271,7 @@ ret_t rtl8367c_getAsicLutFlushFid(rtk_uint32* pFid) * Note: * None */ - /*޸RTL8367C_PORTIDMAX*/ + /*modification:RTL8367C_PORTIDMAX*/ ret_t rtl8367c_setAsicLutDisableAging(rtk_uint32 port, rtk_uint32 disabled) { if(port > RTL8367C_PORTIDMAX) @@ -1295,7 +1295,7 @@ ret_t rtl8367c_setAsicLutDisableAging(rtk_uint32 port, rtk_uint32 disabled) * Note: * None */ - /*޸RTL8367C_PORTIDMAX*/ + /*modification:RTL8367C_PORTIDMAX*/ ret_t rtl8367c_getAsicLutDisableAging(rtk_uint32 port, rtk_uint32 *pDisabled) { if(port > RTL8367C_PORTIDMAX) @@ -1504,9 +1504,9 @@ ret_t rtl8367c_getAsicLutLinkDownForceAging(rtk_uint32 *pEnable) /* Function Name: * rtl8367c_setAsicLutIpmcFwdRouterPort * Description: - * Set IPMC packet forward to rounter port also or not + * Set IPMC packet forward to router port also or not * Input: - * enable - 1: Inlcude router port, 0, exclude router port + * enable - 1: Include router port, 0, exclude router port * Output: * None * Return: @@ -1527,11 +1527,11 @@ ret_t rtl8367c_setAsicLutIpmcFwdRouterPort(rtk_uint32 enable) /* Function Name: * rtl8367c_getAsicLutIpmcFwdRouterPort * Description: - * Get IPMC packet forward to rounter port also or not + * Get IPMC packet forward to router port also or not * Input: * None * Output: - * pEnable - 1: Inlcude router port, 0, exclude router port + * pEnable - 1: Include router port, 0, exclude router port * Return: * RT_ERR_OK - Success * RT_ERR_SMI - SMI access error diff --git a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_mib.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_mib.c index c9aaa01d3..7da098c49 100644 --- a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_mib.c +++ b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_mib.c @@ -22,7 +22,7 @@ * Reset global/queue manage or per-port MIB counter * Input: * greset - Global reset - * qmreset - Queue maganement reset + * qmreset - Queue management reset * portmask - Port reset mask * Output: * None @@ -59,7 +59,7 @@ ret_t rtl8367c_setAsicMIBsCounterReset(rtk_uint32 greset, rtk_uint32 qmreset, rt * Input: * port - Physical port number (0~7) * mibIdx - MIB counter index - * pCounter - MIB retrived counter + * pCounter - MIB retrieved counter * Output: * None * Return: @@ -69,9 +69,9 @@ ret_t rtl8367c_setAsicMIBsCounterReset(rtk_uint32 greset, rtk_uint32 qmreset, rt * RT_ERR_BUSYWAIT_TIMEOUT - MIB is busy at retrieving * RT_ERR_STAT_CNTR_FAIL - MIB is resetting * Note: - * Before MIBs counter retrieving, writting accessing address to ASIC at first and check the MIB + * Before MIBs counter retrieving, writing accessing address to ASIC at first and check the MIB * control register status. If busy bit of MIB control is set, that means MIB counter have been - * waiting for preparing, then software must wait atfer this busy flag reset by ASIC. This driver + * waiting for preparing, then software must wait after this busy flag reset by ASIC. This driver * did not recycle reading user desired counter. Software must use driver again to get MIB counter * if return value is not RT_ERR_OK. */ @@ -124,7 +124,7 @@ ret_t rtl8367c_getAsicMIBsCounter(rtk_uint32 port, RTL8367C_MIBCOUNTER mibIdx, r /*writing access counter address first*/ /*This address is SRAM address, and SRAM address = MIB register address >> 2*/ - /*then ASIC will prepare 64bits counter wait for being retrived*/ + /*then ASIC will prepare 64bits counter wait for being retrieved*/ /*Write Mib related address to access control register*/ retVal = rtl8367c_setAsicReg(RTL8367C_REG_MIB_ADDRESS, (mibAddr >> 2)); if(retVal != RT_ERR_OK) @@ -183,7 +183,7 @@ ret_t rtl8367c_getAsicMIBsCounter(rtk_uint32 port, RTL8367C_MIBCOUNTER mibIdx, r /* Function Name: * rtl8367c_getAsicMIBsLogCounter * Description: - * Get MIBs Loggin counter + * Get MIBs Logging counter * Input: * index - The index of 32 logging counter (0 ~ 31) * Output: @@ -260,7 +260,7 @@ ret_t rtl8367c_getAsicMIBsLogCounter(rtk_uint32 index, rtk_uint32 *pCounter) * RT_ERR_OK - Success * RT_ERR_SMI - SMI access error * Note: - * Software need to check this control register atfer doing port resetting or global resetting + * Software need to check this control register after doing port resetting or global resetting */ ret_t rtl8367c_getAsicMIBsControl(rtk_uint32* pMask) { @@ -513,7 +513,7 @@ ret_t rtl8367c_setAsicMIBsResetLoggingCounter(rtk_uint32 index) /* Function Name: * rtl8367c_setAsicMIBsLength * Description: - * Set MIB length couting mode + * Set MIB length counting mode * Input: * txLengthMode - 0: tag length doesn't be counted. 1: tag length is counted. * rxLengthMode - 0: tag length doesn't be counted. 1: tag length is counted. @@ -542,7 +542,7 @@ ret_t rtl8367c_setAsicMIBsLength(rtk_uint32 txLengthMode, rtk_uint32 rxLengthMod /* Function Name: * rtl8367c_setAsicMIBsLength * Description: - * Set MIB length couting mode + * Set MIB length counting mode * Input: * None. * Output: diff --git a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_port.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_port.c index 78e80a0b2..fae046639 100644 --- a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_port.c +++ b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_port.c @@ -951,7 +951,7 @@ rtk_uint8 Sgmii_Init[SGMII_INIT_SIZE] = { * Set UNDA behavior * Input: * port - port ID - * behavior - 0: flooding to unknwon DA portmask; 1: drop; 2:trap; 3: flooding + * behavior - 0: flooding to unknown DA portmask; 1: drop; 2:trap; 3: flooding * Output: * None * Return: @@ -981,7 +981,7 @@ ret_t rtl8367c_setAsicPortUnknownDaBehavior(rtk_uint32 port, rtk_uint32 behavior * Input: * port - port ID * Output: - * pBehavior - 0: flooding to unknwon DA portmask; 1: drop; 2:trap; 3: flooding + * pBehavior - 0: flooding to unknown DA portmask; 1: drop; 2:trap; 3: flooding * Return: * RT_ERR_OK - Success * RT_ERR_SMI - SMI access error @@ -3724,7 +3724,7 @@ ret_t rtl8367c_setAsicPortExtMode(rtk_uint32 id, rtk_uint32 mode) return retVal; /* 1: MAC link = SGMII SerDes link - 0: MAC link = SGMII config link cfg_sgmii_link + 0: MAC link = SGMII config link (cfg_sgmii_link) */ if ((retVal = rtl8367c_setAsicRegBit(0x1d95, 2, 0)) != RT_ERR_OK) return retVal; @@ -4032,7 +4032,7 @@ ret_t rtl8367c_setAsicPortExtMode(rtk_uint32 id, rtk_uint32 mode) if ((retVal = rtl8367c_setAsicRegBits(0x1d95, 0x1f00, 0x2)) != RT_ERR_OK) return retVal; - /*select MAC link source when port6/7 be set sgmii mode cfg_sgmii_link*/ + /*select MAC link source when port6/7 be set sgmii mode (cfg_sgmii_link)*/ if ((retVal = rtl8367c_setAsicRegBit(0x1d95, 2, 0)) != RT_ERR_OK) return retVal; } diff --git a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_qos.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_qos.c index 89c3c3e02..69081049e 100644 --- a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_qos.c +++ b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_qos.c @@ -11,7 +11,7 @@ * $Date: 2017-03-08 15:13:58 +0800 (週三, 08 三月 2017) $ * * Purpose : RTL8367C switch high-level API for RTL8367C - * Feature : Qos related functions + * Feature : QoS related functions * */ diff --git a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_scheduling.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_scheduling.c index 8ebd6796d..32d9b2084 100644 --- a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_scheduling.c +++ b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_scheduling.c @@ -19,7 +19,7 @@ /* Function Name: * rtl8367c_setAsicLeakyBucketParameter * Description: - * Set Leaky Bucket Paramters + * Set Leaky Bucket Parameters * Input: * tick - Tick is used for time slot size unit * token - Token is used for adding budget in each time slot @@ -55,7 +55,7 @@ ret_t rtl8367c_setAsicLeakyBucketParameter(rtk_uint32 tick, rtk_uint32 token) /* Function Name: * rtl8367c_getAsicLeakyBucketParameter * Description: - * Get Leaky Bucket Paramters + * Get Leaky Bucket Parameters * Input: * tick - Tick is used for time slot size unit * token - Token is used for adding budget in each time slot @@ -166,7 +166,7 @@ ret_t rtl8367c_getAsicAprMeter(rtk_uint32 port, rtk_uint32 qid, rtk_uint32 *apri * Set per-port APR enable * Input: * port - Physical port number (0~7) - * aprEnable - APR enable seting 1:enable 0:disable + * aprEnable - APR enable setting 1:enable 0:disable * Output: * None * Return: @@ -193,7 +193,7 @@ ret_t rtl8367c_setAsicAprEnable(rtk_uint32 port, rtk_uint32 aprEnable) * Get per-port APR enable * Input: * port - Physical port number (0~7) - * aprEnable - APR enable seting 1:enable 0:disable + * aprEnable - APR enable setting 1:enable 0:disable * Output: * None * Return: diff --git a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_svlan.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_svlan.c index f19ceba5a..e199664b5 100644 --- a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_svlan.c +++ b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_svlan.c @@ -140,7 +140,7 @@ ret_t rtl8367c_getAsicSvlanUplinkPortMask(rtk_uint32* pPortmask) * RT_ERR_SMI - SMI access error * Note: * Ether type of S-tag in 802.1ad is 0x88a8 and there are existed ether type 0x9100 and 0x9200 - * for Q-in-Q SLAN design. User can set mathced ether type as service provider supported protocol + * for Q-in-Q SLAN design. User can set matched ether type as service provider supported protocol */ ret_t rtl8367c_setAsicSvlanTpid(rtk_uint32 protocolType) { @@ -344,7 +344,7 @@ ret_t rtl8367c_getAsicSvlanDefaultVlan(rtk_uint32 port, rtk_uint32* pIndex) /* Function Name: * rtl8367c_setAsicSvlanIngressUntag * Description: - * Set action received un-Stag frame from unplink port + * Set action received un-Stag frame from uplink port * Input: * mode - 0:Drop 1:Trap 2:Assign SVLAN * Output: @@ -362,7 +362,7 @@ ret_t rtl8367c_setAsicSvlanIngressUntag(rtk_uint32 mode) /* Function Name: * rtl8367c_getAsicSvlanIngressUntag * Description: - * Get action received un-Stag frame from unplink port + * Get action received un-Stag frame from uplink port * Input: * pMode - 0:Drop 1:Trap 2:Assign SVLAN * Output: @@ -380,7 +380,7 @@ ret_t rtl8367c_getAsicSvlanIngressUntag(rtk_uint32* pMode) /* Function Name: * rtl8367c_setAsicSvlanIngressUnmatch * Description: - * Set action received unmatched Stag frame from unplink port + * Set action received unmatched Stag frame from uplink port * Input: * mode - 0:Drop 1:Trap 2:Assign SVLAN * Output: @@ -398,7 +398,7 @@ ret_t rtl8367c_setAsicSvlanIngressUnmatch(rtk_uint32 mode) /* Function Name: * rtl8367c_getAsicSvlanIngressUnmatch * Description: - * Get action received unmatched Stag frame from unplink port + * Get action received unmatched Stag frame from uplink port * Input: * pMode - 0:Drop 1:Trap 2:Assign SVLAN * Output: @@ -417,7 +417,7 @@ ret_t rtl8367c_getAsicSvlanIngressUnmatch(rtk_uint32* pMode) /* Function Name: * rtl8367c_setAsicSvlanEgressUnassign * Description: - * Set unplink stream without egress SVID action + * Set uplink stream without egress SVID action * Input: * enabled - 1:Trap egress unassigned frames to CPU, 0: Use SVLAN setup in VS_CPSVIDX as egress SVID * Output: @@ -435,7 +435,7 @@ ret_t rtl8367c_setAsicSvlanEgressUnassign(rtk_uint32 enabled) /* Function Name: * rtl8367c_getAsicSvlanEgressUnassign * Description: - * Get unplink stream without egress SVID action + * Get uplink stream without egress SVID action * Input: * pEnabled - 1:Trap egress unassigned frames to CPU, 0: Use SVLAN setup in VS_CPSVIDX as egress SVID * Output: @@ -580,7 +580,7 @@ ret_t rtl8367c_getAsicSvlanMemberConfiguration(rtk_uint32 index,rtl8367c_svlan_m * RT_ERR_SMI - SMI access error * RT_ERR_ENTRY_INDEX - Invalid entry index * Note: - * ASIC will check upstream's VID and assign related SVID to mathed packet + * ASIC will check upstream's VID and assign related SVID to matched packet */ ret_t rtl8367c_setAsicSvlanC2SConf(rtk_uint32 index, rtk_uint32 evid, rtk_uint32 portmask, rtk_uint32 svidx) { diff --git a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_unknownMulticast.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_unknownMulticast.c index fcebd1b7f..a3455bbeb 100644 --- a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_unknownMulticast.c +++ b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_unknownMulticast.c @@ -11,7 +11,7 @@ * $Date: 2017-03-08 15:13:58 +0800 (週三, 08 三月 2017) $ * * Purpose : RTL8367C switch high-level API for RTL8367C - * Feature : Unkown multicast related functions + * Feature : Unknown multicast related functions * */ diff --git a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/smi.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/smi.c index c272cad48..70e767f42 100644 --- a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/smi.c +++ b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/smi.c @@ -421,7 +421,7 @@ rtk_int32 smi_write(rtk_uint32 mAddrs, rtk_uint32 rData) con = 0; do { con++; - _smi_readBit(1, &ACK); /* ACK for writting data [7:0] */ + _smi_readBit(1, &ACK); /* ACK for writing data [7:0] */ } while ((ACK != 0) && (con < ack_timer)); if (ACK != 0) ret = RT_ERR_FAILED; @@ -430,7 +430,7 @@ rtk_int32 smi_write(rtk_uint32 mAddrs, rtk_uint32 rData) con = 0; do { con++; - _smi_readBit(1, &ACK); /* ACK for writting data [15:8] */ + _smi_readBit(1, &ACK); /* ACK for writing data [15:8] */ } while ((ACK != 0) && (con < ack_timer)); if (ACK != 0) ret = RT_ERR_FAILED; diff --git a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/stat.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/stat.c index 3a328b0ca..3fd028a29 100644 --- a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/stat.c +++ b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/stat.c @@ -140,7 +140,7 @@ rtk_api_ret_t rtk_stat_global_get(rtk_stat_global_type_t cntr_idx, rtk_stat_coun if (cntr_idx!=DOT1D_TP_LEARNED_ENTRY_DISCARDS_INDEX) return RT_ERR_STAT_INVALID_GLOBAL_CNTR; - if ((retVal = rtl8367c_getAsicMIBsCounter(0, cntr_idx, pCntr)) != RT_ERR_OK) + if ((retVal = rtl8367c_getAsicMIBsCounter(0, (RTL8367C_MIBCOUNTER)cntr_idx, pCntr)) != RT_ERR_OK) return retVal; return RT_ERR_OK; @@ -172,7 +172,7 @@ rtk_api_ret_t rtk_stat_global_getAll(rtk_stat_global_cntr_t *pGlobal_cntrs) if(NULL == pGlobal_cntrs) return RT_ERR_NULL_POINTER; - if ((retVal = rtl8367c_getAsicMIBsCounter(0,DOT1D_TP_LEARNED_ENTRY_DISCARDS_INDEX, &pGlobal_cntrs->dot1dTpLearnedEntryDiscards)) != RT_ERR_OK) + if ((retVal = rtl8367c_getAsicMIBsCounter(0, dot1dTpLearnedEntryDiscards, &pGlobal_cntrs->dot1dTpLearnedEntryDiscards)) != RT_ERR_OK) return retVal; return RT_ERR_OK; @@ -265,7 +265,7 @@ static rtk_api_ret_t _get_asic_mib_idx(rtk_stat_port_type_t cnt_idx, RTL8367C_MI * port - port id. * cntr_idx - port counter index. * Output: - * pCntr - MIB retrived counter. + * pCntr - MIB retrieved counter. * Return: * RT_ERR_OK - OK * RT_ERR_FAILED - Failed @@ -592,7 +592,7 @@ rtk_api_ret_t rtk_stat_lengthMode_set(rtk_stat_lengthMode_t txMode, rtk_stat_len /* Function Name: * rtk_stat_lengthMode_get * Description: - * Get Legnth mode. + * Get Length mode. * Input: * None. * Output: diff --git a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/storm.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/storm.c index 13cf4e3cb..68063cdfa 100644 --- a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/storm.c +++ b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/storm.c @@ -279,7 +279,7 @@ rtk_api_ret_t rtk_rate_stormControlPortEnable_get(rtk_port_t port, rtk_rate_stor * RT_ERR_ENABLE - Invalid IFG parameter * Note: * - * This API can set per-port bypass stomr filter control frame type including RMA and igmp. + * This API can set per-port bypass storm filter control frame type including RMA and IGMP. * The bypass frame type is as following: * - BYPASS_BRG_GROUP, * - BYPASS_FD_PAUSE, @@ -414,7 +414,7 @@ rtk_api_ret_t rtk_storm_bypass_set(rtk_storm_bypass_t type, rtk_enable_t enable) * RT_ERR_SMI - SMI access error * RT_ERR_INPUT - Invalid input parameters. * Note: - * This API can get per-port bypass stomr filter control frame type including RMA and igmp. + * This API can get per-port bypass storm filter control frame type including RMA and IGMP. * The bypass frame type is as following: * - BYPASS_BRG_GROUP, * - BYPASS_FD_PAUSE, @@ -526,7 +526,7 @@ rtk_api_ret_t rtk_storm_bypass_get(rtk_storm_bypass_t type, rtk_enable_t *pEnabl /* Function Name: * rtk_rate_stormControlExtPortmask_set * Description: - * Set externsion storm control port mask + * Set extension storm control port mask * Input: * pPortmask - port mask * Output: @@ -562,7 +562,7 @@ rtk_api_ret_t rtk_rate_stormControlExtPortmask_set(rtk_portmask_t *pPortmask) /* Function Name: * rtk_rate_stormControlExtPortmask_get * Description: - * Set externsion storm control port mask + * Set extension storm control port mask * Input: * None * Output: @@ -598,10 +598,10 @@ rtk_api_ret_t rtk_rate_stormControlExtPortmask_get(rtk_portmask_t *pPortmask) /* Function Name: * rtk_rate_stormControlExtEnable_set * Description: - * Set externsion storm control state + * Set extension storm control state * Input: * stormType - storm group type - * enable - externsion storm control state + * enable - extension storm control state * Output: * None * Return: @@ -653,11 +653,11 @@ rtk_api_ret_t rtk_rate_stormControlExtEnable_set(rtk_rate_storm_group_t stormTyp /* Function Name: * rtk_rate_stormControlExtEnable_get * Description: - * Get externsion storm control state + * Get extension storm control state * Input: * stormType - storm group type * Output: - * pEnable - externsion storm control state + * pEnable - extension storm control state * Return: * RT_ERR_OK * RT_ERR_FAILED @@ -707,10 +707,10 @@ rtk_api_ret_t rtk_rate_stormControlExtEnable_get(rtk_rate_storm_group_t stormTyp /* Function Name: * rtk_rate_stormControlExtMeterIdx_set * Description: - * Set externsion storm control meter index + * Set extension storm control meter index * Input: * stormType - storm group type - * index - externsion storm control state + * index - extension storm control state * Output: * None * Return: @@ -762,10 +762,10 @@ rtk_api_ret_t rtk_rate_stormControlExtMeterIdx_set(rtk_rate_storm_group_t stormT /* Function Name: * rtk_rate_stormControlExtMeterIdx_get * Description: - * Get externsion storm control meter index + * Get extension storm control meter index * Input: * stormType - storm group type - * pIndex - externsion storm control state + * pIndex - extension storm control state * Output: * None * Return: diff --git a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/svlan.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/svlan.c index bf4ef044d..067291526 100644 --- a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/svlan.c +++ b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/svlan.c @@ -41,7 +41,7 @@ rtk_svlan_lookupType_t svlan_lookupType; * RT_ERR_SMI - SMI access error * Note: * Ether type of S-tag in 802.1ad is 0x88a8 and there are existed ether type 0x9100 and 0x9200 for Q-in-Q SLAN design. - * User can set mathced ether type as service provider supported protocol. + * User can set matched ether type as service provider supported protocol. */ rtk_api_ret_t rtk_svlan_init(void) { @@ -250,7 +250,7 @@ rtk_api_ret_t rtk_svlan_servicePort_del(rtk_port_t port) * RT_ERR_INPUT - Invalid input parameter. * Note: * Ether type of S-tag in 802.1ad is 0x88a8 and there are existed ether type 0x9100 and 0x9200 for Q-in-Q SLAN design. - * User can set mathced ether type as service provider supported protocol. + * User can set matched ether type as service provider supported protocol. */ rtk_api_ret_t rtk_svlan_tpidEntry_set(rtk_svlan_tpid_t svlan_tag_id) { @@ -391,8 +391,8 @@ rtk_api_ret_t rtk_svlan_priorityRef_get(rtk_svlan_pri_ref_t *pRef) * RT_ERR_PORT_MASK - Invalid portmask. * RT_ERR_SVLAN_TABLE_FULL - SVLAN configuration is full. * Note: - * The API can set system 64 accepted s-tag frame format. Only 64 SVID S-tag frame will be accpeted - * to receiving from uplink ports. Other SVID S-tag frame or S-untagged frame will be droped by default setup. + * The API can set system 64 accepted s-tag frame format. Only 64 SVID S-tag frame will be accepted + * to receiving from uplink ports. Other SVID S-tag frame or S-untagged frame will be dropped by default setup. * - rtk_svlan_memberCfg_t->svid is SVID of SVLAN member configuration. * - rtk_svlan_memberCfg_t->memberport is member port mask of SVLAN member configuration. * - rtk_svlan_memberCfg_t->fid is filtering database of SVLAN member configuration. @@ -626,8 +626,8 @@ rtk_api_ret_t rtk_svlan_memberPortEntry_set(rtk_vlan_t svid, rtk_svlan_memberCfg * RT_ERR_SVLAN_ENTRY_NOT_FOUND - specified svlan entry not found. * RT_ERR_INPUT - Invalid input parameters. * Note: - * The API can get system 64 accepted s-tag frame format. Only 64 SVID S-tag frame will be accpeted - * to receiving from uplink ports. Other SVID S-tag frame or S-untagged frame will be droped. + * The API can get system 64 accepted s-tag frame format. Only 64 SVID S-tag frame will be accepted + * to receiving from uplink ports. Other SVID S-tag frame or S-untagged frame will be dropped. */ rtk_api_ret_t rtk_svlan_memberPortEntry_get(rtk_vlan_t svid, rtk_svlan_memberCfg_t *pSvlan_cfg) { @@ -794,8 +794,8 @@ rtk_api_ret_t rtk_svlan_memberPortEntry_adv_set(rtk_uint32 idx, rtk_svlan_member * RT_ERR_SVLAN_ENTRY_NOT_FOUND - specified svlan entry not found. * RT_ERR_INPUT - Invalid input parameters. * Note: - * The API can get system 64 accepted s-tag frame format. Only 64 SVID S-tag frame will be accpeted - * to receiving from uplink ports. Other SVID S-tag frame or S-untagged frame will be droped. + * The API can get system 64 accepted s-tag frame format. Only 64 SVID S-tag frame will be accepted + * to receiving from uplink ports. Other SVID S-tag frame or S-untagged frame will be dropped. */ rtk_api_ret_t rtk_svlan_memberPortEntry_adv_get(rtk_uint32 idx, rtk_svlan_memberCfg_t *pSvlan_cfg) { @@ -948,7 +948,7 @@ rtk_api_ret_t rtk_svlan_defaultSvlan_get(rtk_port_t port, rtk_vlan_t *pSvid) * RT_ERR_INPUT - Invalid input parameters. * Note: * The API can set system C2S configuration. ASIC will check upstream's VID and assign related - * SVID to mathed packet. There are 128 SVLAN C2S configurations. + * SVID to matched packet. There are 128 SVLAN C2S configurations. */ rtk_api_ret_t rtk_svlan_c2s_add(rtk_vlan_t vid, rtk_port_t src_port, rtk_vlan_t svid) { @@ -1011,7 +1011,7 @@ rtk_api_ret_t rtk_svlan_c2s_add(rtk_vlan_t vid, rtk_port_t src_port, rtk_vlan_t } else { - /* New svidx, remove src_port and find a new slot to add a new enrty */ + /* New svidx, remove src_port and find a new slot to add a new entry */ pmsk = pmsk & ~(1 << phyPort); if(pmsk == 0) c2s_svidx = 0; @@ -1263,7 +1263,7 @@ rtk_api_ret_t rtk_svlan_untag_action_set(rtk_svlan_untag_action_t action, rtk_vl * Note: * The API can Get action of downstream Un-Stag packet. A SVID assigned * to the un-stag is also retrieved by this API. The parameter pSvid is - * only refernced when the action is UNTAG_ASSIGN + * only referenced when the action is UNTAG_ASSIGN */ rtk_api_ret_t rtk_svlan_untag_action_get(rtk_svlan_untag_action_t *pAction, rtk_vlan_t *pSvid) { @@ -1313,8 +1313,8 @@ rtk_api_ret_t rtk_svlan_untag_action_get(rtk_svlan_untag_action_t *pAction, rtk_ * RT_ERR_INPUT - Invalid input parameters. * Note: * The API can configure action of downstream Un-match packet. A SVID assigned - * to the un-match is also supported by this API. The parameter od svid is - * only refernced when the action is set to UNMATCH_ASSIGN + * to the un-match is also supported by this API. The parameter of svid is + * only referenced when the action is set to UNMATCH_ASSIGN */ rtk_api_ret_t rtk_svlan_unmatch_action_set(rtk_svlan_unmatch_action_t action, rtk_vlan_t svid) { @@ -1379,7 +1379,7 @@ rtk_api_ret_t rtk_svlan_unmatch_action_set(rtk_svlan_unmatch_action_t action, rt * Note: * The API can Get action of downstream Un-match packet. A SVID assigned * to the un-match is also retrieved by this API. The parameter pSvid is - * only refernced when the action is UNMATCH_ASSIGN + * only referenced when the action is UNMATCH_ASSIGN */ rtk_api_ret_t rtk_svlan_unmatch_action_get(rtk_svlan_unmatch_action_t *pAction, rtk_vlan_t *pSvid) { @@ -1567,7 +1567,7 @@ rtk_api_ret_t rtk_svlan_dmac_vidsel_get(rtk_port_t port, rtk_enable_t *pEnable) * RT_ERR_OUT_OF_RANGE - input out of range. * RT_ERR_INPUT - Invalid input parameters. * Note: - * The API can set IP mutlicast to SVID configuration. If upstream packet is IPv4 multicast + * The API can set IP multicast to SVID configuration. If upstream packet is IPv4 multicast * packet and DIP is matched MC2S configuration, ASIC will assign egress SVID to the packet. * There are 32 SVLAN multicast configurations for IP and L2 multicast. */ @@ -1662,7 +1662,7 @@ rtk_api_ret_t rtk_svlan_ipmc2s_add(ipaddr_t ipmc, ipaddr_t ipmcMsk,rtk_vlan_t sv * RT_ERR_SVLAN_VID - Invalid SVLAN VID parameter. * RT_ERR_OUT_OF_RANGE - input out of range. * Note: - * The API can delete IP mutlicast to SVID configuration. There are 32 SVLAN multicast configurations for IP and L2 multicast. + * The API can delete IP multicast to SVID configuration. There are 32 SVLAN multicast configurations for IP and L2 multicast. */ rtk_api_ret_t rtk_svlan_ipmc2s_del(ipaddr_t ipmc, ipaddr_t ipmcMsk) { @@ -1714,7 +1714,7 @@ rtk_api_ret_t rtk_svlan_ipmc2s_del(ipaddr_t ipmc, ipaddr_t ipmcMsk) * RT_ERR_INPUT - Invalid input parameters. * RT_ERR_OUT_OF_RANGE - input out of range. * Note: - * The API can get IP mutlicast to SVID configuration. There are 32 SVLAN multicast configurations for IP and L2 multicast. + * The API can get IP multicast to SVID configuration. There are 32 SVLAN multicast configurations for IP and L2 multicast. */ rtk_api_ret_t rtk_svlan_ipmc2s_get(ipaddr_t ipmc, ipaddr_t ipmcMsk, rtk_vlan_t *pSvid) { @@ -1771,7 +1771,7 @@ rtk_api_ret_t rtk_svlan_ipmc2s_get(ipaddr_t ipmc, ipaddr_t ipmcMsk, rtk_vlan_t * * RT_ERR_OUT_OF_RANGE - input out of range. * RT_ERR_INPUT - Invalid input parameters. * Note: - * The API can set L2 Mutlicast to SVID configuration. If upstream packet is L2 multicast + * The API can set L2 Multicast to SVID configuration. If upstream packet is L2 multicast * packet and DMAC is matched, ASIC will assign egress SVID to the packet. There are 32 * SVLAN multicast configurations for IP and L2 multicast. */ @@ -1868,7 +1868,7 @@ rtk_api_ret_t rtk_svlan_l2mc2s_add(rtk_mac_t mac, rtk_mac_t macMsk, rtk_vlan_t s * RT_ERR_SVLAN_VID - Invalid SVLAN VID parameter. * RT_ERR_OUT_OF_RANGE - input out of range. * Note: - * The API can delete Mutlicast to SVID configuration. There are 32 SVLAN multicast configurations for IP and L2 multicast. + * The API can delete Multicast to SVID configuration. There are 32 SVLAN multicast configurations for IP and L2 multicast. */ rtk_api_ret_t rtk_svlan_l2mc2s_del(rtk_mac_t mac, rtk_mac_t macMsk) { @@ -1924,7 +1924,7 @@ rtk_api_ret_t rtk_svlan_l2mc2s_del(rtk_mac_t mac, rtk_mac_t macMsk) * RT_ERR_INPUT - Invalid input parameters. * RT_ERR_OUT_OF_RANGE - input out of range. * Note: - * The API can get L2 mutlicast to SVID configuration. There are 32 SVLAN multicast configurations for IP and L2 multicast. + * The API can get L2 multicast to SVID configuration. There are 32 SVLAN multicast configurations for IP and L2 multicast. */ rtk_api_ret_t rtk_svlan_l2mc2s_get(rtk_mac_t mac, rtk_mac_t macMsk, rtk_vlan_t *pSvid) { diff --git a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/vlan.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/vlan.c index f7480c490..b407c3008 100644 --- a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/vlan.c +++ b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367c/vlan.c @@ -106,7 +106,7 @@ rtk_api_ret_t rtk_vlan_init(void) return retVal; } - /* Updata Databse */ + /* Update Database */ vlan_mbrCfgUsage[0] = MBRCFG_USED_BY_VLAN; vlan_mbrCfgVid[0] = 1; @@ -950,7 +950,7 @@ rtk_api_ret_t rtk_vlan_protoAndPortBasedVlan_add(rtk_port_t port, rtk_vlan_proto { if ((retVal = rtl8367c_getAsicVlanProtocolBasedGroupData(i, &ppb_data_cfg)) != RT_ERR_OK) return retVal; - tmp = pInfo->frame_type; + tmp = (rtl8367c_provlan_frametype)pInfo->frame_type; if (ppb_data_cfg.etherType == pInfo->proto_type && ppb_data_cfg.frameType == tmp) { /*Already exist*/ @@ -976,7 +976,7 @@ rtk_api_ret_t rtk_vlan_protoAndPortBasedVlan_add(rtk_port_t port, rtk_vlan_proto else if (emptyframe_type; + ppb_data_cfg.frameType = (rtl8367c_provlan_frametype)pInfo->frame_type; ppb_data_cfg.etherType = pInfo->proto_type; if ((retVal = rtl8367c_setAsicVlanProtocolBasedGroupData(empty, &ppb_data_cfg)) != RT_ERR_OK) return retVal; @@ -1267,7 +1267,7 @@ rtk_api_ret_t rtk_vlan_tagMode_set(rtk_port_t port, rtk_vlan_tagMode_t tag_mode) if (tag_mode >= VLAN_TAG_MODE_END) return RT_ERR_PORT_ID; - if ((retVal = rtl8367c_setAsicVlanEgressTagMode(rtk_switch_port_L2P_get(port), tag_mode)) != RT_ERR_OK) + if ((retVal = rtl8367c_setAsicVlanEgressTagMode(rtk_switch_port_L2P_get(port), (rtl8367c_egtagmode)tag_mode)) != RT_ERR_OK) return retVal; return RT_ERR_OK; @@ -1576,7 +1576,7 @@ rtk_api_ret_t rtk_vlan_stg_get(rtk_vlan_t vid, rtk_stp_msti_id_t *pStg) * Set port-based filtering database * Input: * port - Port id. - * enable - ebable port-based FID + * enable - enable port-based FID * fid - Specified filtering database. * Output: * None @@ -1624,7 +1624,7 @@ rtk_api_ret_t rtk_vlan_portFid_set(rtk_port_t port, rtk_enable_t enable, rtk_fid * Input: * port - Port id. * Output: - * pEnable - ebable port-based FID + * pEnable - enable port-based FID * pFid - Specified filtering database. * Return: * RT_ERR_OK - OK diff --git a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367s_mdio.c b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367s_mdio.c index 08d2b57d4..b4d4554d4 100644 --- a/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367s_mdio.c +++ b/target/linux/mediatek/files/drivers/net/phy/rtk/rtl8367s_mdio.c @@ -211,7 +211,7 @@ void init_gsw(void) set_rtl8367s_rgmii(); } -// bleow are platform driver +// below are platform driver static const struct of_device_id rtk_gsw_match[] = { { .compatible = "mediatek,rtk-gsw" }, {}, @@ -258,7 +258,7 @@ static int rtk_gsw_probe(struct platform_device *pdev) init_gsw(); - //init default vlan or init swocnfig + //init default vlan or init swconfig if(!of_property_read_string(pdev->dev.of_node, "mediatek,port_map", &pm)) { diff --git a/target/linux/mediatek/filogic/base-files/etc/board.d/01_leds b/target/linux/mediatek/filogic/base-files/etc/board.d/01_leds index 52d761805..16d8617c5 100644 --- a/target/linux/mediatek/filogic/base-files/etc/board.d/01_leds +++ b/target/linux/mediatek/filogic/base-files/etc/board.d/01_leds @@ -6,33 +6,120 @@ board=$(board_name) board_config_update case $board in -abt,asr3000) - ucidef_set_led_netdev "wan" "WAN" "green:wan" "eth1" +confiabits,mt7981) + ucidef_set_led_netdev "lan1" "lan1" "blue:lan-1" "lan1" "link tx rx" + ucidef_set_led_netdev "lan2" "lan2" "blue:lan-2" "lan2" "link tx rx" + ucidef_set_led_netdev "lan3" "lan3" "blue:lan-3" "lan3" "link tx rx" + ucidef_set_led_netdev "wan" "wan" "blue:wan" "wan" "link tx rx" ;; -bananapi,bpi-r4) +bananapi,bpi-r3-mini) + ucidef_set_led_netdev "lan1" "LAN" "mdio-bus:0e:green:lan" "eth0" "link_2500 link_1000 tx rx" + ucidef_set_led_netdev "lan2" "LAN" "mdio-bus:0e:yellow:lan" "eth0" "link_2500 link_100 tx rx" + ucidef_set_led_netdev "wan1" "WAN" "mdio-bus:0f:green:wan" "eth1" "link_2500 link_1000 tx rx" + ucidef_set_led_netdev "wan2" "WAN" "mdio-bus:0f:yellow:wan" "eth1" "link_2500 link_100 tx rx" + ucidef_set_led_netdev "wlan2g" "WLAN2G" "blue:wlan-1" "phy0-ap0" + ucidef_set_led_netdev "wlan5g" "WLAN5G" "blue:wlan-2" "phy1-ap0" + ;; +bananapi,bpi-r4|\ +bananapi,bpi-r4-poe) ucidef_set_led_netdev "wan" "wan" "mt7530-0:00:green:lan" "wan" "link tx rx" ucidef_set_led_netdev "lan1" "lan1" "mt7530-0:01:green:lan" "lan1" "link tx rx" ucidef_set_led_netdev "lan2" "lan2" "mt7530-0:02:green:lan" "lan2" "link tx rx" ucidef_set_led_netdev "lan3" "lan3" "mt7530-0:03:green:lan" "lan3" "link tx rx" ;; -hf,m7986r1*) - ucidef_set_led_netdev "led-1" "LAN1" "led-1" "lan1" - ucidef_set_led_netdev "led-2" "LAN2" "led-2" "lan2" - ucidef_set_led_netdev "led-3" "LAN3" "led-3" "lan3" - ucidef_set_led_netdev "led-4" "LAN4" "led-4" "lan4" - ucidef_set_led_netdev "led-5" "WWAN" "led-5" "usb0" +cudy,re3000-v1) + ucidef_set_led_netdev "lan" "lan" "green:lan" "eth0" "link tx rx" + ;; +cudy,wr3000-v1) + ucidef_set_led_netdev "wan" "wan" "blue:wan" "wan" + ;; +glinet,gl-x3000|\ +glinet,gl-xe3000) + ucidef_set_led_default "power" "POWER" "green:power" "1" + ucidef_set_led_netdev "wan" "WAN" "green:wan" "eth0" + ucidef_set_led_netdev "5g_1" "5G_1" "green:5g:led1" "wwan0" + ucidef_set_led_netdev "5g_2" "5G_2" "green:5g:led2" "wwan0" + ucidef_set_led_netdev "5g_3" "5G_3" "green:5g:led3" "wwan0" + ucidef_set_led_netdev "5g_4" "5G_4" "green:5g:led4" "wwan0" + ucidef_set_led_netdev "wlan2g" "WLAN2G" "green:wifi2g" "phy0-ap0" + ucidef_set_led_netdev "wlan5g" "WLAN5G" "green:wifi5g" "phy1-ap0" + ;; +mercusys,mr90x-v1) + ucidef_set_led_netdev "lan-0" "lan-0" "green:lan-0" "lan0" "link tx rx" + ucidef_set_led_netdev "lan-1" "lan-1" "green:lan-1" "lan1" "link tx rx" + ucidef_set_led_netdev "lan-2" "lan-2" "green:lan-2" "lan2" "link tx rx" + ucidef_set_led_netdev "wan" "wan" "green:wan" "eth1" "link tx rx" + ;; +netgear,wax220) + ucidef_set_led_netdev "eth0" "LAN" "green:lan" "eth0" + ucidef_set_led_netdev "wlan2g" "WLAN2G" "blue:wlan2g" "phy0-ap0" + ucidef_set_led_netdev "wlan5g" "WLAN5G" "blue:wlan5g" "phy1-ap0" ;; -imou,lc-hx3001|\ nokia,ea0326gmp) - ucidef_set_led_netdev "lan" "LAN" "green:lan" "br-lan" - ucidef_set_led_netdev "wan" "WAN" "green:wan" "eth1" + ucidef_set_led_netdev "wan" "WAN" "green:wan" "eth1" "link" + ucidef_set_led_netdev "lan" "LAN" "green:lan" "br-lan" "link" + ucidef_set_led_netdev "wlan" "WLAN" "green:wlan" "phy1-ap0" "link" ;; -xiaomi,mi-router-wr30u) - ucidef_set_led_netdev "wan" "wan" "blue:internet" "wan" +openembed,som7981) + ucidef_set_led_netdev "lanact" "LANACT" "green:lan" "eth1" "rx tx" + ucidef_set_led_netdev "lanlink" "LANLINK" "amber:lan" "eth1" "link" ;; -xiaomi,redmi-router-ax6000) +openwrt,one) + ucidef_set_led_netdev "wanact" "WANACT" "mdio-bus:0f:green:wan" "eth0" "rx tx" + ucidef_set_led_netdev "wanlink" "WANLINK" "mdio-bus:0f:amber:wan" "eth0" "link" + ucidef_set_led_netdev "lanact" "LANACT" "green:lan" "eth1" "rx tx" + ucidef_set_led_netdev "lanlink" "LANLINK" "amber:lan" "eth1" "link" + ;; +routerich,ax3000) + ucidef_set_led_netdev "lan-1" "lan-1" "blue:lan-1" "lan1" "link tx rx" + ucidef_set_led_netdev "lan-2" "lan-2" "blue:lan-2" "lan2" "link tx rx" + ucidef_set_led_netdev "lan-3" "lan-3" "blue:lan-3" "lan3" "link tx rx" + ucidef_set_led_netdev "wan" "wan" "blue:wan" "wan" "link tx rx" + ucidef_set_led_netdev "wan-off" "wan-off" "red:wan" "wan" "link" + ;; +smartrg,sdg-8733|\ +smartrg,sdg-8734) + ucidef_set_led_netdev "lan-1-green" "LAN1" "mdio-bus:08:green:lan" "lan1" "link_2500 link_5000" + ucidef_set_led_netdev "lan-1-orange" "LAN1" "mdio-bus:08:orange:lan" "lan1" "link_100 link_1000" + ucidef_set_led_netdev "lan-1-white" "LAN1" "mdio-bus:08:white:lan" "lan1" "link_10000" + ucidef_set_led_netdev "lan-2-green" "LAN2" "mt7530-0:01:green:lan" "lan2" "link_1000" + ucidef_set_led_netdev "lan-2-amber" "LAN2" "mt7530-0:01:amber:lan" "lan2" "link_100 link_10" + ucidef_set_led_netdev "lan-3-green" "LAN3" "mt7530-0:02:green:lan" "lan3" "link_1000" + ucidef_set_led_netdev "lan-3-amber" "LAN3" "mt7530-0:02:amber:lan" "lan3" "link_100 link_10" + ucidef_set_led_netdev "lan-4-green" "LAN4" "mt7530-0:03:green:lan" "lan4" "link_1000" + ucidef_set_led_netdev "lan-4-amber" "LAN4" "mt7530-0:03:amber:lan" "lan4" "link_100 link_10" + ucidef_set_led_netdev "wan-green" "WAN" "mdio-bus:00:green:wan" "wan" "link_2500 link_5000" + ucidef_set_led_netdev "wan-orange" "WAN" "mdio-bus:00:orange:wan" "wan" "link_100 link_1000" + ucidef_set_led_netdev "wan-white" "WAN" "mdio-bus:00:white:wan" "wan" "link_10000" + ;; +wavlink,wl-wn586x3) + ucidef_set_led_netdev "lan-1" "lan-1" "blue:lan-1" "lan1" "link tx rx" + ucidef_set_led_netdev "lan-2" "lan-2" "blue:lan-2" "lan2" "link tx rx" + ucidef_set_led_netdev "wan" "wan" "blue:wan" "eth1" "link tx rx" + ;; +tplink,re6000xd) + ucidef_set_led_netdev "lan-1" "lan-1" "blue:lan-0" "lan1" "link tx rx" + ucidef_set_led_netdev "lan-2" "lan-2" "blue:lan-1" "lan2" "link tx rx" + ucidef_set_led_netdev "eth1" "lan-3" "blue:lan-2" "eth1" "link tx rx" + ;; +xiaomi,mi-router-wr30u-stock|\ +xiaomi,mi-router-wr30u-ubootmod) + ucidef_set_led_netdev "wan" "wan" "blue:wan" "wan" "link tx rx" + ;; +xiaomi,redmi-router-ax6000-stock|\ +xiaomi,redmi-router-ax6000-ubootmod) ucidef_set_led_netdev "wan" "wan" "rgb:network" "wan" ;; +zbtlink,zbt-z8103ax) + ucidef_set_led_netdev "wan" "wan" "green:wan" "eth1" "link tx rx" + ;; +zyxel_ex5601-t0-stock|\ +zyxel,ex5601-t0-ubootmod) + ucidef_set_led_netdev "lan" "LAN" "green:lan" "eth0" "link tx rx" + ucidef_set_led_netdev "wan" "WAN" "green:inet" "eth1" "link tx rx" + ucidef_set_led_netdev "wifi-24g" "WIFI-2.4G" "green:wifi24g" "phy0-ap0" "link tx rx" + ucidef_set_led_netdev "wifi-5g" "WIFI-5G" "green:wifi5g" "phy1-ap0" "link tx rx" + ;; esac board_config_flush diff --git a/target/linux/mediatek/filogic/base-files/etc/board.d/02_network b/target/linux/mediatek/filogic/base-files/etc/board.d/02_network index 5586a6a8b..1a210810b 100644 --- a/target/linux/mediatek/filogic/base-files/etc/board.d/02_network +++ b/target/linux/mediatek/filogic/base-files/etc/board.d/02_network @@ -8,59 +8,113 @@ mediatek_setup_interfaces() local board="$1" case $board in - abt,asr3000|\ - cmcc,rax3000m*|\ - h3c,magic-nx30-pro|\ - imou,lc-hx3001|\ - nokia,ea0326gmp) - ucidef_set_interfaces_lan_wan "lan1 lan2 lan3" eth1 + acelink,ew-7886cax) + ucidef_set_interface_lan "eth0" "dhcp" + ;; + acer,predator-w6) + ucidef_set_interfaces_lan_wan "lan1 lan2 lan3 game" eth1 + ;; + asus,rt-ax59u|\ + cetron,ct3003|\ + confiabits,mt7981|\ + cudy,wr3000-v1|\ + jcg,q30-pro|\ + qihoo,360t7|\ + routerich,ax3000) + ucidef_set_interfaces_lan_wan "lan1 lan2 lan3" wan ;; asus,tuf-ax4200|\ - jdcloud,re-cs-05|\ + jdcloud,re-cp-03|\ + mediatek,mt7981-rfb|\ netcore,n60|\ - ruijie,rg-x60-pro) + ruijie,rg-x60-pro|\ + unielec,u7981-01*|\ + zbtlink,zbt-z8102ax) ucidef_set_interfaces_lan_wan "lan1 lan2 lan3 lan4" eth1 ;; + asus,tuf-ax6000) + ucidef_set_interfaces_lan_wan "lan1 lan2 lan3 lan4 lan5" eth1 + ;; bananapi,bpi-r3) ucidef_set_interfaces_lan_wan "lan1 lan2 lan3 lan4 sfp2" "eth1 wan" ;; - bananapi,bpi-r4) + bananapi,bpi-r3-mini|\ + edgecore,eap111) + ucidef_set_interfaces_lan_wan eth0 eth1 + ;; + bananapi,bpi-r4|\ + bananapi,bpi-r4-poe) ucidef_set_interfaces_lan_wan "lan1 lan2 lan3 eth1" "wan eth2" ;; - cetron,ct3003*|\ - fzs,5gcpe-p3|\ - jcg,q30-pro|\ - qihoo,360t7) - ucidef_set_interfaces_lan_wan "lan1 lan2 lan3" wan + cmcc,rax3000m|\ + h3c,magic-nx30-pro|\ + nokia,ea0326gmp|\ + zbtlink,zbt-z8103ax) + ucidef_set_interfaces_lan_wan "lan1 lan2 lan3" eth1 ;; - hf,m7986r1*) - ucidef_set_interfaces_lan_wan "lan2 lan3 lan4" lan1 + comfast,cf-e393ax) + ucidef_set_interfaces_lan_wan "lan1" eth1 ;; + cudy,m3000-v1|\ + cudy,tr3000-v1|\ glinet,gl-mt2500|\ - glinet,gl-mt3000) + glinet,gl-mt3000|\ + glinet,gl-x3000|\ + glinet,gl-xe3000|\ + openembed,som7981|\ + openwrt,one) ucidef_set_interfaces_lan_wan eth1 eth0 ;; - mediatek,mt7986a-rfb|\ + dlink,aquila-pro-ai-m30-a1) + ucidef_set_interfaces_lan_wan "lan1 lan2 lan3 lan4" internet + ;; + glinet,gl-mt6000|\ + tplink,tl-xdr4288|\ + tplink,tl-xdr6088) + ucidef_set_interfaces_lan_wan "lan1 lan2 lan3 lan4 lan5" eth1 + ;; + mediatek,mt7986a-rfb) + ucidef_set_interfaces_lan_wan "lan1 lan2 lan3 lan4 lan6" "eth1 wan" + ;; mediatek,mt7986b-rfb) ucidef_set_interfaces_lan_wan "lan0 lan1 lan2 lan3" eth1 ;; mediatek,mt7988a-rfb) ucidef_set_interfaces_lan_wan "lan0 lan1 lan2 lan3 eth1" eth2 ;; - glinet,gl-mt6000|\ - tplink,tl-xdr4288|\ - tplink,tl-xdr6088|\ - tplink,tl-xtr8488) - ucidef_set_interfaces_lan_wan "lan1 lan2 lan3 lan4 lan5" eth1 + mercusys,mr90x-v1) + ucidef_set_interfaces_lan_wan "lan0 lan1 lan2" eth1 ;; - tplink,tl-xdr6086) + cudy,re3000-v1|\ + netgear,wax220|\ + ubnt,unifi-6-plus|\ + zyxel,nwa50ax-pro) + ucidef_set_interface_lan "eth0" + ;; + smartrg,sdg-8622|\ + smartrg,sdg-8632|\ + yuncore,ax835) + ucidef_set_interfaces_lan_wan lan wan + ;; + tplink,tl-xdr6086|\ + wavlink,wl-wn586x3) ucidef_set_interfaces_lan_wan "lan1 lan2" eth1 ;; - xiaomi,mi-router-wr30u|\ + tplink,re6000xd) + ucidef_set_interface_lan "lan1 lan2 eth1" + ;; xiaomi,mi-router-ax3000t|\ - xiaomi,redmi-router-ax6000) + xiaomi,mi-router-ax3000t-ubootmod|\ + xiaomi,mi-router-wr30u-stock|\ + xiaomi,mi-router-wr30u-ubootmod|\ + xiaomi,redmi-router-ax6000-stock|\ + xiaomi,redmi-router-ax6000-ubootmod) ucidef_set_interfaces_lan_wan "lan2 lan3 lan4" wan ;; + zyxel,ex5601-t0-stock|\ + zyxel,ex5601-t0-ubootmod) + ucidef_set_interfaces_lan_wan "lan1 lan2 lan3 lan4" eth1 + ;; *) ucidef_set_interfaces_lan_wan "lan1 lan2 lan3 lan4" wan ;; @@ -75,50 +129,32 @@ mediatek_setup_macs() local label_mac="" case $board in - asus,tuf-ax4200) - CI_UBIPART="UBI_DEV" - addr=$(mtd_get_mac_binary_ubi "Factory" 0x4) - wan_mac="${addr}" - lan_mac="${addr}" - ;; bananapi,bpi-r3|\ bananapi,bpi-r3-mini|\ bananapi,bpi-r4) wan_mac=$(macaddr_add $(cat /sys/class/net/eth0/address) 1) ;; - cmcc,rax3000m-emmc) - wan_mac=$(mmc_get_mac_binary factory 0x2a) - lan_mac=$(mmc_get_mac_binary factory 0x24) - label_mac=$wan_mac + cmcc,rax3000m) + case "$(cmdline_get_var root)" in + /dev/mmc*) + wan_mac=$(mmc_get_mac_binary factory 0x2a) + lan_mac=$(mmc_get_mac_binary factory 0x24) + label_mac=$wan_mac ;; - cmcc,rax3000m-nand) - wan_mac=$(mtd_get_mac_binary factory 0x2a) - lan_mac=$(mtd_get_mac_binary factory 0x24) - label_mac=$lan_mac - ;; - glinet,gl-mt2500) - label_mac="$(get_mac_binary "/dev/mmcblk0boot1" 0xa)" - wan_mac="$label_mac" - lan_mac="$(macaddr_add $label_mac 1)" - ;; - glinet,gl-mt6000) - label_mac=$(mmc_get_mac_binary factory 0x0a) - wan_mac=$label_mac - lan_mac=$(macaddr_add "$label_mac" 2) + esac ;; h3c,magic-nx30-pro) wan_mac=$(mtd_get_mac_ascii pdt_data_1 ethaddr) lan_mac=$(macaddr_add "$wan_mac" 1) label_mac=$wan_mac ;; - imou,lc-hx3001) - lan_mac=$(mtd_get_mac_ascii u-boot-env mac) - wan_mac=$(macaddr_add "$lan_mac" 2) - label_mac=$lan_mac + mercusys,mr90x-v1|\ + tplink,re6000xd) + label_mac=$(get_mac_binary "/tmp/tp_data/default-mac" 0) + lan_mac=$label_mac ;; - jdcloud,re-cs-05) - wan_mac=$(mmc_get_mac_binary factory 0x24) - lan_mac=$(mmc_get_mac_binary factory 0x2a) + netgear,wax220) + lan_mac=$(mtd_get_mac_ascii u-boot-env mac) label_mac=$lan_mac ;; qihoo,360t7) @@ -131,12 +167,28 @@ mediatek_setup_macs() wan_mac=$label_mac lan_mac=$(macaddr_add "$label_mac" 1) ;; - xiaomi,mi-router-wr30u|\ + smartrg,sdg-8612|\ + smartrg,sdg-8614|\ + smartrg,sdg-8622|\ + smartrg,sdg-8632|\ + smartrg,sdg-8733|\ + smartrg,sdg-8734) + label_mac=$(mmc_get_mac_ascii mfginfo MFG_MAC) + wan_mac=$label_mac + lan_mac=$(macaddr_add "$label_mac" 1) + ;; xiaomi,mi-router-ax3000t|\ - xiaomi,redmi-router-ax6000) + xiaomi,mi-router-ax3000t-ubootmod|\ + xiaomi,mi-router-wr30u-stock|\ + xiaomi,mi-router-wr30u-ubootmod|\ + xiaomi,redmi-router-ax6000-stock|\ + xiaomi,redmi-router-ax6000-ubootmod) wan_mac=$(mtd_get_mac_ascii Bdata ethaddr_wan) label_mac=$wan_mac ;; + yuncore,ax835) + label_mac=$(mtd_get_mac_binary "Factory" 0x4) + ;; esac [ -n "$lan_mac" ] && ucidef_set_interface_macaddr "lan" $lan_mac diff --git a/target/linux/mediatek/filogic/base-files/etc/board.d/03_gpio_switches b/target/linux/mediatek/filogic/base-files/etc/board.d/03_gpio_switches new file mode 100644 index 000000000..4cbec1ef0 --- /dev/null +++ b/target/linux/mediatek/filogic/base-files/etc/board.d/03_gpio_switches @@ -0,0 +1,19 @@ +. /lib/functions/uci-defaults.sh + +board_config_update + +board=$(board_name) + +case "$board" in +zbtlink,zbt-z8102ax) + ucidef_add_gpio_switch "5g1" "Power 1st modem" "5g1" "1" + ucidef_add_gpio_switch "5g2" "Power 2nd modem" "5g2" "1" + ucidef_add_gpio_switch "pcie" "Power PCIe port" "pcie" "1" + ucidef_add_gpio_switch "sim1" "SIM 1" "sim1" "1" + ucidef_add_gpio_switch "sim2" "SIM 2" "sim2" "1" + ;; +esac + +board_config_flush + +exit 0 diff --git a/target/linux/mediatek/filogic/base-files/etc/board.d/05_compat-version b/target/linux/mediatek/filogic/base-files/etc/board.d/05_compat-version index e0e1a8ecc..d0cfd8f0a 100644 --- a/target/linux/mediatek/filogic/base-files/etc/board.d/05_compat-version +++ b/target/linux/mediatek/filogic/base-files/etc/board.d/05_compat-version @@ -6,7 +6,7 @@ board_config_update case "$(board_name)" in bananapi,bpi-r3) - ucidef_set_compat_version "1.1" + ucidef_set_compat_version "1.2" ;; esac diff --git a/target/linux/mediatek/filogic/base-files/etc/hotplug.d/firmware/11-mt76-caldata b/target/linux/mediatek/filogic/base-files/etc/hotplug.d/firmware/11-mt76-caldata index 742abc5f4..920a16d05 100644 --- a/target/linux/mediatek/filogic/base-files/etc/hotplug.d/firmware/11-mt76-caldata +++ b/target/linux/mediatek/filogic/base-files/etc/hotplug.d/firmware/11-mt76-caldata @@ -7,25 +7,53 @@ board=$(board_name) case "$FIRMWARE" in +"mediatek/mt7915_eeprom.bin") + case "$board" in + smartrg,sdg-8622) + caldata_extract_mmc "factory" 0xa0000 0x1000 + ;; + esac + ;; +"mediatek/mt7916_eeprom.bin") + case "$board" in + acer,predator-w6|\ + smartrg,sdg-8632) + caldata_extract_mmc "factory" 0xa0000 0x1000 + ;; + esac + ;; "mediatek/mt7981_eeprom_mt7976_dbdc.bin") case "$board" in - cmcc,rax3000m-emmc) + cmcc,rax3000m) + case "$(cmdline_get_var root)" in + /dev/mmc*) + caldata_extract_mmc "factory" 0x0 0x1000 + ;; + esac + ;; + ubnt,unifi-6-plus) caldata_extract_mmc "factory" 0x0 0x1000 ;; esac ;; -"mediatek/mt7986_eeprom_mt7976_dbdc.bin") +"mediatek/mt7986_eeprom_mt7975_dual.bin") case "$board" in - asus,tuf-ax4200) - CI_UBIPART="UBI_DEV" - caldata_extract_ubi "Factory" 0x0 0x1000 + mercusys,mr90x-v1|\ + tplink,re6000xd) + ln -sf /tmp/tp_data/MT7986_EEPROM.bin \ + /lib/firmware/$FIRMWARE + ;; + smartrg,sdg-8612|\ + smartrg,sdg-8614|\ + smartrg,sdg-8622|\ + smartrg,sdg-8632) + caldata_extract_mmc "factory" 0x0 0x1000 ;; esac ;; -"mediatek/mt7986_eeprom_mt7976_dual.bin") +"mediatek/mt7986_eeprom_mt7976.bin") case "$board" in - glinet,gl-mt6000|\ - jdcloud,re-cs-05) + acer,predator-w6) caldata_extract_mmc "factory" 0x0 0x1000 ;; esac diff --git a/target/linux/mediatek/filogic/base-files/etc/hotplug.d/ieee80211/11_fix_wifi_mac b/target/linux/mediatek/filogic/base-files/etc/hotplug.d/ieee80211/11_fix_wifi_mac index a1e86697f..942facee8 100644 --- a/target/linux/mediatek/filogic/base-files/etc/hotplug.d/ieee80211/11_fix_wifi_mac +++ b/target/linux/mediatek/filogic/base-files/etc/hotplug.d/ieee80211/11_fix_wifi_mac @@ -10,12 +10,24 @@ PHYNBR=${DEVPATH##*/phy} board=$(board_name) case "$board" in - abt,asr3000) - addr=$(mtd_get_mac_binary "art" 0x6) - [ "$PHYNBR" = "1" ] && \ - macaddr_setbit_la "$(macaddr_add $addr 0x600000)" > /sys${DEVPATH}/macaddress + acer,predator-w6) + key_path="/var/qcidata/data" + [ "$PHYNBR" = "0" ] && cat $key_path/2gMAC > /sys${DEVPATH}/macaddress + [ "$PHYNBR" = "1" ] && cat $key_path/6gMAC > /sys${DEVPATH}/macaddress + [ "$PHYNBR" = "2" ] && cat $key_path/5gMAC > /sys${DEVPATH}/macaddress ;; - asus,tuf-ax4200) + asus,rt-ax59u) + CI_UBIPART="UBI_DEV" + addr=$(mtd_get_mac_binary_ubi "Factory" 0x4) + # Originally, phy1 is phy0 mac with LA and 28th bits set. However, this would conflict + # addresses on multiple VIFs with the other radio when bit 28 is already set. + # Set LA and 28 bits and increment mac-address instead. + [ "$PHYNBR" = "1" ] && \ + macaddr_setbit_la $(macaddr_setbit $(macaddr_add $addr 1) 28) > \ + /sys${DEVPATH}/macaddress + ;; + asus,tuf-ax4200|\ + asus,tuf-ax6000) CI_UBIPART="UBI_DEV" addr=$(mtd_get_mac_binary_ubi "Factory" 0x4) # Originally, phy0 is phy1 mac with LA bit set. However, this would conflict @@ -24,23 +36,61 @@ case "$board" in [ "$PHYNBR" = "0" ] && macaddr_setbit_la $(macaddr_add $addr 1) > /sys${DEVPATH}/macaddress [ "$PHYNBR" = "1" ] && echo "$addr" > /sys${DEVPATH}/macaddress ;; - bananapi,bpi-r3) + bananapi,bpi-r3|\ + bananapi,bpi-r3-mini) addr=$(cat /sys/class/net/eth0/address) [ "$PHYNBR" = "0" ] && macaddr_add $addr 2 > /sys${DEVPATH}/macaddress [ "$PHYNBR" = "1" ] && macaddr_add $addr 3 > /sys${DEVPATH}/macaddress ;; - bananapi,bpi-r4) + bananapi,bpi-r4|\ + bananapi,bpi-r4-poe) addr=$(cat /sys/class/net/eth0/address) [ "$PHYNBR" = "0" ] && macaddr_add $addr 2 > /sys${DEVPATH}/macaddress [ "$PHYNBR" = "1" ] && macaddr_add $addr 3 > /sys${DEVPATH}/macaddress [ "$PHYNBR" = "2" ] && macaddr_add $addr 4 > /sys${DEVPATH}/macaddress ;; - cetron,ct3003*) + cetron,ct3003) addr=$(mtd_get_mac_binary "art" 0) [ "$PHYNBR" = "0" ] && macaddr_add $addr 1 > /sys${DEVPATH}/macaddress [ "$PHYNBR" = "1" ] && macaddr_setbit_la $(macaddr_add $addr 2) > /sys${DEVPATH}/macaddress ;; - glinet,gl-mt6000) + cmcc,rax3000m) + case "$(cmdline_get_var root)" in + /dev/mmc*) + addr=$(mmc_get_mac_binary factory 0xa) + ;; + *) + addr=$(mtd_get_mac_binary factory 0xa) + ;; + esac + [ "$PHYNBR" = "1" ] && echo "$addr" > /sys${DEVPATH}/macaddress + ;; + comfast,cf-e393ax) + addr=$(mtd_get_mac_binary "Factory" 0x8000) + [ "$PHYNBR" = "1" ] && macaddr_add $addr 1 > /sys${DEVPATH}/macaddress + ;; + cudy,tr3000-v1|\ + cudy,re3000-v1) + addr=$(mtd_get_mac_binary bdinfo 0xde00) + [ "$PHYNBR" = "0" ] && echo "$addr" > /sys${DEVPATH}/macaddress + [ "$PHYNBR" = "1" ] && macaddr_setbit_la $(macaddr_add $addr 1) > /sys${DEVPATH}/macaddress + ;; + cudy,m3000-v1|\ + cudy,wr3000-v1) + addr=$(mtd_get_mac_binary bdinfo 0xde00) + # Originally, phy0 is phy1 mac with LA bit set. However, this would conflict + # addresses on multiple VIFs with the other radio. Set LA bit and increment + # mac-address instead. + [ "$PHYNBR" = "0" ] && echo "$addr" > /sys${DEVPATH}/macaddress + [ "$PHYNBR" = "1" ] && macaddr_setbit_la $(macaddr_add $addr 1) > /sys${DEVPATH}/macaddress + ;; + dlink,aquila-pro-ai-m30-a1) + addr=$(mtd_get_mac_binary "Odm" 0x81) + [ "$PHYNBR" = "1" ] && macaddr_add $addr 3 > /sys${DEVPATH}/macaddress + ;; + glinet,gl-mt6000|\ + glinet,gl-x3000|\ + glinet,gl-xe3000) addr=$(mmc_get_mac_binary factory 0x04) [ "$PHYNBR" = "0" ] && echo "$addr" > /sys${DEVPATH}/macaddress [ "$PHYNBR" = "1" ] && macaddr_add $addr 1 > /sys${DEVPATH}/macaddress @@ -50,21 +100,34 @@ case "$board" in [ "$PHYNBR" = "0" ] && macaddr_add $addr 2 > /sys${DEVPATH}/macaddress [ "$PHYNBR" = "1" ] && macaddr_add $addr 3 > /sys${DEVPATH}/macaddress ;; - imou,lc-hx3001) - addr=$(mtd_get_mac_ascii u-boot-env mac) - [ "$PHYNBR" = "0" ] && macaddr_add $addr 1 > /sys${DEVPATH}/macaddress - [ "$PHYNBR" = "1" ] && macaddr_add $addr 3 > /sys${DEVPATH}/macaddress - ;; jcg,q30-pro|\ netcore,n60) # Originally, phy1 is phy0 mac with LA bit set. However, this would conflict # addresses on multiple VIFs with the other radio. Use label mac to set LA bit. [ "$PHYNBR" = "1" ] && macaddr_setbit_la $(get_mac_label) > /sys${DEVPATH}/macaddress ;; + jdcloud,re-cp-03) + [ "$PHYNBR" = "1" ] && mmc_get_mac_binary factory 0xa > /sys${DEVPATH}/macaddress + ;; + mercusys,mr90x-v1|\ + tplink,re6000xd) + addr=$(get_mac_binary "/tmp/tp_data/default-mac" 0) + [ "$PHYNBR" = "0" ] && echo "$addr" > /sys${DEVPATH}/macaddress + [ "$PHYNBR" = "1" ] && macaddr_add $addr -1 > /sys${DEVPATH}/macaddress + ;; + netgear,wax220) + hw_mac_addr=$(mtd_get_mac_ascii u-boot-env mac) + [ "$PHYNBR" = "0" ] && macaddr_add $hw_mac_addr 2 > /sys${DEVPATH}/macaddress + [ "$PHYNBR" = "1" ] && macaddr_add $hw_mac_addr 3 > /sys${DEVPATH}/macaddress + ;; nokia,ea0326gmp) - addr=$(mtd_get_mac_binary Factory 0x28) + addr=$(cat /sys/class/net/eth0/address) + [ "$PHYNBR" = "0" ] && macaddr_add $addr 1 > /sys${DEVPATH}/macaddress [ "$PHYNBR" = "1" ] && macaddr_add $addr 2 > /sys${DEVPATH}/macaddress ;; + openembed,som7981) + [ "$PHYNBR" = "1" ] && cat /sys/class/net/eth0/address > /sys${DEVPATH}/macaddress + ;; qihoo,360t7) addr=$(mtd_get_mac_ascii factory lanMac) [ "$PHYNBR" = "0" ] && macaddr_add $addr 2 > /sys${DEVPATH}/macaddress @@ -75,12 +138,43 @@ case "$board" in [ "$PHYNBR" = "0" ] && macaddr_add $addr 2 > /sys${DEVPATH}/macaddress [ "$PHYNBR" = "1" ] && macaddr_add $addr 3 > /sys${DEVPATH}/macaddress ;; + smartrg,sdg-8612|\ + smartrg,sdg-8614|\ + smartrg,sdg-8622|\ + smartrg,sdg-8632) + addr=$(mmc_get_mac_ascii mfginfo MFG_MAC) + [ "$PHYNBR" = "0" ] && macaddr_add $addr 2 > /sys${DEVPATH}/macaddress + [ "$PHYNBR" = "1" ] && macaddr_add $addr 3 > /sys${DEVPATH}/macaddress + [ "$PHYNBR" = "2" ] && macaddr_add $addr 4 > /sys${DEVPATH}/macaddress + ;; + smartrg,sdg-8733|\ + smartrg,sdg-8634) + addr=$(mmc_get_mac_ascii mfginfo MFG_MAC) + [ "$PHYNBR" = "0" ] && macaddr_add $addr 4 > /sys${DEVPATH}/macaddress + [ "$PHYNBR" = "1" ] && macaddr_add $addr a > /sys${DEVPATH}/macaddress + [ "$PHYNBR" = "2" ] && macaddr_add $addr 6 > /sys${DEVPATH}/macaddress + ;; tplink,tl-xdr4288|\ tplink,tl-xdr6086|\ tplink,tl-xdr6088) - [ "$PHYNBR" = "1" ] && macaddr_add $(get_mac_label) 2 > /sys${DEVPATH}/macaddress + [ "$PHYNBR" = "0" ] && get_mac_label > /sys${DEVPATH}/macaddress ;; - tplink,tl-xtr8488) - [ "$PHYNBR" = "2" ] && macaddr_add $(get_mac_label) 2 > /sys${DEVPATH}/macaddress + ubnt,unifi-6-plus) + addr=$(mtd_get_mac_binary EEPROM 0x6) + [ "$PHYNBR" = "0" ] && echo "$addr" > /sys${DEVPATH}/macaddress + [ "$PHYNBR" = "1" ] && macaddr_add $addr 1 > /sys${DEVPATH}/macaddress + ;; + routerich,ax3000|\ + zbtlink,zbt-z8102ax|\ + zbtlink,zbt-z8103ax|\ + zyxel,ex5601-t0|\ + zyxel,ex5601-t0-ubootmod) + addr=$(mtd_get_mac_binary "Factory" 0x4) + [ "$PHYNBR" = "1" ] && macaddr_add $addr 1 > /sys${DEVPATH}/macaddress + ;; + zyxel,nwa50ax-pro) + hw_mac_addr="$(mtd_get_mac_binary mrd 0x1fff8)" + [ "$PHYNBR" = "0" ] && macaddr_add $hw_mac_addr 1 > /sys${DEVPATH}/macaddress + [ "$PHYNBR" = "1" ] && macaddr_add $hw_mac_addr 2 > /sys${DEVPATH}/macaddress ;; esac diff --git a/target/linux/mediatek/filogic/base-files/etc/init.d/bootcount b/target/linux/mediatek/filogic/base-files/etc/init.d/bootcount new file mode 100755 index 000000000..e186589f2 --- /dev/null +++ b/target/linux/mediatek/filogic/base-files/etc/init.d/bootcount @@ -0,0 +1,19 @@ +#!/bin/sh /etc/rc.common +# SPDX-License-Identifier: GPL-2.0-only + +START=99 + +boot() { + case $(board_name) in + dlink,aquila-pro-ai-m30-a1) + if grep -q bootpart=ubi0 /proc/cmdline; then + fw_setenv bootpart 0 + else + fw_setenv bootpart 1 + fi + ;; + zyxel,ex5700-telenor) + fw_setenv uboot_bootcount 0 + ;; + esac +} diff --git a/target/linux/mediatek/filogic/base-files/etc/uci-defaults/05_fix-compat-version b/target/linux/mediatek/filogic/base-files/etc/uci-defaults/05_fix-compat-version index 4486f2f09..f39d2575e 100644 --- a/target/linux/mediatek/filogic/base-files/etc/uci-defaults/05_fix-compat-version +++ b/target/linux/mediatek/filogic/base-files/etc/uci-defaults/05_fix-compat-version @@ -2,7 +2,7 @@ case "$(board_name)" in bananapi,bpi-r3) - uci set system.@system[0].compat_version="1.1" + uci set system.@system[0].compat_version="1.2" uci commit system ;; esac diff --git a/target/linux/mediatek/filogic/base-files/lib/preinit/04_set_netdev_label b/target/linux/mediatek/filogic/base-files/lib/preinit/04_set_netdev_label new file mode 100644 index 000000000..110e023b9 --- /dev/null +++ b/target/linux/mediatek/filogic/base-files/lib/preinit/04_set_netdev_label @@ -0,0 +1,15 @@ +set_netdev_labels() { + local dir + local label + local netdev + + for dir in /sys/class/net/*; do + [ -r "$dir/of_node/label" ] || continue + read -r label < "$dir/of_node/label" + netdev="${dir##*/}" + [ "$netdev" = "$label" ] && continue + ip link set "$netdev" name "$label" + done +} + +boot_hook_add preinit_main set_netdev_labels diff --git a/target/linux/mediatek/filogic/base-files/lib/preinit/05_extract_factory_data.sh b/target/linux/mediatek/filogic/base-files/lib/preinit/05_extract_factory_data.sh new file mode 100644 index 000000000..87287a7d1 --- /dev/null +++ b/target/linux/mediatek/filogic/base-files/lib/preinit/05_extract_factory_data.sh @@ -0,0 +1,25 @@ +. /lib/functions/system.sh + +predator_w6_factory_extract() { + local mmc_part + + mmc_part="$(find_mmc_part qcidata)" + + mkdir -p /var/qcidata/data + mkdir -p /var/qcidata/mount + + mount -r "$mmc_part" /var/qcidata/mount + + cp /var/qcidata/mount/factory/*MAC "/var/qcidata/data/" + umount "/var/qcidata/mount" +} + +preinit_extract_factory() { + case $(board_name) in + acer,predator-w6) + predator_w6_factory_extract + ;; + esac +} + +boot_hook_add preinit_main preinit_extract_factory diff --git a/target/linux/mediatek/filogic/base-files/lib/preinit/09_mount_cfg_part b/target/linux/mediatek/filogic/base-files/lib/preinit/09_mount_cfg_part new file mode 100644 index 000000000..11e3b598a --- /dev/null +++ b/target/linux/mediatek/filogic/base-files/lib/preinit/09_mount_cfg_part @@ -0,0 +1,24 @@ +. /lib/functions/system.sh + +mount_ubi_part() { + local part_name="$1" + local mtd_num=$(grep $part_name /proc/mtd | cut -c4) + local ubi_num=$(ubiattach -m $mtd_num | \ + awk -F',' '/UBI device number [0-9]{1,}/{print $1}' | \ + awk '{print $4}') + mkdir /tmp/$part_name + mount -r -t ubifs ubi$ubi_num:$part_name /tmp/$part_name +} + +preinit_mount_cfg_part() { + case $(board_name) in + mercusys,mr90x-v1|\ + tplink,re6000xd) + mount_ubi_part "tp_data" + ;; + *) + ;; + esac +} + +boot_hook_add preinit_main preinit_mount_cfg_part diff --git a/target/linux/mediatek/filogic/base-files/lib/preinit/10_fix_eth_mac.sh b/target/linux/mediatek/filogic/base-files/lib/preinit/10_fix_eth_mac.sh index ec078741c..fefca2327 100644 --- a/target/linux/mediatek/filogic/base-files/lib/preinit/10_fix_eth_mac.sh +++ b/target/linux/mediatek/filogic/base-files/lib/preinit/10_fix_eth_mac.sh @@ -2,12 +2,47 @@ preinit_set_mac_address() { case $(board_name) in - asus,tuf-ax4200) + acer,predator-w6) + key_path="/var/qcidata/data" + ip link set dev lan1 address "$(cat $key_path/LANMAC)" + ip link set dev lan2 address "$(cat $key_path/LANMAC)" + ip link set dev lan3 address "$(cat $key_path/LANMAC)" + ip link set dev game address "$(cat $key_path/LANMAC)" + ip link set dev eth1 address "$(cat $key_path/WANMAC)" + ;; + asus,tuf-ax4200|\ + asus,tuf-ax6000) CI_UBIPART="UBI_DEV" addr=$(mtd_get_mac_binary_ubi "Factory" 0x4) ip link set dev eth0 address "$addr" ip link set dev eth1 address "$addr" ;; + mercusys,mr90x-v1|\ + tplink,re6000xd) + addr=$(get_mac_binary "/tmp/tp_data/default-mac" 0) + ip link set dev eth1 address "$(macaddr_add $addr 1)" + ;; + smartrg,sdg-8612|\ + smartrg,sdg-8614|\ + smartrg,sdg-8733|\ + smartrg,sdg-8734) + addr=$(mmc_get_mac_ascii mfginfo MFG_MAC) + lan_addr=$(macaddr_add $addr 1) + ip link set dev wan address "$addr" + ip link set dev eth0 address "$lan_addr" + ip link set dev lan1 address "$lan_addr" + ip link set dev lan2 address "$lan_addr" + ip link set dev lan3 address "$lan_addr" + ip link set dev lan4 address "$lan_addr" + ;; + smartrg,sdg-8622|\ + smartrg,sdg-8632) + addr=$(mmc_get_mac_ascii mfginfo MFG_MAC) + ip link set dev wan address "$addr" + ip link set dev lan address "$(macaddr_add $addr 1)" + ;; + *) + ;; esac } diff --git a/target/linux/mediatek/filogic/base-files/lib/preinit/75_rootfs_prepare b/target/linux/mediatek/filogic/base-files/lib/preinit/75_rootfs_prepare new file mode 100644 index 000000000..0a32073e0 --- /dev/null +++ b/target/linux/mediatek/filogic/base-files/lib/preinit/75_rootfs_prepare @@ -0,0 +1,35 @@ +# SPDX-License-Identifier: GPL-2.0-or-later OR BSD-2-Clause + +rootfs_create() { + local blocks + + blocks=$(cat /sys/class/ubi/ubi0/avail_eraseblocks) + [ -z "$blocks" ] && { + echo "Failed to read amount of available erase blocks" >&2 + return + } + + # Delete after getting available blocks: Make sure enough space is + # left to recreate these volumes. + ubirmvol /dev/ubi0 -N kernel_backup + ubirmvol /dev/ubi0 -N rootfs_backup + + # Use 90% of remaining flash size for "rootfs_data" + ubimkvol /dev/ubi0 -n 20 -N rootfs_data --lebs $((blocks / 100 * 90)) + mknod -m 0600 /dev/ubi0_20 c 250 21 +} + +rootfs_prepare() { + case $(board_name) in + netgear,wax220) + if ! ubinfo /dev/ubi0 -N rootfs_data &>/dev/null; then + echo "Creating \"rootfs_data\" UBI volume" + rootfs_create + fi + ;; + *) + ;; + esac +} + +boot_hook_add preinit_main rootfs_prepare diff --git a/target/linux/mediatek/filogic/base-files/lib/preinit/81_fix_eeprom b/target/linux/mediatek/filogic/base-files/lib/preinit/81_fix_eeprom deleted file mode 100644 index ee36ffe7c..000000000 --- a/target/linux/mediatek/filogic/base-files/lib/preinit/81_fix_eeprom +++ /dev/null @@ -1,23 +0,0 @@ -. /lib/functions/caldata.sh - -preinit_fix_eeprom() { - case $(board_name) in - glinet,gl-mt6000|\ - jdcloud,re-cs-05) - mmc_part=$(find_mmc_part factory) - FIRMWARE="mediatek/mt7986_eeprom_mt7976_dual.bin" - [ ! -e /lib/firmware/"$FIRMWARE" ] && \ - export FIRMWARE="$FIRMWARE" && \ - caldata_extract_mmc "factory" 0x0 0x1000 - ;; - mercusys,mr90x-v1) - eeprom="/lib/firmware/mediatek/mt7986_eeprom_mt7975_dual.bin" - [ ! -e $eeprom ] && \ - ln -sf /tmp/tp_data/MT7986_EEPROM.bin $eeprom - ;; - *) - ;; - esac -} - -boot_hook_add preinit_main preinit_fix_eeprom diff --git a/target/linux/mediatek/filogic/base-files/lib/upgrade/platform.sh b/target/linux/mediatek/filogic/base-files/lib/upgrade/platform.sh index e87b2e17c..2fed8a0ab 100755 --- a/target/linux/mediatek/filogic/base-files/lib/upgrade/platform.sh +++ b/target/linux/mediatek/filogic/base-files/lib/upgrade/platform.sh @@ -1,4 +1,5 @@ REQUIRE_IMAGE_METADATA=1 +RAMFS_COPY_BIN='fitblk' asus_initial_setup() { @@ -11,28 +12,93 @@ asus_initial_setup() ubimkvol /dev/ubi0 -N jffs2 -s 0x3e000 } +xiaomi_initial_setup() +{ + # initialize UBI and setup uboot-env if it's running on initramfs + [ "$(rootfs_type)" = "tmpfs" ] || return 0 + + local mtdnum="$( find_mtd_index ubi )" + if [ ! "$mtdnum" ]; then + echo "unable to find mtd partition ubi" + return 1 + fi + + local kern_mtdnum="$( find_mtd_index ubi_kernel )" + if [ ! "$kern_mtdnum" ]; then + echo "unable to find mtd partition ubi_kernel" + return 1 + fi + + ubidetach -m "$mtdnum" + ubiformat /dev/mtd$mtdnum -y + + ubidetach -m "$kern_mtdnum" + ubiformat /dev/mtd$kern_mtdnum -y + + if ! fw_printenv -n flag_try_sys2_failed &>/dev/null; then + echo "failed to access u-boot-env. skip env setup." + return 0 + fi + + fw_setenv boot_wait on + fw_setenv uart_en 1 + fw_setenv flag_boot_rootfs 0 + fw_setenv flag_last_success 1 + fw_setenv flag_boot_success 1 + fw_setenv flag_try_sys1_failed 8 + fw_setenv flag_try_sys2_failed 8 + + local board=$(board_name) + case "$board" in + xiaomi,mi-router-ax3000t|\ + xiaomi,mi-router-wr30u-stock) + fw_setenv mtdparts "nmbm0:1024k(bl2),256k(Nvram),256k(Bdata),2048k(factory),2048k(fip),256k(crash),256k(crash_log),34816k(ubi),34816k(ubi1),32768k(overlay),12288k(data),256k(KF)" + ;; + xiaomi,redmi-router-ax6000-stock) + fw_setenv mtdparts "nmbm0:1024k(bl2),256k(Nvram),256k(Bdata),2048k(factory),2048k(fip),256k(crash),256k(crash_log),30720k(ubi),30720k(ubi1),51200k(overlay)" + ;; + esac +} + platform_do_upgrade() { local board=$(board_name) case "$board" in - asus,tuf-ax4200) + acer,predator-w6|\ + smartrg,sdg-8612|\ + smartrg,sdg-8614|\ + smartrg,sdg-8622|\ + smartrg,sdg-8632|\ + smartrg,sdg-8733|\ + smartrg,sdg-8734) + CI_KERNPART="kernel" + CI_ROOTPART="rootfs" + emmc_do_upgrade "$1" + ;; + asus,rt-ax59u|\ + asus,tuf-ax4200|\ + asus,tuf-ax6000) CI_UBIPART="UBI_DEV" CI_KERNPART="linux" nand_do_upgrade "$1" ;; bananapi,bpi-r3|\ - bananapi,bpi-r4) - local rootdev="$(cmdline_get_var root)" - rootdev="${rootdev##*/}" - rootdev="${rootdev%p[0-9]*}" - case "$rootdev" in - mmc*) - CI_ROOTDEV="$rootdev" - CI_KERNPART="production" + bananapi,bpi-r3-mini|\ + bananapi,bpi-r4|\ + bananapi,bpi-r4-poe|\ + jdcloud,re-cp-03|\ + mediatek,mt7988a-rfb|\ + openwrt,one) + [ -e /dev/fit0 ] && fitblk /dev/fit0 + [ -e /dev/fitrw ] && fitblk /dev/fitrw + bootdev="$(fitblk_get_bootdev)" + case "$bootdev" in + mmcblk*) + EMMC_KERN_DEV="/dev/$bootdev" emmc_do_upgrade "$1" ;; mtdblock*) - PART_NAME="fit" + PART_NAME="/dev/mtd${bootdev:8}" default_do_upgrade "$1" ;; ubiblock*) @@ -41,14 +107,90 @@ platform_do_upgrade() { ;; esac ;; - cmcc,rax3000m-emmc|\ + cmcc,rax3000m) + case "$(cmdline_get_var root)" in + /dev/mmc*) + CI_KERNPART="production" + emmc_do_upgrade "$1" + ;; + *) + CI_KERNPART="fit" + nand_do_upgrade "$1" + ;; + esac + ;; + cudy,re3000-v1|\ + cudy,wr3000-v1|\ + yuncore,ax835) + default_do_upgrade "$1" + ;; glinet,gl-mt2500|\ glinet,gl-mt6000|\ - jdcloud,re-cs-05) + glinet,gl-x3000|\ + glinet,gl-xe3000) CI_KERNPART="kernel" CI_ROOTPART="rootfs" emmc_do_upgrade "$1" ;; + h3c,magic-nx30-pro|\ + jcg,q30-pro|\ + mediatek,mt7981-rfb|\ + netcore,n60|\ + qihoo,360t7|\ + xiaomi,mi-router-ax3000t-ubootmod|\ + xiaomi,mi-router-wr30u-ubootmod) + CI_KERNPART="fit" + nand_do_upgrade "$1" + ;; + mercusys,mr90x-v1|\ + tplink,re6000xd) + CI_UBIPART="ubi0" + nand_do_upgrade "$1" + ;; + nokia,ea0326gmp|\ + tplink,tl-xdr4288|\ + tplink,tl-xdr6086|\ + tplink,tl-xdr6088|\ + xiaomi,redmi-router-ax6000-ubootmod) + [ -e /dev/fit0 ] && fitblk /dev/fit0 + [ -e /dev/fitrw ] && fitblk /dev/fitrw + CI_KERNPART="fit" + nand_do_upgrade "$1" + ;; + ubnt,unifi-6-plus) + CI_KERNPART="kernel0" + EMMC_ROOT_DEV="$(cmdline_get_var root)" + emmc_do_upgrade "$1" + ;; + xiaomi,mi-router-ax3000t|\ + xiaomi,mi-router-wr30u-stock|\ + xiaomi,redmi-router-ax6000-stock) + CI_KERN_UBIPART=ubi_kernel + CI_ROOT_UBIPART=ubi + nand_do_upgrade "$1" + ;; + zyxel,ex5601-t0-ubootmod) + CI_KERNPART="fit" + CI_ROOTPART="ubi_rootfs" + nand_do_upgrade "$1" + ;; + unielec,u7981-01*) + local rootdev="$(cmdline_get_var root)" + rootdev="${rootdev##*/}" + rootdev="${rootdev%p[0-9]*}" + case "$rootdev" in + mmc*) + CI_ROOTDEV="$rootdev" + CI_KERNPART="kernel" + CI_ROOTPART="rootfs" + emmc_do_upgrade "$1" + ;; + *) + CI_KERNPART="fit" + nand_do_upgrade "$1" + ;; + esac + ;; *) nand_do_upgrade "$1" ;; @@ -65,7 +207,10 @@ platform_check_image() { case "$board" in bananapi,bpi-r3|\ - bananapi,bpi-r4) + bananapi,bpi-r3-mini|\ + bananapi,bpi-r4|\ + bananapi,bpi-r4-poe|\ + cmcc,rax3000m) [ "$magic" != "d00dfeed" ] && { echo "Invalid image type." return 1 @@ -74,7 +219,7 @@ platform_check_image() { ;; *) nand_do_platform_check "$board" "$1" - return 0 + return $? ;; esac @@ -83,35 +228,54 @@ platform_check_image() { platform_copy_config() { case "$(board_name)" in - bananapi,bpi-r3) + cmcc,rax3000m) case "$(cmdline_get_var root)" in /dev/mmc*) emmc_copy_config ;; esac ;; - bananapi,bpi-r4) - case "$(platform_get_bootdev)" in + bananapi,bpi-r3|\ + bananapi,bpi-r3-mini|\ + bananapi,bpi-r4|\ + bananapi,bpi-r4-poe) + case "$(fitblk_get_bootdev)" in mmcblk*) emmc_copy_config ;; esac ;; - cmcc,rax3000m-emmc|\ + acer,predator-w6|\ glinet,gl-mt2500|\ glinet,gl-mt6000|\ - jdcloud,re-cs-05) + glinet,gl-x3000|\ + glinet,gl-xe3000|\ + jdcloud,re-cp-03|\ + smartrg,sdg-8612|\ + smartrg,sdg-8614|\ + smartrg,sdg-8622|\ + smartrg,sdg-8632|\ + smartrg,sdg-8733|\ + smartrg,sdg-8734|\ + ubnt,unifi-6-plus) emmc_copy_config ;; esac - } - +} + platform_pre_upgrade() { local board=$(board_name) case "$board" in - asus,tuf-ax4200) + asus,rt-ax59u|\ + asus,tuf-ax4200|\ + asus,tuf-ax6000) asus_initial_setup ;; + xiaomi,mi-router-ax3000t|\ + xiaomi,mi-router-wr30u-stock|\ + xiaomi,redmi-router-ax6000-stock) + xiaomi_initial_setup + ;; esac } diff --git a/target/linux/mediatek/filogic/config-5.15 b/target/linux/mediatek/filogic/config-5.15 deleted file mode 100644 index c8af636c2..000000000 --- a/target/linux/mediatek/filogic/config-5.15 +++ /dev/null @@ -1,442 +0,0 @@ -CONFIG_64BIT=y -# CONFIG_AHCI_MTK is not set -CONFIG_AQUANTIA_PHY=y -CONFIG_ARCH_DMA_ADDR_T_64BIT=y -CONFIG_ARCH_KEEP_MEMBLOCK=y -CONFIG_ARCH_MEDIATEK=y -CONFIG_ARCH_MHP_MEMMAP_ON_MEMORY_ENABLE=y -CONFIG_ARCH_MMAP_RND_BITS=18 -CONFIG_ARCH_MMAP_RND_BITS_MAX=24 -CONFIG_ARCH_MMAP_RND_BITS_MIN=18 -CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=11 -CONFIG_ARCH_PROC_KCORE_TEXT=y -CONFIG_ARCH_SPARSEMEM_ENABLE=y -CONFIG_ARCH_STACKWALK=y -CONFIG_ARCH_SUSPEND_POSSIBLE=y -CONFIG_ARCH_WANTS_NO_INSTR=y -CONFIG_ARM64=y -CONFIG_ARM64_4K_PAGES=y -CONFIG_ARM64_CRYPTO=y -CONFIG_ARM64_ERRATUM_843419=y -CONFIG_ARM64_LD_HAS_FIX_ERRATUM_843419=y -CONFIG_ARM64_MODULE_PLTS=y -CONFIG_ARM64_PAGE_SHIFT=12 -CONFIG_ARM64_PA_BITS=48 -CONFIG_ARM64_PA_BITS_48=y -# CONFIG_ARM64_SW_TTBR0_PAN is not set -CONFIG_ARM64_TAGGED_ADDR_ABI=y -CONFIG_ARM64_VA_BITS=39 -CONFIG_ARM64_VA_BITS_39=y -CONFIG_ARM_AMBA=y -CONFIG_ARM_ARCH_TIMER=y -CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y -CONFIG_ARM_GIC=y -CONFIG_ARM_GIC_V2M=y -CONFIG_ARM_GIC_V3=y -CONFIG_ARM_GIC_V3_ITS=y -CONFIG_ARM_GIC_V3_ITS_PCI=y -CONFIG_ARM_MEDIATEK_CPUFREQ=y -CONFIG_ARM_PMU=y -CONFIG_ARM_PSCI_FW=y -CONFIG_ATA=y -CONFIG_AUDIT_ARCH_COMPAT_GENERIC=y -CONFIG_BLK_DEV_LOOP=y -CONFIG_BLK_DEV_SD=y -CONFIG_BLK_MQ_PCI=y -CONFIG_BLK_PM=y -CONFIG_BSD_PROCESS_ACCT=y -CONFIG_BSD_PROCESS_ACCT_V3=y -CONFIG_CC_HAVE_SHADOW_CALL_STACK=y -CONFIG_CC_HAVE_STACKPROTECTOR_SYSREG=y -CONFIG_CLKSRC_MMIO=y -CONFIG_CLONE_BACKWARDS=y -CONFIG_CMDLINE_OVERRIDE=y -CONFIG_COMMON_CLK=y -CONFIG_COMMON_CLK_MEDIATEK=y -# CONFIG_COMMON_CLK_MT2712 is not set -# CONFIG_COMMON_CLK_MT6779 is not set -# CONFIG_COMMON_CLK_MT6797 is not set -# CONFIG_COMMON_CLK_MT7622 is not set -CONFIG_COMMON_CLK_MT7981=y -CONFIG_COMMON_CLK_MT7981_ETHSYS=y -CONFIG_COMMON_CLK_MT7986=y -CONFIG_COMMON_CLK_MT7986_ETHSYS=y -CONFIG_COMMON_CLK_MT7988=y -# CONFIG_COMMON_CLK_MT8173 is not set -# CONFIG_COMMON_CLK_MT8183 is not set -# CONFIG_COMMON_CLK_MT8516 is not set -# CONFIG_COMPAT_32BIT_TIME is not set -CONFIG_CONFIGFS_FS=y -CONFIG_CONSOLE_LOGLEVEL_DEFAULT=15 -# CONFIG_CPUFREQ_DT is not set -CONFIG_CPU_FREQ=y -# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set -CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y -CONFIG_CPU_FREQ_GOV_ATTR_SET=y -CONFIG_CPU_FREQ_GOV_COMMON=y -CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y -CONFIG_CPU_FREQ_GOV_ONDEMAND=y -CONFIG_CPU_FREQ_GOV_PERFORMANCE=y -CONFIG_CPU_FREQ_GOV_POWERSAVE=y -CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y -CONFIG_CPU_FREQ_GOV_USERSPACE=y -CONFIG_CPU_FREQ_STAT=y -CONFIG_CPU_RMAP=y -CONFIG_CPU_THERMAL=y -CONFIG_CRC16=y -CONFIG_CRYPTO_AES_ARM64=y -CONFIG_CRYPTO_AES_ARM64_CE=y -CONFIG_CRYPTO_AES_ARM64_CE_BLK=y -CONFIG_CRYPTO_AES_ARM64_CE_CCM=y -CONFIG_CRYPTO_CMAC=y -CONFIG_CRYPTO_CRC32=y -CONFIG_CRYPTO_CRC32C=y -CONFIG_CRYPTO_CRYPTD=y -CONFIG_CRYPTO_DEFLATE=y -CONFIG_CRYPTO_DRBG=y -CONFIG_CRYPTO_DRBG_HMAC=y -CONFIG_CRYPTO_DRBG_MENU=y -CONFIG_CRYPTO_ECB=y -CONFIG_CRYPTO_ECC=y -CONFIG_CRYPTO_ECDH=y -CONFIG_CRYPTO_GHASH_ARM64_CE=y -CONFIG_CRYPTO_HASH_INFO=y -CONFIG_CRYPTO_HMAC=y -CONFIG_CRYPTO_JITTERENTROPY=y -CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y -CONFIG_CRYPTO_LIB_SHA256=y -CONFIG_CRYPTO_LZO=y -CONFIG_CRYPTO_RNG=y -CONFIG_CRYPTO_RNG2=y -CONFIG_CRYPTO_RNG_DEFAULT=y -CONFIG_CRYPTO_SHA256=y -CONFIG_CRYPTO_SHA256_ARM64=y -CONFIG_CRYPTO_SHA2_ARM64_CE=y -CONFIG_CRYPTO_SHA512=y -CONFIG_CRYPTO_SIMD=y -CONFIG_CRYPTO_ZSTD=y -CONFIG_DCACHE_WORD_ACCESS=y -CONFIG_DEBUG_MISC=y -CONFIG_DIMLIB=y -CONFIG_DMADEVICES=y -CONFIG_DMATEST=y -CONFIG_DMA_DIRECT_REMAP=y -CONFIG_DMA_ENGINE=y -CONFIG_DMA_ENGINE_RAID=y -CONFIG_DMA_OF=y -CONFIG_DMA_REMAP=y -CONFIG_DMA_VIRTUAL_CHANNELS=y -CONFIG_DTC=y -CONFIG_DYNAMIC_DEBUG=y -CONFIG_EDAC_SUPPORT=y -CONFIG_EINT_MTK=y -CONFIG_EXT4_FS=y -CONFIG_F2FS_FS=y -CONFIG_FIT_PARTITION=y -CONFIG_FIXED_PHY=y -CONFIG_FIX_EARLYCON_MEM=y -CONFIG_FRAME_POINTER=y -CONFIG_FS_IOMAP=y -CONFIG_FS_MBCACHE=y -CONFIG_FWNODE_MDIO=y -CONFIG_FW_LOADER_PAGED_BUF=y -CONFIG_GENERIC_ALLOCATOR=y -CONFIG_GENERIC_ARCH_TOPOLOGY=y -CONFIG_GENERIC_BUG=y -CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y -CONFIG_GENERIC_CLOCKEVENTS=y -CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y -CONFIG_GENERIC_CPU_AUTOPROBE=y -CONFIG_GENERIC_CPU_VULNERABILITIES=y -CONFIG_GENERIC_CSUM=y -CONFIG_GENERIC_EARLY_IOREMAP=y -CONFIG_GENERIC_FIND_FIRST_BIT=y -CONFIG_GENERIC_GETTIMEOFDAY=y -CONFIG_GENERIC_IDLE_POLL_SETUP=y -CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y -CONFIG_GENERIC_IRQ_SHOW=y -CONFIG_GENERIC_IRQ_SHOW_LEVEL=y -CONFIG_GENERIC_LIB_DEVMEM_IS_ALLOWED=y -CONFIG_GENERIC_MSI_IRQ=y -CONFIG_GENERIC_MSI_IRQ_DOMAIN=y -CONFIG_GENERIC_PCI_IOMAP=y -CONFIG_GENERIC_PHY=y -CONFIG_GENERIC_PINCONF=y -CONFIG_GENERIC_PINCTRL_GROUPS=y -CONFIG_GENERIC_PINMUX_FUNCTIONS=y -CONFIG_GENERIC_SCHED_CLOCK=y -CONFIG_GENERIC_SMP_IDLE_THREAD=y -CONFIG_GENERIC_STRNCPY_FROM_USER=y -CONFIG_GENERIC_STRNLEN_USER=y -CONFIG_GENERIC_TIME_VSYSCALL=y -CONFIG_GLOB=y -CONFIG_GPIO_CDEV=y -CONFIG_GRO_CELLS=y -CONFIG_HANDLE_DOMAIN_IRQ=y -CONFIG_HARDIRQS_SW_RESEND=y -CONFIG_HAS_DMA=y -CONFIG_HAS_IOMEM=y -CONFIG_HAS_IOPORT_MAP=y -CONFIG_HWMON=y -CONFIG_HW_RANDOM=y -CONFIG_HW_RANDOM_MTK=y -CONFIG_I2C=y -CONFIG_I2C_BOARDINFO=y -CONFIG_I2C_CHARDEV=y -CONFIG_I2C_MT65XX=y -CONFIG_ICPLUS_PHY=y -CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000 -CONFIG_INITRAMFS_SOURCE="" -CONFIG_IO_URING=y -CONFIG_IRQCHIP=y -CONFIG_IRQ_DOMAIN=y -CONFIG_IRQ_DOMAIN_HIERARCHY=y -CONFIG_IRQ_FORCED_THREADING=y -CONFIG_IRQ_TIME_ACCOUNTING=y -CONFIG_IRQ_WORK=y -CONFIG_JBD2=y -CONFIG_JUMP_LABEL=y -CONFIG_LIBFDT=y -CONFIG_LOCK_DEBUGGING_SUPPORT=y -CONFIG_LOCK_SPIN_ON_OWNER=y -CONFIG_LZO_COMPRESS=y -CONFIG_LZO_DECOMPRESS=y -CONFIG_MAGIC_SYSRQ=y -CONFIG_MAXLINEAR_GPHY=y -CONFIG_MDIO_BUS=y -CONFIG_MDIO_DEVICE=y -CONFIG_MDIO_DEVRES=y -CONFIG_MEDIATEK_2P5G_PHY=y -CONFIG_MEDIATEK_GE_PHY=y -CONFIG_MEDIATEK_GE_SOC_PHY=y -CONFIG_MEDIATEK_WATCHDOG=y -CONFIG_MEMFD_CREATE=y -CONFIG_MESSAGE_LOGLEVEL_DEFAULT=7 -CONFIG_MFD_SYSCON=y -CONFIG_MIGRATION=y -CONFIG_MMC=y -CONFIG_MMC_BLOCK=y -CONFIG_MMC_CQHCI=y -CONFIG_MMC_MTK=y -CONFIG_MODULES_TREE_LOOKUP=y -CONFIG_MODULES_USE_ELF_RELA=y -CONFIG_MTD_NAND_CORE=y -CONFIG_MTD_NAND_ECC=y -CONFIG_MTD_NAND_ECC_MEDIATEK=y -CONFIG_MTD_NAND_ECC_SW_HAMMING=y -CONFIG_MTD_NAND_MTK=y -CONFIG_MTD_NAND_MTK_BMT=y -CONFIG_MTD_PARSER_TRX=y -CONFIG_MTD_RAW_NAND=y -CONFIG_MTD_SPI_NAND=y -CONFIG_MTD_SPI_NOR=y -CONFIG_MTD_SPLIT_FIRMWARE=y -CONFIG_MTD_SPLIT_FIT_FW=y -CONFIG_MTD_UBI=y -CONFIG_MTD_UBI_BEB_LIMIT=20 -CONFIG_MTD_UBI_BLOCK=y -CONFIG_MTD_UBI_FASTMAP=y -CONFIG_MTD_UBI_WL_THRESHOLD=4096 -# CONFIG_MTK_CMDQ is not set -# CONFIG_MTK_CQDMA is not set -CONFIG_MTK_EFUSE=y -CONFIG_MTK_HSDMA=y -CONFIG_MTK_INFRACFG=y -CONFIG_MTK_PMIC_WRAP=y -CONFIG_MTK_SCPSYS=y -CONFIG_MTK_SCPSYS_PM_DOMAINS=y -CONFIG_MTK_THERMAL=y -CONFIG_MTK_TIMER=y -# CONFIG_MTK_UART_APDMA is not set -CONFIG_MUTEX_SPIN_ON_OWNER=y -CONFIG_NEED_DMA_MAP_STATE=y -CONFIG_NEED_SG_DMA_LENGTH=y -CONFIG_NET_DEVLINK=y -CONFIG_NET_DSA=y -CONFIG_NET_DSA_MT7530=y -CONFIG_NET_DSA_MT7530_MDIO=y -CONFIG_NET_DSA_MT7530_MMIO=y -CONFIG_NET_DSA_TAG_MTK=y -CONFIG_NET_FLOW_LIMIT=y -CONFIG_NET_MEDIATEK_SOC=y -CONFIG_NET_MEDIATEK_SOC_USXGMII=y -CONFIG_NET_MEDIATEK_SOC_WED=y -CONFIG_NET_SELFTESTS=y -CONFIG_NET_SWITCHDEV=y -CONFIG_NET_VENDOR_MEDIATEK=y -CONFIG_NLS=y -CONFIG_NO_HZ_COMMON=y -CONFIG_NO_HZ_IDLE=y -CONFIG_NR_CPUS=4 -CONFIG_NVMEM=y -CONFIG_NVMEM_SYSFS=y -CONFIG_OF=y -CONFIG_OF_ADDRESS=y -CONFIG_OF_DYNAMIC=y -CONFIG_OF_EARLY_FLATTREE=y -CONFIG_OF_FLATTREE=y -CONFIG_OF_GPIO=y -CONFIG_OF_IRQ=y -CONFIG_OF_KOBJ=y -CONFIG_OF_MDIO=y -CONFIG_OF_OVERLAY=y -CONFIG_OF_RESOLVE=y -CONFIG_PADATA=y -CONFIG_PAGE_POOL=y -CONFIG_PAGE_POOL_STATS=y -CONFIG_PARTITION_PERCPU=y -CONFIG_PCI=y -CONFIG_PCIEAER=y -CONFIG_PCIEASPM=y -# CONFIG_PCIEASPM_DEFAULT is not set -CONFIG_PCIEASPM_PERFORMANCE=y -# CONFIG_PCIEASPM_POWERSAVE is not set -# CONFIG_PCIEASPM_POWER_SUPERSAVE is not set -CONFIG_PCIEPORTBUS=y -# CONFIG_PCIE_MEDIATEK is not set -CONFIG_PCIE_MEDIATEK_GEN3=y -CONFIG_PCIE_PME=y -CONFIG_PCI_DEBUG=y -CONFIG_PCI_DOMAINS=y -CONFIG_PCI_DOMAINS_GENERIC=y -CONFIG_PCI_MSI=y -CONFIG_PCI_MSI_IRQ_DOMAIN=y -CONFIG_PCS_MTK_LYNXI=y -CONFIG_PERF_EVENTS=y -CONFIG_PGTABLE_LEVELS=3 -CONFIG_PHYLIB=y -CONFIG_PHYLINK=y -CONFIG_PHYS_ADDR_T_64BIT=y -CONFIG_PHY_MTK_TPHY=y -# CONFIG_PHY_MTK_UFS is not set -CONFIG_PHY_MTK_XSPHY=y -CONFIG_PINCTRL=y -# CONFIG_PINCTRL_MT2712 is not set -# CONFIG_PINCTRL_MT6765 is not set -# CONFIG_PINCTRL_MT6797 is not set -# CONFIG_PINCTRL_MT7622 is not set -CONFIG_PINCTRL_MT7981=y -CONFIG_PINCTRL_MT7986=y -CONFIG_PINCTRL_MT7988=y -# CONFIG_PINCTRL_MT8173 is not set -# CONFIG_PINCTRL_MT8183 is not set -CONFIG_PINCTRL_MT8516=y -CONFIG_PINCTRL_MTK=y -CONFIG_PINCTRL_MTK_MOORE=y -CONFIG_PINCTRL_MTK_V2=y -CONFIG_PM=y -CONFIG_PM_CLK=y -CONFIG_PM_GENERIC_DOMAINS=y -CONFIG_PM_GENERIC_DOMAINS_OF=y -CONFIG_PM_OPP=y -CONFIG_POWER_RESET=y -CONFIG_POWER_RESET_SYSCON=y -CONFIG_POWER_SUPPLY=y -CONFIG_PRINTK_TIME=y -CONFIG_PSTORE=y -CONFIG_PSTORE_COMPRESS=y -CONFIG_PSTORE_COMPRESS_DEFAULT="deflate" -CONFIG_PSTORE_CONSOLE=y -CONFIG_PSTORE_DEFLATE_COMPRESS=y -CONFIG_PSTORE_DEFLATE_COMPRESS_DEFAULT=y -CONFIG_PSTORE_PMSG=y -CONFIG_PSTORE_RAM=y -CONFIG_PTP_1588_CLOCK_OPTIONAL=y -CONFIG_PWM=y -CONFIG_PWM_MEDIATEK=y -# CONFIG_PWM_MTK_DISP is not set -CONFIG_PWM_SYSFS=y -CONFIG_QUEUED_RWLOCKS=y -CONFIG_QUEUED_SPINLOCKS=y -CONFIG_RAS=y -CONFIG_RATIONAL=y -# CONFIG_RAVE_SP_CORE is not set -CONFIG_REALTEK_PHY=y -CONFIG_REED_SOLOMON=y -CONFIG_REED_SOLOMON_DEC8=y -CONFIG_REED_SOLOMON_ENC8=y -CONFIG_REGMAP=y -CONFIG_REGMAP_I2C=y -CONFIG_REGMAP_MMIO=y -CONFIG_REGULATOR=y -CONFIG_REGULATOR_FIXED_VOLTAGE=y -CONFIG_REGULATOR_MT6380=y -CONFIG_REGULATOR_RT5190A=y -CONFIG_RESET_CONTROLLER=y -CONFIG_RESET_TI_SYSCON=y -CONFIG_RFS_ACCEL=y -CONFIG_RODATA_FULL_DEFAULT_ENABLED=y -CONFIG_RPS=y -CONFIG_RTC_CLASS=y -CONFIG_RTC_DRV_MT7622=y -CONFIG_RTC_I2C_AND_SPI=y -CONFIG_RTL8367S_GSW=y -CONFIG_RWSEM_SPIN_ON_OWNER=y -CONFIG_SCHED_MC=y -CONFIG_SCSI=y -CONFIG_SCSI_COMMON=y -# CONFIG_SECTION_MISMATCH_WARN_ONLY is not set -CONFIG_SERIAL_8250_FSL=y -CONFIG_SERIAL_8250_MT6577=y -CONFIG_SERIAL_8250_NR_UARTS=3 -CONFIG_SERIAL_8250_RUNTIME_UARTS=3 -CONFIG_SERIAL_DEV_BUS=y -CONFIG_SERIAL_DEV_CTRL_TTYPORT=y -CONFIG_SERIAL_MCTRL_GPIO=y -CONFIG_SERIAL_OF_PLATFORM=y -CONFIG_SGL_ALLOC=y -CONFIG_SG_POOL=y -CONFIG_SMP=y -CONFIG_SOCK_RX_QUEUE_MAPPING=y -CONFIG_SPARSEMEM=y -CONFIG_SPARSEMEM_EXTREME=y -CONFIG_SPARSEMEM_VMEMMAP=y -CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y -CONFIG_SPARSE_IRQ=y -CONFIG_SPI=y -CONFIG_SPI_DYNAMIC=y -CONFIG_SPI_MASTER=y -CONFIG_SPI_MEM=y -CONFIG_SPI_MT65XX=y -CONFIG_SPI_MTK_NOR=y -CONFIG_SPI_MTK_SNFI=y -CONFIG_SRCU=y -CONFIG_SWIOTLB=y -CONFIG_SWPHY=y -CONFIG_SYSCTL_EXCEPTION_TRACE=y -CONFIG_THERMAL=y -CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y -CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0 -CONFIG_THERMAL_GOV_BANG_BANG=y -CONFIG_THERMAL_GOV_FAIR_SHARE=y -CONFIG_THERMAL_GOV_STEP_WISE=y -CONFIG_THERMAL_GOV_USER_SPACE=y -CONFIG_THERMAL_HWMON=y -CONFIG_THERMAL_OF=y -CONFIG_THERMAL_WRITABLE_TRIPS=y -CONFIG_THREAD_INFO_IN_TASK=y -CONFIG_TICK_CPU_ACCOUNTING=y -CONFIG_TIMER_OF=y -CONFIG_TIMER_PROBE=y -CONFIG_TRACE_IRQFLAGS_NMI_SUPPORT=y -CONFIG_TREE_RCU=y -CONFIG_TREE_SRCU=y -CONFIG_UBIFS_FS=y -# CONFIG_UCLAMP_TASK is not set -# CONFIG_UNMAP_KERNEL_AT_EL0 is not set -CONFIG_USB_SUPPORT=y -CONFIG_VMAP_STACK=y -CONFIG_WATCHDOG_CORE=y -CONFIG_WATCHDOG_PRETIMEOUT_DEFAULT_GOV_PANIC=y -CONFIG_WATCHDOG_PRETIMEOUT_GOV=y -# CONFIG_WATCHDOG_PRETIMEOUT_GOV_NOOP is not set -CONFIG_WATCHDOG_PRETIMEOUT_GOV_PANIC=y -CONFIG_WATCHDOG_PRETIMEOUT_GOV_SEL=m -CONFIG_WATCHDOG_SYSFS=y -CONFIG_XPS=y -CONFIG_XXHASH=y -CONFIG_ZLIB_DEFLATE=y -CONFIG_ZLIB_INFLATE=y -CONFIG_ZONE_DMA32=y -CONFIG_ZSTD_COMPRESS=y -CONFIG_ZSTD_DECOMPRESS=y diff --git a/target/linux/mediatek/filogic/config-6.1 b/target/linux/mediatek/filogic/config-6.1 deleted file mode 100644 index 36cb9c1e4..000000000 --- a/target/linux/mediatek/filogic/config-6.1 +++ /dev/null @@ -1,473 +0,0 @@ -CONFIG_64BIT=y -# CONFIG_AHCI_MTK is not set -CONFIG_AQUANTIA_PHY=y -CONFIG_ARCH_BINFMT_ELF_EXTRA_PHDRS=y -CONFIG_ARCH_CORRECT_STACKTRACE_ON_KRETPROBE=y -CONFIG_ARCH_DMA_ADDR_T_64BIT=y -CONFIG_ARCH_KEEP_MEMBLOCK=y -CONFIG_ARCH_MEDIATEK=y -CONFIG_ARCH_MHP_MEMMAP_ON_MEMORY_ENABLE=y -CONFIG_ARCH_MMAP_RND_BITS=18 -CONFIG_ARCH_MMAP_RND_BITS_MAX=24 -CONFIG_ARCH_MMAP_RND_BITS_MIN=18 -CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=11 -CONFIG_ARCH_NR_GPIO=0 -CONFIG_ARCH_PROC_KCORE_TEXT=y -CONFIG_ARCH_SPARSEMEM_ENABLE=y -CONFIG_ARCH_STACKWALK=y -CONFIG_ARCH_SUSPEND_POSSIBLE=y -CONFIG_ARCH_WANTS_NO_INSTR=y -CONFIG_ARCH_WANTS_THP_SWAP=y -CONFIG_ARM64=y -CONFIG_ARM64_4K_PAGES=y -CONFIG_ARM64_ERRATUM_843419=y -CONFIG_ARM64_LD_HAS_FIX_ERRATUM_843419=y -CONFIG_ARM64_PAGE_SHIFT=12 -CONFIG_ARM64_PA_BITS=48 -CONFIG_ARM64_PA_BITS_48=y -CONFIG_ARM64_TAGGED_ADDR_ABI=y -CONFIG_ARM64_VA_BITS=39 -CONFIG_ARM64_VA_BITS_39=y -CONFIG_ARM_AMBA=y -CONFIG_ARM_ARCH_TIMER=y -CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y -CONFIG_ARM_GIC=y -CONFIG_ARM_GIC_V2M=y -CONFIG_ARM_GIC_V3=y -CONFIG_ARM_GIC_V3_ITS=y -CONFIG_ARM_GIC_V3_ITS_PCI=y -CONFIG_ARM_MEDIATEK_CPUFREQ=y -CONFIG_ARM_PMU=y -CONFIG_ARM_PSCI_FW=y -CONFIG_ATA=y -CONFIG_AUDIT_ARCH_COMPAT_GENERIC=y -CONFIG_BLK_DEV_LOOP=y -CONFIG_BLK_DEV_SD=y -CONFIG_BLK_MQ_PCI=y -CONFIG_BLK_PM=y -CONFIG_BSD_PROCESS_ACCT=y -CONFIG_BSD_PROCESS_ACCT_V3=y -CONFIG_CC_HAVE_SHADOW_CALL_STACK=y -CONFIG_CC_HAVE_STACKPROTECTOR_SYSREG=y -CONFIG_CC_IMPLICIT_FALLTHROUGH="-Wimplicit-fallthrough=5" -CONFIG_CC_NO_ARRAY_BOUNDS=y -CONFIG_CLKSRC_MMIO=y -CONFIG_CLONE_BACKWARDS=y -CONFIG_CMDLINE_OVERRIDE=y -CONFIG_COMMON_CLK=y -CONFIG_COMMON_CLK_MEDIATEK=y -# CONFIG_COMMON_CLK_MT2712 is not set -# CONFIG_COMMON_CLK_MT6779 is not set -# CONFIG_COMMON_CLK_MT6795 is not set -# CONFIG_COMMON_CLK_MT6797 is not set -# CONFIG_COMMON_CLK_MT7622 is not set -CONFIG_COMMON_CLK_MT7981=y -CONFIG_COMMON_CLK_MT7981_ETHSYS=y -CONFIG_COMMON_CLK_MT7986=y -CONFIG_COMMON_CLK_MT7986_ETHSYS=y -CONFIG_COMMON_CLK_MT7988=y -# CONFIG_COMMON_CLK_MT8173 is not set -# CONFIG_COMMON_CLK_MT8183 is not set -# CONFIG_COMMON_CLK_MT8186 is not set -# CONFIG_COMMON_CLK_MT8195 is not set -# CONFIG_COMMON_CLK_MT8365 is not set -# CONFIG_COMMON_CLK_MT8516 is not set -CONFIG_COMPACT_UNEVICTABLE_DEFAULT=1 -# CONFIG_COMPAT_32BIT_TIME is not set -CONFIG_CONFIGFS_FS=y -CONFIG_CONSOLE_LOGLEVEL_DEFAULT=15 -CONFIG_CONTEXT_TRACKING=y -CONFIG_CONTEXT_TRACKING_IDLE=y -# CONFIG_CPUFREQ_DT is not set -CONFIG_CPU_FREQ=y -# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set -CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y -CONFIG_CPU_FREQ_GOV_ATTR_SET=y -CONFIG_CPU_FREQ_GOV_COMMON=y -CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y -CONFIG_CPU_FREQ_GOV_ONDEMAND=y -CONFIG_CPU_FREQ_GOV_PERFORMANCE=y -CONFIG_CPU_FREQ_GOV_POWERSAVE=y -CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y -CONFIG_CPU_FREQ_GOV_USERSPACE=y -CONFIG_CPU_FREQ_STAT=y -CONFIG_CPU_LITTLE_ENDIAN=y -CONFIG_CPU_RMAP=y -CONFIG_CPU_THERMAL=y -CONFIG_CRC16=y -CONFIG_CRYPTO_AES_ARM64=y -CONFIG_CRYPTO_AES_ARM64_CE=y -CONFIG_CRYPTO_AES_ARM64_CE_BLK=y -CONFIG_CRYPTO_AES_ARM64_CE_CCM=y -CONFIG_CRYPTO_CMAC=y -CONFIG_CRYPTO_CRC32=y -CONFIG_CRYPTO_CRC32C=y -CONFIG_CRYPTO_CRYPTD=y -CONFIG_CRYPTO_DEFLATE=y -CONFIG_CRYPTO_DRBG=y -CONFIG_CRYPTO_DRBG_HMAC=y -CONFIG_CRYPTO_DRBG_MENU=y -CONFIG_CRYPTO_ECB=y -CONFIG_CRYPTO_ECC=y -CONFIG_CRYPTO_ECDH=y -CONFIG_CRYPTO_GHASH_ARM64_CE=y -CONFIG_CRYPTO_HASH_INFO=y -CONFIG_CRYPTO_HMAC=y -CONFIG_CRYPTO_JITTERENTROPY=y -CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y -CONFIG_CRYPTO_LIB_SHA1=y -CONFIG_CRYPTO_LIB_SHA256=y -CONFIG_CRYPTO_LIB_UTILS=y -CONFIG_CRYPTO_LZO=y -CONFIG_CRYPTO_RNG=y -CONFIG_CRYPTO_RNG2=y -CONFIG_CRYPTO_RNG_DEFAULT=y -CONFIG_CRYPTO_SHA256=y -CONFIG_CRYPTO_SHA256_ARM64=y -CONFIG_CRYPTO_SHA2_ARM64_CE=y -CONFIG_CRYPTO_SHA3=y -CONFIG_CRYPTO_SHA512=y -CONFIG_CRYPTO_ZSTD=y -CONFIG_DCACHE_WORD_ACCESS=y -CONFIG_DEBUG_INFO=y -CONFIG_DEBUG_MISC=y -CONFIG_DIMLIB=y -CONFIG_DMADEVICES=y -CONFIG_DMATEST=y -CONFIG_DMA_DIRECT_REMAP=y -CONFIG_DMA_ENGINE=y -CONFIG_DMA_ENGINE_RAID=y -CONFIG_DMA_OF=y -CONFIG_DMA_VIRTUAL_CHANNELS=y -CONFIG_DTC=y -CONFIG_EDAC_SUPPORT=y -CONFIG_EINT_MTK=y -CONFIG_EXCLUSIVE_SYSTEM_RAM=y -CONFIG_EXT4_FS=y -CONFIG_F2FS_FS=y -CONFIG_FIT_PARTITION=y -CONFIG_FIXED_PHY=y -CONFIG_FIX_EARLYCON_MEM=y -CONFIG_FRAME_POINTER=y -CONFIG_FS_IOMAP=y -CONFIG_FS_MBCACHE=y -CONFIG_FWNODE_MDIO=y -CONFIG_FW_LOADER_PAGED_BUF=y -CONFIG_FW_LOADER_SYSFS=y -CONFIG_GCC11_NO_ARRAY_BOUNDS=y -CONFIG_GCC_SUPPORTS_DYNAMIC_FTRACE_WITH_REGS=y -CONFIG_GENERIC_ALLOCATOR=y -CONFIG_GENERIC_ARCH_TOPOLOGY=y -CONFIG_GENERIC_BUG=y -CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y -CONFIG_GENERIC_CLOCKEVENTS=y -CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y -CONFIG_GENERIC_CPU_AUTOPROBE=y -CONFIG_GENERIC_CPU_VULNERABILITIES=y -CONFIG_GENERIC_CSUM=y -CONFIG_GENERIC_EARLY_IOREMAP=y -CONFIG_GENERIC_GETTIMEOFDAY=y -CONFIG_GENERIC_IDLE_POLL_SETUP=y -CONFIG_GENERIC_IOREMAP=y -CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y -CONFIG_GENERIC_IRQ_SHOW=y -CONFIG_GENERIC_IRQ_SHOW_LEVEL=y -CONFIG_GENERIC_LIB_DEVMEM_IS_ALLOWED=y -CONFIG_GENERIC_MSI_IRQ=y -CONFIG_GENERIC_MSI_IRQ_DOMAIN=y -CONFIG_GENERIC_PCI_IOMAP=y -CONFIG_GENERIC_PHY=y -CONFIG_GENERIC_PINCONF=y -CONFIG_GENERIC_PINCTRL_GROUPS=y -CONFIG_GENERIC_PINMUX_FUNCTIONS=y -CONFIG_GENERIC_SCHED_CLOCK=y -CONFIG_GENERIC_SMP_IDLE_THREAD=y -CONFIG_GENERIC_STRNCPY_FROM_USER=y -CONFIG_GENERIC_STRNLEN_USER=y -CONFIG_GENERIC_TIME_VSYSCALL=y -CONFIG_GLOB=y -CONFIG_GPIO_CDEV=y -CONFIG_GRO_CELLS=y -CONFIG_HARDIRQS_SW_RESEND=y -CONFIG_HAS_DMA=y -CONFIG_HAS_IOMEM=y -CONFIG_HAS_IOPORT_MAP=y -CONFIG_HWMON=y -CONFIG_HW_RANDOM=y -CONFIG_HW_RANDOM_MTK=y -CONFIG_I2C=y -CONFIG_I2C_BOARDINFO=y -CONFIG_I2C_CHARDEV=y -CONFIG_I2C_MT65XX=y -CONFIG_ICPLUS_PHY=y -CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000 -CONFIG_INITRAMFS_SOURCE="" -CONFIG_IRQCHIP=y -CONFIG_IRQ_DOMAIN=y -CONFIG_IRQ_DOMAIN_HIERARCHY=y -CONFIG_IRQ_FORCED_THREADING=y -CONFIG_IRQ_TIME_ACCOUNTING=y -CONFIG_IRQ_WORK=y -CONFIG_JBD2=y -CONFIG_JUMP_LABEL=y -CONFIG_LIBFDT=y -CONFIG_LOCK_DEBUGGING_SUPPORT=y -CONFIG_LOCK_SPIN_ON_OWNER=y -CONFIG_LZO_COMPRESS=y -CONFIG_LZO_DECOMPRESS=y -CONFIG_MAGIC_SYSRQ=y -CONFIG_MAXLINEAR_GPHY=y -CONFIG_MDIO_BUS=y -CONFIG_MDIO_DEVICE=y -CONFIG_MDIO_DEVRES=y -CONFIG_MEDIATEK_2P5G_PHY=y -CONFIG_MEDIATEK_GE_PHY=y -CONFIG_MEDIATEK_GE_SOC_PHY=y -CONFIG_MEDIATEK_WATCHDOG=y -CONFIG_MEMFD_CREATE=y -CONFIG_MESSAGE_LOGLEVEL_DEFAULT=7 -CONFIG_MFD_SYSCON=y -CONFIG_MIGRATION=y -CONFIG_MMC=y -CONFIG_MMC_BLOCK=y -CONFIG_MMC_CQHCI=y -CONFIG_MMC_MTK=y -CONFIG_MODULES_TREE_LOOKUP=y -CONFIG_MODULES_USE_ELF_RELA=y -CONFIG_MTD_NAND_CORE=y -CONFIG_MTD_NAND_ECC=y -CONFIG_MTD_NAND_ECC_MEDIATEK=y -CONFIG_MTD_NAND_ECC_SW_HAMMING=y -CONFIG_MTD_NAND_MTK=y -CONFIG_MTD_NAND_MTK_BMT=y -CONFIG_MTD_PARSER_TRX=y -CONFIG_MTD_RAW_NAND=y -CONFIG_MTD_SPI_NAND=y -CONFIG_MTD_SPI_NOR=y -CONFIG_MTD_SPLIT_FIRMWARE=y -CONFIG_MTD_SPLIT_FIT_FW=y -CONFIG_MTD_UBI=y -CONFIG_MTD_UBI_BEB_LIMIT=20 -CONFIG_MTD_UBI_BLOCK=y -CONFIG_MTD_UBI_FASTMAP=y -CONFIG_MTD_UBI_WL_THRESHOLD=4096 -# CONFIG_MTK_CMDQ is not set -# CONFIG_MTK_CQDMA is not set -CONFIG_MTK_HSDMA=y -CONFIG_MTK_INFRACFG=y -CONFIG_MTK_PMIC_WRAP=y -CONFIG_MTK_SCPSYS=y -CONFIG_MTK_SCPSYS_PM_DOMAINS=y -# CONFIG_MTK_SVS is not set -CONFIG_MTK_THERMAL=y -CONFIG_MTK_TIMER=y -# CONFIG_MTK_UART_APDMA is not set -CONFIG_MUTEX_SPIN_ON_OWNER=y -CONFIG_NEED_DMA_MAP_STATE=y -CONFIG_NEED_SG_DMA_LENGTH=y -CONFIG_NET_DEVLINK=y -CONFIG_NET_DSA=y -CONFIG_NET_DSA_MT7530=y -CONFIG_NET_DSA_MT7530_MDIO=y -CONFIG_NET_DSA_MT7530_MMIO=y -CONFIG_NET_DSA_TAG_MTK=y -CONFIG_NET_FLOW_LIMIT=y -CONFIG_NET_MEDIATEK_SOC=y -CONFIG_NET_MEDIATEK_SOC_USXGMII=y -CONFIG_NET_MEDIATEK_SOC_WED=y -CONFIG_NET_SELFTESTS=y -CONFIG_NET_SWITCHDEV=y -CONFIG_NET_VENDOR_MEDIATEK=y -CONFIG_NLS=y -CONFIG_NO_HZ_COMMON=y -CONFIG_NO_HZ_IDLE=y -CONFIG_NR_CPUS=4 -CONFIG_NVMEM=y -CONFIG_NVMEM_MTK_EFUSE=y -CONFIG_NVMEM_SYSFS=y -CONFIG_OF=y -CONFIG_OF_ADDRESS=y -CONFIG_OF_DYNAMIC=y -CONFIG_OF_EARLY_FLATTREE=y -CONFIG_OF_FLATTREE=y -CONFIG_OF_GPIO=y -CONFIG_OF_IRQ=y -CONFIG_OF_KOBJ=y -CONFIG_OF_MDIO=y -CONFIG_OF_OVERLAY=y -CONFIG_OF_RESOLVE=y -CONFIG_PADATA=y -CONFIG_PAGE_POOL=y -CONFIG_PAGE_POOL_STATS=y -CONFIG_PAGE_SIZE_LESS_THAN_256KB=y -CONFIG_PAGE_SIZE_LESS_THAN_64KB=y -CONFIG_PARTITION_PERCPU=y -CONFIG_PCI=y -CONFIG_PCIEAER=y -CONFIG_PCIEASPM=y -# CONFIG_PCIEASPM_DEFAULT is not set -CONFIG_PCIEASPM_PERFORMANCE=y -# CONFIG_PCIEASPM_POWERSAVE is not set -# CONFIG_PCIEASPM_POWER_SUPERSAVE is not set -CONFIG_PCIEPORTBUS=y -# CONFIG_PCIE_MEDIATEK is not set -CONFIG_PCIE_MEDIATEK_GEN3=y -CONFIG_PCIE_PME=y -CONFIG_PCI_DEBUG=y -CONFIG_PCI_DOMAINS=y -CONFIG_PCI_DOMAINS_GENERIC=y -CONFIG_PCI_MSI=y -CONFIG_PCI_MSI_IRQ_DOMAIN=y -CONFIG_PCS_MTK_LYNXI=y -CONFIG_PERF_EVENTS=y -CONFIG_PGTABLE_LEVELS=3 -CONFIG_PHYLIB=y -CONFIG_PHYLIB_LEDS=y -CONFIG_PHYLINK=y -CONFIG_PHYS_ADDR_T_64BIT=y -# CONFIG_PHY_MTK_DP is not set -# CONFIG_PHY_MTK_PCIE is not set -CONFIG_PHY_MTK_TPHY=y -# CONFIG_PHY_MTK_UFS is not set -CONFIG_PHY_MTK_XSPHY=y -CONFIG_PINCTRL=y -# CONFIG_PINCTRL_MT2712 is not set -# CONFIG_PINCTRL_MT6765 is not set -# CONFIG_PINCTRL_MT6795 is not set -# CONFIG_PINCTRL_MT6797 is not set -# CONFIG_PINCTRL_MT7622 is not set -CONFIG_PINCTRL_MT7981=y -CONFIG_PINCTRL_MT7986=y -CONFIG_PINCTRL_MT7988=y -# CONFIG_PINCTRL_MT8173 is not set -# CONFIG_PINCTRL_MT8183 is not set -# CONFIG_PINCTRL_MT8186 is not set -# CONFIG_PINCTRL_MT8188 is not set -# CONFIG_PINCTRL_MT8516 is not set -CONFIG_PINCTRL_MTK_MOORE=y -CONFIG_PINCTRL_MTK_V2=y -# CONFIG_PINCTRL_SINGLE is not set -CONFIG_PM=y -CONFIG_PM_CLK=y -CONFIG_PM_GENERIC_DOMAINS=y -CONFIG_PM_GENERIC_DOMAINS_OF=y -CONFIG_PM_OPP=y -CONFIG_POLYNOMIAL=y -CONFIG_POSIX_CPU_TIMERS_TASK_WORK=y -CONFIG_POWER_RESET=y -CONFIG_POWER_RESET_SYSCON=y -CONFIG_POWER_SUPPLY=y -CONFIG_PREEMPT_NONE_BUILD=y -CONFIG_PRINTK_TIME=y -CONFIG_PSTORE=y -CONFIG_PSTORE_COMPRESS=y -CONFIG_PSTORE_COMPRESS_DEFAULT="deflate" -CONFIG_PSTORE_CONSOLE=y -CONFIG_PSTORE_DEFLATE_COMPRESS=y -CONFIG_PSTORE_DEFLATE_COMPRESS_DEFAULT=y -CONFIG_PSTORE_PMSG=y -CONFIG_PSTORE_RAM=y -CONFIG_PTP_1588_CLOCK_OPTIONAL=y -CONFIG_PWM=y -CONFIG_PWM_MEDIATEK=y -# CONFIG_PWM_MTK_DISP is not set -CONFIG_PWM_SYSFS=y -CONFIG_QUEUED_RWLOCKS=y -CONFIG_QUEUED_SPINLOCKS=y -CONFIG_RANDSTRUCT_NONE=y -CONFIG_RAS=y -CONFIG_RATIONAL=y -# CONFIG_RAVE_SP_CORE is not set -CONFIG_REALTEK_PHY=y -CONFIG_REED_SOLOMON=y -CONFIG_REED_SOLOMON_DEC8=y -CONFIG_REED_SOLOMON_ENC8=y -CONFIG_REGMAP=y -CONFIG_REGMAP_I2C=y -CONFIG_REGMAP_MMIO=y -CONFIG_REGULATOR=y -CONFIG_REGULATOR_FIXED_VOLTAGE=y -CONFIG_REGULATOR_MT6380=y -CONFIG_REGULATOR_RT5190A=y -CONFIG_RESET_CONTROLLER=y -CONFIG_RESET_TI_SYSCON=y -CONFIG_RFS_ACCEL=y -CONFIG_RODATA_FULL_DEFAULT_ENABLED=y -CONFIG_RPS=y -CONFIG_RTC_CLASS=y -CONFIG_RTC_DRV_MT7622=y -CONFIG_RTC_I2C_AND_SPI=y -# CONFIG_RTL8367S_GSW is not set -CONFIG_RWSEM_SPIN_ON_OWNER=y -CONFIG_SCHED_MC=y -CONFIG_SCSI=y -CONFIG_SCSI_COMMON=y -# CONFIG_SECTION_MISMATCH_WARN_ONLY is not set -CONFIG_SERIAL_8250_FSL=y -CONFIG_SERIAL_8250_MT6577=y -CONFIG_SERIAL_8250_NR_UARTS=3 -CONFIG_SERIAL_8250_RUNTIME_UARTS=3 -CONFIG_SERIAL_DEV_BUS=y -CONFIG_SERIAL_DEV_CTRL_TTYPORT=y -CONFIG_SERIAL_MCTRL_GPIO=y -CONFIG_SERIAL_OF_PLATFORM=y -CONFIG_SGL_ALLOC=y -CONFIG_SG_POOL=y -CONFIG_SMP=y -CONFIG_SOCK_RX_QUEUE_MAPPING=y -CONFIG_SOFTIRQ_ON_OWN_STACK=y -CONFIG_SPARSEMEM=y -CONFIG_SPARSEMEM_EXTREME=y -CONFIG_SPARSEMEM_VMEMMAP=y -CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y -CONFIG_SPARSE_IRQ=y -CONFIG_SPI=y -CONFIG_SPI_DYNAMIC=y -CONFIG_SPI_MASTER=y -CONFIG_SPI_MEM=y -CONFIG_SPI_MT65XX=y -# CONFIG_SPI_MTK_NOR is not set -CONFIG_SPI_MTK_SNFI=y -# CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU is not set -CONFIG_SQUASHFS_DECOMP_SINGLE=y -CONFIG_SRCU=y -CONFIG_SWIOTLB=y -CONFIG_SWPHY=y -CONFIG_SYSCTL_EXCEPTION_TRACE=y -CONFIG_THERMAL=y -CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y -CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0 -CONFIG_THERMAL_GOV_BANG_BANG=y -CONFIG_THERMAL_GOV_FAIR_SHARE=y -CONFIG_THERMAL_GOV_STEP_WISE=y -CONFIG_THERMAL_GOV_USER_SPACE=y -CONFIG_THERMAL_HWMON=y -CONFIG_THERMAL_OF=y -CONFIG_THERMAL_WRITABLE_TRIPS=y -CONFIG_THREAD_INFO_IN_TASK=y -CONFIG_TICK_CPU_ACCOUNTING=y -CONFIG_TIMER_OF=y -CONFIG_TIMER_PROBE=y -CONFIG_TRACE_IRQFLAGS_NMI_SUPPORT=y -CONFIG_TREE_RCU=y -CONFIG_TREE_SRCU=y -CONFIG_UBIFS_FS=y -# CONFIG_UCLAMP_TASK is not set -# CONFIG_UNMAP_KERNEL_AT_EL0 is not set -CONFIG_USB_SUPPORT=y -CONFIG_VMAP_STACK=y -CONFIG_WATCHDOG_CORE=y -CONFIG_WATCHDOG_PRETIMEOUT_DEFAULT_GOV_PANIC=y -CONFIG_WATCHDOG_PRETIMEOUT_GOV=y -# CONFIG_WATCHDOG_PRETIMEOUT_GOV_NOOP is not set -CONFIG_WATCHDOG_PRETIMEOUT_GOV_PANIC=y -CONFIG_WATCHDOG_PRETIMEOUT_GOV_SEL=m -CONFIG_WATCHDOG_SYSFS=y -CONFIG_XPS=y -CONFIG_XXHASH=y -CONFIG_ZLIB_DEFLATE=y -CONFIG_ZLIB_INFLATE=y -CONFIG_ZONE_DMA32=y -CONFIG_ZSTD_COMMON=y -CONFIG_ZSTD_COMPRESS=y -CONFIG_ZSTD_DECOMPRESS=y diff --git a/target/linux/mediatek/filogic/config-6.6 b/target/linux/mediatek/filogic/config-6.6 index f6c8ec6d9..6d9d42853 100644 --- a/target/linux/mediatek/filogic/config-6.6 +++ b/target/linux/mediatek/filogic/config-6.6 @@ -48,7 +48,6 @@ CONFIG_AUDIT_ARCH_COMPAT_GENERIC=y CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_SD=y CONFIG_BLK_MQ_PCI=y -CONFIG_BLK_NVMEM=y CONFIG_BLK_PM=y CONFIG_BLOCK_NOTIFIERS=y CONFIG_BSD_PROCESS_ACCT=y diff --git a/target/linux/mediatek/filogic/target.mk b/target/linux/mediatek/filogic/target.mk index 4e5cde3d6..d1637e06a 100644 --- a/target/linux/mediatek/filogic/target.mk +++ b/target/linux/mediatek/filogic/target.mk @@ -2,7 +2,7 @@ ARCH:=aarch64 SUBTARGET:=filogic BOARDNAME:=Filogic 8x0 (MT798x) CPU_TYPE:=cortex-a53 -DEFAULT_PACKAGES += kmod-crypto-hw-safexcel kmod-mt7915e wpad-openssl uboot-envtools +DEFAULT_PACKAGES += fitblk kmod-phy-aquantia kmod-crypto-hw-safexcel wpad-basic-mbedtls uboot-envtools KERNELNAME:=Image dtbs define Target/Description diff --git a/target/linux/mediatek/image/Makefile b/target/linux/mediatek/image/Makefile index 97164428e..d4f79ec97 100644 --- a/target/linux/mediatek/image/Makefile +++ b/target/linux/mediatek/image/Makefile @@ -6,6 +6,8 @@ include $(TOPDIR)/rules.mk include $(INCLUDE_DIR)/image.mk +DEVICE_VARS += NETGEAR_ENC_MODEL NETGEAR_ENC_REGION NETGEAR_ENC_HW_ID_LIST NETGEAR_ENC_MODEL_LIST + loadaddr-$(CONFIG_TARGET_mediatek_mt7622) := 0x44000000 loadaddr-$(CONFIG_TARGET_mediatek_mt7623) := 0x80008000 loadaddr-$(CONFIG_TARGET_mediatek_mt7629) := 0x40008000 @@ -22,6 +24,10 @@ define Device/Default KERNEL_LOADADDR = $(loadaddr-y) FILESYSTEMS := squashfs DEVICE_DTS_DIR := $(DTS_DIR) + NETGEAR_ENC_MODEL := + NETGEAR_ENC_REGION := + NETGEAR_ENC_HW_ID_LIST := + NETGEAR_ENC_MODEL_LIST := IMAGES := sysupgrade.bin IMAGE/sysupgrade.bin := append-kernel | pad-to 128k | append-rootfs | \ pad-rootfs | append-metadata diff --git a/target/linux/mediatek/image/filogic.mk b/target/linux/mediatek/image/filogic.mk index d5eb8b811..94b3098b3 100644 --- a/target/linux/mediatek/image/filogic.mk +++ b/target/linux/mediatek/image/filogic.mk @@ -52,6 +52,44 @@ define Build/mt798x-gpt rm $@.tmp endef +metadata_gl_json = \ + '{ $(if $(IMAGE_METADATA),$(IMAGE_METADATA)$(comma)) \ + "metadata_version": "1.1", \ + "compat_version": "$(call json_quote,$(compat_version))", \ + $(if $(DEVICE_COMPAT_MESSAGE),"compat_message": "$(call json_quote,$(DEVICE_COMPAT_MESSAGE))"$(comma)) \ + $(if $(filter-out 1.0,$(compat_version)),"new_supported_devices": \ + [$(call metadata_devices,$(SUPPORTED_DEVICES))]$(comma) \ + "supported_devices": ["$(call json_quote,$(legacy_supported_message))"]$(comma)) \ + $(if $(filter 1.0,$(compat_version)),"supported_devices":[$(call metadata_devices,$(SUPPORTED_DEVICES))]$(comma)) \ + "version": { \ + "release": "$(call json_quote,$(VERSION_NUMBER))", \ + "date": "$(shell TZ='Asia/Chongqing' date '+%Y%m%d%H%M%S')", \ + "dist": "$(call json_quote,$(VERSION_DIST))", \ + "version": "$(call json_quote,$(VERSION_NUMBER))", \ + "revision": "$(call json_quote,$(REVISION))", \ + "target": "$(call json_quote,$(TARGETID))", \ + "board": "$(call json_quote,$(if $(BOARD_NAME),$(BOARD_NAME),$(DEVICE_NAME)))" \ + } \ + }' + +define Build/append-gl-metadata + $(if $(SUPPORTED_DEVICES),-echo $(call metadata_gl_json,$(SUPPORTED_DEVICES)) | fwtool -I - $@) + sha256sum "$@" | cut -d" " -f1 > "$@.sha256sum" + [ ! -s "$(BUILD_KEY)" -o ! -s "$(BUILD_KEY).ucert" -o ! -s "$@" ] || { \ + cp "$(BUILD_KEY).ucert" "$@.ucert" ;\ + usign -S -m "$@" -s "$(BUILD_KEY)" -x "$@.sig" ;\ + ucert -A -c "$@.ucert" -x "$@.sig" ;\ + fwtool -S "$@.ucert" "$@" ;\ + } +endef + +define Build/zyxel-nwa-fit-filogic + $(TOPDIR)/scripts/mkits-zyxel-fit-filogic.sh \ + $@.its $@ "80 e1 ff ff ff ff ff ff ff ff" + PATH=$(LINUX_DIR)/scripts/dtc:$(PATH) mkimage -f $@.its $@.new + @mv $@.new $@ +endef + define Build/cetron-header $(eval magic=$(word 1,$(1))) $(eval model=$(word 2,$(1))) @@ -67,19 +105,102 @@ define Build/cetron-header rm $@.tmp endef -define Device/abt_asr3000 - DEVICE_VENDOR := ABT - DEVICE_MODEL := ASR3000 - DEVICE_DTS := mt7981b-abt-asr3000 +define Device/acelink_ew-7886cax + DEVICE_VENDOR := Acelink + DEVICE_MODEL := EW-7886CAX + DEVICE_DTS := mt7986a-acelink-ew-7886cax DEVICE_DTS_DIR := ../dts + DEVICE_PACKAGES := kmod-mt7915e kmod-mt7986-firmware mt7986-wo-firmware UBINIZE_OPTS := -E 5 BLOCKSIZE := 128k PAGESIZE := 2048 + IMAGE_SIZE := 65536k KERNEL_IN_UBI := 1 - DEVICE_PACKAGES := kmod-mt7981-firmware mt7981-wo-firmware + IMAGES += factory.bin + IMAGE/factory.bin := append-ubi | check-size $$$$(IMAGE_SIZE) IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata endef -TARGET_DEVICES += abt_asr3000 +TARGET_DEVICES += acelink_ew-7886cax + +define Device/acer_predator-w6 + DEVICE_VENDOR := Acer + DEVICE_MODEL := Predator W6 + DEVICE_DTS := mt7986a-acer-predator-w6 + DEVICE_DTS_DIR := ../dts + DEVICE_DTS_LOADADDR := 0x47000000 + DEVICE_PACKAGES := kmod-usb3 kmod-mt7915e kmod-mt7916-firmware kmod-mt7986-firmware mt7986-wo-firmware e2fsprogs f2fsck mkf2fs + IMAGES := sysupgrade.bin + KERNEL := kernel-bin | lzma | fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb + KERNEL_INITRAMFS := kernel-bin | lzma | \ + fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb with-initrd | pad-to 64k + IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata +endef +TARGET_DEVICES += acer_predator-w6 + +define Device/adtran_smartrg + DEVICE_VENDOR := Adtran + DEVICE_DTS_DIR := ../dts + DEVICE_PACKAGES := e2fsprogs f2fsck mkf2fs kmod-hwmon-pwmfan + IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata +endef + +define Device/smartrg_sdg-8612 +$(call Device/adtran_smartrg) + DEVICE_MODEL := SDG-8612 + DEVICE_DTS := mt7986a-smartrg-SDG-8612 + DEVICE_PACKAGES += kmod-mt7915e kmod-mt7986-firmware mt7986-wo-firmware +endef +TARGET_DEVICES += smartrg_sdg-8612 + +define Device/smartrg_sdg-8614 +$(call Device/adtran_smartrg) + DEVICE_MODEL := SDG-8614 + DEVICE_DTS := mt7986a-smartrg-SDG-8614 + DEVICE_PACKAGES += kmod-mt7915e kmod-mt7986-firmware mt7986-wo-firmware +endef +TARGET_DEVICES += smartrg_sdg-8614 + +define Device/smartrg_sdg-8622 +$(call Device/adtran_smartrg) + DEVICE_MODEL := SDG-8622 + DEVICE_DTS := mt7986a-smartrg-SDG-8622 + DEVICE_PACKAGES += kmod-mt7915e kmod-mt7915-firmware kmod-mt7986-firmware mt7986-wo-firmware +endef +TARGET_DEVICES += smartrg_sdg-8622 + +define Device/smartrg_sdg-8632 +$(call Device/adtran_smartrg) + DEVICE_MODEL := SDG-8632 + DEVICE_DTS := mt7986a-smartrg-SDG-8632 + DEVICE_PACKAGES += kmod-mt7915e kmod-mt7915-firmware kmod-mt7986-firmware mt7986-wo-firmware +endef +TARGET_DEVICES += smartrg_sdg-8632 + +define Device/smartrg_sdg-8733 +$(call Device/adtran_smartrg) + DEVICE_MODEL := SDG-8733 + DEVICE_DTS := mt7988a-smartrg-SDG-8733 + DEVICE_PACKAGES += kmod-mt7996-firmware kmod-phy-aquantia kmod-usb3 +endef +TARGET_DEVICES += smartrg_sdg-8733 + +define Device/smartrg_sdg-8734 +$(call Device/adtran_smartrg) + DEVICE_MODEL := SDG-8734 + DEVICE_DTS := mt7988a-smartrg-SDG-8734 + DEVICE_PACKAGES += kmod-mt7996-firmware kmod-phy-aquantia kmod-sfp kmod-usb3 +endef +TARGET_DEVICES += smartrg_sdg-8734 + +define Device/asus_rt-ax59u + DEVICE_VENDOR := ASUS + DEVICE_MODEL := RT-AX59U + DEVICE_DTS := mt7986a-asus-rt-ax59u + DEVICE_DTS_DIR := ../dts + DEVICE_PACKAGES := kmod-usb3 kmod-mt7915e kmod-mt7986-firmware mt7986-wo-firmware + IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata +endef +TARGET_DEVICES += asus_rt-ax59u define Device/asus_tuf-ax4200 DEVICE_VENDOR := ASUS @@ -87,7 +208,7 @@ define Device/asus_tuf-ax4200 DEVICE_DTS := mt7986a-asus-tuf-ax4200 DEVICE_DTS_DIR := ../dts DEVICE_DTS_LOADADDR := 0x47000000 - DEVICE_PACKAGES := kmod-usb3 kmod-mt7986-firmware mt7986-wo-firmware + DEVICE_PACKAGES := kmod-usb3 kmod-mt7915e kmod-mt7986-firmware mt7986-wo-firmware IMAGES := sysupgrade.bin KERNEL := kernel-bin | lzma | \ fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb @@ -97,14 +218,34 @@ define Device/asus_tuf-ax4200 endef TARGET_DEVICES += asus_tuf-ax4200 +define Device/asus_tuf-ax6000 + DEVICE_VENDOR := ASUS + DEVICE_MODEL := TUF-AX6000 + DEVICE_DTS := mt7986a-asus-tuf-ax6000 + DEVICE_DTS_DIR := ../dts + DEVICE_DTS_LOADADDR := 0x47000000 + DEVICE_PACKAGES := kmod-usb3 kmod-mt7915e kmod-mt7986-firmware mt7986-wo-firmware + IMAGES := sysupgrade.bin + KERNEL := kernel-bin | lzma | \ + fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb + KERNEL_INITRAMFS := kernel-bin | lzma | \ + fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb with-initrd | pad-to 64k + IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata +endef +TARGET_DEVICES += asus_tuf-ax6000 + define Device/bananapi_bpi-r3 DEVICE_VENDOR := Bananapi DEVICE_MODEL := BPi-R3 DEVICE_DTS := mt7986a-bananapi-bpi-r3 DEVICE_DTS_CONFIG := config-mt7986a-bananapi-bpi-r3 - DEVICE_DTS_OVERLAY:= mt7986a-bananapi-bpi-r3-emmc mt7986a-bananapi-bpi-r3-nand mt7986a-bananapi-bpi-r3-nor mt7986a-bananapi-bpi-r3-sd + DEVICE_DTS_OVERLAY:= mt7986a-bananapi-bpi-r3-emmc mt7986a-bananapi-bpi-r3-nand \ + mt7986a-bananapi-bpi-r3-nor mt7986a-bananapi-bpi-r3-sd \ + mt7986a-bananapi-bpi-r3-respeaker-2mics DEVICE_DTS_DIR := $(DTS_DIR)/ - DEVICE_PACKAGES := kmod-hwmon-pwmfan kmod-i2c-gpio kmod-mt7986-firmware kmod-sfp kmod-usb3 e2fsprogs f2fsck mkf2fs mt7986-wo-firmware + DEVICE_DTS_LOADADDR := 0x43f00000 + DEVICE_PACKAGES := kmod-hwmon-pwmfan kmod-i2c-gpio kmod-mt7915e kmod-mt7986-firmware kmod-sfp kmod-usb3 \ + e2fsprogs f2fsck mkf2fs mt7986-wo-firmware IMAGES := sysupgrade.itb KERNEL_LOADADDR := 0x44000000 KERNEL_INITRAMFS_SUFFIX := -recovery.itb @@ -117,7 +258,7 @@ define Device/bananapi_bpi-r3 ARTIFACT/emmc-bl31-uboot.fip := mt7986-bl31-uboot bananapi_bpi-r3-emmc ARTIFACT/nor-preloader.bin := mt7986-bl2 nor-ddr4 ARTIFACT/nor-bl31-uboot.fip := mt7986-bl31-uboot bananapi_bpi-r3-nor - ARTIFACT/snand-preloader.bin := mt7986-bl2 spim-nand-ddr4 + ARTIFACT/snand-preloader.bin := mt7986-bl2 spim-nand-ubi-ddr4 ARTIFACT/snand-bl31-uboot.fip := mt7986-bl31-uboot bananapi_bpi-r3-snand ARTIFACT/sdcard.img.gz := mt798x-gpt sdmmc |\ pad-to 17k | mt7986-bl2 sdmmc-ddr4 |\ @@ -125,7 +266,7 @@ define Device/bananapi_bpi-r3 $(if $(CONFIG_TARGET_ROOTFS_INITRAMFS),\ pad-to 12M | append-image-stage initramfs-recovery.itb | check-size 44m |\ ) \ - pad-to 44M | mt7986-bl2 spim-nand-ddr4 |\ + pad-to 44M | mt7986-bl2 spim-nand-ubi-ddr4 |\ pad-to 45M | mt7986-bl31-uboot bananapi_bpi-r3-snand |\ pad-to 49M | mt7986-bl2 nor-ddr4 |\ pad-to 50M | mt7986-bl31-uboot bananapi_bpi-r3-nor |\ @@ -136,17 +277,64 @@ define Device/bananapi_bpi-r3 pad-to 64M | append-image squashfs-sysupgrade.itb | check-size |\ ) \ gzip +ifeq ($(DUMP),) IMAGE_SIZE := $$(shell expr 64 + $$(CONFIG_TARGET_ROOTFS_PARTSIZE))m +endif KERNEL := kernel-bin | gzip KERNEL_INITRAMFS := kernel-bin | lzma | \ fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb with-initrd | pad-to 64k IMAGE/sysupgrade.itb := append-kernel | fit gzip $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb external-static-with-rootfs | pad-rootfs | append-metadata DEVICE_DTC_FLAGS := --pad 4096 - DEVICE_COMPAT_VERSION := 1.1 - DEVICE_COMPAT_MESSAGE := Device tree overlay mechanism needs bootloader update + DEVICE_COMPAT_VERSION := 1.2 + DEVICE_COMPAT_MESSAGE := SPI-NAND flash layout changes require bootloader update endef TARGET_DEVICES += bananapi_bpi-r3 +define Device/bananapi_bpi-r3-mini + DEVICE_VENDOR := Bananapi + DEVICE_MODEL := BPi-R3 Mini + DEVICE_DTS := mt7986a-bananapi-bpi-r3-mini + DEVICE_DTS_CONFIG := config-mt7986a-bananapi-bpi-r3-mini + DEVICE_DTS_DIR := ../dts + DEVICE_DTS_LOADADDR := 0x43f00000 + DEVICE_PACKAGES := kmod-hwmon-pwmfan kmod-mt7915e kmod-mt7986-firmware kmod-phy-airoha-en8811h \ + kmod-usb3 e2fsprogs f2fsck mkf2fs mt7986-wo-firmware + KERNEL_LOADADDR := 0x44000000 + KERNEL := kernel-bin | gzip + KERNEL_INITRAMFS := kernel-bin | lzma | \ + fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb with-initrd | pad-to 64k + KERNEL_INITRAMFS_SUFFIX := -recovery.itb + BLOCKSIZE := 128k + PAGESIZE := 2048 + KERNEL_IN_UBI := 1 + UBOOTENV_IN_UBI := 1 + IMAGES := snand-factory.bin sysupgrade.itb +ifeq ($(DUMP),) + IMAGE_SIZE := $$(shell expr 64 + $$(CONFIG_TARGET_ROOTFS_PARTSIZE))m +endif + IMAGE/sysupgrade.itb := append-kernel | \ + fit gzip $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb external-static-with-rootfs | \ + pad-rootfs | append-metadata + ARTIFACTS := \ + emmc-gpt.bin emmc-preloader.bin emmc-bl31-uboot.fip \ + snand-factory.bin snand-preloader.bin snand-bl31-uboot.fip + ARTIFACT/emmc-gpt.bin := mt798x-gpt emmc + ARTIFACT/emmc-preloader.bin := mt7986-bl2 emmc-ddr4 + ARTIFACT/emmc-bl31-uboot.fip := mt7986-bl31-uboot bananapi_bpi-r3-mini-emmc + ARTIFACT/snand-factory.bin := mt7986-bl2 spim-nand-ubi-ddr4 | pad-to 256k | \ + mt7986-bl2 spim-nand-ubi-ddr4 | pad-to 512k | \ + mt7986-bl2 spim-nand-ubi-ddr4 | pad-to 768k | \ + mt7986-bl2 spim-nand-ubi-ddr4 | pad-to 2048k | \ + ubinize-image fit squashfs-sysupgrade.itb + ARTIFACT/snand-preloader.bin := mt7986-bl2 spim-nand-ubi-ddr4 + ARTIFACT/snand-bl31-uboot.fip := mt7986-bl31-uboot bananapi_bpi-r3-mini-snand + UBINIZE_PARTS := fip=:$(STAGING_DIR_IMAGE)/mt7986_bananapi_bpi-r3-mini-snand-u-boot.fip +ifneq ($(CONFIG_PACKAGE_airoha-en8811h-firmware),) + UBINIZE_PARTS += en8811h-fw=:$(STAGING_DIR_IMAGE)/EthMD32.bin +endif +endef +TARGET_DEVICES += bananapi_bpi-r3-mini + define Device/bananapi_bpi-r4-common DEVICE_VENDOR := Bananapi DEVICE_DTS_DIR := $(DTS_DIR)/ @@ -196,13 +384,22 @@ define Device/bananapi_bpi-r4 endef TARGET_DEVICES += bananapi_bpi-r4 +define Device/bananapi_bpi-r4-poe + DEVICE_MODEL := BPi-R4 2.5GE + DEVICE_DTS := mt7988a-bananapi-bpi-r4-poe + DEVICE_DTS_CONFIG := config-mt7988a-bananapi-bpi-r4-poe + $(call Device/bananapi_bpi-r4-common) + DEVICE_PACKAGES += mt7988-2p5g-phy-firmware +endef +TARGET_DEVICES += bananapi_bpi-r4-poe + define Device/cetron_ct3003 DEVICE_VENDOR := Cetron DEVICE_MODEL := CT3003 DEVICE_DTS := mt7981b-cetron-ct3003 DEVICE_DTS_DIR := ../dts SUPPORTED_DEVICES += mediatek,mt7981-spim-snand-rfb - DEVICE_PACKAGES := kmod-mt7981-firmware mt7981-wo-firmware + DEVICE_PACKAGES := kmod-mt7915e kmod-mt7981-firmware mt7981-wo-firmware UBINIZE_OPTS := -E 5 BLOCKSIZE := 128k PAGESIZE := 2048 @@ -213,78 +410,199 @@ define Device/cetron_ct3003 endef TARGET_DEVICES += cetron_ct3003 -define Device/cetron_ct3003-mod - DEVICE_VENDOR := Cetron - DEVICE_MODEL := CT3003 (U-Boot mod) - DEVICE_DTS := mt7981b-cetron-ct3003-mod - DEVICE_DTS_DIR := ../dts - DEVICE_PACKAGES := kmod-mt7981-firmware mt7981-wo-firmware - UBINIZE_OPTS := -E 5 - BLOCKSIZE := 128k - PAGESIZE := 2048 - KERNEL_IN_UBI := 1 - IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata -endef -TARGET_DEVICES += cetron_ct3003-mod - -define Device/cmcc_rax3000m-emmc +define Device/cmcc_rax3000m DEVICE_VENDOR := CMCC - DEVICE_MODEL := RAX3000M (eMMC version) - DEVICE_DTS := mt7981b-cmcc-rax3000m-emmc + DEVICE_MODEL := RAX3000M + DEVICE_DTS := mt7981b-cmcc-rax3000m + DEVICE_DTS_OVERLAY := mt7981b-cmcc-rax3000m-emmc mt7981b-cmcc-rax3000m-nand DEVICE_DTS_DIR := ../dts - DEVICE_PACKAGES := kmod-mt7981-firmware mt7981-wo-firmware kmod-usb3 \ - automount f2fsck mkf2fs - KERNEL := kernel-bin | lzma | fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb + DEVICE_DTC_FLAGS := --pad 4096 + DEVICE_DTS_LOADADDR := 0x43f00000 + DEVICE_PACKAGES := kmod-mt7915e kmod-mt7981-firmware mt7981-wo-firmware kmod-usb3 \ + e2fsprogs f2fsck mkf2fs + KERNEL_LOADADDR := 0x44000000 + KERNEL := kernel-bin | gzip KERNEL_INITRAMFS := kernel-bin | lzma | \ fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb with-initrd | pad-to 64k - IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata + KERNEL_INITRAMFS_SUFFIX := -recovery.itb + KERNEL_IN_UBI := 1 + UBOOTENV_IN_UBI := 1 + IMAGES := sysupgrade.itb + IMAGE_SIZE := $$(shell expr 64 + $$(CONFIG_TARGET_ROOTFS_PARTSIZE))m + IMAGE/sysupgrade.itb := append-kernel | \ + fit gzip $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb external-static-with-rootfs | \ + pad-rootfs | append-metadata + ARTIFACTS := \ + emmc-gpt.bin emmc-preloader.bin emmc-bl31-uboot.fip \ + nand-preloader.bin nand-bl31-uboot.fip + ARTIFACT/emmc-gpt.bin := mt798x-gpt emmc + ARTIFACT/emmc-preloader.bin := mt7981-bl2 emmc-ddr4 + ARTIFACT/emmc-bl31-uboot.fip := mt7981-bl31-uboot cmcc_rax3000m-emmc + ARTIFACT/nand-preloader.bin := mt7981-bl2 spim-nand-ddr4 + ARTIFACT/nand-bl31-uboot.fip := mt7981-bl31-uboot cmcc_rax3000m-nand endef -TARGET_DEVICES += cmcc_rax3000m-emmc +TARGET_DEVICES += cmcc_rax3000m -define Device/cmcc_rax3000m-nand - DEVICE_VENDOR := CMCC - DEVICE_MODEL := RAX3000M (NAND version) - DEVICE_DTS := mt7981b-cmcc-rax3000m-nand +define Device/comfast_cf-e393ax + DEVICE_VENDOR := Comfast + DEVICE_MODEL := CF-E393AX + DEVICE_DTS := mt7981a-comfast-cf-e393ax DEVICE_DTS_DIR := ../dts - DEVICE_PACKAGES := kmod-mt7981-firmware mt7981-wo-firmware kmod-usb3 automount + DEVICE_DTC_FLAGS := --pad 4096 + DEVICE_DTS_LOADADDR := 0x43f00000 + DEVICE_PACKAGES := kmod-mt7915e kmod-mt7981-firmware mt7981-wo-firmware + KERNEL_LOADADDR := 0x44000000 + KERNEL = kernel-bin | lzma | \ + fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb + KERNEL_INITRAMFS = kernel-bin | lzma | \ + fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb with-initrd UBINIZE_OPTS := -E 5 BLOCKSIZE := 128k PAGESIZE := 2048 - IMAGE_SIZE := 116736k + IMAGE_SIZE := 65536k KERNEL_IN_UBI := 1 - IMAGES += factory.bin + IMAGES := sysupgrade.bin factory.bin IMAGE/factory.bin := append-ubi | check-size $$$$(IMAGE_SIZE) IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata - KERNEL = kernel-bin | lzma | \ - fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb - KERNEL_INITRAMFS = kernel-bin | lzma | \ - fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb with-initrd endef -TARGET_DEVICES += cmcc_rax3000m-nand +TARGET_DEVICES += comfast_cf-e393ax -define Device/fzs_5gcpe-p3 - DEVICE_VENDOR := FZS - DEVICE_MODEL := 5GCPE P3 - DEVICE_DTS := mt7981b-fzs-5gcpe-p3 +define Device/confiabits_mt7981 + DEVICE_VENDOR := Confiabits + DEVICE_MODEL := MT7981 + DEVICE_DTS := mt7981b-confiabits-mt7981 DEVICE_DTS_DIR := ../dts + SUPPORTED_DEVICES += mediatek,mt7981-spim-snand-2500wan-gmac2-rfb UBINIZE_OPTS := -E 5 BLOCKSIZE := 128k PAGESIZE := 2048 + IMAGE_SIZE := 65536k KERNEL_IN_UBI := 1 - DEVICE_PACKAGES := kmod-mt7981-firmware mt7981-wo-firmware kmod-usb3 IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata + DEVICE_PACKAGES := kmod-usb3 kmod-mt7915e kmod-mt7981-firmware mt7981-wo-firmware endef -TARGET_DEVICES += fzs_5gcpe-p3 +TARGET_DEVICES += confiabits_mt7981 + +define Device/cudy_m3000-v1 + DEVICE_VENDOR := Cudy + DEVICE_MODEL := M3000 + DEVICE_VARIANT := v1 + DEVICE_DTS := mt7981b-cudy-m3000-v1 + DEVICE_DTS_DIR := ../dts + SUPPORTED_DEVICES += R37 + DEVICE_DTS_LOADADDR := 0x44000000 + BLOCKSIZE := 128k + PAGESIZE := 2048 + IMAGE_SIZE := 65536k + KERNEL_IN_UBI := 1 + KERNEL := kernel-bin | lzma | \ + fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb + KERNEL_INITRAMFS := kernel-bin | lzma | \ + fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb with-initrd | pad-to 64k + IMAGES := sysupgrade.bin + IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata + DEVICE_PACKAGES := kmod-mt7915e kmod-mt7981-firmware mt7981-wo-firmware +endef +TARGET_DEVICES += cudy_m3000-v1 + +define Device/cudy_re3000-v1 + DEVICE_VENDOR := Cudy + DEVICE_MODEL := RE3000 + DEVICE_VARIANT := v1 + DEVICE_DTS := mt7981b-cudy-re3000-v1 + DEVICE_DTS_DIR := ../dts + DEVICE_DTS_LOADADDR := 0x47000000 + IMAGES := sysupgrade.bin + IMAGE_SIZE := 15424k + SUPPORTED_DEVICES += R36 + KERNEL := kernel-bin | lzma | \ + fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb + KERNEL_INITRAMFS := kernel-bin | lzma | \ + fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb with-initrd | pad-to 64k + IMAGE/sysupgrade.bin := append-kernel | pad-to 128k | append-rootfs | pad-rootfs | check-size | append-metadata + DEVICE_PACKAGES := kmod-mt7915e kmod-mt7981-firmware mt7981-wo-firmware +endef +TARGET_DEVICES += cudy_re3000-v1 + +define Device/cudy_tr3000-v1 + DEVICE_VENDOR := Cudy + DEVICE_MODEL := TR3000 + DEVICE_VARIANT := v1 + DEVICE_DTS := mt7981b-cudy-tr3000-v1 + DEVICE_DTS_DIR := ../dts + SUPPORTED_DEVICES += R47 + UBINIZE_OPTS := -E 5 + BLOCKSIZE := 128k + PAGESIZE := 2048 + IMAGE_SIZE := 65536k + KERNEL_IN_UBI := 1 + IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata + DEVICE_PACKAGES := kmod-usb3 kmod-mt7915e kmod-mt7981-firmware mt7981-wo-firmware +endef +TARGET_DEVICES += cudy_tr3000-v1 + +define Device/cudy_wr3000-v1 + DEVICE_VENDOR := Cudy + DEVICE_MODEL := WR3000 + DEVICE_VARIANT := v1 + DEVICE_DTS := mt7981b-cudy-wr3000-v1 + DEVICE_DTS_DIR := ../dts + DEVICE_DTS_LOADADDR := 0x47000000 + IMAGES := sysupgrade.bin + IMAGE_SIZE := 15424k + SUPPORTED_DEVICES += R31 + KERNEL := kernel-bin | lzma | \ + fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb + KERNEL_INITRAMFS := kernel-bin | lzma | \ + fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb with-initrd | pad-to 64k + IMAGE/sysupgrade.bin := append-kernel | pad-to 128k | append-rootfs | pad-rootfs | check-size | append-metadata + DEVICE_PACKAGES := kmod-mt7915e kmod-mt7981-firmware mt7981-wo-firmware +endef +TARGET_DEVICES += cudy_wr3000-v1 + +define Device/dlink_aquila-pro-ai-m30-a1 + DEVICE_VENDOR := D-Link + DEVICE_MODEL := AQUILA PRO AI M30 + DEVICE_VARIANT := A1 + DEVICE_DTS := mt7981b-dlink-aquila-pro-ai-m30-a1 + DEVICE_DTS_DIR := ../dts + DEVICE_PACKAGES := kmod-leds-gca230718 kmod-mt7915e kmod-mt7981-firmware mt7981-wo-firmware + KERNEL_IN_UBI := 1 + IMAGES += recovery.bin + IMAGE_SIZE := 51200k + IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata + IMAGE/recovery.bin := sysupgrade-tar | pad-to $$(IMAGE_SIZE) | dlink-ai-recovery-header DLK6E6110001 \x6A\x28\xEE\x0B \x00\x00\x2C\x00 \x00\x00\x20\x03 \x61\x6E +endef +TARGET_DEVICES += dlink_aquila-pro-ai-m30-a1 + +define Device/edgecore_eap111 + DEVICE_VENDOR := Edgecore + DEVICE_MODEL := EAP111 + DEVICE_DTS := mt7981a-edgecore-eap111 + DEVICE_DTS_DIR := ../dts + DEVICE_DTS_LOADADDR := 0x47000000 + BLOCKSIZE := 128k + PAGESIZE := 2048 + UBINIZE_OPTS := -E 5 + KERNEL_IN_UBI := 1 + IMAGE_SIZE := 65536k + IMAGES := sysupgrade.bin factory.bin + IMAGE/factory.bin := append-ubi | check-size $$$$(IMAGE_SIZE) + IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata + DEVICE_PACKAGES := kmod-mt7915e kmod-mt7981-firmware mt7981-wo-firmware +endef +TARGET_DEVICES += edgecore_eap111 define Device/glinet_gl-mt2500 DEVICE_VENDOR := GL.iNet DEVICE_MODEL := GL-MT2500 DEVICE_DTS := mt7981b-glinet-gl-mt2500 DEVICE_DTS_DIR := ../dts - DEVICE_PACKAGES := e2fsprogs f2fsck mkf2fs kmod-usb3 + DEVICE_DTS_LOADADDR := 0x47000000 + DEVICE_PACKAGES := -wpad-basic-mbedtls e2fsprogs f2fsck mkf2fs kmod-usb3 SUPPORTED_DEVICES += glinet,mt2500-emmc IMAGES := sysupgrade.bin - IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata + IMAGE/sysupgrade.bin := sysupgrade-tar | append-gl-metadata endef TARGET_DEVICES += glinet_gl-mt2500 @@ -293,12 +611,14 @@ define Device/glinet_gl-mt3000 DEVICE_MODEL := GL-MT3000 DEVICE_DTS := mt7981b-glinet-gl-mt3000 DEVICE_DTS_DIR := ../dts - DEVICE_PACKAGES := kmod-mt7981-firmware mt7981-wo-firmware kmod-hwmon-pwmfan kmod-usb3 + SUPPORTED_DEVICES += glinet,mt3000-snand + DEVICE_PACKAGES := kmod-mt7915e kmod-mt7981-firmware mt7981-wo-firmware kmod-hwmon-pwmfan kmod-usb3 UBINIZE_OPTS := -E 5 BLOCKSIZE := 128k PAGESIZE := 2048 + IMAGE_SIZE := 246272k KERNEL_IN_UBI := 1 - IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata + IMAGE/sysupgrade.bin := sysupgrade-tar | append-gl-metadata endef TARGET_DEVICES += glinet_gl-mt3000 @@ -307,15 +627,41 @@ define Device/glinet_gl-mt6000 DEVICE_MODEL := GL-MT6000 DEVICE_DTS := mt7986a-glinet-gl-mt6000 DEVICE_DTS_DIR := ../dts - DEVICE_PACKAGES := e2fsprogs f2fsck mkf2fs kmod-usb3 kmod-mt7986-firmware mt7986-wo-firmware - UBINIZE_OPTS := -E 5 - BLOCKSIZE := 128k - PAGESIZE := 2048 - IMAGES := sysupgrade.bin - IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata + DEVICE_PACKAGES := e2fsprogs f2fsck mkf2fs kmod-usb3 kmod-mt7915e kmod-mt7986-firmware mt7986-wo-firmware + IMAGES += factory.bin + IMAGE/factory.bin := append-kernel | pad-to 32M | append-rootfs + IMAGE/sysupgrade.bin := sysupgrade-tar | append-gl-metadata + ARTIFACTS := preloader.bin bl31-uboot.fip + ARTIFACT/preloader.bin := mt7986-bl2 emmc-ddr4 + ARTIFACT/bl31-uboot.fip := mt7986-bl31-uboot glinet_gl-mt6000 endef TARGET_DEVICES += glinet_gl-mt6000 +define Device/glinet_gl-x3000-xe3000-common + DEVICE_VENDOR := GL.iNet + DEVICE_DTS_DIR := ../dts + DEVICE_PACKAGES := kmod-mt7915e kmod-mt7981-firmware mt7981-wo-firmware mkf2fs \ + kmod-fs-f2fs kmod-hwmon-pwmfan kmod-usb3 kmod-usb-serial-option \ + kmod-usb-storage kmod-usb-net-qmi-wwan uqmi + IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata +endef + +define Device/glinet_gl-x3000 + DEVICE_MODEL := GL-X3000 + DEVICE_DTS := mt7981a-glinet-gl-x3000 + SUPPORTED_DEVICES := glinet,gl-x3000 + $(call Device/glinet_gl-x3000-xe3000-common) +endef +TARGET_DEVICES += glinet_gl-x3000 + +define Device/glinet_gl-xe3000 + DEVICE_MODEL := GL-XE3000 + DEVICE_DTS := mt7981a-glinet-gl-xe3000 + SUPPORTED_DEVICES := glinet,gl-xe3000 + $(call Device/glinet_gl-x3000-xe3000-common) +endef +TARGET_DEVICES += glinet_gl-xe3000 + define Device/h3c_magic-nx30-pro DEVICE_VENDOR := H3C DEVICE_MODEL := Magic NX30 Pro @@ -325,26 +671,22 @@ define Device/h3c_magic-nx30-pro BLOCKSIZE := 128k PAGESIZE := 2048 KERNEL_IN_UBI := 1 + UBOOTENV_IN_UBI := 1 IMAGE_SIZE := 65536k - IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata - DEVICE_PACKAGES := kmod-mt7981-firmware mt7981-wo-firmware + IMAGES := sysupgrade.itb + KERNEL_INITRAMFS_SUFFIX := -recovery.itb + KERNEL := kernel-bin | gzip + KERNEL_INITRAMFS := kernel-bin | lzma | \ + fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb with-initrd | pad-to 64k + IMAGE/sysupgrade.itb := append-kernel | \ + fit gzip $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb external-static-with-rootfs | append-metadata + DEVICE_PACKAGES := kmod-mt7915e kmod-mt7981-firmware mt7981-wo-firmware + ARTIFACTS := preloader.bin bl31-uboot.fip + ARTIFACT/preloader.bin := mt7981-bl2 spim-nand-ddr3 + ARTIFACT/bl31-uboot.fip := mt7981-bl31-uboot h3c_magic-nx30-pro endef TARGET_DEVICES += h3c_magic-nx30-pro -define Device/imou_lc-hx3001 - DEVICE_VENDOR := IMOU - DEVICE_MODEL := LC-HX3001 - DEVICE_DTS := mt7981b-imou-lc-hx3001 - DEVICE_DTS_DIR := ../dts - UBINIZE_OPTS := -E 5 - BLOCKSIZE := 128k - PAGESIZE := 2048 - KERNEL_IN_UBI := 1 - DEVICE_PACKAGES := kmod-mt7981-firmware mt7981-wo-firmware - IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata -endef -TARGET_DEVICES += imou_lc-hx3001 - define Device/jcg_q30-pro DEVICE_VENDOR := JCG DEVICE_MODEL := Q30 PRO @@ -354,27 +696,109 @@ define Device/jcg_q30-pro BLOCKSIZE := 128k PAGESIZE := 2048 KERNEL_IN_UBI := 1 - DEVICE_PACKAGES := kmod-mt7981-firmware mt7981-wo-firmware - IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata + UBOOTENV_IN_UBI := 1 + IMAGES := sysupgrade.itb + KERNEL_INITRAMFS_SUFFIX := -recovery.itb + KERNEL := kernel-bin | gzip + KERNEL_INITRAMFS := kernel-bin | lzma | \ + fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb with-initrd | pad-to 64k + IMAGE/sysupgrade.itb := append-kernel | \ + fit gzip $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb external-static-with-rootfs | append-metadata + DEVICE_PACKAGES := kmod-mt7915e kmod-mt7981-firmware mt7981-wo-firmware + ARTIFACTS := preloader.bin bl31-uboot.fip + ARTIFACT/preloader.bin := mt7981-bl2 spim-nand-ddr3 + ARTIFACT/bl31-uboot.fip := mt7981-bl31-uboot jcg_q30-pro endef TARGET_DEVICES += jcg_q30-pro -define Device/jdcloud_re-cs-05 +define Device/jdcloud_re-cp-03 DEVICE_VENDOR := JDCloud - DEVICE_MODEL := AX6000 - DEVICE_DTS := mt7986a-jdcloud-re-cs-05 + DEVICE_MODEL := RE-CP-03 + DEVICE_DTS := mt7986a-jdcloud-re-cp-03 DEVICE_DTS_DIR := ../dts - DEVICE_PACKAGES := e2fsprogs f2fsck mkf2fs kmod-mt7986-firmware mt7986-wo-firmware - IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata + DEVICE_DTC_FLAGS := --pad 4096 + DEVICE_DTS_LOADADDR := 0x43f00000 + DEVICE_PACKAGES := kmod-mt7915e kmod-mt7986-firmware mt7986-wo-firmware \ + e2fsprogs f2fsck mkf2fs + KERNEL_LOADADDR := 0x44000000 + KERNEL := kernel-bin | gzip + KERNEL_INITRAMFS := kernel-bin | lzma | \ + fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb with-initrd | pad-to 64k + KERNEL_INITRAMFS_SUFFIX := -recovery.itb + IMAGES := sysupgrade.itb + IMAGE_SIZE := $$(shell expr 64 + $$(CONFIG_TARGET_ROOTFS_PARTSIZE))m + IMAGE/sysupgrade.itb := append-kernel | \ + fit gzip $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb external-static-with-rootfs | \ + pad-rootfs | append-metadata + ARTIFACTS :=gpt.bin preloader.bin bl31-uboot.fip + ARTIFACT/gpt.bin := mt798x-gpt emmc + ARTIFACT/preloader.bin := mt7986-bl2 emmc-ddr4 + ARTIFACT/bl31-uboot.fip := mt7986-bl31-uboot jdcloud_re-cp-03 endef -TARGET_DEVICES += jdcloud_re-cs-05 +TARGET_DEVICES += jdcloud_re-cp-03 -define Device/mediatek_mt7986a-rfb +define Device/mediatek_mt7981-rfb DEVICE_VENDOR := MediaTek - DEVICE_MODEL := MTK7986 rfba AP + DEVICE_MODEL := MT7981 rfb + DEVICE_DTS := mt7981-rfb + DEVICE_DTS_OVERLAY:= \ + mt7981-rfb-spim-nand \ + mt7981-rfb-mxl-2p5g-phy-eth1 \ + mt7981-rfb-mxl-2p5g-phy-swp5 + DEVICE_DTS_DIR := $(DTS_DIR)/ + DEVICE_DTC_FLAGS := --pad 4096 + DEVICE_DTS_LOADADDR := 0x43f00000 + DEVICE_PACKAGES := kmod-mt7915e kmod-mt7981-firmware kmod-usb3 e2fsprogs f2fsck mkf2fs mt7981-wo-firmware + KERNEL_LOADADDR := 0x44000000 + KERNEL := kernel-bin | gzip + KERNEL_INITRAMFS := kernel-bin | lzma | \ + fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb with-initrd | pad-to 64k + KERNEL_INITRAMFS_SUFFIX := .itb + KERNEL_IN_UBI := 1 + UBOOTENV_IN_UBI := 1 + IMAGES := sysupgrade.itb + IMAGE_SIZE := $$(shell expr 64 + $$(CONFIG_TARGET_ROOTFS_PARTSIZE))m + IMAGE/sysupgrade.itb := append-kernel | fit gzip $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb external-with-rootfs | pad-rootfs | append-metadata + ARTIFACTS := \ + emmc-preloader.bin emmc-bl31-uboot.fip \ + nor-preloader.bin nor-bl31-uboot.fip \ + sdcard.img.gz \ + snfi-nand-preloader.bin snfi-nand-bl31-uboot.fip \ + spim-nand-preloader.bin spim-nand-bl31-uboot.fip + ARTIFACT/emmc-preloader.bin := mt7981-bl2 emmc-ddr3 + ARTIFACT/emmc-bl31-uboot.fip := mt7981-bl31-uboot rfb-emmc + ARTIFACT/nor-preloader.bin := mt7981-bl2 nor-ddr3 + ARTIFACT/nor-bl31-uboot.fip := mt7981-bl31-uboot rfb-emmc + ARTIFACT/snfi-nand-preloader.bin := mt7981-bl2 snand-ddr3 + ARTIFACT/snfi-nand-bl31-uboot.fip := mt7981-bl31-uboot rfb-snfi + ARTIFACT/spim-nand-preloader.bin := mt7981-bl2 spim-nand-ddr3 + ARTIFACT/spim-nand-bl31-uboot.fip := mt7981-bl31-uboot rfb-spim-nand + ARTIFACT/sdcard.img.gz := mt798x-gpt sdmmc |\ + pad-to 17k | mt7981-bl2 sdmmc-ddr3 |\ + pad-to 6656k | mt7981-bl31-uboot rfb-sd |\ + $(if $(CONFIG_TARGET_ROOTFS_INITRAMFS),\ + pad-to 12M | append-image-stage initramfs.itb | check-size 44m |\ + ) \ + pad-to 44M | mt7981-bl2 spim-nand-ddr3 |\ + pad-to 45M | mt7981-bl31-uboot rfb-spim-nand |\ + pad-to 49M | mt7981-bl2 nor-ddr3 |\ + pad-to 50M | mt7981-bl31-uboot rfb-nor |\ + pad-to 51M | mt7981-bl2 snand-ddr3 |\ + pad-to 53M | mt7981-bl31-uboot rfb-snfi |\ + $(if $(CONFIG_TARGET_ROOTFS_SQUASHFS),\ + pad-to 64M | append-image squashfs-sysupgrade.itb | check-size |\ + ) \ + gzip +endef +TARGET_DEVICES += mediatek_mt7981-rfb + +define Device/mediatek_mt7986a-rfb-nand + DEVICE_VENDOR := MediaTek + DEVICE_MODEL := MT7986 rfba AP (NAND) DEVICE_DTS := mt7986a-rfb-spim-nand DEVICE_DTS_DIR := $(DTS_DIR)/ - SUPPORTED_DEVICES := mediatek,mt7986a-rfb + DEVICE_PACKAGES := kmod-mt7915e kmod-mt7986-firmware mt7986-wo-firmware + SUPPORTED_DEVICES := mediatek,mt7986a-rfb-snand UBINIZE_OPTS := -E 5 BLOCKSIZE := 128k PAGESIZE := 2048 @@ -388,14 +812,14 @@ define Device/mediatek_mt7986a-rfb KERNEL_INITRAMFS = kernel-bin | lzma | \ fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb with-initrd endef -TARGET_DEVICES += mediatek_mt7986a-rfb +TARGET_DEVICES += mediatek_mt7986a-rfb-nand define Device/mediatek_mt7986b-rfb DEVICE_VENDOR := MediaTek DEVICE_MODEL := MTK7986 rfbb AP DEVICE_DTS := mt7986b-rfb DEVICE_DTS_DIR := $(DTS_DIR)/ - DEVICE_PACKAGES := kmod-mt7986-firmware mt7986-wo-firmware + DEVICE_PACKAGES := kmod-mt7915e kmod-mt7986-firmware mt7986-wo-firmware SUPPORTED_DEVICES := mediatek,mt7986b-rfb UBINIZE_OPTS := -E 5 BLOCKSIZE := 128k @@ -417,6 +841,7 @@ define Device/mediatek_mt7988a-rfb mt7988a-rfb-sd \ mt7988a-rfb-snfi-nand \ mt7988a-rfb-spim-nand \ + mt7988a-rfb-spim-nand-factory \ mt7988a-rfb-spim-nor \ mt7988a-rfb-eth1-aqr \ mt7988a-rfb-eth1-i2p5g-phy \ @@ -428,7 +853,7 @@ define Device/mediatek_mt7988a-rfb DEVICE_DTS_DIR := $(DTS_DIR)/ DEVICE_DTC_FLAGS := --pad 4096 DEVICE_DTS_LOADADDR := 0x45f00000 - DEVICE_PACKAGES := kmod-sfp + DEVICE_PACKAGES := mt7988-2p5g-phy-firmware kmod-sfp KERNEL_LOADADDR := 0x46000000 KERNEL := kernel-bin | gzip KERNEL_INITRAMFS := kernel-bin | lzma | \ @@ -448,7 +873,7 @@ define Device/mediatek_mt7988a-rfb ARTIFACT/emmc-bl31-uboot.fip := mt7988-bl31-uboot rfb-emmc ARTIFACT/nor-preloader.bin := mt7988-bl2 nor-comb ARTIFACT/nor-bl31-uboot.fip := mt7988-bl31-uboot rfb-nor - ARTIFACT/snand-preloader.bin := mt7988-bl2 spim-nand-comb + ARTIFACT/snand-preloader.bin := mt7988-bl2 spim-nand-ubi-comb ARTIFACT/snand-bl31-uboot.fip := mt7988-bl31-uboot rfb-snand ARTIFACT/sdcard.img.gz := mt798x-gpt sdmmc |\ pad-to 17k | mt7988-bl2 sdmmc-comb |\ @@ -470,21 +895,19 @@ define Device/mediatek_mt7988a-rfb endef TARGET_DEVICES += mediatek_mt7988a-rfb -define Device/hf_m7986r1-nand - DEVICE_VENDOR := HF - DEVICE_MODEL := M7986R1 - DEVICE_DTS := mt7986a-hf-m7986r1-nand +define Device/mercusys_mr90x-v1 + DEVICE_VENDOR := MERCUSYS + DEVICE_MODEL := MR90X v1 + DEVICE_DTS := mt7986b-mercusys-mr90x-v1 DEVICE_DTS_DIR := ../dts + DEVICE_PACKAGES := kmod-mt7915e kmod-mt7986-firmware mt7986-wo-firmware UBINIZE_OPTS := -E 5 BLOCKSIZE := 128k PAGESIZE := 2048 - IMAGE_SIZE := 116736k - KERNEL_IN_UBI := 1 - DEVICE_PACKAGES := kmod-usb3 kmod-mt7921e kmod-usb-serial-option kmod-usb-net-rndis - SUPPORTED_DEVICES += HF-M7986R1 + IMAGE_SIZE := 51200k IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata endef -TARGET_DEVICES +=hf_m7986r1-nand +TARGET_DEVICES += mercusys_mr90x-v1 define Device/netcore_n60 DEVICE_VENDOR := Netcore @@ -495,25 +918,128 @@ define Device/netcore_n60 BLOCKSIZE := 128k PAGESIZE := 2048 KERNEL_IN_UBI := 1 - DEVICE_PACKAGES := kmod-mt7986-firmware mt7986-wo-firmware - IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata + UBOOTENV_IN_UBI := 1 + IMAGES := sysupgrade.itb + KERNEL_INITRAMFS_SUFFIX := -recovery.itb + KERNEL := kernel-bin | gzip + KERNEL_INITRAMFS := kernel-bin | lzma | \ + fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb with-initrd | pad-to 64k + IMAGE/sysupgrade.itb := append-kernel | \ + fit gzip $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb external-static-with-rootfs | append-metadata + DEVICE_PACKAGES := kmod-mt7915e kmod-mt7986-firmware mt7986-wo-firmware + ARTIFACTS := preloader.bin bl31-uboot.fip + ARTIFACT/preloader.bin := mt7986-bl2 spim-nand-ddr3 + ARTIFACT/bl31-uboot.fip := mt7986-bl31-uboot netcore_n60 endef TARGET_DEVICES += netcore_n60 +define Device/netgear_wax220 + DEVICE_VENDOR := NETGEAR + DEVICE_MODEL := WAX220 + DEVICE_DTS := mt7986b-netgear-wax220 + DEVICE_DTS_DIR := ../dts + NETGEAR_ENC_MODEL := WAX220 + NETGEAR_ENC_REGION := US + DEVICE_PACKAGES := kmod-mt7915e kmod-mt7986-firmware mt7986-wo-firmware + KERNEL_INITRAMFS_SUFFIX := -recovery.itb + IMAGE_SIZE := 32768k + IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata + IMAGES += factory.img + # Padding to 10M seems to be required by OEM web interface + IMAGE/factory.img := sysupgrade-tar | \ + pad-to 10M | check-size | netgear-encrypted-factory +endef +TARGET_DEVICES += netgear_wax220 + define Device/nokia_ea0326gmp DEVICE_VENDOR := Nokia DEVICE_MODEL := EA0326GMP DEVICE_DTS := mt7981b-nokia-ea0326gmp DEVICE_DTS_DIR := ../dts + DEVICE_PACKAGES := kmod-mt7915e kmod-mt7981-firmware mt7981-wo-firmware UBINIZE_OPTS := -E 5 BLOCKSIZE := 128k PAGESIZE := 2048 KERNEL_IN_UBI := 1 - DEVICE_PACKAGES := kmod-mt7981-firmware mt7981-wo-firmware - IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata + UBOOTENV_IN_UBI := 1 + IMAGES := sysupgrade.itb + KERNEL_INITRAMFS_SUFFIX := -recovery.itb + KERNEL := kernel-bin | gzip + KERNEL_INITRAMFS := kernel-bin | lzma | \ + fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb with-initrd | pad-to 64k + IMAGE/sysupgrade.itb := append-kernel | \ + fit gzip $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb external-static-with-rootfs | append-metadata + ARTIFACTS := preloader.bin bl31-uboot.fip + ARTIFACT/preloader.bin := mt7981-bl2 spim-nand-ddr3 + ARTIFACT/bl31-uboot.fip := mt7981-bl31-uboot nokia_ea0326gmp endef TARGET_DEVICES += nokia_ea0326gmp +define Device/openembed_som7981 + DEVICE_VENDOR := OpenEmbed + DEVICE_MODEL := SOM7981 + DEVICE_DTS := mt7981b-openembed-som7981 + DEVICE_DTS_DIR := ../dts + DEVICE_PACKAGES := kmod-mt7915e kmod-mt7981-firmware mt7981-wo-firmware kmod-usb3 + UBINIZE_OPTS := -E 5 + BLOCKSIZE := 128k + PAGESIZE := 2048 + IMAGE_SIZE := 244224k + KERNEL_IN_UBI := 1 + IMAGES += factory.bin + IMAGE/factory.bin := append-ubi | check-size $$$$(IMAGE_SIZE) + IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata +endef +TARGET_DEVICES += openembed_som7981 + +define Build/append-openwrt-one-eeprom + dd if=$(STAGING_DIR_IMAGE)/mt7981_eeprom_mt7976_dbdc.bin >> $@ +endef + +define Device/openwrt_one + DEVICE_VENDOR := OpenWrt + DEVICE_MODEL := One + DEVICE_DTS := mt7981b-openwrt-one + DEVICE_DTS_DIR := ../dts + DEVICE_DTC_FLAGS := --pad 4096 + DEVICE_DTS_LOADADDR := 0x43f00000 + DEVICE_PACKAGES := kmod-mt7915e kmod-mt7981-firmware mt7981-wo-firmware kmod-rtc-pcf8563 kmod-usb3 kmod-nvme kmod-phy-airoha-en8811h + KERNEL_LOADADDR := 0x44000000 + KERNEL := kernel-bin | gzip + KERNEL_INITRAMFS := kernel-bin | lzma | \ + fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb with-initrd | pad-to 64k + KERNEL_INITRAMFS_SUFFIX := .itb + KERNEL_IN_UBI := 1 + UBOOTENV_IN_UBI := 1 + IMAGES := sysupgrade.itb + IMAGE_SIZE := $$(shell expr 64 + $$(CONFIG_TARGET_ROOTFS_PARTSIZE))m + IMAGE/sysupgrade.itb := append-kernel | fit gzip $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb external-with-rootfs | pad-rootfs | append-metadata + ARTIFACTS := \ + nor-preloader.bin nor-bl31-uboot.fip \ + snand-preloader.bin snand-bl31-uboot.fip \ + factory.ubi snand-factory.bin nor-factory.bin + ARTIFACT/nor-preloader.bin := mt7981-bl2 nor-ddr4 + ARTIFACT/nor-bl31-uboot.fip := mt7981-bl31-uboot openwrt_one-nor + ARTIFACT/snand-preloader.bin := mt7981-bl2 spim-nand-ubi-ddr4 + ARTIFACT/snand-bl31-uboot.fip := mt7981-bl31-uboot openwrt_one-snand + ARTIFACT/factory.ubi := ubinize-image fit squashfs-sysupgrade.itb + ARTIFACT/snand-factory.bin := mt7981-bl2 spim-nand-ubi-ddr4 | pad-to 256k | \ + mt7981-bl2 spim-nand-ubi-ddr4 | pad-to 512k | \ + mt7981-bl2 spim-nand-ubi-ddr4 | pad-to 768k | \ + mt7981-bl2 spim-nand-ubi-ddr4 | pad-to 1024k | \ + ubinize-image fit squashfs-sysupgrade.itb + ARTIFACT/nor-factory.bin := mt7981-bl2 nor-ddr4 | pad-to 256k | \ + append-openwrt-one-eeprom | pad-to 1024k | \ + mt7981-bl31-uboot openwrt_one-nor | pad-to 512k | \ + append-image-stage initramfs.itb + UBINIZE_OPTS := -E 5 + BLOCKSIZE := 128k + PAGESIZE := 2048 + UBINIZE_PARTS := fip=:$(STAGING_DIR_IMAGE)/mt7981_openwrt_one-snand-u-boot.fip recovery=:$(KDIR)/tmp/openwrt-mediatek-filogic-openwrt_one-initramfs.itb \ + $(if $(wildcard $(TOPDIR)/openwrt-mediatek-filogic-openwrt_one-calibration.itb), calibration=:$(TOPDIR)/openwrt-mediatek-filogic-openwrt_one-calibration.itb) +endef +TARGET_DEVICES += openwrt_one + define Device/qihoo_360t7 DEVICE_VENDOR := Qihoo DEVICE_MODEL := 360T7 @@ -523,99 +1049,411 @@ define Device/qihoo_360t7 BLOCKSIZE := 128k PAGESIZE := 2048 KERNEL_IN_UBI := 1 - DEVICE_PACKAGES := kmod-mt7981-firmware mt7981-wo-firmware - IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata + UBOOTENV_IN_UBI := 1 + IMAGES := sysupgrade.itb + KERNEL_INITRAMFS_SUFFIX := -recovery.itb + KERNEL := kernel-bin | gzip + KERNEL_INITRAMFS := kernel-bin | lzma | \ + fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb with-initrd | pad-to 64k + IMAGE/sysupgrade.itb := append-kernel | \ + fit gzip $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb external-static-with-rootfs | append-metadata + DEVICE_PACKAGES := kmod-mt7915e kmod-mt7981-firmware mt7981-wo-firmware + ARTIFACTS := preloader.bin bl31-uboot.fip + ARTIFACT/preloader.bin := mt7981-bl2 spim-nand-ddr3 + ARTIFACT/bl31-uboot.fip := mt7981-bl31-uboot qihoo_360t7 endef TARGET_DEVICES += qihoo_360t7 +define Device/routerich_ax3000 + DEVICE_VENDOR := Routerich + DEVICE_MODEL := AX3000 + DEVICE_DTS := mt7981b-routerich-ax3000 + DEVICE_DTS_DIR := ../dts + DEVICE_PACKAGES := kmod-mt7915e kmod-mt7981-firmware mt7981-wo-firmware kmod-usb3 + IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata + SUPPORTED_DEVICES += mediatek,mt7981-spim-snand-rfb +endef +TARGET_DEVICES += routerich_ax3000 + define Device/ruijie_rg-x60-pro DEVICE_VENDOR := Ruijie DEVICE_MODEL := RG-X60 Pro DEVICE_DTS := mt7986a-ruijie-rg-x60-pro DEVICE_DTS_DIR := ../dts - DEVICE_PACKAGES := kmod-mt7986-firmware mt7986-wo-firmware + DEVICE_PACKAGES := kmod-mt7915e kmod-mt7986-firmware mt7986-wo-firmware IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata endef TARGET_DEVICES += ruijie_rg-x60-pro -define Device/tplink_tl-common +define Device/tplink_re6000xd + DEVICE_VENDOR := TP-Link + DEVICE_MODEL := RE6000XD + DEVICE_DTS := mt7986b-tplink-re6000xd + DEVICE_DTS_DIR := ../dts + DEVICE_PACKAGES := kmod-mt7915e kmod-mt7986-firmware mt7986-wo-firmware + UBINIZE_OPTS := -E 5 + BLOCKSIZE := 128k + PAGESIZE := 2048 + IMAGE_SIZE := 51200k + IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata +endef +TARGET_DEVICES += tplink_re6000xd + +define Device/tplink_tl-xdr-common DEVICE_VENDOR := TP-Link DEVICE_DTS_DIR := ../dts UBINIZE_OPTS := -E 5 BLOCKSIZE := 128k PAGESIZE := 2048 KERNEL_IN_UBI := 1 - DEVICE_PACKAGES := kmod-usb3 kmod-mt7986-firmware mt7986-wo-firmware - IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata + UBOOTENV_IN_UBI := 1 + IMAGES := sysupgrade.itb + KERNEL_INITRAMFS_SUFFIX := -recovery.itb + KERNEL := kernel-bin | gzip + KERNEL_INITRAMFS := kernel-bin | lzma | \ + fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb with-initrd | pad-to 64k + IMAGE/sysupgrade.itb := append-kernel | \ + fit gzip $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb external-with-rootfs | append-metadata + DEVICE_PACKAGES := fitblk kmod-usb3 kmod-mt7915e kmod-mt7986-firmware mt7986-wo-firmware + ARTIFACTS := preloader.bin bl31-uboot.fip + ARTIFACT/preloader.bin := mt7986-bl2 spim-nand-ddr3 endef define Device/tplink_tl-xdr4288 DEVICE_MODEL := TL-XDR4288 DEVICE_DTS := mt7986a-tplink-tl-xdr4288 - $(call Device/tplink_tl-common) + ARTIFACT/bl31-uboot.fip := mt7986-bl31-uboot tplink_tl-xdr4288 + $(call Device/tplink_tl-xdr-common) endef TARGET_DEVICES += tplink_tl-xdr4288 define Device/tplink_tl-xdr6086 DEVICE_MODEL := TL-XDR6086 DEVICE_DTS := mt7986a-tplink-tl-xdr6086 - $(call Device/tplink_tl-common) + ARTIFACT/bl31-uboot.fip := mt7986-bl31-uboot tplink_tl-xdr6086 + $(call Device/tplink_tl-xdr-common) endef TARGET_DEVICES += tplink_tl-xdr6086 define Device/tplink_tl-xdr6088 DEVICE_MODEL := TL-XDR6088 DEVICE_DTS := mt7986a-tplink-tl-xdr6088 - $(call Device/tplink_tl-common) + ARTIFACT/bl31-uboot.fip := mt7986-bl31-uboot tplink_tl-xdr6088 + $(call Device/tplink_tl-xdr-common) endef TARGET_DEVICES += tplink_tl-xdr6088 -define Device/tplink_tl-xtr8488 - DEVICE_MODEL := TL-XTR8488 - DEVICE_DTS := mt7986a-tplink-tl-xtr8488 - DEVICE_PACKAGES += kmod-mt7915-firmware - $(call Device/tplink_tl-common) +define Device/ubnt_unifi-6-plus + DEVICE_VENDOR := Ubiquiti + DEVICE_MODEL := UniFi 6 Plus + DEVICE_DTS := mt7981a-ubnt-unifi-6-plus + DEVICE_DTS_DIR := ../dts + DEVICE_PACKAGES := kmod-mt7915e kmod-mt7981-firmware mt7981-wo-firmware e2fsprogs f2fsck mkf2fs fdisk partx-utils + IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata endef -TARGET_DEVICES += tplink_tl-xtr8488 +TARGET_DEVICES += ubnt_unifi-6-plus + +define Device/unielec_u7981-01 + DEVICE_VENDOR := Unielec + DEVICE_MODEL := U7981-01 + DEVICE_DTS_DIR := ../dts + DEVICE_PACKAGES := kmod-mt7915e kmod-mt7981-firmware mt7981-wo-firmware kmod-usb3 e2fsprogs f2fsck mkf2fs fdisk partx-utils + IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata +endef + +define Device/unielec_u7981-01-emmc + DEVICE_DTS := mt7981b-unielec-u7981-01-emmc + DEVICE_VARIANT := (EMMC) + $(call Device/unielec_u7981-01) +endef +TARGET_DEVICES += unielec_u7981-01-emmc + +define Device/unielec_u7981-01-nand + DEVICE_DTS := mt7981b-unielec-u7981-01-nand + DEVICE_VARIANT := (NAND) + $(call Device/unielec_u7981-01) +endef +TARGET_DEVICES += unielec_u7981-01-nand + +define Device/wavlink_wl-wn586x3 + DEVICE_VENDOR := WAVLINK + DEVICE_MODEL := WL-WN586X3 + DEVICE_DTS := mt7981b-wavlink-wl-wn586x3 + DEVICE_DTS_DIR := ../dts + DEVICE_DTS_LOADADDR := 0x47000000 + IMAGE_SIZE := 15424k + DEVICE_PACKAGES := kmod-mt7915e kmod-mt7981-firmware mt7981-wo-firmware +endef +TARGET_DEVICES += wavlink_wl-wn586x3 define Device/xiaomi_mi-router-ax3000t DEVICE_VENDOR := Xiaomi DEVICE_MODEL := Mi Router AX3000T - DEVICE_DTS := mt7981b-xiaomi-ax3000t + DEVICE_DTS := mt7981b-xiaomi-mi-router-ax3000t DEVICE_DTS_DIR := ../dts UBINIZE_OPTS := -E 5 BLOCKSIZE := 128k PAGESIZE := 2048 - KERNEL_IN_UBI := 1 - DEVICE_PACKAGES := kmod-mt7981-firmware mt7981-wo-firmware + DEVICE_PACKAGES := kmod-mt7915e kmod-mt7981-firmware mt7981-wo-firmware +ifneq ($(CONFIG_TARGET_ROOTFS_INITRAMFS),) + ARTIFACTS := initramfs-factory.ubi + ARTIFACT/initramfs-factory.ubi := append-image-stage initramfs-kernel.bin | ubinize-kernel +endif IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata endef TARGET_DEVICES += xiaomi_mi-router-ax3000t -define Device/xiaomi_mi-router-wr30u +define Device/xiaomi_mi-router-ax3000t-ubootmod DEVICE_VENDOR := Xiaomi - DEVICE_MODEL := Mi Router WR30U - DEVICE_DTS := mt7981b-xiaomi-wr30u + DEVICE_MODEL := Mi Router AX3000T (OpenWrt U-Boot layout) + DEVICE_DTS := mt7981b-xiaomi-mi-router-ax3000t-ubootmod DEVICE_DTS_DIR := ../dts UBINIZE_OPTS := -E 5 BLOCKSIZE := 128k PAGESIZE := 2048 + DEVICE_PACKAGES := kmod-mt7915e kmod-mt7981-firmware mt7981-wo-firmware KERNEL_IN_UBI := 1 - DEVICE_PACKAGES := kmod-mt7981-firmware mt7981-wo-firmware - IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata + UBOOTENV_IN_UBI := 1 + IMAGES := sysupgrade.itb + KERNEL_INITRAMFS_SUFFIX := -recovery.itb + KERNEL := kernel-bin | gzip + KERNEL_INITRAMFS := kernel-bin | lzma | \ + fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb with-initrd | pad-to 64k + IMAGE/sysupgrade.itb := append-kernel | \ + fit gzip $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb external-static-with-rootfs | append-metadata + ARTIFACTS := preloader.bin bl31-uboot.fip + ARTIFACT/preloader.bin := mt7981-bl2 spim-nand-ddr3 + ARTIFACT/bl31-uboot.fip := mt7981-bl31-uboot xiaomi_mi-router-ax3000t +ifneq ($(CONFIG_TARGET_ROOTFS_INITRAMFS),) + ARTIFACTS += initramfs-factory.ubi + ARTIFACT/initramfs-factory.ubi := append-image-stage initramfs-recovery.itb | ubinize-kernel +endif endef -TARGET_DEVICES += xiaomi_mi-router-wr30u +TARGET_DEVICES += xiaomi_mi-router-ax3000t-ubootmod -define Device/xiaomi_redmi-router-ax6000 +define Device/xiaomi_mi-router-wr30u-stock DEVICE_VENDOR := Xiaomi - DEVICE_MODEL := Redmi Router AX6000 - DEVICE_DTS := mt7986a-xiaomi-redmi-router-ax6000 + DEVICE_MODEL := Mi Router WR30U (stock layout) + DEVICE_DTS := mt7981b-xiaomi-mi-router-wr30u-stock DEVICE_DTS_DIR := ../dts - DEVICE_PACKAGES := kmod-leds-ws2812b kmod-mt7986-firmware mt7986-wo-firmware + UBINIZE_OPTS := -E 5 + BLOCKSIZE := 128k + PAGESIZE := 2048 + DEVICE_PACKAGES := kmod-mt7915e kmod-mt7981-firmware mt7981-wo-firmware +ifneq ($(CONFIG_TARGET_ROOTFS_INITRAMFS),) + ARTIFACTS := initramfs-factory.ubi + ARTIFACT/initramfs-factory.ubi := append-image-stage initramfs-kernel.bin | ubinize-kernel +endif + IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata +endef +TARGET_DEVICES += xiaomi_mi-router-wr30u-stock + +define Device/xiaomi_mi-router-wr30u-ubootmod + DEVICE_VENDOR := Xiaomi + DEVICE_MODEL := Mi Router WR30U (OpenWrt U-Boot layout) + DEVICE_DTS := mt7981b-xiaomi-mi-router-wr30u-ubootmod + DEVICE_DTS_DIR := ../dts + UBINIZE_OPTS := -E 5 + BLOCKSIZE := 128k + PAGESIZE := 2048 + DEVICE_PACKAGES := kmod-mt7915e kmod-mt7981-firmware mt7981-wo-firmware + KERNEL_IN_UBI := 1 + UBOOTENV_IN_UBI := 1 + IMAGES := sysupgrade.itb + KERNEL_INITRAMFS_SUFFIX := -recovery.itb + KERNEL := kernel-bin | gzip + KERNEL_INITRAMFS := kernel-bin | lzma | \ + fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb with-initrd | pad-to 64k + IMAGE/sysupgrade.itb := append-kernel | \ + fit gzip $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb external-static-with-rootfs | append-metadata + ARTIFACTS := preloader.bin bl31-uboot.fip + ARTIFACT/preloader.bin := mt7981-bl2 spim-nand-ddr3 + ARTIFACT/bl31-uboot.fip := mt7981-bl31-uboot xiaomi_mi-router-wr30u +ifneq ($(CONFIG_TARGET_ROOTFS_INITRAMFS),) + ARTIFACTS += initramfs-factory.ubi + ARTIFACT/initramfs-factory.ubi := append-image-stage initramfs-recovery.itb | ubinize-kernel +endif +endef +TARGET_DEVICES += xiaomi_mi-router-wr30u-ubootmod + +define Device/xiaomi_redmi-router-ax6000-stock + DEVICE_VENDOR := Xiaomi + DEVICE_MODEL := Redmi Router AX6000 (stock layout) + DEVICE_DTS := mt7986a-xiaomi-redmi-router-ax6000-stock + DEVICE_DTS_DIR := ../dts + DEVICE_PACKAGES := kmod-leds-ws2812b kmod-mt7915e kmod-mt7986-firmware mt7986-wo-firmware + UBINIZE_OPTS := -E 5 + BLOCKSIZE := 128k + PAGESIZE := 2048 +ifneq ($(CONFIG_TARGET_ROOTFS_INITRAMFS),) + ARTIFACTS := initramfs-factory.ubi + ARTIFACT/initramfs-factory.ubi := append-image-stage initramfs-kernel.bin | ubinize-kernel +endif + IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata +endef +TARGET_DEVICES += xiaomi_redmi-router-ax6000-stock + +define Device/xiaomi_redmi-router-ax6000-ubootmod + DEVICE_VENDOR := Xiaomi + DEVICE_MODEL := Redmi Router AX6000 (OpenWrt U-Boot layout) + DEVICE_DTS := mt7986a-xiaomi-redmi-router-ax6000-ubootmod + DEVICE_DTS_DIR := ../dts + DEVICE_PACKAGES := kmod-leds-ws2812b kmod-mt7915e kmod-mt7986-firmware mt7986-wo-firmware + KERNEL_INITRAMFS_SUFFIX := -recovery.itb + IMAGES := sysupgrade.itb UBINIZE_OPTS := -E 5 BLOCKSIZE := 128k PAGESIZE := 2048 KERNEL_IN_UBI := 1 + UBOOTENV_IN_UBI := 1 + KERNEL := kernel-bin | gzip + KERNEL_INITRAMFS := kernel-bin | lzma | \ + fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb with-initrd | pad-to 64k + IMAGE/sysupgrade.itb := append-kernel | \ + fit gzip $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb external-static-with-rootfs | append-metadata + ARTIFACTS := preloader.bin bl31-uboot.fip + ARTIFACT/preloader.bin := mt7986-bl2 spim-nand-ddr4 + ARTIFACT/bl31-uboot.fip := mt7986-bl31-uboot xiaomi_redmi-router-ax6000 +ifneq ($(CONFIG_TARGET_ROOTFS_INITRAMFS),) + ARTIFACTS += initramfs-factory.ubi + ARTIFACT/initramfs-factory.ubi := append-image-stage initramfs-recovery.itb | ubinize-kernel +endif +endef +TARGET_DEVICES += xiaomi_redmi-router-ax6000-ubootmod + +define Device/yuncore_ax835 + DEVICE_VENDOR := YunCore + DEVICE_MODEL := AX835 + DEVICE_DTS := mt7981b-yuncore-ax835 + DEVICE_DTS_DIR := ../dts + DEVICE_DTS_LOADADDR := 0x47000000 + IMAGES := sysupgrade.bin + IMAGE_SIZE := 14336k + SUPPORTED_DEVICES += mediatek,mt7981-spim-nor-rfb + KERNEL := kernel-bin | lzma | \ + fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb + KERNEL_INITRAMFS := kernel-bin | lzma | \ + fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb with-initrd | pad-to 64k + IMAGE/sysupgrade.bin := append-kernel | pad-to 128k | append-rootfs | pad-rootfs | check-size | append-metadata + DEVICE_PACKAGES := kmod-mt7915e kmod-mt7981-firmware mt7981-wo-firmware +endef +TARGET_DEVICES += yuncore_ax835 + + +define Device/zbtlink_zbt-z8102ax + DEVICE_VENDOR := Zbtlink + DEVICE_MODEL := ZBT-Z8102AX + DEVICE_DTS := mt7981b-zbtlink-zbt-z8102ax + DEVICE_DTS_DIR := ../dts + DEVICE_PACKAGES := kmod-mt7915e kmod-mt7981-firmware mt7981-wo-firmware kmod-usb3 kmod-usb-net-qmi-wwan kmod-usb-serial-option + KERNEL_IN_UBI := 1 + UBINIZE_OPTS := -E 5 + BLOCKSIZE := 128k + PAGESIZE := 2048 + IMAGE_SIZE := 65536k + IMAGES += factory.bin + IMAGE/factory.bin := append-ubi | check-size $$(IMAGE_SIZE) IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata endef -TARGET_DEVICES += xiaomi_redmi-router-ax6000 +TARGET_DEVICES += zbtlink_zbt-z8102ax + +define Device/zbtlink_zbt-z8103ax + DEVICE_VENDOR := Zbtlink + DEVICE_MODEL := ZBT-Z8103AX + DEVICE_DTS := mt7981b-zbtlink-zbt-z8103ax + DEVICE_DTS_DIR := ../dts + DEVICE_PACKAGES := kmod-mt7915e kmod-mt7981-firmware mt7981-wo-firmware + KERNEL_IN_UBI := 1 + UBINIZE_OPTS := -E 5 + BLOCKSIZE := 128k + PAGESIZE := 2048 + IMAGE_SIZE := 65536k + IMAGES += factory.bin + IMAGE/factory.bin := append-ubi | check-size $$(IMAGE_SIZE) + IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata +endef +TARGET_DEVICES += zbtlink_zbt-z8103ax + +define Device/zyxel_ex5601-t0-stock + DEVICE_VENDOR := Zyxel + DEVICE_MODEL := EX5601-T0 + DEVICE_VARIANT := (stock layout) + DEVICE_DTS := mt7986a-zyxel-ex5601-t0-stock + DEVICE_DTS_DIR := ../dts + DEVICE_PACKAGES := kmod-mt7915e kmod-mt7986-firmware mt7986-wo-firmware kmod-usb3 + SUPPORTED_DEVICES := mediatek,mt7986a-rfb-snand + UBINIZE_OPTS := -E 5 + BLOCKSIZE := 256k + PAGESIZE := 4096 + IMAGE_SIZE := 65536k + KERNEL_IN_UBI := 1 + IMAGES += factory.bin + IMAGE/factory.bin := append-ubi | check-size $$$$(IMAGE_SIZE) + IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata + KERNEL = kernel-bin | lzma | \ + fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb + KERNEL_INITRAMFS = kernel-bin | lzma | \ + fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb with-initrd +endef +TARGET_DEVICES += zyxel_ex5601-t0-stock + +define Device/zyxel_ex5601-t0-ubootmod + DEVICE_VENDOR := Zyxel + DEVICE_MODEL := EX5601-T0 + DEVICE_VARIANT := (OpenWrt U-Boot layout) + DEVICE_DTS := mt7986a-zyxel-ex5601-t0-ubootmod + DEVICE_DTS_DIR := ../dts + DEVICE_PACKAGES := kmod-mt7915e kmod-mt7986-firmware mt7986-wo-firmware kmod-usb3 + KERNEL_INITRAMFS_SUFFIX := -recovery.itb + IMAGES := sysupgrade.itb + UBINIZE_OPTS := -E 5 + BLOCKSIZE := 256k + PAGESIZE := 4096 + KERNEL_IN_UBI := 1 + UBOOTENV_IN_UBI := 1 + KERNEL := kernel-bin | lzma + KERNEL_INITRAMFS := kernel-bin | lzma | \ + fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb with-initrd + IMAGE/sysupgrade.itb := append-kernel | \ + fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb external-static-with-rootfs | append-metadata + ARTIFACTS := preloader.bin bl31-uboot.fip + ARTIFACT/preloader.bin := mt7986-bl2 spim-nand-4k-ddr4 + ARTIFACT/bl31-uboot.fip := mt7986-bl31-uboot zyxel_ex5601-t0 +ifneq ($(CONFIG_TARGET_ROOTFS_INITRAMFS),) + ARTIFACTS += initramfs-factory.ubi + ARTIFACT/initramfs-factory.ubi := append-image-stage initramfs-recovery.itb | ubinize-kernel +endif +endef +TARGET_DEVICES += zyxel_ex5601-t0-ubootmod + +define Device/zyxel_ex5700-telenor + DEVICE_VENDOR := ZyXEL + DEVICE_MODEL := EX5700 (Telenor) + DEVICE_DTS := mt7986a-zyxel-ex5700-telenor + DEVICE_DTS_DIR := ../dts + DEVICE_PACKAGES := kmod-ubootenv-nvram kmod-usb3 kmod-mt7915e kmod-mt7916-firmware kmod-mt7986-firmware mt7986-wo-firmware + UBINIZE_OPTS := -E 5 + BLOCKSIZE := 128k + PAGESIZE := 2048 + IMAGE_SIZE := 65536k + IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata +endef +TARGET_DEVICES += zyxel_ex5700-telenor + +define Device/zyxel_nwa50ax-pro + DEVICE_VENDOR := ZyXEL + DEVICE_MODEL := NWA50AX Pro + DEVICE_DTS := mt7981b-zyxel-nwa50ax-pro + DEVICE_DTS_DIR := ../dts + DEVICE_PACKAGES := kmod-mt7915e kmod-mt7981-firmware mt7981-wo-firmware zyxel-bootconfig + DEVICE_DTS_LOADADDR := 0x44000000 + UBINIZE_OPTS := -E 5 + BLOCKSIZE := 128k + PAGESIZE := 2048 + IMAGE_SIZE := 51200k + KERNEL_IN_UBI := 1 + IMAGES += factory.bin + IMAGE/factory.bin := append-ubi | check-size $$$$(IMAGE_SIZE) | zyxel-nwa-fit-filogic + IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata +endef +TARGET_DEVICES += zyxel_nwa50ax-pro diff --git a/target/linux/mediatek/image/mt7622.mk b/target/linux/mediatek/image/mt7622.mk index 3bd8bcb15..f91720479 100644 --- a/target/linux/mediatek/image/mt7622.mk +++ b/target/linux/mediatek/image/mt7622.mk @@ -1,27 +1,13 @@ DTS_DIR := $(DTS_DIR)/mediatek +DEVICE_VARS += BUFFALO_TRX_MAGIC + define Image/Prepare # For UBI we want only one extra block rm -f $(KDIR)/ubi_mark echo -ne '\xde\xad\xc0\xde' > $(KDIR)/ubi_mark endef -define Build/buffalo-kernel-trx - $(eval magic=$(word 1,$(1))) - $(eval dummy=$(word 2,$(1))) - $(eval kern_size=$(if $(KERNEL_SIZE),$(KERNEL_SIZE),0x400000)) - - $(if $(dummy),touch $(dummy)) - $(STAGING_DIR_HOST)/bin/otrx create $@.new \ - $(if $(magic),-M $(magic),) \ - -f $@ \ - $(if $(dummy),\ - -a 0x20000 \ - -b $$(( $(subst k, * 1024,$(kern_size)) )) \ - -f $(dummy),) - mv $@.new $@ -endef - define Build/bl2 cat $(STAGING_DIR_IMAGE)/mt7622-$1-bl2.img >> $@ endef @@ -30,6 +16,21 @@ define Build/bl31-uboot cat $(STAGING_DIR_IMAGE)/mt7622_$1-u-boot.fip >> $@ endef +define Build/uboot-bin + cat $(STAGING_DIR_IMAGE)/mt7622_$1-u-boot.bin >> $@ +endef + +define Build/uboot-fit + $(TOPDIR)/scripts/mkits.sh \ + -D $(DEVICE_NAME) -o $@.its -k $@ \ + -C $(word 1,$(1)) \ + -a 0x41e00000 -e 0x41e00000 \ + -c "config-1" \ + -A $(LINUX_KARCH) -v u-boot + PATH=$(LINUX_DIR)/scripts/dtc:$(PATH) mkimage -f $@.its $@.new + @mv $@.new $@ +endef + define Build/mt7622-gpt cp $@ $@.tmp 2>/dev/null || true ptgen -g -o $@.tmp -a 1 -l 1024 \ @@ -51,19 +52,6 @@ define Build/mt7622-gpt rm $@.tmp endef -define Build/trx-nand - # kernel: always use 4 MiB (-28 B or TRX header) to allow upgrades even - # if it grows up between releases - # root: UBI with one extra block containing UBI mark to trigger erasing - # rest of partition - $(STAGING_DIR_HOST)/bin/otrx create $@.new \ - -M 0x32504844 \ - -f $(IMAGE_KERNEL) -a 0x20000 -b 0x400000 \ - -f $@ \ - -A $(KDIR)/ubi_mark -a 0x20000 - mv $@.new $@ -endef - define Device/bananapi_bpi-r64 DEVICE_VENDOR := Bananapi DEVICE_MODEL := BPi-R64 @@ -71,12 +59,13 @@ define Device/bananapi_bpi-r64 DEVICE_DTS_OVERLAY := mt7622-bananapi-bpi-r64-pcie1 mt7622-bananapi-bpi-r64-sata DEVICE_PACKAGES := kmod-ata-ahci-mtk kmod-btmtkuart kmod-usb3 e2fsprogs mkf2fs f2fsck DEVICE_DTC_FLAGS := --pad 4096 + DEVICE_DTS_LOADADDR := 0x43f00000 ARTIFACTS := emmc-preloader.bin emmc-bl31-uboot.fip sdcard.img.gz snand-preloader.bin snand-bl31-uboot.fip IMAGES := sysupgrade.itb KERNEL_INITRAMFS_SUFFIX := -recovery.itb ARTIFACT/emmc-preloader.bin := bl2 emmc-2ddr ARTIFACT/emmc-bl31-uboot.fip := bl31-uboot bananapi_bpi-r64-emmc - ARTIFACT/snand-preloader.bin := bl2 snand-2ddr + ARTIFACT/snand-preloader.bin := bl2 snand-ubi-2ddr ARTIFACT/snand-bl31-uboot.fip := bl31-uboot bananapi_bpi-r64-snand ARTIFACT/sdcard.img.gz := mt7622-gpt sdmmc |\ pad-to 512k | bl2 sdmmc-2ddr |\ @@ -87,50 +76,104 @@ define Device/bananapi_bpi-r64 pad-to 38912k | mt7622-gpt emmc |\ pad-to 39424k | bl2 emmc-2ddr |\ pad-to 40960k | bl31-uboot bananapi_bpi-r64-emmc |\ - pad-to 43008k | bl2 snand-2ddr |\ + pad-to 43008k | bl2 snand-ubi-2ddr |\ pad-to 43520k | bl31-uboot bananapi_bpi-r64-snand |\ $(if $(CONFIG_TARGET_ROOTFS_SQUASHFS), \ pad-to 46080k | append-image squashfs-sysupgrade.itb | check-size |\ ) \ gzip +ifeq ($(DUMP),) IMAGE_SIZE := $$(shell expr 45 + $$(CONFIG_TARGET_ROOTFS_PARTSIZE))m +endif KERNEL := kernel-bin | gzip KERNEL_INITRAMFS := kernel-bin | lzma | fit lzma $$(DTS_DIR)/$$(DEVICE_DTS).dtb with-initrd | pad-to 128k IMAGE/sysupgrade.itb := append-kernel | fit gzip $$(DTS_DIR)/$$(DEVICE_DTS).dtb external-static-with-rootfs | append-metadata - DEVICE_COMPAT_VERSION := 1.1 - DEVICE_COMPAT_MESSAGE := Device tree overlay mechanism needs bootloader update + DEVICE_COMPAT_VERSION := 1.2 + DEVICE_COMPAT_MESSAGE := SPI-NAND flash layout changes require bootloader update endef TARGET_DEVICES += bananapi_bpi-r64 -define Device/buffalo_wsr-2533dhp2 +define Device/buffalo_wsr DEVICE_VENDOR := Buffalo - DEVICE_MODEL := WSR-2533DHP2 - DEVICE_DTS := mt7622-buffalo-wsr-2533dhp2 DEVICE_DTS_DIR := ../dts - IMAGE_SIZE := 59392k - KERNEL_SIZE := 4096k + KERNEL_SIZE := 6144k BLOCKSIZE := 128k PAGESIZE := 2048 - SUBPAGESIZE := 512 UBINIZE_OPTS := -E 5 BUFFALO_TAG_PLATFORM := MTK BUFFALO_TAG_VERSION := 9.99 BUFFALO_TAG_MINOR := 9.99 IMAGES += factory.bin factory-uboot.bin - KERNEL_INITRAMFS := kernel-bin | lzma | \ + KERNEL_INITRAMFS = kernel-bin | lzma | \ fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb with-initrd | \ - buffalo-kernel-trx - IMAGE/factory.bin := append-ubi | trx-nand | \ - buffalo-enc WSR-2533DHP2 $$(BUFFALO_TAG_VERSION) -l | \ - buffalo-tag-dhp WSR-2533DHP2 JP JP | buffalo-enc-tag -l | buffalo-dhp-image - IMAGE/factory-uboot.bin := append-ubi | trx-nand - IMAGE/sysupgrade.bin := append-kernel | \ - buffalo-kernel-trx 0x32504844 $(KDIR)/tmp/$$(DEVICE_NAME).null | \ + buffalo-trx + IMAGE/factory.bin = append-ubi | \ + buffalo-trx $$$$(BUFFALO_TRX_MAGIC) $$$$@ $(KDIR)/ubi_mark | \ + buffalo-enc $$(DEVICE_MODEL) $$(BUFFALO_TAG_VERSION) -l | \ + buffalo-tag-dhp $$(DEVICE_MODEL) JP JP | buffalo-enc-tag -l | buffalo-dhp-image + IMAGE/factory-uboot.bin := append-ubi | \ + buffalo-trx $$$$(BUFFALO_TRX_MAGIC) $$$$@ $(KDIR)/ubi_mark + IMAGE/sysupgrade.bin := \ + buffalo-trx $$$$(BUFFALO_TRX_MAGIC) $(KDIR)/tmp/$$(DEVICE_NAME).null | \ sysupgrade-tar kernel=$$$$@ | append-metadata +endef + +define Device/buffalo_wsr-2533dhp2 + $(Device/buffalo_wsr) + DEVICE_MODEL := WSR-2533DHP2 + DEVICE_DTS := mt7622-buffalo-wsr-2533dhp2 + IMAGE_SIZE := 59392k + SUBPAGESIZE := 512 + BUFFALO_TRX_MAGIC := 0x32504844 DEVICE_PACKAGES := kmod-mt7615-firmware swconfig + DEVICE_COMPAT_VERSION := 1.1 + DEVICE_COMPAT_MESSAGE := Partition table has been changed due to kernel size restrictions. \ + Please upgrade via sysupgrade with factory-uboot.bin image and '-F' option. \ + (Warning: your configurations will be erased!) endef TARGET_DEVICES += buffalo_wsr-2533dhp2 +define Device/buffalo_wsr-3200ax4s + $(Device/buffalo_wsr) + DEVICE_MODEL := WSR-3200AX4S + DEVICE_DTS := mt7622-buffalo-wsr-3200ax4s + IMAGE_SIZE := 24576k + BUFFALO_TRX_MAGIC := 0x33504844 + DEVICE_PACKAGES := kmod-mt7915-firmware +endef +TARGET_DEVICES += buffalo_wsr-3200ax4s + +define Device/dlink_eagle-pro-ai-ax3200-a1 + IMAGE_SIZE := 46080k + DEVICE_VENDOR := D-Link + DEVICE_VARIANT := A1 + DEVICE_DTS_DIR := ../dts + DEVICE_PACKAGES := kmod-mt7915-firmware + KERNEL_SIZE := 8192k + BLOCKSIZE := 128k + PAGESIZE := 2048 + UBINIZE_OPTS := -E 5 + IMAGES += tftp.bin recovery.bin + IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata + IMAGE/tftp.bin := append-kernel | pad-to $$(KERNEL_SIZE) | append-ubi | check-size +endef + +define Device/dlink_eagle-pro-ai-m32-a1 + $(Device/dlink_eagle-pro-ai-ax3200-a1) + DEVICE_MODEL := EAGLE PRO AI M32 + DEVICE_DTS := mt7622-dlink-eagle-pro-ai-m32-a1 + IMAGE/recovery.bin := append-kernel | pad-to $$(KERNEL_SIZE) | append-ubi | pad-to $$(IMAGE_SIZE) | dlink-ai-recovery-header DLK6E6010001 \x8D\x57\x30\x0B \x00\x00\x2C\x00 \x00\x00\xD0\x02 \x60\x6E +endef +TARGET_DEVICES += dlink_eagle-pro-ai-m32-a1 + +define Device/dlink_eagle-pro-ai-r32-a1 + $(Device/dlink_eagle-pro-ai-ax3200-a1) + DEVICE_MODEL := EAGLE PRO AI R32 + DEVICE_DTS := mt7622-dlink-eagle-pro-ai-r32-a1 + IMAGE/recovery.bin := append-kernel | pad-to $$(KERNEL_SIZE) | append-ubi | pad-to $$(IMAGE_SIZE) | dlink-ai-recovery-header DLK6E6015001 \x8D\x57\x30\x0B \x00\x00\x2C\x00 \x00\x00\xD0\x02 \x60\x6E +endef +TARGET_DEVICES += dlink_eagle-pro-ai-r32-a1 + define Device/elecom_wrc-2533gent DEVICE_VENDOR := Elecom DEVICE_MODEL := WRC-2533GENT @@ -194,8 +237,10 @@ define Device/linksys_e8450-ubi IMAGES := sysupgrade.itb IMAGE/sysupgrade.itb := append-kernel | fit gzip $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb external-static-with-rootfs | append-metadata ARTIFACTS := preloader.bin bl31-uboot.fip - ARTIFACT/preloader.bin := bl2 snand-1ddr + ARTIFACT/preloader.bin := bl2 snand-ubi-1ddr ARTIFACT/bl31-uboot.fip := bl31-uboot linksys_e8450 + DEVICE_COMPAT_VERSION := 2.0 + DEVICE_COMPAT_MESSAGE := SPI-NAND flash layout changes require bootloader update. Please run the UBI installer version 1.1.0+ (unsigned) first. endef TARGET_DEVICES += linksys_e8450-ubi @@ -217,7 +262,7 @@ define Device/mediatek_mt7622-rfb1-ubi UBINIZE_OPTS := -E 5 BLOCKSIZE := 128k PAGESIZE := 2048 - KERNEL_SIZE := 4194304 + KERNEL_SIZE := 6291456 IMAGE_SIZE := 32768k IMAGES += factory.bin IMAGE/factory.bin := append-kernel | pad-to $$(KERNEL_SIZE) | append-ubi | \ @@ -262,12 +307,21 @@ define Device/ruijie_rg-ew3200gx-pro endef TARGET_DEVICES += ruijie_rg-ew3200gx-pro +define Device/reyee_ax3200-e5 + DEVICE_VENDOR := reyee + DEVICE_MODEL := AX3200 E5 + DEVICE_DTS := mt7622-reyee-ax3200-e5 + DEVICE_DTS_DIR := ../dts + DEVICE_PACKAGES := kmod-mt7915-firmware +endef +TARGET_DEVICES += reyee_ax3200-e5 + define Device/totolink_a8000ru DEVICE_VENDOR := TOTOLINK DEVICE_MODEL := A8000RU DEVICE_DTS := mt7622-totolink-a8000ru DEVICE_DTS_DIR := ../dts - DEVICE_PACKAGES := kmod-mt7615-firmware swconfig + DEVICE_PACKAGES := kmod-mt7615-firmware kmod-usb3 swconfig IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata endef TARGET_DEVICES += totolink_a8000ru @@ -298,7 +352,7 @@ define Device/ubnt_unifi-6-lr-v1-ubootmod IMAGE/sysupgrade.itb := append-kernel | fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb external-static-with-rootfs | pad-rootfs | append-metadata ARTIFACTS := preloader.bin bl31-uboot.fip ARTIFACT/preloader.bin := bl2 nor-2ddr - ARTIFACT/bl31-uboot.fip := bl31-uboot ubnt_unifi-6-lr + ARTIFACT/bl31-uboot.fip := bl31-uboot ubnt_unifi-6-lr-v1 SUPPORTED_DEVICES += ubnt,unifi-6-lr-ubootmod endef TARGET_DEVICES += ubnt_unifi-6-lr-v1-ubootmod @@ -328,10 +382,39 @@ define Device/ubnt_unifi-6-lr-v2-ubootmod IMAGE/sysupgrade.itb := append-kernel | fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb external-static-with-rootfs | pad-rootfs | append-metadata ARTIFACTS := preloader.bin bl31-uboot.fip ARTIFACT/preloader.bin := bl2 nor-2ddr - ARTIFACT/bl31-uboot.fip := bl31-uboot ubnt_unifi-6-lr + ARTIFACT/bl31-uboot.fip := bl31-uboot ubnt_unifi-6-lr-v2 endef TARGET_DEVICES += ubnt_unifi-6-lr-v2-ubootmod +define Device/ubnt_unifi-6-lr-v3 + DEVICE_VENDOR := Ubiquiti + DEVICE_MODEL := UniFi 6 LR + DEVICE_VARIANT := v3 + DEVICE_DTS_CONFIG := config@1 + DEVICE_DTS := mt7622-ubnt-unifi-6-lr-v3 + DEVICE_DTS_DIR := ../dts + DEVICE_PACKAGES := kmod-mt7915-firmware +endef +TARGET_DEVICES += ubnt_unifi-6-lr-v3 + +define Device/ubnt_unifi-6-lr-v3-ubootmod + DEVICE_VENDOR := Ubiquiti + DEVICE_MODEL := UniFi 6 LR + DEVICE_VARIANT := v3 U-Boot mod + DEVICE_DTS := mt7622-ubnt-unifi-6-lr-v3-ubootmod + DEVICE_DTS_DIR := ../dts + DEVICE_PACKAGES := kmod-mt7915-firmware + KERNEL := kernel-bin | lzma + KERNEL_INITRAMFS_SUFFIX := -recovery.itb + KERNEL_INITRAMFS := kernel-bin | lzma | fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb with-initrd | pad-to 64k + IMAGES := sysupgrade.itb + IMAGE/sysupgrade.itb := append-kernel | fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb external-static-with-rootfs | pad-rootfs | append-metadata + ARTIFACTS := preloader.bin bl31-uboot.fip + ARTIFACT/preloader.bin := bl2 nor-2ddr + ARTIFACT/bl31-uboot.fip := bl31-uboot ubnt_unifi-6-lr-v3 +endef +TARGET_DEVICES += ubnt_unifi-6-lr-v3-ubootmod + define Device/xiaomi_redmi-router-ax6s DEVICE_VENDOR := Xiaomi DEVICE_MODEL := Redmi Router AX6S @@ -342,12 +425,20 @@ define Device/xiaomi_redmi-router-ax6s BOARD_NAME := xiaomi,redmi-router-ax6s DEVICE_PACKAGES := kmod-mt7915-firmware UBINIZE_OPTS := -E 5 - IMAGES += factory.bin BLOCKSIZE := 128k PAGESIZE := 2048 - KERNEL_SIZE := 4096k + KERNEL := kernel-bin | gzip + KERNEL_INITRAMFS := kernel-bin | lzma | fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb with-initrd | pad-to 64k KERNEL_INITRAMFS_SUFFIX := -recovery.itb - IMAGE/factory.bin := append-kernel | pad-to $$(KERNEL_SIZE) | append-ubi - IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata + IMAGES := sysupgrade.itb + IMAGE/sysupgrade.itb := append-kernel | fit gzip $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb external-static-with-rootfs | append-metadata + ARTIFACTS := ubi-loader.itb + ARTIFACT/ubi-loader.itb := uboot-bin xiaomi_redmi-router-ax6s-ubi-loader | lzma | uboot-fit lzma +ifneq ($(CONFIG_TARGET_ROOTFS_SQUASHFS),) + ARTIFACTS += factory.bin + ARTIFACT/factory.bin := uboot-bin xiaomi_redmi-router-ax6s-ubi-loader | lzma | uboot-fit lzma | pad-to 512k | ubinize-image fit squashfs-sysupgrade.itb +endif + DEVICE_COMPAT_VERSION := 2.0 + DEVICE_COMPAT_MESSAGE := Flash layout changes require a manual reinstall using factory.bin. endef TARGET_DEVICES += xiaomi_redmi-router-ax6s diff --git a/target/linux/mediatek/image/mt7623.mk b/target/linux/mediatek/image/mt7623.mk index 5828c4d76..93625c405 100644 --- a/target/linux/mediatek/image/mt7623.mk +++ b/target/linux/mediatek/image/mt7623.mk @@ -1,3 +1,7 @@ +ifneq ($(KERNEL),6.1) +DTS_DIR := $(DTS_DIR)/mediatek +endif + DEVICE_VARS += UBOOT_TARGET UBOOT_OFFSET UBOOT_IMAGE # The bootrom of MT7623 expects legacy MediaTek headers present in @@ -96,7 +100,9 @@ define Device/bananapi_bpi-r2 KERNEL := kernel-bin | gzip KERNEL_INITRAMFS_SUFFIX := -recovery.itb KERNEL_INITRAMFS := kernel-bin | gzip | fit gzip $$(DTS_DIR)/$$(DEVICE_DTS).dtb with-initrd +ifeq ($(DUMP),) IMAGE_SIZE := $$(shell expr 48 + $$(CONFIG_TARGET_ROOTFS_PARTSIZE))m +endif IMAGE/sysupgrade.itb := append-kernel | fit gzip $$(DTS_DIR)/$$(DEVICE_DTS).dtb external-static-with-rootfs | append-metadata ARTIFACT/preloader.bin := mt7623-mbr emmc |\ pad-to 2k | append-preloader $$(UBOOT_TARGET) @@ -114,6 +120,8 @@ define Device/bananapi_bpi-r2 gzip ARTIFACTS := u-boot.bin preloader.bin sdcard.img.gz SUPPORTED_DEVICES := bananapi,bpi-r2 + DEVICE_COMPAT_VERSION := 1.1 + DEVICE_COMPAT_MESSAGE := Bootloader update required for switch to fitblk endef TARGET_DEVICES += bananapi_bpi-r2 @@ -130,7 +138,9 @@ define Device/unielec_u7623-02 UBOOT_TARGET := mt7623a_unielec_u7623 UBOOT_IMAGE := u-boot-mtk.bin UBOOT_PATH := $(STAGING_DIR_IMAGE)/$$(UBOOT_TARGET)-$$(UBOOT_IMAGE) +ifeq ($(DUMP),) IMAGE_SIZE := $$(shell expr 48 + $$(CONFIG_TARGET_ROOTFS_PARTSIZE))m +endif IMAGES := sysupgrade.itb KERNEL := kernel-bin | gzip KERNEL_INITRAMFS_SUFFIX := -recovery.itb diff --git a/target/linux/mediatek/image/mt7629.mk b/target/linux/mediatek/image/mt7629.mk index ef4b75235..9f0ea9895 100644 --- a/target/linux/mediatek/image/mt7629.mk +++ b/target/linux/mediatek/image/mt7629.mk @@ -1,3 +1,7 @@ +ifneq ($(KERNEL),6.1) +DTS_DIR := $(DTS_DIR)/mediatek +endif + define Device/mediatek_mt7629-rfb DEVICE_VENDOR := MediaTek DEVICE_MODEL := MT7629 rfb AP @@ -5,3 +9,55 @@ define Device/mediatek_mt7629-rfb DEVICE_PACKAGES := swconfig endef TARGET_DEVICES += mediatek_mt7629-rfb + +define Device/iptime_a6004mx + DEVICE_VENDOR := ipTIME + DEVICE_MODEL := A6004MX + DEVICE_DTS := mt7629-iptime-a6004mx + DEVICE_DTS_DIR := ../dts + DEVICE_PACKAGES := kmod-usb3 uboot-envtools + UBINIZE_OPTS := -E 5 + BLOCKSIZE := 128k + PAGESIZE := 2048 + KERNEL := $$(KERNEL) | pad-offset 128k 2048 | iptime-crc32 a6004mx + KERNEL_INITRAMFS := $$(KERNEL_INITRAMFS) | pad-offset 128k 2048 | iptime-crc32 a6004mx + IMAGES += recovery.bin + IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata + IMAGE/recovery.bin := append-kernel | pad-to 128k | append-ubi | append-metadata +endef +TARGET_DEVICES += iptime_a6004mx + +define Device/netgear_ex6250-v2 + DEVICE_VENDOR := NETGEAR + DEVICE_MODEL := EX6250 + DEVICE_VARIANT := v2 + DEVICE_ALT0_VENDOR := NETGEAR + DEVICE_ALT0_MODEL := EX6400 + DEVICE_ALT0_VARIANT := v3 + DEVICE_ALT1_VENDOR := NETGEAR + DEVICE_ALT1_MODEL := EX6410 + DEVICE_ALT1_VARIANT := v2 + DEVICE_ALT2_VENDOR := NETGEAR + DEVICE_ALT2_MODEL := EX6470 + DEVICE_DTS := mt7629-netgear-ex6250-v2 + DEVICE_DTS_DIR := ../dts + DEVICE_PACKAGES := uboot-envtools + NETGEAR_ENC_MODEL := EX6250v2 + NETGEAR_ENC_REGION := US + NETGEAR_ENC_HW_ID_LIST := 1010000003630000_NETGEAR;1010000003540000_NETGEAR + NETGEAR_ENC_MODEL_LIST := EX6250v2;EX6400v3;EX6470;EX6410v2 + IMAGE_SIZE := 13120k + IMAGES += factory.img + IMAGE/factory.img := append-kernel | pad-to 128k | append-rootfs | \ + pad-rootfs | check-size | netgear-encrypted-factory +endef +TARGET_DEVICES += netgear_ex6250-v2 + +define Device/tplink_eap225-v5 + DEVICE_VENDOR := TP-Link + DEVICE_MODEL := EAP225 + DEVICE_VARIANT := v5 + DEVICE_DTS := mt7629-tplink_eap225-v5 + DEVICE_DTS_DIR := ../dts +endef +TARGET_DEVICES += tplink_eap225-v5 diff --git a/target/linux/mediatek/mt7622/base-files/etc/board.d/02_network b/target/linux/mediatek/mt7622/base-files/etc/board.d/02_network index cf18c25f8..6bda6e11f 100644 --- a/target/linux/mediatek/mt7622/base-files/etc/board.d/02_network +++ b/target/linux/mediatek/mt7622/base-files/etc/board.d/02_network @@ -8,34 +8,41 @@ mediatek_setup_interfaces() local board="$1" case $board in - bananapi,bpi-r64|\ - elecom,wrc-x3200gst3|\ - linksys,e8450|\ - linksys,e8450-ubi|\ - mediatek,mt7622-rfb1|\ - mediatek,mt7622-rfb1-ubi|\ - netgear,wax206|\ - ruijie,rg-ew3200gx-pro) - ucidef_set_interfaces_lan_wan "lan1 lan2 lan3 lan4" wan - ;; buffalo,wsr-2533dhp2) ucidef_add_switch "switch0" \ "0:lan" "1:lan" "2:lan" "3:lan" "4:wan" "6@eth0" ;; - ubnt,unifi-6-lr|\ - ubnt,unifi-6-lr-ubootmod) + dlink,eagle-pro-ai-m32-a1) + ucidef_set_interfaces_lan_wan "lan1 lan2" wan + ;; + elecom,wrc-2533gent|\ + totolink,a8000ru) + ucidef_add_switch "switch0" \ + "0:lan" "1:lan" "2:lan" "3:lan" "4:wan" "6u@eth0" "5u@eth1" + ;; + ubnt,unifi-6-lr*) ucidef_set_interface_lan "eth0" ;; xiaomi,redmi-router-ax6s) ucidef_set_interfaces_lan_wan "lan1 lan2 lan3" wan ;; *) - ucidef_add_switch "switch0" \ - "0:lan" "1:lan" "2:lan" "3:lan" "4:wan" "6u@eth0" "5u@eth1" + ucidef_set_interfaces_lan_wan "lan1 lan2 lan3 lan4" wan ;; esac } +DEV_PATH_WMAC=platform/18000000.wmac +DEV_PATH_PCIE0=1a143000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0 +DEV_PATH_PCIE1=1a145000.pcie/pci0001:00/0001:00:01.0/0001:01:00.0 + +mediatek_setup_wlan() +{ + dt_is_enabled wmac@18000000 && ucidef_add_wlan $DEV_PATH_WMAC + dt_is_enabled pcie@1a143000 && ucidef_add_wlan $DEV_PATH_PCIE0 + dt_is_enabled pcie@1a145000 && ucidef_add_wlan $DEV_PATH_PCIE1 +} + mediatek_setup_macs() { local board="$1" @@ -44,6 +51,12 @@ mediatek_setup_macs() local label_mac="" case $board in + buffalo,wsr-3200ax4s) + lan_mac=$(mtd_get_mac_ascii board_data "mac") + wan_mac=$lan_mac + label_mac=$lan_mac + ;; + reyee,ax3200-e5|\ ruijie,rg-ew3200gx-pro) lan_mac=$(macaddr_add $(get_mac_label) 1) ;; @@ -62,6 +75,7 @@ board_config_update board=$(board_name) mediatek_setup_interfaces $board mediatek_setup_macs $board +mediatek_setup_wlan $board board_config_flush exit 0 diff --git a/target/linux/mediatek/mt7622/base-files/etc/board.d/05_compat-version b/target/linux/mediatek/mt7622/base-files/etc/board.d/05_compat-version index c8fb2c08f..68c397a95 100644 --- a/target/linux/mediatek/mt7622/base-files/etc/board.d/05_compat-version +++ b/target/linux/mediatek/mt7622/base-files/etc/board.d/05_compat-version @@ -6,7 +6,10 @@ board_config_update case "$(board_name)" in bananapi,bpi-r64) - ucidef_set_compat_version "1.1" + ucidef_set_compat_version "1.2" + ;; + linksys,e8450-ubi) + ucidef_set_compat_version "2.0" ;; esac diff --git a/target/linux/mediatek/mt7622/base-files/etc/hotplug.d/ieee80211/11_fix_wifi_mac b/target/linux/mediatek/mt7622/base-files/etc/hotplug.d/ieee80211/11_fix_wifi_mac index d57346574..7ee9f2407 100644 --- a/target/linux/mediatek/mt7622/base-files/etc/hotplug.d/ieee80211/11_fix_wifi_mac +++ b/target/linux/mediatek/mt7622/base-files/etc/hotplug.d/ieee80211/11_fix_wifi_mac @@ -10,6 +10,15 @@ PHYNBR=${DEVPATH##*/phy} board=$(board_name) case "$board" in + bananapi,bpi-r64) + [ "$PHYNBR" = "0" ] && macaddr_add $(cat /sys/class/net/eth0/address) 2 > /sys${DEVPATH}/macaddress + ;; + buffalo,wsr-3200ax4s) + basemac=$(mtd_get_mac_ascii board_data "mac") + [ "$PHYNBR" = "0" ] && macaddr_add $basemac 1 > /sys${DEVPATH}/macaddress + [ "$PHYNBR" = "1" ] && macaddr_add $basemac 8 > /sys${DEVPATH}/macaddress + ;; + reyee,ax3200-e5|\ ruijie,rg-ew3200gx-pro) [ "$PHYNBR" = "0" ] && macaddr_add $(get_mac_label) 3 > /sys${DEVPATH}/macaddress [ "$PHYNBR" = "1" ] && macaddr_add $(get_mac_label) 2 > /sys${DEVPATH}/macaddress diff --git a/target/linux/mediatek/mt7622/base-files/etc/init.d/bootcount b/target/linux/mediatek/mt7622/base-files/etc/init.d/bootcount index bc4eeb653..19a321b48 100755 --- a/target/linux/mediatek/mt7622/base-files/etc/init.d/bootcount +++ b/target/linux/mediatek/mt7622/base-files/etc/init.d/bootcount @@ -4,6 +4,14 @@ START=99 boot() { case $(board_name) in + dlink,eagle-pro-ai-m32-a1|\ + dlink,eagle-pro-ai-r32-a1) + if grep -q boot_part=Kernel1 /proc/cmdline; then + fw_setenv boot_part 1 + else + fw_setenv boot_part 2 + fi + ;; linksys,e8450) mtd erase senv || true ;; diff --git a/target/linux/mediatek/mt7622/base-files/etc/uci-defaults/05_fix-compat-version b/target/linux/mediatek/mt7622/base-files/etc/uci-defaults/05_fix-compat-version index c77e1cb8b..dd224f3d8 100644 --- a/target/linux/mediatek/mt7622/base-files/etc/uci-defaults/05_fix-compat-version +++ b/target/linux/mediatek/mt7622/base-files/etc/uci-defaults/05_fix-compat-version @@ -2,9 +2,18 @@ case "$(board_name)" in bananapi,bpi-r64) + uci set system.@system[0].compat_version="1.2" + uci commit system + ;; + buffalo,wsr-2533dhp2) uci set system.@system[0].compat_version="1.1" uci commit system ;; + linksys,e8450-ubi|\ + xiaomi,redmi-router-ax6s) + uci set system.@system[0].compat_version="2.0" + uci commit system + ;; esac exit 0 diff --git a/target/linux/mediatek/mt7622/base-files/etc/uci-defaults/09_fix_crc b/target/linux/mediatek/mt7622/base-files/etc/uci-defaults/09_fix_crc index 81cb6b18b..59b00a6e6 100644 --- a/target/linux/mediatek/mt7622/base-files/etc/uci-defaults/09_fix_crc +++ b/target/linux/mediatek/mt7622/base-files/etc/uci-defaults/09_fix_crc @@ -7,4 +7,8 @@ buffalo,wsr-2533dhp2) mtd -M 0x44485032 ${kernel_size:+-c 0x$kernel_size} fixtrx firmware && exit 0 exit 1 ;; +buffalo,wsr-3200ax4s) + mtd -M 0x44485033 ${kernel_size:+-c 0x$kernel_size} fixtrx firmware && exit 0 + exit 1 + ;; esac diff --git a/target/linux/mediatek/mt7622/base-files/lib/upgrade/platform.sh b/target/linux/mediatek/mt7622/base-files/lib/upgrade/platform.sh index a9899edf4..59375ccd9 100755 --- a/target/linux/mediatek/mt7622/base-files/lib/upgrade/platform.sh +++ b/target/linux/mediatek/mt7622/base-files/lib/upgrade/platform.sh @@ -1,27 +1,38 @@ REQUIRE_IMAGE_METADATA=1 +RAMFS_COPY_BIN='fitblk' platform_do_upgrade() { local board=$(board_name) local file_type=$(identify $1) case "$board" in - bananapi,bpi-r64) - local rootdev="$(cmdline_get_var root)" - rootdev="${rootdev##*/}" - rootdev="${rootdev%p[0-9]*}" - case "$rootdev" in - mmc*) - CI_ROOTDEV="$rootdev" - CI_KERNPART="production" + bananapi,bpi-r64|\ + linksys,e8450-ubi|\ + ubnt,unifi-6-lr-v1-ubootmod|\ + ubnt,unifi-6-lr-v2-ubootmod|\ + ubnt,unifi-6-lr-v3-ubootmod|\ + xiaomi,redmi-router-ax6s) + [ -e /dev/fit0 ] && fitblk /dev/fit0 + [ -e /dev/fitrw ] && fitblk /dev/fitrw + bootdev="$(fitblk_get_bootdev)" + case "$bootdev" in + mmcblk*) + EMMC_KERN_DEV="/dev/$bootdev" emmc_do_upgrade "$1" ;; - *) + mtdblock*) + PART_NAME="/dev/mtd${bootdev:8}" + default_do_upgrade "$1" + ;; + ubiblock*) CI_KERNPART="fit" nand_do_upgrade "$1" ;; esac ;; - buffalo,wsr-2533dhp2) + + buffalo,wsr-2533dhp2|\ + buffalo,wsr-3200ax4s) local magic="$(get_magic_long "$1")" # use "mtd write" if the magic is "DHP2 (0x44485032)" @@ -33,15 +44,12 @@ platform_do_upgrade() { nand_do_upgrade "$1" fi ;; + dlink,eagle-pro-ai-m32-a1|\ + dlink,eagle-pro-ai-r32-a1|\ elecom,wrc-x3200gst3|\ mediatek,mt7622-rfb1-ubi|\ netgear,wax206|\ - totolink,a8000ru|\ - xiaomi,redmi-router-ax6s) - nand_do_upgrade "$1" - ;; - linksys,e8450-ubi) - CI_KERNPART="fit" + totolink,a8000ru) nand_do_upgrade "$1" ;; linksys,e8450) @@ -67,15 +75,18 @@ platform_check_image() { [ "$#" -gt 1 ] && return 1 case "$board" in - buffalo,wsr-2533dhp2) + buffalo,wsr-2533dhp2|\ + buffalo,wsr-3200ax4s) buffalo_check_image "$board" "$magic" "$1" || return 1 ;; + dlink,eagle-pro-ai-m32-a1|\ + dlink,eagle-pro-ai-r32-a1|\ elecom,wrc-x3200gst3|\ mediatek,mt7622-rfb1-ubi|\ netgear,wax206|\ - totolink,a8000ru|\ - xiaomi,redmi-router-ax6s) + totolink,a8000ru) nand_do_platform_check "$board" "$1" + return $? ;; *) [ "$magic" != "d00dfeed" ] && { @@ -92,9 +103,7 @@ platform_check_image() { platform_copy_config() { case "$(board_name)" in bananapi,bpi-r64) - export_bootdevice - export_partdevice rootdev 0 - if echo $rootdev | grep -q mmc; then + if fitblk_get_bootdev | grep -q mmc; then emmc_copy_config fi ;; diff --git a/target/linux/mediatek/mt7622/config-5.15 b/target/linux/mediatek/mt7622/config-5.15 deleted file mode 100644 index 47df81b14..000000000 --- a/target/linux/mediatek/mt7622/config-5.15 +++ /dev/null @@ -1,464 +0,0 @@ -CONFIG_64BIT=y -# CONFIG_AHCI_MTK is not set -CONFIG_AQUANTIA_PHY=y -CONFIG_ARCH_DMA_ADDR_T_64BIT=y -CONFIG_ARCH_KEEP_MEMBLOCK=y -CONFIG_ARCH_MEDIATEK=y -CONFIG_ARCH_MHP_MEMMAP_ON_MEMORY_ENABLE=y -CONFIG_ARCH_MMAP_RND_BITS=18 -CONFIG_ARCH_MMAP_RND_BITS_MAX=24 -CONFIG_ARCH_MMAP_RND_BITS_MIN=18 -CONFIG_ARCH_MMAP_RND_COMPAT_BITS=11 -CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=11 -CONFIG_ARCH_PROC_KCORE_TEXT=y -CONFIG_ARCH_SPARSEMEM_ENABLE=y -CONFIG_ARCH_STACKWALK=y -CONFIG_ARCH_SUSPEND_POSSIBLE=y -CONFIG_ARCH_WANTS_NO_INSTR=y -CONFIG_ARM64=y -CONFIG_ARM64_4K_PAGES=y -# CONFIG_ARM64_CNP is not set -CONFIG_ARM64_CRYPTO=y -CONFIG_ARM64_ERRATUM_843419=y -CONFIG_ARM64_ERRATUM_845719=y -CONFIG_ARM64_LD_HAS_FIX_ERRATUM_843419=y -CONFIG_ARM64_MODULE_PLTS=y -CONFIG_ARM64_PAGE_SHIFT=12 -CONFIG_ARM64_PA_BITS=48 -CONFIG_ARM64_PA_BITS_48=y -# CONFIG_ARM64_SW_TTBR0_PAN is not set -CONFIG_ARM64_TAGGED_ADDR_ABI=y -CONFIG_ARM64_VA_BITS=39 -CONFIG_ARM64_VA_BITS_39=y -# CONFIG_ARMV8_DEPRECATED is not set -CONFIG_ARM_AMBA=y -CONFIG_ARM_ARCH_TIMER=y -CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y -CONFIG_ARM_GIC=y -CONFIG_ARM_GIC_V2M=y -CONFIG_ARM_GIC_V3=y -CONFIG_ARM_GIC_V3_ITS=y -CONFIG_ARM_GIC_V3_ITS_PCI=y -CONFIG_ARM_MEDIATEK_CPUFREQ=y -CONFIG_ARM_PMU=y -CONFIG_ARM_PSCI_FW=y -CONFIG_ATA=y -CONFIG_AUDIT_ARCH_COMPAT_GENERIC=y -CONFIG_BLK_DEV_LOOP=y -CONFIG_BLK_DEV_SD=y -CONFIG_BLK_MQ_PCI=y -CONFIG_BLK_PM=y -CONFIG_BLOCK_COMPAT=y -CONFIG_BSD_PROCESS_ACCT=y -CONFIG_BSD_PROCESS_ACCT_V3=y -CONFIG_CC_HAVE_STACKPROTECTOR_SYSREG=y -CONFIG_CLKSRC_MMIO=y -CONFIG_CLONE_BACKWARDS=y -# CONFIG_CMDLINE_OVERRIDE is not set -CONFIG_COMMON_CLK=y -CONFIG_COMMON_CLK_MEDIATEK=y -CONFIG_COMMON_CLK_MT2712=y -# CONFIG_COMMON_CLK_MT2712_BDPSYS is not set -# CONFIG_COMMON_CLK_MT2712_IMGSYS is not set -# CONFIG_COMMON_CLK_MT2712_JPGDECSYS is not set -# CONFIG_COMMON_CLK_MT2712_MFGCFG is not set -# CONFIG_COMMON_CLK_MT2712_MMSYS is not set -# CONFIG_COMMON_CLK_MT2712_VDECSYS is not set -# CONFIG_COMMON_CLK_MT2712_VENCSYS is not set -# CONFIG_COMMON_CLK_MT6779 is not set -# CONFIG_COMMON_CLK_MT6797 is not set -CONFIG_COMMON_CLK_MT7622=y -CONFIG_COMMON_CLK_MT7622_AUDSYS=y -CONFIG_COMMON_CLK_MT7622_ETHSYS=y -CONFIG_COMMON_CLK_MT7622_HIFSYS=y -# CONFIG_COMMON_CLK_MT7981 is not set -# CONFIG_COMMON_CLK_MT7986 is not set -# CONFIG_COMMON_CLK_MT7988 is not set -# CONFIG_COMMON_CLK_MT8173 is not set -# CONFIG_COMMON_CLK_MT8183 is not set -# CONFIG_COMMON_CLK_MT8183_AUDIOSYS is not set -# CONFIG_COMMON_CLK_MT8183_CAMSYS is not set -# CONFIG_COMMON_CLK_MT8183_IMGSYS is not set -# CONFIG_COMMON_CLK_MT8183_IPU_ADL is not set -# CONFIG_COMMON_CLK_MT8183_IPU_CONN is not set -# CONFIG_COMMON_CLK_MT8183_IPU_CORE0 is not set -# CONFIG_COMMON_CLK_MT8183_IPU_CORE1 is not set -# CONFIG_COMMON_CLK_MT8183_MFGCFG is not set -# CONFIG_COMMON_CLK_MT8183_MMSYS is not set -# CONFIG_COMMON_CLK_MT8183_VDECSYS is not set -# CONFIG_COMMON_CLK_MT8183_VENCSYS is not set -# CONFIG_COMMON_CLK_MT8516 is not set -# CONFIG_COMMON_CLK_MT8516_AUDSYS is not set -CONFIG_COMPAT=y -CONFIG_COMPAT_32BIT_TIME=y -CONFIG_COMPAT_BINFMT_ELF=y -CONFIG_COMPAT_NETLINK_MESSAGES=y -CONFIG_COMPAT_OLD_SIGACTION=y -CONFIG_CONFIGFS_FS=y -CONFIG_CONSOLE_LOGLEVEL_DEFAULT=15 -# CONFIG_CPUFREQ_DT is not set -CONFIG_CPU_FREQ=y -# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set -CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y -CONFIG_CPU_FREQ_GOV_ATTR_SET=y -CONFIG_CPU_FREQ_GOV_COMMON=y -CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y -CONFIG_CPU_FREQ_GOV_ONDEMAND=y -CONFIG_CPU_FREQ_GOV_PERFORMANCE=y -CONFIG_CPU_FREQ_GOV_POWERSAVE=y -CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y -CONFIG_CPU_FREQ_GOV_USERSPACE=y -CONFIG_CPU_FREQ_STAT=y -CONFIG_CPU_RMAP=y -CONFIG_CPU_THERMAL=y -CONFIG_CRC16=y -CONFIG_CRYPTO_AES_ARM64=y -CONFIG_CRYPTO_AES_ARM64_CE=y -CONFIG_CRYPTO_AES_ARM64_CE_BLK=y -CONFIG_CRYPTO_AES_ARM64_CE_CCM=y -CONFIG_CRYPTO_BLAKE2S=y -CONFIG_CRYPTO_CMAC=y -CONFIG_CRYPTO_CRC32=y -CONFIG_CRYPTO_CRC32C=y -CONFIG_CRYPTO_CRYPTD=y -CONFIG_CRYPTO_DEFLATE=y -CONFIG_CRYPTO_DRBG=y -CONFIG_CRYPTO_DRBG_HMAC=y -CONFIG_CRYPTO_DRBG_MENU=y -CONFIG_CRYPTO_ECB=y -CONFIG_CRYPTO_ECC=y -CONFIG_CRYPTO_ECDH=y -CONFIG_CRYPTO_GHASH_ARM64_CE=y -CONFIG_CRYPTO_HASH_INFO=y -CONFIG_CRYPTO_HMAC=y -CONFIG_CRYPTO_JITTERENTROPY=y -CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y -CONFIG_CRYPTO_LIB_SHA256=y -CONFIG_CRYPTO_LZO=y -CONFIG_CRYPTO_RNG=y -CONFIG_CRYPTO_RNG2=y -CONFIG_CRYPTO_RNG_DEFAULT=y -CONFIG_CRYPTO_SHA256=y -CONFIG_CRYPTO_SHA256_ARM64=y -CONFIG_CRYPTO_SHA2_ARM64_CE=y -CONFIG_CRYPTO_SHA512=y -CONFIG_CRYPTO_SIMD=y -CONFIG_CRYPTO_ZSTD=y -CONFIG_DCACHE_WORD_ACCESS=y -CONFIG_DEBUG_MISC=y -CONFIG_DIMLIB=y -CONFIG_DMADEVICES=y -CONFIG_DMA_DIRECT_REMAP=y -CONFIG_DMA_ENGINE=y -CONFIG_DMA_ENGINE_RAID=y -CONFIG_DMA_OF=y -CONFIG_DMA_REMAP=y -CONFIG_DMA_VIRTUAL_CHANNELS=y -CONFIG_DTC=y -CONFIG_DYNAMIC_DEBUG=y -CONFIG_EDAC_SUPPORT=y -CONFIG_EINT_MTK=y -CONFIG_EXT4_FS=y -CONFIG_F2FS_FS=y -CONFIG_FIT_PARTITION=y -CONFIG_FIXED_PHY=y -CONFIG_FIX_EARLYCON_MEM=y -CONFIG_FRAME_POINTER=y -CONFIG_FS_IOMAP=y -CONFIG_FS_MBCACHE=y -CONFIG_FWNODE_MDIO=y -CONFIG_FW_LOADER_PAGED_BUF=y -CONFIG_GENERIC_ALLOCATOR=y -CONFIG_GENERIC_ARCH_TOPOLOGY=y -CONFIG_GENERIC_BUG=y -CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y -CONFIG_GENERIC_CLOCKEVENTS=y -CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y -CONFIG_GENERIC_CPU_AUTOPROBE=y -CONFIG_GENERIC_CPU_VULNERABILITIES=y -CONFIG_GENERIC_CSUM=y -CONFIG_GENERIC_EARLY_IOREMAP=y -CONFIG_GENERIC_FIND_FIRST_BIT=y -CONFIG_GENERIC_GETTIMEOFDAY=y -CONFIG_GENERIC_IDLE_POLL_SETUP=y -CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y -CONFIG_GENERIC_IRQ_SHOW=y -CONFIG_GENERIC_IRQ_SHOW_LEVEL=y -CONFIG_GENERIC_LIB_DEVMEM_IS_ALLOWED=y -CONFIG_GENERIC_MSI_IRQ=y -CONFIG_GENERIC_MSI_IRQ_DOMAIN=y -CONFIG_GENERIC_PCI_IOMAP=y -CONFIG_GENERIC_PHY=y -CONFIG_GENERIC_PINCONF=y -CONFIG_GENERIC_PINCTRL_GROUPS=y -CONFIG_GENERIC_PINMUX_FUNCTIONS=y -CONFIG_GENERIC_SCHED_CLOCK=y -CONFIG_GENERIC_SMP_IDLE_THREAD=y -CONFIG_GENERIC_STRNCPY_FROM_USER=y -CONFIG_GENERIC_STRNLEN_USER=y -CONFIG_GENERIC_TIME_VSYSCALL=y -CONFIG_GLOB=y -CONFIG_GPIO_CDEV=y -CONFIG_GRO_CELLS=y -CONFIG_HANDLE_DOMAIN_IRQ=y -CONFIG_HARDIRQS_SW_RESEND=y -CONFIG_HAS_DMA=y -CONFIG_HAS_IOMEM=y -CONFIG_HAS_IOPORT_MAP=y -CONFIG_HW_RANDOM=y -CONFIG_HW_RANDOM_MTK=y -CONFIG_I2C=y -CONFIG_I2C_BOARDINFO=y -CONFIG_I2C_CHARDEV=y -CONFIG_I2C_MT65XX=y -CONFIG_ICPLUS_PHY=y -CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000 -CONFIG_INITRAMFS_SOURCE="" -CONFIG_IRQCHIP=y -CONFIG_IRQ_DOMAIN=y -CONFIG_IRQ_DOMAIN_HIERARCHY=y -CONFIG_IRQ_FORCED_THREADING=y -CONFIG_IRQ_TIME_ACCOUNTING=y -CONFIG_IRQ_WORK=y -CONFIG_JBD2=y -CONFIG_JUMP_LABEL=y -CONFIG_LIBFDT=y -CONFIG_LOCK_DEBUGGING_SUPPORT=y -CONFIG_LOCK_SPIN_ON_OWNER=y -CONFIG_LZO_COMPRESS=y -CONFIG_LZO_DECOMPRESS=y -CONFIG_MAGIC_SYSRQ=y -CONFIG_MDIO_BUS=y -CONFIG_MDIO_DEVICE=y -CONFIG_MDIO_DEVRES=y -# CONFIG_MEDIATEK_2P5G_PHY is not set -CONFIG_MEDIATEK_GE_PHY=y -# CONFIG_MEDIATEK_GE_SOC_PHY is not set -CONFIG_MEDIATEK_WATCHDOG=y -CONFIG_MEMFD_CREATE=y -CONFIG_MESSAGE_LOGLEVEL_DEFAULT=7 -CONFIG_MFD_SYSCON=y -CONFIG_MIGRATION=y -CONFIG_MMC=y -CONFIG_MMC_BLOCK=y -CONFIG_MMC_CQHCI=y -CONFIG_MMC_MTK=y -CONFIG_MODULES_TREE_LOOKUP=y -CONFIG_MODULES_USE_ELF_RELA=y -CONFIG_MTD_NAND_CORE=y -CONFIG_MTD_NAND_ECC=y -CONFIG_MTD_NAND_ECC_MEDIATEK=y -CONFIG_MTD_NAND_ECC_SW_HAMMING=y -CONFIG_MTD_NAND_MTK=y -CONFIG_MTD_NAND_MTK_BMT=y -CONFIG_MTD_PARSER_TRX=y -CONFIG_MTD_RAW_NAND=y -CONFIG_MTD_SPI_NAND=y -CONFIG_MTD_SPI_NOR=y -CONFIG_MTD_SPI_NOR_USE_VARIABLE_ERASE=y -CONFIG_MTD_SPLIT_FIRMWARE=y -CONFIG_MTD_SPLIT_FIT_FW=y -CONFIG_MTD_UBI=y -CONFIG_MTD_UBI_BEB_LIMIT=20 -CONFIG_MTD_UBI_FASTMAP=y -CONFIG_MTD_UBI_BLOCK=y -CONFIG_MTD_UBI_WL_THRESHOLD=4096 -# CONFIG_MTK_CMDQ is not set -# CONFIG_MTK_CQDMA is not set -CONFIG_MTK_EFUSE=y -CONFIG_MTK_HSDMA=y -CONFIG_MTK_INFRACFG=y -CONFIG_MTK_PMIC_WRAP=y -CONFIG_MTK_SCPSYS=y -CONFIG_MTK_SCPSYS_PM_DOMAINS=y -CONFIG_MTK_THERMAL=y -CONFIG_MTK_TIMER=y -# CONFIG_MTK_UART_APDMA is not set -CONFIG_MUTEX_SPIN_ON_OWNER=y -CONFIG_NEED_DMA_MAP_STATE=y -CONFIG_NEED_SG_DMA_LENGTH=y -CONFIG_NET_DEVLINK=y -CONFIG_NET_DSA=y -CONFIG_NET_DSA_MT7530=y -CONFIG_NET_DSA_MT7530_MDIO=y -# CONFIG_NET_DSA_MT7530_MMIO is not set -CONFIG_NET_DSA_TAG_MTK=y -CONFIG_NET_FLOW_LIMIT=y -CONFIG_NET_MEDIATEK_SOC=y -# CONFIG_NET_MEDIATEK_SOC_USXGMII is not set -CONFIG_NET_MEDIATEK_SOC_WED=y -CONFIG_NET_SELFTESTS=y -CONFIG_NET_SWITCHDEV=y -CONFIG_NET_VENDOR_MEDIATEK=y -CONFIG_NLS=y -CONFIG_NO_HZ_COMMON=y -CONFIG_NO_HZ_IDLE=y -CONFIG_NR_CPUS=2 -CONFIG_NVMEM=y -CONFIG_NVMEM_SYSFS=y -CONFIG_OF=y -CONFIG_OF_ADDRESS=y -CONFIG_OF_DYNAMIC=y -CONFIG_OF_EARLY_FLATTREE=y -CONFIG_OF_FLATTREE=y -CONFIG_OF_GPIO=y -CONFIG_OF_IRQ=y -CONFIG_OF_KOBJ=y -CONFIG_OF_MDIO=y -CONFIG_OF_OVERLAY=y -CONFIG_OF_RESOLVE=y -CONFIG_OLD_SIGSUSPEND3=y -CONFIG_PADATA=y -CONFIG_PARTITION_PERCPU=y -CONFIG_PCI=y -CONFIG_PCIEAER=y -CONFIG_PCIEASPM=y -# CONFIG_PCIEASPM_DEFAULT is not set -CONFIG_PCIEASPM_PERFORMANCE=y -# CONFIG_PCIEASPM_POWERSAVE is not set -# CONFIG_PCIEASPM_POWER_SUPERSAVE is not set -CONFIG_PCIEPORTBUS=y -CONFIG_PCIE_MEDIATEK=y -CONFIG_PCIE_PME=y -CONFIG_PCI_DEBUG=y -CONFIG_PCI_DOMAINS=y -CONFIG_PCI_DOMAINS_GENERIC=y -CONFIG_PCI_MSI=y -CONFIG_PCI_MSI_IRQ_DOMAIN=y -CONFIG_PERF_EVENTS=y -CONFIG_PGTABLE_LEVELS=3 -CONFIG_PHYLIB=y -CONFIG_PHYLINK=y -CONFIG_PHYS_ADDR_T_64BIT=y -CONFIG_PHY_MTK_TPHY=y -# CONFIG_PHY_MTK_UFS is not set -# CONFIG_PHY_MTK_XSPHY is not set -CONFIG_PINCTRL=y -# CONFIG_PINCTRL_MT2712 is not set -# CONFIG_PINCTRL_MT6765 is not set -# CONFIG_PINCTRL_MT6797 is not set -CONFIG_PINCTRL_MT7622=y -# CONFIG_PINCTRL_MT7981 is not set -# CONFIG_PINCTRL_MT7986 is not set -# CONFIG_PINCTRL_MT7988 is not set -# CONFIG_PINCTRL_MT8173 is not set -# CONFIG_PINCTRL_MT8183 is not set -CONFIG_PINCTRL_MT8516=y -CONFIG_PINCTRL_MTK=y -CONFIG_PINCTRL_MTK_MOORE=y -CONFIG_PINCTRL_MTK_V2=y -CONFIG_PM=y -CONFIG_PM_CLK=y -CONFIG_PM_GENERIC_DOMAINS=y -CONFIG_PM_GENERIC_DOMAINS_OF=y -CONFIG_PM_OPP=y -CONFIG_POWER_RESET=y -CONFIG_POWER_RESET_SYSCON=y -CONFIG_POWER_SUPPLY=y -CONFIG_PRINTK_TIME=y -CONFIG_PSTORE=y -CONFIG_PSTORE_COMPRESS=y -CONFIG_PSTORE_COMPRESS_DEFAULT="deflate" -CONFIG_PSTORE_CONSOLE=y -CONFIG_PSTORE_DEFLATE_COMPRESS=y -CONFIG_PSTORE_DEFLATE_COMPRESS_DEFAULT=y -CONFIG_PSTORE_PMSG=y -CONFIG_PSTORE_RAM=y -CONFIG_PTP_1588_CLOCK_OPTIONAL=y -CONFIG_PWM=y -CONFIG_PWM_MEDIATEK=y -# CONFIG_PWM_MTK_DISP is not set -CONFIG_PWM_SYSFS=y -CONFIG_QUEUED_RWLOCKS=y -CONFIG_QUEUED_SPINLOCKS=y -CONFIG_RAS=y -CONFIG_RATIONAL=y -# CONFIG_RAVE_SP_CORE is not set -CONFIG_REALTEK_PHY=y -CONFIG_REED_SOLOMON=y -CONFIG_REED_SOLOMON_DEC8=y -CONFIG_REED_SOLOMON_ENC8=y -CONFIG_REGMAP=y -CONFIG_REGMAP_MMIO=y -CONFIG_REGULATOR=y -CONFIG_REGULATOR_FIXED_VOLTAGE=y -CONFIG_REGULATOR_MT6380=y -# CONFIG_REGULATOR_RT5190A is not set -CONFIG_RESET_CONTROLLER=y -CONFIG_RFS_ACCEL=y -CONFIG_RODATA_FULL_DEFAULT_ENABLED=y -CONFIG_RPS=y -CONFIG_RTC_CLASS=y -CONFIG_RTC_DRV_MT7622=y -CONFIG_RTC_I2C_AND_SPI=y -CONFIG_RTL8367S_GSW=y -CONFIG_RWSEM_SPIN_ON_OWNER=y -CONFIG_SCHED_MC=y -CONFIG_SCSI=y -CONFIG_SCSI_COMMON=y -# CONFIG_SECTION_MISMATCH_WARN_ONLY is not set -CONFIG_SERIAL_8250_FSL=y -CONFIG_SERIAL_8250_MT6577=y -CONFIG_SERIAL_8250_NR_UARTS=3 -CONFIG_SERIAL_8250_RUNTIME_UARTS=3 -CONFIG_SERIAL_DEV_BUS=y -CONFIG_SERIAL_DEV_CTRL_TTYPORT=y -CONFIG_SERIAL_MCTRL_GPIO=y -CONFIG_SERIAL_OF_PLATFORM=y -CONFIG_SGL_ALLOC=y -CONFIG_SG_POOL=y -CONFIG_SMP=y -CONFIG_SOCK_RX_QUEUE_MAPPING=y -CONFIG_SPARSEMEM=y -CONFIG_SPARSEMEM_EXTREME=y -CONFIG_SPARSEMEM_VMEMMAP=y -CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y -CONFIG_SPARSE_IRQ=y -CONFIG_SPI=y -CONFIG_SPI_DYNAMIC=y -CONFIG_SPI_MASTER=y -CONFIG_SPI_MEM=y -CONFIG_SPI_MT65XX=y -CONFIG_SPI_MTK_NOR=y -CONFIG_SPI_MTK_SNFI=y -CONFIG_SRCU=y -CONFIG_SWCONFIG=y -CONFIG_SWIOTLB=y -CONFIG_SWPHY=y -CONFIG_SYSCTL_EXCEPTION_TRACE=y -CONFIG_SYSVIPC_COMPAT=y -CONFIG_THERMAL=y -CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y -CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0 -CONFIG_THERMAL_EMULATION=y -CONFIG_THERMAL_GOV_BANG_BANG=y -CONFIG_THERMAL_GOV_FAIR_SHARE=y -CONFIG_THERMAL_GOV_STEP_WISE=y -CONFIG_THERMAL_GOV_USER_SPACE=y -CONFIG_THERMAL_OF=y -CONFIG_THERMAL_WRITABLE_TRIPS=y -CONFIG_THREAD_INFO_IN_TASK=y -CONFIG_TICK_CPU_ACCOUNTING=y -CONFIG_TIMER_OF=y -CONFIG_TIMER_PROBE=y -CONFIG_TREE_RCU=y -CONFIG_TREE_SRCU=y -CONFIG_UBIFS_FS=y -# CONFIG_UCLAMP_TASK is not set -# CONFIG_UNMAP_KERNEL_AT_EL0 is not set -CONFIG_USB_SUPPORT=y -CONFIG_VMAP_STACK=y -CONFIG_WATCHDOG_CORE=y -CONFIG_WATCHDOG_PRETIMEOUT_DEFAULT_GOV_PANIC=y -CONFIG_WATCHDOG_PRETIMEOUT_GOV=y -# CONFIG_WATCHDOG_PRETIMEOUT_GOV_NOOP is not set -CONFIG_WATCHDOG_PRETIMEOUT_GOV_PANIC=y -CONFIG_WATCHDOG_PRETIMEOUT_GOV_SEL=m -CONFIG_WATCHDOG_SYSFS=y -CONFIG_XPS=y -CONFIG_XXHASH=y -CONFIG_ZLIB_DEFLATE=y -CONFIG_ZLIB_INFLATE=y -CONFIG_ZONE_DMA32=y -CONFIG_ZSTD_COMPRESS=y -CONFIG_ZSTD_DECOMPRESS=y diff --git a/target/linux/mediatek/mt7622/config-6.1 b/target/linux/mediatek/mt7622/config-6.1 deleted file mode 100644 index 7055e4d72..000000000 --- a/target/linux/mediatek/mt7622/config-6.1 +++ /dev/null @@ -1,472 +0,0 @@ -CONFIG_64BIT=y -# CONFIG_AHCI_MTK is not set -CONFIG_AQUANTIA_PHY=y -CONFIG_ARCH_BINFMT_ELF_EXTRA_PHDRS=y -CONFIG_ARCH_CORRECT_STACKTRACE_ON_KRETPROBE=y -CONFIG_ARCH_DMA_ADDR_T_64BIT=y -CONFIG_ARCH_FORCE_MAX_ORDER=11 -CONFIG_ARCH_KEEP_MEMBLOCK=y -CONFIG_ARCH_MEDIATEK=y -CONFIG_ARCH_MHP_MEMMAP_ON_MEMORY_ENABLE=y -CONFIG_ARCH_MMAP_RND_BITS=18 -CONFIG_ARCH_MMAP_RND_BITS_MAX=24 -CONFIG_ARCH_MMAP_RND_BITS_MIN=18 -CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=11 -CONFIG_ARCH_NR_GPIO=0 -CONFIG_ARCH_PROC_KCORE_TEXT=y -CONFIG_ARCH_SPARSEMEM_ENABLE=y -CONFIG_ARCH_STACKWALK=y -CONFIG_ARCH_SUSPEND_POSSIBLE=y -CONFIG_ARCH_WANTS_NO_INSTR=y -CONFIG_ARCH_WANTS_THP_SWAP=y -CONFIG_ARM64=y -CONFIG_ARM64_4K_PAGES=y -CONFIG_ARM64_ERRATUM_843419=y -CONFIG_ARM64_LD_HAS_FIX_ERRATUM_843419=y -CONFIG_ARM64_PAGE_SHIFT=12 -CONFIG_ARM64_PA_BITS=48 -CONFIG_ARM64_PA_BITS_48=y -CONFIG_ARM64_TAGGED_ADDR_ABI=y -CONFIG_ARM64_VA_BITS=39 -CONFIG_ARM64_VA_BITS_39=y -CONFIG_ARM_AMBA=y -CONFIG_ARM_ARCH_TIMER=y -CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y -CONFIG_ARM_GIC=y -CONFIG_ARM_GIC_V2M=y -CONFIG_ARM_GIC_V3=y -CONFIG_ARM_GIC_V3_ITS=y -CONFIG_ARM_GIC_V3_ITS_PCI=y -CONFIG_ARM_MEDIATEK_CPUFREQ=y -CONFIG_ARM_PMU=y -CONFIG_ARM_PSCI_FW=y -CONFIG_ATA=y -CONFIG_AUDIT_ARCH_COMPAT_GENERIC=y -CONFIG_BLK_DEV_LOOP=y -CONFIG_BLK_DEV_SD=y -CONFIG_BLK_MQ_PCI=y -CONFIG_BLK_PM=y -CONFIG_BSD_PROCESS_ACCT=y -CONFIG_BSD_PROCESS_ACCT_V3=y -CONFIG_CC_HAVE_SHADOW_CALL_STACK=y -CONFIG_CC_HAVE_STACKPROTECTOR_SYSREG=y -CONFIG_CC_IMPLICIT_FALLTHROUGH="-Wimplicit-fallthrough=5" -CONFIG_CC_NO_ARRAY_BOUNDS=y -CONFIG_CLKSRC_MMIO=y -CONFIG_CLONE_BACKWARDS=y -# CONFIG_CMDLINE_OVERRIDE is not set -CONFIG_COMMON_CLK=y -CONFIG_COMMON_CLK_MEDIATEK=y -CONFIG_COMMON_CLK_MT2712=y -# CONFIG_COMMON_CLK_MT2712_BDPSYS is not set -# CONFIG_COMMON_CLK_MT2712_IMGSYS is not set -# CONFIG_COMMON_CLK_MT2712_JPGDECSYS is not set -# CONFIG_COMMON_CLK_MT2712_MFGCFG is not set -# CONFIG_COMMON_CLK_MT2712_MMSYS is not set -# CONFIG_COMMON_CLK_MT2712_VDECSYS is not set -# CONFIG_COMMON_CLK_MT2712_VENCSYS is not set -# CONFIG_COMMON_CLK_MT6779 is not set -# CONFIG_COMMON_CLK_MT6795 is not set -# CONFIG_COMMON_CLK_MT6797 is not set -CONFIG_COMMON_CLK_MT7622=y -CONFIG_COMMON_CLK_MT7622_AUDSYS=y -CONFIG_COMMON_CLK_MT7622_ETHSYS=y -CONFIG_COMMON_CLK_MT7622_HIFSYS=y -# CONFIG_COMMON_CLK_MT7981 is not set -# CONFIG_COMMON_CLK_MT7986 is not set -# CONFIG_COMMON_CLK_MT7988 is not set -# CONFIG_COMMON_CLK_MT8173 is not set -# CONFIG_COMMON_CLK_MT8183 is not set -# CONFIG_COMMON_CLK_MT8186 is not set -# CONFIG_COMMON_CLK_MT8195 is not set -# CONFIG_COMMON_CLK_MT8365 is not set -# CONFIG_COMMON_CLK_MT8516 is not set -CONFIG_COMPACT_UNEVICTABLE_DEFAULT=1 -CONFIG_COMPAT_32BIT_TIME=y -CONFIG_CONFIGFS_FS=y -CONFIG_CONSOLE_LOGLEVEL_DEFAULT=15 -CONFIG_CONTEXT_TRACKING=y -CONFIG_CONTEXT_TRACKING_IDLE=y -# CONFIG_CPUFREQ_DT is not set -CONFIG_CPU_FREQ=y -CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y -# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set -CONFIG_CPU_FREQ_GOV_ATTR_SET=y -CONFIG_CPU_FREQ_GOV_COMMON=y -CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y -CONFIG_CPU_FREQ_GOV_ONDEMAND=y -CONFIG_CPU_FREQ_GOV_PERFORMANCE=y -CONFIG_CPU_FREQ_GOV_POWERSAVE=y -CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y -CONFIG_CPU_FREQ_GOV_USERSPACE=y -CONFIG_CPU_FREQ_STAT=y -CONFIG_CPU_LITTLE_ENDIAN=y -CONFIG_CPU_RMAP=y -CONFIG_CPU_THERMAL=y -CONFIG_CRC16=y -CONFIG_CRYPTO_AES_ARM64=y -CONFIG_CRYPTO_AES_ARM64_CE=y -CONFIG_CRYPTO_AES_ARM64_CE_BLK=y -CONFIG_CRYPTO_AES_ARM64_CE_CCM=y -CONFIG_CRYPTO_CMAC=y -CONFIG_CRYPTO_CRC32=y -CONFIG_CRYPTO_CRC32C=y -CONFIG_CRYPTO_CRYPTD=y -CONFIG_CRYPTO_DEFLATE=y -CONFIG_CRYPTO_DRBG=y -CONFIG_CRYPTO_DRBG_HMAC=y -CONFIG_CRYPTO_DRBG_MENU=y -CONFIG_CRYPTO_ECB=y -CONFIG_CRYPTO_ECC=y -CONFIG_CRYPTO_ECDH=y -CONFIG_CRYPTO_GHASH_ARM64_CE=y -CONFIG_CRYPTO_HASH_INFO=y -CONFIG_CRYPTO_HMAC=y -CONFIG_CRYPTO_JITTERENTROPY=y -CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y -CONFIG_CRYPTO_LIB_SHA1=y -CONFIG_CRYPTO_LIB_SHA256=y -CONFIG_CRYPTO_LIB_UTILS=y -CONFIG_CRYPTO_LZO=y -CONFIG_CRYPTO_RNG=y -CONFIG_CRYPTO_RNG2=y -CONFIG_CRYPTO_RNG_DEFAULT=y -CONFIG_CRYPTO_SHA256=y -CONFIG_CRYPTO_SHA256_ARM64=y -CONFIG_CRYPTO_SHA2_ARM64_CE=y -CONFIG_CRYPTO_SHA512=y -CONFIG_CRYPTO_ZSTD=y -CONFIG_DCACHE_WORD_ACCESS=y -CONFIG_DEBUG_INFO=y -CONFIG_DEBUG_MISC=y -CONFIG_DIMLIB=y -CONFIG_DMADEVICES=y -CONFIG_DMA_DIRECT_REMAP=y -CONFIG_DMA_ENGINE=y -CONFIG_DMA_OF=y -CONFIG_DMA_VIRTUAL_CHANNELS=y -CONFIG_DTC=y -CONFIG_EDAC_SUPPORT=y -CONFIG_EINT_MTK=y -CONFIG_EXCLUSIVE_SYSTEM_RAM=y -CONFIG_EXT4_FS=y -CONFIG_F2FS_FS=y -CONFIG_FIT_PARTITION=y -CONFIG_FIXED_PHY=y -CONFIG_FIX_EARLYCON_MEM=y -CONFIG_FRAME_POINTER=y -CONFIG_FRAME_WARN=2048 -CONFIG_FS_IOMAP=y -CONFIG_FS_MBCACHE=y -CONFIG_FWNODE_MDIO=y -CONFIG_FW_LOADER_PAGED_BUF=y -CONFIG_FW_LOADER_SYSFS=y -CONFIG_GCC11_NO_ARRAY_BOUNDS=y -CONFIG_GCC_SUPPORTS_DYNAMIC_FTRACE_WITH_REGS=y -CONFIG_GENERIC_ALLOCATOR=y -CONFIG_GENERIC_ARCH_TOPOLOGY=y -CONFIG_GENERIC_BUG=y -CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y -CONFIG_GENERIC_CLOCKEVENTS=y -CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y -CONFIG_GENERIC_CPU_AUTOPROBE=y -CONFIG_GENERIC_CPU_VULNERABILITIES=y -CONFIG_GENERIC_CSUM=y -CONFIG_GENERIC_EARLY_IOREMAP=y -CONFIG_GENERIC_GETTIMEOFDAY=y -CONFIG_GENERIC_IDLE_POLL_SETUP=y -CONFIG_GENERIC_IOREMAP=y -CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y -CONFIG_GENERIC_IRQ_SHOW=y -CONFIG_GENERIC_IRQ_SHOW_LEVEL=y -CONFIG_GENERIC_LIB_DEVMEM_IS_ALLOWED=y -CONFIG_GENERIC_MSI_IRQ=y -CONFIG_GENERIC_MSI_IRQ_DOMAIN=y -CONFIG_GENERIC_PCI_IOMAP=y -CONFIG_GENERIC_PHY=y -CONFIG_GENERIC_PINCONF=y -CONFIG_GENERIC_PINCTRL_GROUPS=y -CONFIG_GENERIC_PINMUX_FUNCTIONS=y -CONFIG_GENERIC_SCHED_CLOCK=y -CONFIG_GENERIC_SMP_IDLE_THREAD=y -CONFIG_GENERIC_STRNCPY_FROM_USER=y -CONFIG_GENERIC_STRNLEN_USER=y -CONFIG_GENERIC_TIME_VSYSCALL=y -CONFIG_GLOB=y -CONFIG_GPIO_CDEV=y -CONFIG_GRO_CELLS=y -CONFIG_HARDIRQS_SW_RESEND=y -CONFIG_HAS_DMA=y -CONFIG_HAS_IOMEM=y -CONFIG_HAS_IOPORT_MAP=y -CONFIG_HW_RANDOM=y -CONFIG_HW_RANDOM_MTK=y -CONFIG_I2C=y -CONFIG_I2C_BOARDINFO=y -CONFIG_I2C_CHARDEV=y -CONFIG_I2C_MT65XX=y -CONFIG_ICPLUS_PHY=y -CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000 -CONFIG_INITRAMFS_SOURCE="" -CONFIG_IRQCHIP=y -CONFIG_IRQ_DOMAIN=y -CONFIG_IRQ_DOMAIN_HIERARCHY=y -CONFIG_IRQ_FORCED_THREADING=y -CONFIG_IRQ_TIME_ACCOUNTING=y -CONFIG_IRQ_WORK=y -CONFIG_JBD2=y -CONFIG_JUMP_LABEL=y -CONFIG_LIBFDT=y -CONFIG_LOCK_DEBUGGING_SUPPORT=y -CONFIG_LOCK_SPIN_ON_OWNER=y -CONFIG_LZO_COMPRESS=y -CONFIG_LZO_DECOMPRESS=y -CONFIG_MAGIC_SYSRQ=y -CONFIG_MAXLINEAR_GPHY=y -CONFIG_MDIO_BUS=y -CONFIG_MDIO_DEVICE=y -CONFIG_MDIO_DEVRES=y -# CONFIG_MEDIATEK_2P5G_PHY is not set -CONFIG_MEDIATEK_GE_PHY=y -# CONFIG_MEDIATEK_GE_SOC_PHY is not set -CONFIG_MEDIATEK_WATCHDOG=y -CONFIG_MEMFD_CREATE=y -CONFIG_MESSAGE_LOGLEVEL_DEFAULT=7 -CONFIG_MFD_SYSCON=y -CONFIG_MIGRATION=y -CONFIG_MMC=y -CONFIG_MMC_BLOCK=y -CONFIG_MMC_CQHCI=y -CONFIG_MMC_MTK=y -CONFIG_MODULES_TREE_LOOKUP=y -CONFIG_MODULES_USE_ELF_RELA=y -CONFIG_MTD_NAND_CORE=y -CONFIG_MTD_NAND_ECC=y -CONFIG_MTD_NAND_ECC_MEDIATEK=y -CONFIG_MTD_NAND_ECC_SW_HAMMING=y -CONFIG_MTD_NAND_MTK=y -CONFIG_MTD_NAND_MTK_BMT=y -CONFIG_MTD_PARSER_TRX=y -CONFIG_MTD_RAW_NAND=y -CONFIG_MTD_SPI_NAND=y -CONFIG_MTD_SPI_NOR=y -CONFIG_MTD_SPI_NOR_USE_VARIABLE_ERASE=y -CONFIG_MTD_SPLIT_FIRMWARE=y -CONFIG_MTD_SPLIT_FIT_FW=y -CONFIG_MTD_UBI=y -CONFIG_MTD_UBI_BEB_LIMIT=20 -CONFIG_MTD_UBI_BLOCK=y -CONFIG_MTD_UBI_FASTMAP=y -CONFIG_MTD_UBI_WL_THRESHOLD=4096 -# CONFIG_MTK_CMDQ is not set -# CONFIG_MTK_CQDMA is not set -CONFIG_MTK_HSDMA=y -CONFIG_MTK_INFRACFG=y -CONFIG_MTK_PMIC_WRAP=y -CONFIG_MTK_SCPSYS=y -CONFIG_MTK_SCPSYS_PM_DOMAINS=y -# CONFIG_MTK_SVS is not set -CONFIG_MTK_THERMAL=y -CONFIG_MTK_TIMER=y -# CONFIG_MTK_UART_APDMA is not set -CONFIG_MUTEX_SPIN_ON_OWNER=y -CONFIG_NEED_DMA_MAP_STATE=y -CONFIG_NEED_SG_DMA_LENGTH=y -CONFIG_NET_DEVLINK=y -CONFIG_NET_DSA=y -CONFIG_NET_DSA_MT7530=y -CONFIG_NET_DSA_MT7530_MDIO=y -# CONFIG_NET_DSA_MT7530_MMIO is not set -CONFIG_NET_DSA_TAG_MTK=y -CONFIG_NET_FLOW_LIMIT=y -CONFIG_NET_MEDIATEK_SOC=y -# CONFIG_NET_MEDIATEK_SOC_USXGMII is not set -CONFIG_NET_MEDIATEK_SOC_WED=y -CONFIG_NET_SELFTESTS=y -CONFIG_NET_SWITCHDEV=y -CONFIG_NET_VENDOR_MEDIATEK=y -CONFIG_NLS=y -CONFIG_NO_HZ_COMMON=y -CONFIG_NO_HZ_IDLE=y -CONFIG_NR_CPUS=2 -CONFIG_NVMEM=y -CONFIG_NVMEM_MTK_EFUSE=y -CONFIG_NVMEM_SYSFS=y -CONFIG_OF=y -CONFIG_OF_ADDRESS=y -CONFIG_OF_DYNAMIC=y -CONFIG_OF_EARLY_FLATTREE=y -CONFIG_OF_FLATTREE=y -CONFIG_OF_GPIO=y -CONFIG_OF_IRQ=y -CONFIG_OF_KOBJ=y -CONFIG_OF_MDIO=y -CONFIG_OF_OVERLAY=y -CONFIG_OF_RESOLVE=y -CONFIG_PADATA=y -CONFIG_PAGE_POOL=y -CONFIG_PAGE_POOL_STATS=y -CONFIG_PAGE_SIZE_LESS_THAN_256KB=y -CONFIG_PAGE_SIZE_LESS_THAN_64KB=y -CONFIG_PARTITION_PERCPU=y -CONFIG_PCI=y -CONFIG_PCIEAER=y -CONFIG_PCIEASPM=y -# CONFIG_PCIEASPM_DEFAULT is not set -CONFIG_PCIEASPM_PERFORMANCE=y -# CONFIG_PCIEASPM_POWERSAVE is not set -# CONFIG_PCIEASPM_POWER_SUPERSAVE is not set -CONFIG_PCIEPORTBUS=y -CONFIG_PCIE_MEDIATEK=y -CONFIG_PCIE_PME=y -CONFIG_PCI_DEBUG=y -CONFIG_PCI_DOMAINS=y -CONFIG_PCI_DOMAINS_GENERIC=y -CONFIG_PCI_MSI=y -CONFIG_PCI_MSI_IRQ_DOMAIN=y -CONFIG_PCS_MTK_LYNXI=y -CONFIG_PERF_EVENTS=y -CONFIG_PGTABLE_LEVELS=3 -CONFIG_PHYLIB=y -CONFIG_PHYLINK=y -CONFIG_PHYS_ADDR_T_64BIT=y -# CONFIG_PHY_MTK_DP is not set -# CONFIG_PHY_MTK_PCIE is not set -CONFIG_PHY_MTK_TPHY=y -# CONFIG_PHY_MTK_UFS is not set -# CONFIG_PHY_MTK_XSPHY is not set -CONFIG_PINCTRL=y -# CONFIG_PINCTRL_MT2712 is not set -# CONFIG_PINCTRL_MT6765 is not set -# CONFIG_PINCTRL_MT6795 is not set -# CONFIG_PINCTRL_MT6797 is not set -CONFIG_PINCTRL_MT7622=y -# CONFIG_PINCTRL_MT7981 is not set -# CONFIG_PINCTRL_MT7986 is not set -# CONFIG_PINCTRL_MT7988 is not set -# CONFIG_PINCTRL_MT8173 is not set -# CONFIG_PINCTRL_MT8183 is not set -# CONFIG_PINCTRL_MT8186 is not set -# CONFIG_PINCTRL_MT8188 is not set -# CONFIG_PINCTRL_MT8516 is not set -CONFIG_PINCTRL_MTK_MOORE=y -CONFIG_PINCTRL_MTK_V2=y -CONFIG_PM=y -CONFIG_PM_CLK=y -CONFIG_PM_GENERIC_DOMAINS=y -CONFIG_PM_GENERIC_DOMAINS_OF=y -CONFIG_PM_OPP=y -CONFIG_POSIX_CPU_TIMERS_TASK_WORK=y -CONFIG_POWER_RESET=y -CONFIG_POWER_RESET_SYSCON=y -CONFIG_POWER_SUPPLY=y -CONFIG_PREEMPT_NONE_BUILD=y -CONFIG_PRINTK_TIME=y -CONFIG_PSTORE=y -CONFIG_PSTORE_COMPRESS=y -CONFIG_PSTORE_COMPRESS_DEFAULT="deflate" -CONFIG_PSTORE_CONSOLE=y -CONFIG_PSTORE_DEFLATE_COMPRESS=y -CONFIG_PSTORE_DEFLATE_COMPRESS_DEFAULT=y -CONFIG_PSTORE_PMSG=y -CONFIG_PSTORE_RAM=y -CONFIG_PTP_1588_CLOCK_OPTIONAL=y -CONFIG_PWM=y -CONFIG_PWM_MEDIATEK=y -# CONFIG_PWM_MTK_DISP is not set -CONFIG_PWM_SYSFS=y -CONFIG_QUEUED_RWLOCKS=y -CONFIG_QUEUED_SPINLOCKS=y -CONFIG_RANDSTRUCT_NONE=y -CONFIG_RAS=y -CONFIG_RATIONAL=y -# CONFIG_RAVE_SP_CORE is not set -CONFIG_REALTEK_PHY=y -CONFIG_REED_SOLOMON=y -CONFIG_REED_SOLOMON_DEC8=y -CONFIG_REED_SOLOMON_ENC8=y -CONFIG_REGMAP=y -CONFIG_REGMAP_MMIO=y -CONFIG_REGULATOR=y -CONFIG_REGULATOR_FIXED_VOLTAGE=y -CONFIG_REGULATOR_MT6380=y -CONFIG_RESET_CONTROLLER=y -CONFIG_RFS_ACCEL=y -CONFIG_RODATA_FULL_DEFAULT_ENABLED=y -CONFIG_RPS=y -CONFIG_RTC_CLASS=y -CONFIG_RTC_DRV_MT7622=y -CONFIG_RTC_I2C_AND_SPI=y -CONFIG_RTL8367S_GSW=y -CONFIG_RWSEM_SPIN_ON_OWNER=y -CONFIG_SCHED_MC=y -CONFIG_SCSI=y -CONFIG_SCSI_COMMON=y -# CONFIG_SECTION_MISMATCH_WARN_ONLY is not set -CONFIG_SERIAL_8250_FSL=y -CONFIG_SERIAL_8250_MT6577=y -CONFIG_SERIAL_8250_NR_UARTS=3 -CONFIG_SERIAL_8250_RUNTIME_UARTS=3 -CONFIG_SERIAL_DEV_BUS=y -CONFIG_SERIAL_DEV_CTRL_TTYPORT=y -CONFIG_SERIAL_MCTRL_GPIO=y -CONFIG_SERIAL_OF_PLATFORM=y -CONFIG_SGL_ALLOC=y -CONFIG_SG_POOL=y -CONFIG_SMP=y -CONFIG_SOCK_RX_QUEUE_MAPPING=y -CONFIG_SOFTIRQ_ON_OWN_STACK=y -CONFIG_SPARSEMEM=y -CONFIG_SPARSEMEM_EXTREME=y -CONFIG_SPARSEMEM_VMEMMAP=y -CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y -CONFIG_SPARSE_IRQ=y -CONFIG_SPI=y -CONFIG_SPI_DYNAMIC=y -CONFIG_SPI_MASTER=y -CONFIG_SPI_MEM=y -CONFIG_SPI_MT65XX=y -CONFIG_SPI_MTK_NOR=y -CONFIG_SPI_MTK_SNFI=y -CONFIG_SRCU=y -CONFIG_SWCONFIG=y -CONFIG_SWIOTLB=y -CONFIG_SWPHY=y -CONFIG_SYSCTL_EXCEPTION_TRACE=y -CONFIG_THERMAL=y -CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y -CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0 -CONFIG_THERMAL_EMULATION=y -CONFIG_THERMAL_GOV_BANG_BANG=y -CONFIG_THERMAL_GOV_FAIR_SHARE=y -CONFIG_THERMAL_GOV_STEP_WISE=y -CONFIG_THERMAL_GOV_USER_SPACE=y -CONFIG_THERMAL_OF=y -CONFIG_THERMAL_WRITABLE_TRIPS=y -CONFIG_THREAD_INFO_IN_TASK=y -CONFIG_TICK_CPU_ACCOUNTING=y -CONFIG_TIMER_OF=y -CONFIG_TIMER_PROBE=y -CONFIG_TRACE_IRQFLAGS_NMI_SUPPORT=y -CONFIG_TREE_RCU=y -CONFIG_TREE_SRCU=y -CONFIG_UBIFS_FS=y -# CONFIG_UCLAMP_TASK is not set -# CONFIG_UNMAP_KERNEL_AT_EL0 is not set -CONFIG_USB_SUPPORT=y -CONFIG_VMAP_STACK=y -CONFIG_WATCHDOG_CORE=y -CONFIG_WATCHDOG_PRETIMEOUT_DEFAULT_GOV_PANIC=y -CONFIG_WATCHDOG_PRETIMEOUT_GOV=y -# CONFIG_WATCHDOG_PRETIMEOUT_GOV_NOOP is not set -CONFIG_WATCHDOG_PRETIMEOUT_GOV_PANIC=y -CONFIG_WATCHDOG_PRETIMEOUT_GOV_SEL=m -CONFIG_WATCHDOG_SYSFS=y -CONFIG_XPS=y -CONFIG_XXHASH=y -CONFIG_ZLIB_DEFLATE=y -CONFIG_ZLIB_INFLATE=y -CONFIG_ZONE_DMA32=y -CONFIG_ZSTD_COMMON=y -CONFIG_ZSTD_COMPRESS=y -CONFIG_ZSTD_DECOMPRESS=y diff --git a/target/linux/mediatek/mt7622/target.mk b/target/linux/mediatek/mt7622/target.mk index b1c67f46f..ea0e22e31 100644 --- a/target/linux/mediatek/mt7622/target.mk +++ b/target/linux/mediatek/mt7622/target.mk @@ -2,7 +2,7 @@ ARCH:=aarch64 SUBTARGET:=mt7622 BOARDNAME:=MT7622 CPU_TYPE:=cortex-a53 -DEFAULT_PACKAGES += kmod-mt7622-firmware wpad-openssl uboot-envtools +DEFAULT_PACKAGES += fitblk kmod-mt7622-firmware wpad-basic-mbedtls uboot-envtools KERNELNAME:=Image dtbs define Target/Description diff --git a/target/linux/mediatek/mt7623/base-files/etc/board.d/05_compat-version b/target/linux/mediatek/mt7623/base-files/etc/board.d/05_compat-version new file mode 100644 index 000000000..a4cf133a6 --- /dev/null +++ b/target/linux/mediatek/mt7623/base-files/etc/board.d/05_compat-version @@ -0,0 +1,14 @@ +. /lib/functions.sh +. /lib/functions/uci-defaults.sh + +board_config_update + +case "$(board_name)" in +bananapi,bpi-r2) + ucidef_set_compat_version "1.1" + ;; +esac + +board_config_flush + +exit 0 diff --git a/target/linux/mediatek/mt7623/base-files/etc/uci-defaults/05_fix-compat-version b/target/linux/mediatek/mt7623/base-files/etc/uci-defaults/05_fix-compat-version new file mode 100644 index 000000000..ae3f16002 --- /dev/null +++ b/target/linux/mediatek/mt7623/base-files/etc/uci-defaults/05_fix-compat-version @@ -0,0 +1,10 @@ +. /lib/functions.sh + +case "$(board_name)" in +bananapi,bpi-r2) + uci set system.@system[0].compat_version="1.1" + uci commit system + ;; +esac + +exit 0 diff --git a/target/linux/mediatek/mt7623/base-files/lib/upgrade/platform.sh b/target/linux/mediatek/mt7623/base-files/lib/upgrade/platform.sh index 5d12b6989..9cfb15cf3 100755 --- a/target/linux/mediatek/mt7623/base-files/lib/upgrade/platform.sh +++ b/target/linux/mediatek/mt7623/base-files/lib/upgrade/platform.sh @@ -83,10 +83,10 @@ platform_do_upgrade() { case "$board" in bananapi,bpi-r2|\ unielec,u7623-02) - export_bootdevice - export_partdevice fitpart 3 - [ "$fitpart" ] || return 1 - EMMC_KERN_DEV="/dev/$fitpart" + [ -e /dev/fit0 ] && fitblk /dev/fit0 + [ -e /dev/fitrw ] && fitblk /dev/fitrw + bootdev="$(fitblk_get_bootdev)" + EMMC_KERN_DEV="/dev/$bootdev" emmc_do_upgrade "$1" ;; unielec,u7623-02-emmc-512m) diff --git a/target/linux/mediatek/mt7623/config-5.15 b/target/linux/mediatek/mt7623/config-5.15 deleted file mode 100644 index 5ae596d41..000000000 --- a/target/linux/mediatek/mt7623/config-5.15 +++ /dev/null @@ -1,579 +0,0 @@ -# CONFIG_AIO is not set -CONFIG_ALIGNMENT_TRAP=y -CONFIG_ARCH_32BIT_OFF_T=y -CONFIG_ARCH_HIBERNATION_POSSIBLE=y -CONFIG_ARCH_KEEP_MEMBLOCK=y -CONFIG_ARCH_MEDIATEK=y -CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y -CONFIG_ARCH_MULTIPLATFORM=y -CONFIG_ARCH_MULTI_V6_V7=y -CONFIG_ARCH_MULTI_V7=y -CONFIG_ARCH_NR_GPIO=0 -CONFIG_ARCH_OPTIONAL_KERNEL_RWX=y -CONFIG_ARCH_OPTIONAL_KERNEL_RWX_DEFAULT=y -CONFIG_ARCH_SELECT_MEMORY_MODEL=y -CONFIG_ARCH_SPARSEMEM_ENABLE=y -CONFIG_ARCH_SUSPEND_POSSIBLE=y -CONFIG_ARM=y -CONFIG_ARM_APPENDED_DTB=y -CONFIG_ARM_ARCH_TIMER=y -CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y -# CONFIG_ARM_ATAG_DTB_COMPAT is not set -CONFIG_ARM_CPU_SUSPEND=y -# CONFIG_ARM_CPU_TOPOLOGY is not set -CONFIG_ARM_CRYPTO=y -CONFIG_ARM_DMA_IOMMU_ALIGNMENT=8 -CONFIG_ARM_DMA_USE_IOMMU=y -CONFIG_ARM_GIC=y -CONFIG_ARM_HAS_SG_CHAIN=y -CONFIG_ARM_L1_CACHE_SHIFT=6 -CONFIG_ARM_L1_CACHE_SHIFT_6=y -CONFIG_ARM_MEDIATEK_CPUFREQ=y -CONFIG_ARM_PATCH_IDIV=y -CONFIG_ARM_PATCH_PHYS_VIRT=y -# CONFIG_ARM_SMMU is not set -CONFIG_ARM_THUMB=y -CONFIG_ARM_THUMBEE=y -CONFIG_ARM_UNWIND=y -CONFIG_ARM_VIRT_EXT=y -CONFIG_ASYNC_TX_ENABLE_CHANNEL_SWITCH=y -CONFIG_ATAGS=y -CONFIG_AUTO_ZRELADDR=y -CONFIG_BACKLIGHT_CLASS_DEVICE=y -CONFIG_BACKLIGHT_GPIO=y -CONFIG_BACKLIGHT_LED=y -CONFIG_BACKLIGHT_PWM=y -CONFIG_BINFMT_FLAT_ARGVP_ENVP_ON_STACK=y -CONFIG_BLK_DEV_LOOP=y -CONFIG_BLK_MQ_PCI=y -CONFIG_BLK_PM=y -CONFIG_BOUNCE=y -# CONFIG_CACHE_L2X0 is not set -CONFIG_CLEANCACHE=y -CONFIG_CLKSRC_MMIO=y -CONFIG_CLONE_BACKWARDS=y -CONFIG_CMDLINE="earlyprintk console=ttyS0,115200 rootfstype=squashfs,jffs2" -CONFIG_CMDLINE_FROM_BOOTLOADER=y -# CONFIG_CMDLINE_OVERRIDE is not set -CONFIG_CMDLINE_PARTITION=y -CONFIG_COMMON_CLK=y -CONFIG_COMMON_CLK_MEDIATEK=y -CONFIG_COMMON_CLK_MT2701=y -CONFIG_COMMON_CLK_MT2701_AUDSYS=y -CONFIG_COMMON_CLK_MT2701_BDPSYS=y -CONFIG_COMMON_CLK_MT2701_ETHSYS=y -CONFIG_COMMON_CLK_MT2701_G3DSYS=y -CONFIG_COMMON_CLK_MT2701_HIFSYS=y -CONFIG_COMMON_CLK_MT2701_IMGSYS=y -CONFIG_COMMON_CLK_MT2701_MMSYS=y -CONFIG_COMMON_CLK_MT2701_VDECSYS=y -# CONFIG_COMMON_CLK_MT7622 is not set -# CONFIG_COMMON_CLK_MT7629 is not set -# CONFIG_COMMON_CLK_MT7981 is not set -# CONFIG_COMMON_CLK_MT7986 is not set -# CONFIG_COMMON_CLK_MT7988 is not set -# CONFIG_COMMON_CLK_MT8135 is not set -# CONFIG_COMMON_CLK_MT8173 is not set -CONFIG_COMMON_CLK_MT8516=y -# CONFIG_COMMON_CLK_MT8516_AUDSYS is not set -CONFIG_COMPAT_32BIT_TIME=y -CONFIG_CONFIGFS_FS=y -CONFIG_CONSOLE_TRANSLATIONS=y -CONFIG_COREDUMP=y -# CONFIG_CPUFREQ_DT is not set -CONFIG_CPU_32v6K=y -CONFIG_CPU_32v7=y -CONFIG_CPU_ABRT_EV7=y -CONFIG_CPU_CACHE_V7=y -CONFIG_CPU_CACHE_VIPT=y -CONFIG_CPU_COPY_V6=y -CONFIG_CPU_CP15=y -CONFIG_CPU_CP15_MMU=y -CONFIG_CPU_FREQ=y -CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y -CONFIG_CPU_FREQ_GOV_ATTR_SET=y -CONFIG_CPU_FREQ_GOV_COMMON=y -CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y -CONFIG_CPU_FREQ_GOV_ONDEMAND=y -CONFIG_CPU_FREQ_GOV_PERFORMANCE=y -CONFIG_CPU_FREQ_GOV_POWERSAVE=y -# CONFIG_CPU_FREQ_GOV_USERSPACE is not set -CONFIG_CPU_FREQ_STAT=y -CONFIG_CPU_HAS_ASID=y -CONFIG_CPU_PABRT_V7=y -CONFIG_CPU_PM=y -CONFIG_CPU_RMAP=y -CONFIG_CPU_SPECTRE=y -CONFIG_CPU_THUMB_CAPABLE=y -CONFIG_CPU_TLB_V7=y -CONFIG_CPU_V7=y -CONFIG_CRC16=y -# CONFIG_CRC32_SARWATE is not set -CONFIG_CRC32_SLICEBY8=y -CONFIG_CROSS_MEMORY_ATTACH=y -CONFIG_CRYPTO_CRC32=y -CONFIG_CRYPTO_CRC32C=y -CONFIG_CRYPTO_DEFLATE=y -CONFIG_CRYPTO_DRBG=y -CONFIG_CRYPTO_DRBG_HMAC=y -CONFIG_CRYPTO_DRBG_MENU=y -CONFIG_CRYPTO_HASH_INFO=y -CONFIG_CRYPTO_HMAC=y -CONFIG_CRYPTO_HW=y -CONFIG_CRYPTO_JITTERENTROPY=y -CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y -CONFIG_CRYPTO_LIB_SHA256=y -CONFIG_CRYPTO_LZO=y -CONFIG_CRYPTO_RNG=y -CONFIG_CRYPTO_RNG2=y -CONFIG_CRYPTO_RNG_DEFAULT=y -CONFIG_CRYPTO_SEQIV=y -CONFIG_CRYPTO_SHA1=y -CONFIG_CRYPTO_SHA256=y -CONFIG_CRYPTO_SHA512=y -CONFIG_CRYPTO_ZSTD=y -CONFIG_DCACHE_WORD_ACCESS=y -CONFIG_DEBUG_ALIGN_RODATA=y -CONFIG_DEBUG_BUGVERBOSE=y -CONFIG_DEBUG_GPIO=y -CONFIG_DEBUG_LL=y -CONFIG_DEBUG_LL_INCLUDE="debug/8250.S" -CONFIG_DEBUG_MISC=y -CONFIG_DEBUG_MT6589_UART0=y -# CONFIG_DEBUG_MT8127_UART0 is not set -# CONFIG_DEBUG_MT8135_UART3 is not set -CONFIG_DEBUG_PREEMPT=y -CONFIG_DEBUG_UART_8250=y -CONFIG_DEBUG_UART_8250_SHIFT=2 -CONFIG_DEBUG_UART_PHYS=0x11004000 -CONFIG_DEBUG_UART_VIRT=0xf1004000 -CONFIG_DEBUG_UNCOMPRESS=y -# CONFIG_DEVFREQ_GOV_PASSIVE is not set -# CONFIG_DEVFREQ_GOV_PERFORMANCE is not set -# CONFIG_DEVFREQ_GOV_POWERSAVE is not set -CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND=y -# CONFIG_DEVFREQ_GOV_USERSPACE is not set -# CONFIG_DEVFREQ_THERMAL is not set -CONFIG_DIMLIB=y -CONFIG_DMADEVICES=y -CONFIG_DMA_ENGINE=y -CONFIG_DMA_OF=y -CONFIG_DMA_OPS=y -CONFIG_DMA_REMAP=y -CONFIG_DMA_SHARED_BUFFER=y -CONFIG_DMA_VIRTUAL_CHANNELS=y -CONFIG_DRM=y -CONFIG_DRM_BRIDGE=y -CONFIG_DRM_DISPLAY_CONNECTOR=y -CONFIG_DRM_FBDEV_EMULATION=y -CONFIG_DRM_FBDEV_OVERALLOC=100 -CONFIG_DRM_GEM_CMA_HELPER=y -CONFIG_DRM_GEM_SHMEM_HELPER=y -CONFIG_DRM_KMS_HELPER=y -CONFIG_DRM_LIMA=y -CONFIG_DRM_LVDS_CODEC=y -CONFIG_DRM_MEDIATEK=y -CONFIG_DRM_MEDIATEK_HDMI=y -CONFIG_DRM_MIPI_DSI=y -CONFIG_DRM_PANEL=y -CONFIG_DRM_PANEL_BRIDGE=y -CONFIG_DRM_PANEL_ORIENTATION_QUIRKS=y -CONFIG_DRM_PANEL_RASPBERRYPI_TOUCHSCREEN=y -CONFIG_DRM_SCHED=y -CONFIG_DRM_SIMPLE_BRIDGE=y -CONFIG_DTC=y -CONFIG_DUMMY_CONSOLE=y -CONFIG_EARLY_PRINTK=y -CONFIG_EDAC_ATOMIC_SCRUB=y -CONFIG_EDAC_SUPPORT=y -CONFIG_EINT_MTK=y -CONFIG_ELF_CORE=y -CONFIG_EXT4_FS=y -CONFIG_EXTCON=y -CONFIG_F2FS_FS=y -CONFIG_FB=y -CONFIG_FB_CFB_COPYAREA=y -CONFIG_FB_CFB_FILLRECT=y -CONFIG_FB_CFB_IMAGEBLIT=y -CONFIG_FB_CMDLINE=y -CONFIG_FB_DEFERRED_IO=y -CONFIG_FB_SYS_COPYAREA=y -CONFIG_FB_SYS_FILLRECT=y -CONFIG_FB_SYS_FOPS=y -CONFIG_FB_SYS_IMAGEBLIT=y -CONFIG_FIT_PARTITION=y -CONFIG_FIXED_PHY=y -CONFIG_FIX_EARLYCON_MEM=y -CONFIG_FONT_8x16=y -CONFIG_FONT_8x8=y -CONFIG_FONT_SUPPORT=y -CONFIG_FRAMEBUFFER_CONSOLE=y -CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y -CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y -CONFIG_FREEZER=y -CONFIG_FS_IOMAP=y -CONFIG_FS_MBCACHE=y -CONFIG_FWNODE_MDIO=y -CONFIG_FW_CACHE=y -CONFIG_FW_LOADER_PAGED_BUF=y -CONFIG_GENERIC_ALLOCATOR=y -CONFIG_GENERIC_BUG=y -CONFIG_GENERIC_CLOCKEVENTS=y -CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y -CONFIG_GENERIC_CPU_AUTOPROBE=y -CONFIG_GENERIC_CPU_VULNERABILITIES=y -CONFIG_GENERIC_EARLY_IOREMAP=y -CONFIG_GENERIC_GETTIMEOFDAY=y -CONFIG_GENERIC_IDLE_POLL_SETUP=y -CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y -CONFIG_GENERIC_IRQ_MIGRATION=y -CONFIG_GENERIC_IRQ_MULTI_HANDLER=y -CONFIG_GENERIC_IRQ_SHOW=y -CONFIG_GENERIC_IRQ_SHOW_LEVEL=y -CONFIG_GENERIC_LIB_DEVMEM_IS_ALLOWED=y -CONFIG_GENERIC_MSI_IRQ=y -CONFIG_GENERIC_MSI_IRQ_DOMAIN=y -CONFIG_GENERIC_PCI_IOMAP=y -CONFIG_GENERIC_PHY=y -CONFIG_GENERIC_PINCONF=y -CONFIG_GENERIC_PINCTRL_GROUPS=y -CONFIG_GENERIC_PINMUX_FUNCTIONS=y -CONFIG_GENERIC_SCHED_CLOCK=y -CONFIG_GENERIC_SMP_IDLE_THREAD=y -CONFIG_GENERIC_STRNCPY_FROM_USER=y -CONFIG_GENERIC_STRNLEN_USER=y -CONFIG_GENERIC_TIME_VSYSCALL=y -CONFIG_GENERIC_VDSO_32=y -CONFIG_GPIO_CDEV=y -CONFIG_GRO_CELLS=y -CONFIG_HANDLE_DOMAIN_IRQ=y -CONFIG_HARDEN_BRANCH_PREDICTOR=y -CONFIG_HARDIRQS_SW_RESEND=y -CONFIG_HAS_DMA=y -CONFIG_HAS_IOMEM=y -CONFIG_HAS_IOPORT_MAP=y -CONFIG_HAVE_SMP=y -CONFIG_HDMI=y -CONFIG_HID=y -CONFIG_HIGHMEM=y -CONFIG_HIGHPTE=y -CONFIG_HOTPLUG_CPU=y -CONFIG_HWMON=y -CONFIG_HW_CONSOLE=y -CONFIG_HW_RANDOM=y -CONFIG_HW_RANDOM_MTK=y -CONFIG_HZ_FIXED=0 -CONFIG_I2C=y -CONFIG_I2C_ALGOBIT=y -CONFIG_I2C_BOARDINFO=y -CONFIG_I2C_CHARDEV=y -CONFIG_I2C_MT65XX=y -CONFIG_ICPLUS_PHY=y -CONFIG_IIO=y -CONFIG_INITRAMFS_SOURCE="" -CONFIG_INPUT=y -CONFIG_INPUT_EVDEV=y -CONFIG_INPUT_KEYBOARD=y -CONFIG_INPUT_TOUCHSCREEN=y -CONFIG_IOMMU_API=y -# CONFIG_IOMMU_DEBUGFS is not set -# CONFIG_IOMMU_DEFAULT_DMA_LAZY is not set -CONFIG_IOMMU_DEFAULT_DMA_STRICT=y -# CONFIG_IOMMU_DEFAULT_PASSTHROUGH is not set -CONFIG_IOMMU_IO_PGTABLE=y -CONFIG_IOMMU_IO_PGTABLE_ARMV7S=y -# CONFIG_IOMMU_IO_PGTABLE_ARMV7S_SELFTEST is not set -# CONFIG_IOMMU_IO_PGTABLE_LPAE is not set -CONFIG_IOMMU_SUPPORT=y -CONFIG_IO_URING=y -CONFIG_IRQCHIP=y -CONFIG_IRQ_DOMAIN=y -CONFIG_IRQ_DOMAIN_HIERARCHY=y -CONFIG_IRQ_FORCED_THREADING=y -CONFIG_IRQ_WORK=y -CONFIG_JBD2=y -CONFIG_KALLSYMS=y -CONFIG_KCMP=y -CONFIG_KEYBOARD_MTK_PMIC=y -CONFIG_KMAP_LOCAL=y -CONFIG_KMAP_LOCAL_NON_LINEAR_PTE_ARRAY=y -CONFIG_LCD_CLASS_DEVICE=y -CONFIG_LCD_PLATFORM=y -CONFIG_LEDS_MT6323=y -CONFIG_LIBFDT=y -CONFIG_LOCK_DEBUGGING_SUPPORT=y -CONFIG_LOCK_SPIN_ON_OWNER=y -CONFIG_LOGO=y -CONFIG_LOGO_LINUX_CLUT224=y -# CONFIG_LOGO_LINUX_MONO is not set -# CONFIG_LOGO_LINUX_VGA16 is not set -CONFIG_LZO_COMPRESS=y -CONFIG_LZO_DECOMPRESS=y -# CONFIG_MACH_MT2701 is not set -# CONFIG_MACH_MT6589 is not set -# CONFIG_MACH_MT6592 is not set -CONFIG_MACH_MT7623=y -# CONFIG_MACH_MT7629 is not set -# CONFIG_MACH_MT8127 is not set -# CONFIG_MACH_MT8135 is not set -CONFIG_MAGIC_SYSRQ=y -CONFIG_MAILBOX=y -# CONFIG_MAILBOX_TEST is not set -CONFIG_MDIO_BITBANG=y -CONFIG_MDIO_BUS=y -CONFIG_MDIO_DEVICE=y -CONFIG_MDIO_DEVRES=y -CONFIG_MDIO_GPIO=y -CONFIG_MEDIATEK_GE_PHY=y -# CONFIG_MEDIATEK_GE_PHY_SOC is not set -CONFIG_MEDIATEK_MT6577_AUXADC=y -CONFIG_MEDIATEK_WATCHDOG=y -CONFIG_MEMFD_CREATE=y -CONFIG_MEMORY=y -CONFIG_MFD_CORE=y -# CONFIG_MFD_HI6421_SPMI is not set -CONFIG_MFD_MT6397=y -CONFIG_MFD_SYSCON=y -CONFIG_MIGHT_HAVE_CACHE_L2X0=y -CONFIG_MIGRATION=y -CONFIG_MMC=y -CONFIG_MMC_BLOCK=y -CONFIG_MMC_CQHCI=y -CONFIG_MMC_MTK=y -CONFIG_MMC_SDHCI=y -# CONFIG_MMC_SDHCI_PCI is not set -CONFIG_MMC_SDHCI_PLTFM=y -CONFIG_MODULES_USE_ELF_REL=y -CONFIG_MTD_CMDLINE_PARTS=y -# CONFIG_MTD_NAND_ECC_MEDIATEK is not set -CONFIG_MTD_SPI_NOR=y -CONFIG_MTD_SPLIT_FIRMWARE=y -CONFIG_MTD_SPLIT_UIMAGE_FW=y -CONFIG_MTD_UBI=y -CONFIG_MTD_UBI_BEB_LIMIT=20 -CONFIG_MTD_UBI_BLOCK=y -CONFIG_MTD_UBI_WL_THRESHOLD=4096 -CONFIG_MTK_CMDQ=y -CONFIG_MTK_CMDQ_MBOX=y -CONFIG_MTK_CQDMA=y -CONFIG_MTK_EFUSE=y -# CONFIG_MTK_HSDMA is not set -CONFIG_MTK_INFRACFG=y -CONFIG_MTK_IOMMU=y -CONFIG_MTK_IOMMU_V1=y -CONFIG_MTK_MMSYS=y -CONFIG_MTK_PMIC_WRAP=y -CONFIG_MTK_SCPSYS=y -CONFIG_MTK_SCPSYS_PM_DOMAINS=y -CONFIG_MTK_SMI=y -CONFIG_MTK_THERMAL=y -CONFIG_MTK_TIMER=y -# CONFIG_MTK_UART_APDMA is not set -# CONFIG_MUSB_PIO_ONLY is not set -CONFIG_MUTEX_SPIN_ON_OWNER=y -CONFIG_NEED_DMA_MAP_STATE=y -CONFIG_NEED_SG_DMA_LENGTH=y -CONFIG_NEON=y -CONFIG_NET_DEVLINK=y -CONFIG_NET_DSA=y -CONFIG_NET_DSA_MT7530=y -CONFIG_NET_DSA_MT7530_MDIO=y -# CONFIG_NET_DSA_MT7530_MMIO is not set -CONFIG_NET_DSA_TAG_MTK=y -CONFIG_NET_FLOW_LIMIT=y -CONFIG_NET_MEDIATEK_SOC=y -CONFIG_NET_MEDIATEK_SOC_WED=y -CONFIG_NET_SELFTESTS=y -CONFIG_NET_SWITCHDEV=y -CONFIG_NET_VENDOR_MEDIATEK=y -# CONFIG_NET_VENDOR_WIZNET is not set -CONFIG_NLS=y -CONFIG_NOP_USB_XCEIV=y -CONFIG_NO_HZ=y -CONFIG_NO_HZ_COMMON=y -CONFIG_NO_HZ_IDLE=y -CONFIG_NR_CPUS=4 -CONFIG_NVMEM=y -# CONFIG_NVMEM_SPMI_SDAM is not set -CONFIG_NVMEM_SYSFS=y -CONFIG_OF=y -CONFIG_OF_ADDRESS=y -CONFIG_OF_DYNAMIC=y -CONFIG_OF_EARLY_FLATTREE=y -CONFIG_OF_FLATTREE=y -CONFIG_OF_GPIO=y -CONFIG_OF_IOMMU=y -CONFIG_OF_IRQ=y -CONFIG_OF_KOBJ=y -CONFIG_OF_MDIO=y -CONFIG_OF_OVERLAY=y -CONFIG_OF_RESOLVE=y -CONFIG_OLD_SIGACTION=y -CONFIG_OLD_SIGSUSPEND3=y -CONFIG_PADATA=y -CONFIG_PAGE_OFFSET=0xC0000000 -CONFIG_PAGE_POOL=y -CONFIG_PAGE_POOL_STATS=y -CONFIG_PCI=y -CONFIG_PCIEAER=y -CONFIG_PCIEPORTBUS=y -CONFIG_PCIE_MEDIATEK=y -CONFIG_PCIE_PME=y -CONFIG_PCI_DOMAINS=y -CONFIG_PCI_DOMAINS_GENERIC=y -CONFIG_PCI_MSI=y -CONFIG_PCI_MSI_IRQ_DOMAIN=y -CONFIG_PERF_USE_VMALLOC=y -CONFIG_PGTABLE_LEVELS=2 -CONFIG_PHYLIB=y -CONFIG_PHYLINK=y -CONFIG_PHY_MTK_HDMI=y -CONFIG_PHY_MTK_MIPI_DSI=y -CONFIG_PHY_MTK_TPHY=y -# CONFIG_PHY_MTK_UFS is not set -# CONFIG_PHY_MTK_XSPHY is not set -CONFIG_PINCTRL=y -CONFIG_PINCTRL_MT2701=y -CONFIG_PINCTRL_MT6397=y -CONFIG_PINCTRL_MT7623=y -CONFIG_PINCTRL_MTK=y -CONFIG_PINCTRL_MTK_MOORE=y -CONFIG_PINCTRL_MTK_V2=y -CONFIG_PM=y -CONFIG_PM_CLK=y -CONFIG_PM_DEVFREQ=y -# CONFIG_PM_DEVFREQ_EVENT is not set -CONFIG_PM_GENERIC_DOMAINS=y -CONFIG_PM_GENERIC_DOMAINS_OF=y -CONFIG_PM_GENERIC_DOMAINS_SLEEP=y -CONFIG_PM_OPP=y -CONFIG_PM_SLEEP=y -CONFIG_PM_SLEEP_SMP=y -CONFIG_POWER_RESET=y -# CONFIG_POWER_RESET_MT6323 is not set -CONFIG_POWER_SUPPLY=y -CONFIG_POWER_SUPPLY_HWMON=y -CONFIG_PREEMPT=y -CONFIG_PREEMPTION=y -CONFIG_PREEMPT_COUNT=y -# CONFIG_PREEMPT_NONE is not set -CONFIG_PREEMPT_RCU=y -CONFIG_PRINTK_TIME=y -CONFIG_PTP_1588_CLOCK_OPTIONAL=y -CONFIG_PWM=y -CONFIG_PWM_MEDIATEK=y -# CONFIG_PWM_MTK_DISP is not set -CONFIG_PWM_SYSFS=y -CONFIG_RAS=y -CONFIG_RATIONAL=y -CONFIG_REGMAP=y -CONFIG_REGMAP_MMIO=y -CONFIG_REGULATOR=y -CONFIG_REGULATOR_FIXED_VOLTAGE=y -CONFIG_REGULATOR_GPIO=y -CONFIG_REGULATOR_MT6323=y -# CONFIG_REGULATOR_MT6358 is not set -# CONFIG_REGULATOR_MT6380 is not set -# CONFIG_REGULATOR_MT6397 is not set -# CONFIG_REGULATOR_RT5190A is not set -# CONFIG_REGULATOR_QCOM_LABIBB is not set -# CONFIG_REGULATOR_QCOM_SPMI is not set -# CONFIG_REGULATOR_QCOM_USB_VBUS is not set -CONFIG_RESET_CONTROLLER=y -CONFIG_RFS_ACCEL=y -CONFIG_RPS=y -CONFIG_RTC_CLASS=y -# CONFIG_RTC_DRV_MT6397 is not set -# CONFIG_RTC_DRV_MT7622 is not set -CONFIG_RTC_I2C_AND_SPI=y -CONFIG_RTC_MC146818_LIB=y -# CONFIG_RTL8367S_GSW is not set -CONFIG_RWSEM_SPIN_ON_OWNER=y -# CONFIG_SERIAL_8250_DMA is not set -CONFIG_SERIAL_8250_FSL=y -CONFIG_SERIAL_8250_MT6577=y -CONFIG_SERIAL_8250_NR_UARTS=4 -CONFIG_SERIAL_8250_RUNTIME_UARTS=4 -CONFIG_SERIAL_MCTRL_GPIO=y -CONFIG_SGL_ALLOC=y -CONFIG_SMP=y -# CONFIG_SMP_ON_UP is not set -CONFIG_SOCK_RX_QUEUE_MAPPING=y -CONFIG_SPARSE_IRQ=y -CONFIG_SPI=y -CONFIG_SPI_BITBANG=y -CONFIG_SPI_DYNAMIC=y -CONFIG_SPI_MASTER=y -CONFIG_SPI_MEM=y -CONFIG_SPI_MT65XX=y -# CONFIG_SPI_MTK_NOR is not set -CONFIG_SPMI=y -# CONFIG_SPMI_HISI3670 is not set -CONFIG_SRCU=y -# CONFIG_STRIP_ASM_SYMS is not set -CONFIG_SUSPEND=y -CONFIG_SUSPEND_FREEZER=y -CONFIG_SWPHY=y -CONFIG_SWP_EMULATE=y -CONFIG_SYNC_FILE=y -CONFIG_SYS_SUPPORTS_APM_EMULATION=y -CONFIG_THERMAL=y -CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y -CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0 -CONFIG_THERMAL_GOV_STEP_WISE=y -CONFIG_THERMAL_OF=y -CONFIG_TICK_CPU_ACCOUNTING=y -CONFIG_TIMER_OF=y -CONFIG_TIMER_PROBE=y -CONFIG_TOUCHSCREEN_EDT_FT5X06=y -CONFIG_TREE_RCU=y -CONFIG_TREE_SRCU=y -# CONFIG_UACCE is not set -CONFIG_UBIFS_FS=y -CONFIG_UEVENT_HELPER_PATH="" -CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h" -CONFIG_UNINLINE_SPIN_UNLOCK=y -CONFIG_UNWINDER_ARM=y -CONFIG_USB=y -CONFIG_USB_COMMON=y -CONFIG_USB_F_ACM=y -CONFIG_USB_F_ECM=y -CONFIG_USB_F_MASS_STORAGE=y -CONFIG_USB_GADGET=y -CONFIG_USB_GPIO_VBUS=y -CONFIG_USB_G_MULTI=y -CONFIG_USB_G_MULTI_CDC=y -# CONFIG_USB_G_MULTI_RNDIS is not set -CONFIG_USB_HID=y -CONFIG_USB_HIDDEV=y -CONFIG_USB_INVENTRA_DMA=y -CONFIG_USB_LIBCOMPOSITE=y -CONFIG_USB_MUSB_DUAL_ROLE=y -CONFIG_USB_MUSB_HDRC=y -CONFIG_USB_MUSB_MEDIATEK=y -CONFIG_USB_OTG=y -CONFIG_USB_PHY=y -CONFIG_USB_ROLE_SWITCH=y -CONFIG_USB_SUPPORT=y -CONFIG_USB_U_ETHER=y -CONFIG_USB_U_SERIAL=y -CONFIG_USE_OF=y -CONFIG_VFP=y -CONFIG_VFPv3=y -CONFIG_VIDEOMODE_HELPERS=y -CONFIG_VM_EVENT_COUNTERS=y -CONFIG_VT=y -CONFIG_VT_CONSOLE=y -CONFIG_VT_CONSOLE_SLEEP=y -CONFIG_VT_HW_CONSOLE_BINDING=y -CONFIG_WATCHDOG_CORE=y -CONFIG_XPS=y -CONFIG_XXHASH=y -CONFIG_XZ_DEC_ARM=y -CONFIG_XZ_DEC_BCJ=y -CONFIG_ZBOOT_ROM_BSS=0 -CONFIG_ZBOOT_ROM_TEXT=0 -CONFIG_ZLIB_DEFLATE=y -CONFIG_ZLIB_INFLATE=y -CONFIG_ZSTD_COMPRESS=y -CONFIG_ZSTD_DECOMPRESS=y diff --git a/target/linux/mediatek/mt7623/config-6.1 b/target/linux/mediatek/mt7623/config-6.1 deleted file mode 100644 index b6a75ab80..000000000 --- a/target/linux/mediatek/mt7623/config-6.1 +++ /dev/null @@ -1,609 +0,0 @@ -# CONFIG_AIO is not set -CONFIG_ALIGNMENT_TRAP=y -CONFIG_ARCH_32BIT_OFF_T=y -CONFIG_ARCH_FORCE_MAX_ORDER=11 -CONFIG_ARCH_HIBERNATION_POSSIBLE=y -CONFIG_ARCH_KEEP_MEMBLOCK=y -CONFIG_ARCH_MEDIATEK=y -CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y -CONFIG_ARCH_MULTIPLATFORM=y -CONFIG_ARCH_MULTI_V6_V7=y -CONFIG_ARCH_MULTI_V7=y -CONFIG_ARCH_NR_GPIO=0 -CONFIG_ARCH_OPTIONAL_KERNEL_RWX=y -CONFIG_ARCH_OPTIONAL_KERNEL_RWX_DEFAULT=y -CONFIG_ARCH_SELECT_MEMORY_MODEL=y -CONFIG_ARCH_SPARSEMEM_ENABLE=y -CONFIG_ARCH_SUSPEND_POSSIBLE=y -CONFIG_ARM=y -CONFIG_ARM_APPENDED_DTB=y -CONFIG_ARM_ARCH_TIMER=y -CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y -# CONFIG_ARM_ATAG_DTB_COMPAT is not set -CONFIG_ARM_CPU_SUSPEND=y -# CONFIG_ARM_CPU_TOPOLOGY is not set -CONFIG_ARM_DMA_IOMMU_ALIGNMENT=8 -CONFIG_ARM_DMA_USE_IOMMU=y -CONFIG_ARM_GIC=y -CONFIG_ARM_HAS_GROUP_RELOCS=y -CONFIG_ARM_L1_CACHE_SHIFT=6 -CONFIG_ARM_L1_CACHE_SHIFT_6=y -# CONFIG_ARM_MEDIATEK_CCI_DEVFREQ is not set -CONFIG_ARM_MEDIATEK_CPUFREQ=y -CONFIG_ARM_PATCH_IDIV=y -CONFIG_ARM_PATCH_PHYS_VIRT=y -# CONFIG_ARM_SMMU is not set -CONFIG_ARM_THUMB=y -CONFIG_ARM_THUMBEE=y -CONFIG_ARM_UNWIND=y -CONFIG_ARM_VIRT_EXT=y -CONFIG_ASYNC_TX_ENABLE_CHANNEL_SWITCH=y -CONFIG_ATAGS=y -CONFIG_AUTO_ZRELADDR=y -CONFIG_BACKLIGHT_CLASS_DEVICE=y -CONFIG_BACKLIGHT_GPIO=y -CONFIG_BACKLIGHT_LED=y -CONFIG_BACKLIGHT_PWM=y -CONFIG_BINFMT_FLAT_ARGVP_ENVP_ON_STACK=y -CONFIG_BLK_DEV_LOOP=y -CONFIG_BLK_MQ_PCI=y -CONFIG_BLK_PM=y -CONFIG_BOUNCE=y -# CONFIG_CACHE_L2X0 is not set -CONFIG_CC_HAVE_STACKPROTECTOR_TLS=y -CONFIG_CC_IMPLICIT_FALLTHROUGH="-Wimplicit-fallthrough=5" -CONFIG_CC_NO_ARRAY_BOUNDS=y -CONFIG_CLKSRC_MMIO=y -CONFIG_CLONE_BACKWARDS=y -CONFIG_CMDLINE="earlyprintk console=ttyS0,115200 rootfstype=squashfs,jffs2" -CONFIG_CMDLINE_FROM_BOOTLOADER=y -# CONFIG_CMDLINE_OVERRIDE is not set -CONFIG_CMDLINE_PARTITION=y -CONFIG_COMMON_CLK=y -CONFIG_COMMON_CLK_MEDIATEK=y -CONFIG_COMMON_CLK_MT2701=y -CONFIG_COMMON_CLK_MT2701_AUDSYS=y -CONFIG_COMMON_CLK_MT2701_BDPSYS=y -CONFIG_COMMON_CLK_MT2701_ETHSYS=y -CONFIG_COMMON_CLK_MT2701_G3DSYS=y -CONFIG_COMMON_CLK_MT2701_HIFSYS=y -CONFIG_COMMON_CLK_MT2701_IMGSYS=y -CONFIG_COMMON_CLK_MT2701_MMSYS=y -CONFIG_COMMON_CLK_MT2701_VDECSYS=y -# CONFIG_COMMON_CLK_MT6795 is not set -# CONFIG_COMMON_CLK_MT7622 is not set -# CONFIG_COMMON_CLK_MT7629 is not set -# CONFIG_COMMON_CLK_MT7981 is not set -# CONFIG_COMMON_CLK_MT7986 is not set -# CONFIG_COMMON_CLK_MT7988 is not set -# CONFIG_COMMON_CLK_MT8135 is not set -# CONFIG_COMMON_CLK_MT8173 is not set -# CONFIG_COMMON_CLK_MT8365 is not set -# CONFIG_COMMON_CLK_MT8516 is not set -CONFIG_COMPACT_UNEVICTABLE_DEFAULT=1 -CONFIG_COMPAT_32BIT_TIME=y -CONFIG_CONFIGFS_FS=y -CONFIG_CONSOLE_TRANSLATIONS=y -CONFIG_CONTEXT_TRACKING=y -CONFIG_CONTEXT_TRACKING_IDLE=y -CONFIG_COREDUMP=y -# CONFIG_CPUFREQ_DT is not set -CONFIG_CPU_32v6K=y -CONFIG_CPU_32v7=y -CONFIG_CPU_ABRT_EV7=y -CONFIG_CPU_CACHE_V7=y -CONFIG_CPU_CACHE_VIPT=y -CONFIG_CPU_COPY_V6=y -CONFIG_CPU_CP15=y -CONFIG_CPU_CP15_MMU=y -CONFIG_CPU_FREQ=y -CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y -CONFIG_CPU_FREQ_GOV_ATTR_SET=y -CONFIG_CPU_FREQ_GOV_COMMON=y -CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y -CONFIG_CPU_FREQ_GOV_ONDEMAND=y -CONFIG_CPU_FREQ_GOV_PERFORMANCE=y -CONFIG_CPU_FREQ_GOV_POWERSAVE=y -# CONFIG_CPU_FREQ_GOV_USERSPACE is not set -CONFIG_CPU_FREQ_STAT=y -CONFIG_CPU_HAS_ASID=y -CONFIG_CPU_LITTLE_ENDIAN=y -CONFIG_CPU_PABRT_V7=y -CONFIG_CPU_PM=y -CONFIG_CPU_RMAP=y -CONFIG_CPU_SPECTRE=y -CONFIG_CPU_THUMB_CAPABLE=y -CONFIG_CPU_TLB_V7=y -CONFIG_CPU_V7=y -CONFIG_CRC16=y -# CONFIG_CRC32_SARWATE is not set -CONFIG_CRC32_SLICEBY8=y -CONFIG_CROSS_MEMORY_ATTACH=y -CONFIG_CRYPTO_CRC32=y -CONFIG_CRYPTO_CRC32C=y -CONFIG_CRYPTO_DEFLATE=y -CONFIG_CRYPTO_DRBG=y -CONFIG_CRYPTO_DRBG_HMAC=y -CONFIG_CRYPTO_DRBG_MENU=y -CONFIG_CRYPTO_HASH_INFO=y -CONFIG_CRYPTO_HMAC=y -CONFIG_CRYPTO_HW=y -CONFIG_CRYPTO_JITTERENTROPY=y -CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y -CONFIG_CRYPTO_LIB_SHA1=y -CONFIG_CRYPTO_LIB_SHA256=y -CONFIG_CRYPTO_LIB_UTILS=y -CONFIG_CRYPTO_LZO=y -CONFIG_CRYPTO_RNG=y -CONFIG_CRYPTO_RNG2=y -CONFIG_CRYPTO_RNG_DEFAULT=y -CONFIG_CRYPTO_SEQIV=y -CONFIG_CRYPTO_SHA1=y -CONFIG_CRYPTO_SHA256=y -CONFIG_CRYPTO_SHA512=y -CONFIG_CRYPTO_ZSTD=y -CONFIG_CURRENT_POINTER_IN_TPIDRURO=y -CONFIG_DCACHE_WORD_ACCESS=y -CONFIG_DEBUG_ALIGN_RODATA=y -CONFIG_DEBUG_BUGVERBOSE=y -CONFIG_DEBUG_GPIO=y -CONFIG_DEBUG_INFO=y -CONFIG_DEBUG_LL=y -CONFIG_DEBUG_LL_INCLUDE="debug/8250.S" -CONFIG_DEBUG_MISC=y -CONFIG_DEBUG_MT6589_UART0=y -# CONFIG_DEBUG_MT8127_UART0 is not set -# CONFIG_DEBUG_MT8135_UART3 is not set -CONFIG_DEBUG_PREEMPT=y -CONFIG_DEBUG_UART_8250=y -CONFIG_DEBUG_UART_8250_SHIFT=2 -CONFIG_DEBUG_UART_PHYS=0x11004000 -CONFIG_DEBUG_UART_VIRT=0xf1004000 -# CONFIG_DEVFREQ_GOV_PASSIVE is not set -# CONFIG_DEVFREQ_GOV_PERFORMANCE is not set -# CONFIG_DEVFREQ_GOV_POWERSAVE is not set -CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND=y -# CONFIG_DEVFREQ_GOV_USERSPACE is not set -# CONFIG_DEVFREQ_THERMAL is not set -CONFIG_DIMLIB=y -CONFIG_DMADEVICES=y -CONFIG_DMA_ENGINE=y -CONFIG_DMA_OF=y -CONFIG_DMA_OPS=y -CONFIG_DMA_SHARED_BUFFER=y -CONFIG_DMA_VIRTUAL_CHANNELS=y -CONFIG_DRM=y -CONFIG_DRM_BRIDGE=y -CONFIG_DRM_DISPLAY_CONNECTOR=y -CONFIG_DRM_FBDEV_EMULATION=y -CONFIG_DRM_FBDEV_OVERALLOC=100 -CONFIG_DRM_GEM_DMA_HELPER=y -CONFIG_DRM_GEM_SHMEM_HELPER=y -CONFIG_DRM_KMS_HELPER=y -CONFIG_DRM_LIMA=y -CONFIG_DRM_LVDS_CODEC=y -CONFIG_DRM_MEDIATEK=y -# CONFIG_DRM_MEDIATEK_DP is not set -CONFIG_DRM_MEDIATEK_HDMI=y -CONFIG_DRM_MIPI_DSI=y -CONFIG_DRM_NOMODESET=y -CONFIG_DRM_PANEL=y -CONFIG_DRM_PANEL_BRIDGE=y -CONFIG_DRM_PANEL_ORIENTATION_QUIRKS=y -CONFIG_DRM_PANEL_RASPBERRYPI_TOUCHSCREEN=y -CONFIG_DRM_SCHED=y -CONFIG_DRM_SIMPLE_BRIDGE=y -CONFIG_DTC=y -CONFIG_DUMMY_CONSOLE=y -CONFIG_EARLY_PRINTK=y -CONFIG_EDAC_ATOMIC_SCRUB=y -CONFIG_EDAC_SUPPORT=y -CONFIG_EINT_MTK=y -CONFIG_ELF_CORE=y -CONFIG_EXCLUSIVE_SYSTEM_RAM=y -CONFIG_EXT4_FS=y -CONFIG_EXTCON=y -CONFIG_F2FS_FS=y -CONFIG_FB=y -CONFIG_FB_CFB_COPYAREA=y -CONFIG_FB_CFB_FILLRECT=y -CONFIG_FB_CFB_IMAGEBLIT=y -CONFIG_FB_CMDLINE=y -CONFIG_FB_DEFERRED_IO=y -CONFIG_FB_SYS_COPYAREA=y -CONFIG_FB_SYS_FILLRECT=y -CONFIG_FB_SYS_FOPS=y -CONFIG_FB_SYS_IMAGEBLIT=y -CONFIG_FIT_PARTITION=y -CONFIG_FIXED_PHY=y -CONFIG_FIX_EARLYCON_MEM=y -CONFIG_FONT_8x16=y -CONFIG_FONT_8x8=y -CONFIG_FONT_SUPPORT=y -CONFIG_FRAMEBUFFER_CONSOLE=y -CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y -CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y -CONFIG_FRAME_WARN=1024 -CONFIG_FREEZER=y -CONFIG_FS_IOMAP=y -CONFIG_FS_MBCACHE=y -CONFIG_FWNODE_MDIO=y -CONFIG_FW_CACHE=y -CONFIG_FW_LOADER_PAGED_BUF=y -CONFIG_FW_LOADER_SYSFS=y -CONFIG_GCC11_NO_ARRAY_BOUNDS=y -CONFIG_GENERIC_ALLOCATOR=y -CONFIG_GENERIC_BUG=y -CONFIG_GENERIC_CLOCKEVENTS=y -CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y -CONFIG_GENERIC_CPU_AUTOPROBE=y -CONFIG_GENERIC_CPU_VULNERABILITIES=y -CONFIG_GENERIC_EARLY_IOREMAP=y -CONFIG_GENERIC_GETTIMEOFDAY=y -CONFIG_GENERIC_IDLE_POLL_SETUP=y -CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y -CONFIG_GENERIC_IRQ_MIGRATION=y -CONFIG_GENERIC_IRQ_MULTI_HANDLER=y -CONFIG_GENERIC_IRQ_SHOW=y -CONFIG_GENERIC_IRQ_SHOW_LEVEL=y -CONFIG_GENERIC_LIB_DEVMEM_IS_ALLOWED=y -CONFIG_GENERIC_MSI_IRQ=y -CONFIG_GENERIC_MSI_IRQ_DOMAIN=y -CONFIG_GENERIC_PCI_IOMAP=y -CONFIG_GENERIC_PHY=y -CONFIG_GENERIC_PINCONF=y -CONFIG_GENERIC_PINCTRL_GROUPS=y -CONFIG_GENERIC_PINMUX_FUNCTIONS=y -CONFIG_GENERIC_SCHED_CLOCK=y -CONFIG_GENERIC_SMP_IDLE_THREAD=y -CONFIG_GENERIC_STRNCPY_FROM_USER=y -CONFIG_GENERIC_STRNLEN_USER=y -CONFIG_GENERIC_TIME_VSYSCALL=y -CONFIG_GENERIC_VDSO_32=y -CONFIG_GPIO_CDEV=y -CONFIG_GRO_CELLS=y -CONFIG_HARDEN_BRANCH_PREDICTOR=y -CONFIG_HARDIRQS_SW_RESEND=y -CONFIG_HAS_DMA=y -CONFIG_HAS_IOMEM=y -CONFIG_HAS_IOPORT_MAP=y -CONFIG_HAVE_SMP=y -CONFIG_HDMI=y -CONFIG_HID=y -CONFIG_HIGHMEM=y -CONFIG_HIGHPTE=y -CONFIG_HOTPLUG_CPU=y -CONFIG_HWMON=y -CONFIG_HW_CONSOLE=y -CONFIG_HW_RANDOM=y -CONFIG_HW_RANDOM_MTK=y -CONFIG_HZ_FIXED=0 -CONFIG_I2C=y -CONFIG_I2C_ALGOBIT=y -CONFIG_I2C_BOARDINFO=y -CONFIG_I2C_CHARDEV=y -CONFIG_I2C_MT65XX=y -CONFIG_ICPLUS_PHY=y -CONFIG_IIO=y -CONFIG_INITRAMFS_SOURCE="" -CONFIG_INPUT=y -CONFIG_INPUT_EVDEV=y -CONFIG_INPUT_KEYBOARD=y -CONFIG_INPUT_TOUCHSCREEN=y -CONFIG_IOMMU_API=y -# CONFIG_IOMMU_DEBUGFS is not set -# CONFIG_IOMMU_DEFAULT_DMA_LAZY is not set -CONFIG_IOMMU_DEFAULT_DMA_STRICT=y -# CONFIG_IOMMU_DEFAULT_PASSTHROUGH is not set -CONFIG_IOMMU_IO_PGTABLE=y -CONFIG_IOMMU_IO_PGTABLE_ARMV7S=y -# CONFIG_IOMMU_IO_PGTABLE_ARMV7S_SELFTEST is not set -# CONFIG_IOMMU_IO_PGTABLE_LPAE is not set -CONFIG_IOMMU_SUPPORT=y -CONFIG_IRQCHIP=y -CONFIG_IRQSTACKS=y -CONFIG_IRQ_DOMAIN=y -CONFIG_IRQ_DOMAIN_HIERARCHY=y -CONFIG_IRQ_FORCED_THREADING=y -CONFIG_IRQ_WORK=y -CONFIG_JBD2=y -CONFIG_KALLSYMS=y -CONFIG_KCMP=y -# CONFIG_KEYBOARD_MT6779 is not set -CONFIG_KEYBOARD_MTK_PMIC=y -CONFIG_KMAP_LOCAL=y -CONFIG_KMAP_LOCAL_NON_LINEAR_PTE_ARRAY=y -CONFIG_LCD_CLASS_DEVICE=y -CONFIG_LCD_PLATFORM=y -CONFIG_LEDS_MT6323=y -# CONFIG_LEDS_QCOM_LPG is not set -CONFIG_LIBFDT=y -CONFIG_LOCK_DEBUGGING_SUPPORT=y -CONFIG_LOCK_SPIN_ON_OWNER=y -CONFIG_LOGO=y -CONFIG_LOGO_LINUX_CLUT224=y -# CONFIG_LOGO_LINUX_MONO is not set -# CONFIG_LOGO_LINUX_VGA16 is not set -CONFIG_LZO_COMPRESS=y -CONFIG_LZO_DECOMPRESS=y -# CONFIG_MACH_MT2701 is not set -# CONFIG_MACH_MT6589 is not set -# CONFIG_MACH_MT6592 is not set -CONFIG_MACH_MT7623=y -# CONFIG_MACH_MT7629 is not set -# CONFIG_MACH_MT8127 is not set -# CONFIG_MACH_MT8135 is not set -CONFIG_MAGIC_SYSRQ=y -CONFIG_MAILBOX=y -# CONFIG_MAILBOX_TEST is not set -CONFIG_MDIO_BITBANG=y -CONFIG_MDIO_BUS=y -CONFIG_MDIO_DEVICE=y -CONFIG_MDIO_DEVRES=y -CONFIG_MDIO_GPIO=y -CONFIG_MEDIATEK_GE_PHY=y -CONFIG_MEDIATEK_MT6577_AUXADC=y -CONFIG_MEDIATEK_WATCHDOG=y -CONFIG_MEMFD_CREATE=y -CONFIG_MEMORY=y -CONFIG_MFD_CORE=y -# CONFIG_MFD_HI6421_SPMI is not set -CONFIG_MFD_MT6397=y -CONFIG_MFD_SYSCON=y -CONFIG_MIGHT_HAVE_CACHE_L2X0=y -CONFIG_MIGRATION=y -CONFIG_MMC=y -CONFIG_MMC_BLOCK=y -CONFIG_MMC_CQHCI=y -CONFIG_MMC_MTK=y -CONFIG_MMC_SDHCI=y -# CONFIG_MMC_SDHCI_PCI is not set -CONFIG_MMC_SDHCI_PLTFM=y -CONFIG_MODULES_USE_ELF_REL=y -CONFIG_MTD_CMDLINE_PARTS=y -# CONFIG_MTD_NAND_ECC_MEDIATEK is not set -CONFIG_MTD_SPI_NOR=y -CONFIG_MTD_SPLIT_FIRMWARE=y -CONFIG_MTD_SPLIT_UIMAGE_FW=y -CONFIG_MTD_UBI=y -CONFIG_MTD_UBI_BEB_LIMIT=20 -CONFIG_MTD_UBI_BLOCK=y -CONFIG_MTD_UBI_WL_THRESHOLD=4096 -# CONFIG_MTK_ADSP_MBOX is not set -CONFIG_MTK_CMDQ=y -CONFIG_MTK_CMDQ_MBOX=y -CONFIG_MTK_CQDMA=y -# CONFIG_MTK_HSDMA is not set -CONFIG_MTK_INFRACFG=y -CONFIG_MTK_IOMMU=y -CONFIG_MTK_IOMMU_V1=y -CONFIG_MTK_MMSYS=y -CONFIG_MTK_PMIC_WRAP=y -CONFIG_MTK_SCPSYS=y -CONFIG_MTK_SCPSYS_PM_DOMAINS=y -CONFIG_MTK_SMI=y -# CONFIG_MTK_SVS is not set -CONFIG_MTK_THERMAL=y -CONFIG_MTK_TIMER=y -# CONFIG_MTK_UART_APDMA is not set -# CONFIG_MUSB_PIO_ONLY is not set -CONFIG_MUTEX_SPIN_ON_OWNER=y -CONFIG_NEED_DMA_MAP_STATE=y -CONFIG_NEED_SG_DMA_LENGTH=y -CONFIG_NEON=y -CONFIG_NET_DEVLINK=y -CONFIG_NET_DSA=y -CONFIG_NET_DSA_MT7530=y -CONFIG_NET_DSA_MT7530_MDIO=y -# CONFIG_NET_DSA_MT7530_MMIO is not set -CONFIG_NET_DSA_TAG_MTK=y -CONFIG_NET_FLOW_LIMIT=y -CONFIG_NET_MEDIATEK_SOC=y -CONFIG_NET_MEDIATEK_SOC_WED=y -CONFIG_NET_SELFTESTS=y -CONFIG_NET_SWITCHDEV=y -CONFIG_NET_VENDOR_MEDIATEK=y -# CONFIG_NET_VENDOR_WIZNET is not set -CONFIG_NLS=y -CONFIG_NOP_USB_XCEIV=y -CONFIG_NO_HZ=y -CONFIG_NO_HZ_COMMON=y -CONFIG_NO_HZ_IDLE=y -CONFIG_NR_CPUS=4 -CONFIG_NVMEM=y -CONFIG_NVMEM_MTK_EFUSE=y -# CONFIG_NVMEM_SPMI_SDAM is not set -CONFIG_NVMEM_SYSFS=y -CONFIG_OF=y -CONFIG_OF_ADDRESS=y -CONFIG_OF_DYNAMIC=y -CONFIG_OF_EARLY_FLATTREE=y -CONFIG_OF_FLATTREE=y -CONFIG_OF_GPIO=y -CONFIG_OF_IOMMU=y -CONFIG_OF_IRQ=y -CONFIG_OF_KOBJ=y -CONFIG_OF_MDIO=y -CONFIG_OF_OVERLAY=y -CONFIG_OF_RESOLVE=y -CONFIG_OLD_SIGACTION=y -CONFIG_OLD_SIGSUSPEND3=y -CONFIG_PADATA=y -CONFIG_PAGE_OFFSET=0xC0000000 -CONFIG_PAGE_POOL=y -CONFIG_PAGE_POOL_STATS=y -CONFIG_PAGE_SIZE_LESS_THAN_256KB=y -CONFIG_PAGE_SIZE_LESS_THAN_64KB=y -CONFIG_PCI=y -CONFIG_PCIEAER=y -CONFIG_PCIEPORTBUS=y -CONFIG_PCIE_MEDIATEK=y -CONFIG_PCIE_PME=y -CONFIG_PCI_DOMAINS=y -CONFIG_PCI_DOMAINS_GENERIC=y -CONFIG_PCI_MSI=y -CONFIG_PCI_MSI_IRQ_DOMAIN=y -CONFIG_PCS_MTK_LYNXI=y -CONFIG_PERF_USE_VMALLOC=y -CONFIG_PGTABLE_LEVELS=2 -CONFIG_PHYLIB=y -CONFIG_PHYLINK=y -# CONFIG_PHY_MTK_DP is not set -CONFIG_PHY_MTK_HDMI=y -CONFIG_PHY_MTK_MIPI_DSI=y -# CONFIG_PHY_MTK_PCIE is not set -CONFIG_PHY_MTK_TPHY=y -# CONFIG_PHY_MTK_UFS is not set -# CONFIG_PHY_MTK_XSPHY is not set -CONFIG_PINCTRL=y -CONFIG_PINCTRL_MT2701=y -# CONFIG_PINCTRL_MT6397 is not set -CONFIG_PINCTRL_MT7623=y -CONFIG_PINCTRL_MTK=y -CONFIG_PINCTRL_MTK_MOORE=y -CONFIG_PINCTRL_MTK_V2=y -CONFIG_PM=y -CONFIG_PM_CLK=y -CONFIG_PM_DEVFREQ=y -# CONFIG_PM_DEVFREQ_EVENT is not set -CONFIG_PM_GENERIC_DOMAINS=y -CONFIG_PM_GENERIC_DOMAINS_OF=y -CONFIG_PM_GENERIC_DOMAINS_SLEEP=y -CONFIG_PM_OPP=y -CONFIG_PM_SLEEP=y -CONFIG_PM_SLEEP_SMP=y -CONFIG_POWER_RESET=y -# CONFIG_POWER_RESET_MT6323 is not set -CONFIG_POWER_SUPPLY=y -CONFIG_POWER_SUPPLY_HWMON=y -CONFIG_PREEMPT=y -CONFIG_PREEMPTION=y -CONFIG_PREEMPT_BUILD=y -CONFIG_PREEMPT_COUNT=y -# CONFIG_PREEMPT_NONE is not set -CONFIG_PREEMPT_RCU=y -CONFIG_PRINTK_TIME=y -CONFIG_PTP_1588_CLOCK_OPTIONAL=y -CONFIG_PWM=y -CONFIG_PWM_MEDIATEK=y -# CONFIG_PWM_MTK_DISP is not set -CONFIG_PWM_SYSFS=y -CONFIG_RANDSTRUCT_NONE=y -CONFIG_RAS=y -CONFIG_RATIONAL=y -CONFIG_REGMAP=y -CONFIG_REGMAP_MMIO=y -CONFIG_REGULATOR=y -CONFIG_REGULATOR_FIXED_VOLTAGE=y -CONFIG_REGULATOR_GPIO=y -CONFIG_REGULATOR_MT6323=y -# CONFIG_REGULATOR_MT6331 is not set -# CONFIG_REGULATOR_MT6332 is not set -# CONFIG_REGULATOR_MT6358 is not set -# CONFIG_REGULATOR_MT6380 is not set -# CONFIG_REGULATOR_MT6397 is not set -# CONFIG_REGULATOR_QCOM_LABIBB is not set -# CONFIG_REGULATOR_QCOM_SPMI is not set -# CONFIG_REGULATOR_QCOM_USB_VBUS is not set -CONFIG_RESET_CONTROLLER=y -CONFIG_RFS_ACCEL=y -CONFIG_RPS=y -CONFIG_RTC_CLASS=y -# CONFIG_RTC_DRV_MT6397 is not set -# CONFIG_RTC_DRV_MT7622 is not set -CONFIG_RTC_I2C_AND_SPI=y -CONFIG_RTC_MC146818_LIB=y -# CONFIG_RTL8367S_GSW is not set -CONFIG_RWSEM_SPIN_ON_OWNER=y -# CONFIG_SERIAL_8250_DMA is not set -CONFIG_SERIAL_8250_FSL=y -CONFIG_SERIAL_8250_MT6577=y -CONFIG_SERIAL_8250_NR_UARTS=4 -CONFIG_SERIAL_8250_RUNTIME_UARTS=4 -CONFIG_SERIAL_MCTRL_GPIO=y -CONFIG_SGL_ALLOC=y -CONFIG_SMP=y -# CONFIG_SMP_ON_UP is not set -CONFIG_SOCK_RX_QUEUE_MAPPING=y -CONFIG_SOFTIRQ_ON_OWN_STACK=y -CONFIG_SPARSE_IRQ=y -CONFIG_SPI=y -CONFIG_SPI_BITBANG=y -CONFIG_SPI_DYNAMIC=y -CONFIG_SPI_MASTER=y -CONFIG_SPI_MEM=y -CONFIG_SPI_MT65XX=y -# CONFIG_SPI_MTK_NOR is not set -CONFIG_SPMI=y -# CONFIG_SPMI_HISI3670 is not set -# CONFIG_SPMI_MTK_PMIF is not set -CONFIG_SRCU=y -# CONFIG_STRIP_ASM_SYMS is not set -CONFIG_SUSPEND=y -CONFIG_SUSPEND_FREEZER=y -CONFIG_SWPHY=y -CONFIG_SWP_EMULATE=y -CONFIG_SYNC_FILE=y -CONFIG_SYS_SUPPORTS_APM_EMULATION=y -CONFIG_THERMAL=y -CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y -CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0 -CONFIG_THERMAL_GOV_STEP_WISE=y -CONFIG_THERMAL_OF=y -CONFIG_THREAD_INFO_IN_TASK=y -CONFIG_TICK_CPU_ACCOUNTING=y -CONFIG_TIMER_OF=y -CONFIG_TIMER_PROBE=y -CONFIG_TOUCHSCREEN_EDT_FT5X06=y -CONFIG_TREE_RCU=y -CONFIG_TREE_SRCU=y -# CONFIG_UACCE is not set -CONFIG_UBIFS_FS=y -CONFIG_UEVENT_HELPER_PATH="" -CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h" -CONFIG_UNINLINE_SPIN_UNLOCK=y -CONFIG_UNWINDER_ARM=y -CONFIG_USB=y -CONFIG_USB_COMMON=y -CONFIG_USB_F_ACM=y -CONFIG_USB_F_ECM=y -CONFIG_USB_F_MASS_STORAGE=y -CONFIG_USB_GADGET=y -CONFIG_USB_GPIO_VBUS=y -CONFIG_USB_G_MULTI=y -CONFIG_USB_G_MULTI_CDC=y -# CONFIG_USB_G_MULTI_RNDIS is not set -CONFIG_USB_HID=y -CONFIG_USB_HIDDEV=y -CONFIG_USB_INVENTRA_DMA=y -CONFIG_USB_LIBCOMPOSITE=y -CONFIG_USB_MUSB_DUAL_ROLE=y -CONFIG_USB_MUSB_HDRC=y -CONFIG_USB_MUSB_MEDIATEK=y -CONFIG_USB_OTG=y -CONFIG_USB_PHY=y -CONFIG_USB_ROLE_SWITCH=y -CONFIG_USB_SUPPORT=y -CONFIG_USB_U_ETHER=y -CONFIG_USB_U_SERIAL=y -CONFIG_USE_OF=y -CONFIG_VFP=y -CONFIG_VFPv3=y -CONFIG_VIDEOMODE_HELPERS=y -CONFIG_VM_EVENT_COUNTERS=y -CONFIG_VT=y -CONFIG_VT_CONSOLE=y -CONFIG_VT_CONSOLE_SLEEP=y -CONFIG_VT_HW_CONSOLE_BINDING=y -CONFIG_WATCHDOG_CORE=y -CONFIG_XPS=y -CONFIG_XXHASH=y -CONFIG_XZ_DEC_ARM=y -CONFIG_XZ_DEC_BCJ=y -CONFIG_ZBOOT_ROM_BSS=0 -CONFIG_ZBOOT_ROM_TEXT=0 -CONFIG_ZLIB_DEFLATE=y -CONFIG_ZLIB_INFLATE=y -CONFIG_ZSTD_COMMON=y -CONFIG_ZSTD_COMPRESS=y -CONFIG_ZSTD_DECOMPRESS=y diff --git a/target/linux/mediatek/mt7623/target.mk b/target/linux/mediatek/mt7623/target.mk index 1338b091e..4f84a98ff 100644 --- a/target/linux/mediatek/mt7623/target.mk +++ b/target/linux/mediatek/mt7623/target.mk @@ -9,7 +9,7 @@ CPU_TYPE:=cortex-a7 CPU_SUBTYPE:=neon-vfpv4 KERNELNAME:=Image dtbs zImage FEATURES+=display usbgadget -DEFAULT_PACKAGES+=kmod-crypto-hw-safexcel uboot-envtools +DEFAULT_PACKAGES+=fitblk kmod-crypto-hw-safexcel uboot-envtools define Target/Description Build firmware images for MediaTek mt7623 ARM based boards. diff --git a/target/linux/mediatek/mt7629/base-files/etc/board.d/01_leds b/target/linux/mediatek/mt7629/base-files/etc/board.d/01_leds new file mode 100644 index 000000000..c42ab4713 --- /dev/null +++ b/target/linux/mediatek/mt7629/base-files/etc/board.d/01_leds @@ -0,0 +1,20 @@ +. /lib/functions/leds.sh +. /lib/functions/uci-defaults.sh + +board=$(board_name) + +board_config_update + +case $board in +iptime,a6004mx) + ucidef_set_led_netdev "wan" "WAN" "orange:wan" "eth1" + ;; +netgear,ex6250-v2) + ucidef_set_led_netdev "eth_act" "LAN act" "yellow:eth" "eth0" "tx rx" + ucidef_set_led_netdev "eth_link" "LAN link" "green:eth" "eth0" "link" + ;; +esac + +board_config_flush + +exit 0 diff --git a/target/linux/mediatek/mt7629/base-files/etc/board.d/02_network b/target/linux/mediatek/mt7629/base-files/etc/board.d/02_network index c39417abb..df042f8ad 100644 --- a/target/linux/mediatek/mt7629/base-files/etc/board.d/02_network +++ b/target/linux/mediatek/mt7629/base-files/etc/board.d/02_network @@ -8,11 +8,18 @@ mediatek_setup_interfaces() local board="$1" case $board in + iptime,a6004mx) + ucidef_set_interfaces_lan_wan "lan1 lan2 lan3 lan4" "eth1" + ;; mediatek,mt7629-rfb) ucidef_set_interface_wan "eth1" ucidef_add_switch "switch0" \ "0:lan" "1:lan" "2:lan" "3:lan" "6@eth0" ;; + netgear,ex6250-v2|\ + tplink,eap225-v5) + ucidef_set_interface_lan "eth0" + ;; esac } @@ -21,7 +28,15 @@ mediatek_setup_macs() local board="$1" case $board in + netgear,ex6250-v2) + lan_mac=$(mtd_get_mac_ascii Config mac) + label_mac=$lan_mac + ;; esac + + [ -n "$lan_mac" ] && ucidef_set_interface_macaddr "lan" $lan_mac + [ -n "$wan_mac" ] && ucidef_set_interface_macaddr "wan" $wan_mac + [ -n "$label_mac" ] && ucidef_set_label_macaddr $label_mac } board_config_update diff --git a/target/linux/mediatek/mt7629/base-files/etc/init.d/bootcount b/target/linux/mediatek/mt7629/base-files/etc/init.d/bootcount new file mode 100755 index 000000000..a6b8fac1d --- /dev/null +++ b/target/linux/mediatek/mt7629/base-files/etc/init.d/bootcount @@ -0,0 +1,17 @@ +#!/bin/sh /etc/rc.common +# SPDX-License-Identifier: GPL-2.0-only + +START=99 + +boot() { + case $(board_name) in + iptime,a6004mx) + if [ `fw_printenv boot_sector` = "boot_sector=B" ]; then + echo "bootcount: boot_sector must be A. Rebooting..." + fw_setenv boot_sector A + reboot + exit 1 + fi + ;; + esac +} diff --git a/target/linux/mediatek/mt7629/base-files/lib/upgrade/platform.sh b/target/linux/mediatek/mt7629/base-files/lib/upgrade/platform.sh index 9a613c43b..f10ad14b4 100755 --- a/target/linux/mediatek/mt7629/base-files/lib/upgrade/platform.sh +++ b/target/linux/mediatek/mt7629/base-files/lib/upgrade/platform.sh @@ -9,6 +9,9 @@ platform_do_upgrade() { local board=$(board_name) case "$board" in + iptime,a6004mx) + nand_do_upgrade "$1" + ;; *) default_do_upgrade "$1" ;; diff --git a/target/linux/mediatek/mt7629/config-5.15 b/target/linux/mediatek/mt7629/config-5.15 deleted file mode 100644 index fcf7ae32f..000000000 --- a/target/linux/mediatek/mt7629/config-5.15 +++ /dev/null @@ -1,328 +0,0 @@ -CONFIG_AF_UNIX_OOB=y -CONFIG_ALIGNMENT_TRAP=y -CONFIG_ARCH_32BIT_OFF_T=y -CONFIG_ARCH_HIBERNATION_POSSIBLE=y -CONFIG_ARCH_KEEP_MEMBLOCK=y -CONFIG_ARCH_MEDIATEK=y -CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y -CONFIG_ARCH_MULTIPLATFORM=y -CONFIG_ARCH_MULTI_V6_V7=y -CONFIG_ARCH_MULTI_V7=y -CONFIG_ARCH_NR_GPIO=0 -CONFIG_ARCH_OPTIONAL_KERNEL_RWX=y -CONFIG_ARCH_OPTIONAL_KERNEL_RWX_DEFAULT=y -CONFIG_ARCH_SELECT_MEMORY_MODEL=y -CONFIG_ARCH_SPARSEMEM_ENABLE=y -CONFIG_ARCH_SUSPEND_POSSIBLE=y -CONFIG_ARM=y -CONFIG_ARM_ARCH_TIMER=y -CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y -CONFIG_ARM_CRYPTO=y -CONFIG_ARM_GIC=y -CONFIG_ARM_HAS_SG_CHAIN=y -CONFIG_ARM_HEAVY_MB=y -CONFIG_ARM_L1_CACHE_SHIFT=6 -CONFIG_ARM_L1_CACHE_SHIFT_6=y -CONFIG_ARM_PATCH_IDIV=y -CONFIG_ARM_PATCH_PHYS_VIRT=y -CONFIG_ARM_THUMB=y -CONFIG_ARM_UNWIND=y -CONFIG_ARM_VIRT_EXT=y -CONFIG_ATAGS=y -CONFIG_AUTO_ZRELADDR=y -CONFIG_BINARY_PRINTF=y -CONFIG_BINFMT_FLAT_ARGVP_ENVP_ON_STACK=y -CONFIG_BLK_DEV_SD=y -CONFIG_BLK_MQ_PCI=y -CONFIG_BLK_PM=y -CONFIG_BSD_PROCESS_ACCT=y -CONFIG_BSD_PROCESS_ACCT_V3=y -CONFIG_CACHE_L2X0=y -# CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE is not set -CONFIG_CC_OPTIMIZE_FOR_SIZE=y -CONFIG_CHR_DEV_SCH=y -CONFIG_CLKSRC_MMIO=y -CONFIG_CLONE_BACKWARDS=y -CONFIG_CMDLINE="rootfstype=squashfs,jffs2" -CONFIG_CMDLINE_FROM_BOOTLOADER=y -CONFIG_CMDLINE_OVERRIDE=y -CONFIG_COMMON_CLK=y -CONFIG_COMMON_CLK_MEDIATEK=y -# CONFIG_COMMON_CLK_MT2701 is not set -# CONFIG_COMMON_CLK_MT7622 is not set -CONFIG_COMMON_CLK_MT7629=y -CONFIG_COMMON_CLK_MT7629_ETHSYS=y -CONFIG_COMMON_CLK_MT7629_HIFSYS=y -# CONFIG_COMMON_CLK_MT7981 is not set -# CONFIG_COMMON_CLK_MT7986 is not set -# CONFIG_COMMON_CLK_MT7988 is not set -# CONFIG_COMMON_CLK_MT8135 is not set -# CONFIG_COMMON_CLK_MT8173 is not set -CONFIG_COMMON_CLK_MT8516=y -# CONFIG_COMMON_CLK_MT8516_AUDSYS is not set -CONFIG_COMPAT_32BIT_TIME=y -CONFIG_CPU_32v6K=y -CONFIG_CPU_32v7=y -CONFIG_CPU_ABRT_EV7=y -CONFIG_CPU_CACHE_V7=y -CONFIG_CPU_CACHE_VIPT=y -CONFIG_CPU_COPY_V6=y -CONFIG_CPU_CP15=y -CONFIG_CPU_CP15_MMU=y -CONFIG_CPU_HAS_ASID=y -CONFIG_CPU_IDLE=y -CONFIG_CPU_IDLE_GOV_MENU=y -CONFIG_CPU_PABRT_V7=y -CONFIG_CPU_PM=y -CONFIG_CPU_RMAP=y -CONFIG_CPU_SPECTRE=y -CONFIG_CPU_THUMB_CAPABLE=y -CONFIG_CPU_TLB_V7=y -CONFIG_CPU_V7=y -CONFIG_CRC16=y -CONFIG_CRYPTO_BLAKE2S_ARM=y -CONFIG_CRYPTO_DEFLATE=y -CONFIG_CRYPTO_HASH_INFO=y -CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y -CONFIG_CRYPTO_LZO=y -CONFIG_CRYPTO_RNG2=y -CONFIG_CRYPTO_ZSTD=y -CONFIG_DCACHE_WORD_ACCESS=y -CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S" -CONFIG_DEBUG_MISC=y -CONFIG_DEFAULT_HOSTNAME="(mt7629)" -CONFIG_DIMLIB=y -CONFIG_DMA_OPS=y -CONFIG_DMA_REMAP=y -CONFIG_DTC=y -CONFIG_EDAC_ATOMIC_SCRUB=y -CONFIG_EDAC_SUPPORT=y -CONFIG_EINT_MTK=y -CONFIG_FIXED_PHY=y -CONFIG_FIX_EARLYCON_MEM=y -CONFIG_FWNODE_MDIO=y -CONFIG_FW_LOADER_PAGED_BUF=y -CONFIG_GENERIC_ALLOCATOR=y -CONFIG_GENERIC_ARCH_TOPOLOGY=y -CONFIG_GENERIC_BUG=y -CONFIG_GENERIC_CLOCKEVENTS=y -CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y -CONFIG_GENERIC_CPU_AUTOPROBE=y -CONFIG_GENERIC_CPU_VULNERABILITIES=y -CONFIG_GENERIC_EARLY_IOREMAP=y -CONFIG_GENERIC_GETTIMEOFDAY=y -CONFIG_GENERIC_IDLE_POLL_SETUP=y -CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y -CONFIG_GENERIC_IRQ_MIGRATION=y -CONFIG_GENERIC_IRQ_MULTI_HANDLER=y -CONFIG_GENERIC_IRQ_SHOW=y -CONFIG_GENERIC_IRQ_SHOW_LEVEL=y -CONFIG_GENERIC_LIB_DEVMEM_IS_ALLOWED=y -CONFIG_GENERIC_MSI_IRQ=y -CONFIG_GENERIC_MSI_IRQ_DOMAIN=y -CONFIG_GENERIC_PCI_IOMAP=y -CONFIG_GENERIC_PHY=y -CONFIG_GENERIC_PINCONF=y -CONFIG_GENERIC_PINCTRL_GROUPS=y -CONFIG_GENERIC_PINMUX_FUNCTIONS=y -CONFIG_GENERIC_SCHED_CLOCK=y -CONFIG_GENERIC_SMP_IDLE_THREAD=y -CONFIG_GENERIC_STRNCPY_FROM_USER=y -CONFIG_GENERIC_STRNLEN_USER=y -CONFIG_GENERIC_TIME_VSYSCALL=y -CONFIG_GENERIC_VDSO_32=y -CONFIG_GPIO_CDEV=y -CONFIG_HANDLE_DOMAIN_IRQ=y -# CONFIG_HARDENED_USERCOPY is not set -CONFIG_HARDEN_BRANCH_PREDICTOR=y -CONFIG_HARDIRQS_SW_RESEND=y -CONFIG_HAS_DMA=y -CONFIG_HAS_IOMEM=y -CONFIG_HAS_IOPORT_MAP=y -CONFIG_HAVE_SMP=y -CONFIG_HOTPLUG_CPU=y -CONFIG_HW_RANDOM=y -CONFIG_HW_RANDOM_MTK=y -CONFIG_HZ_FIXED=0 -CONFIG_INITRAMFS_SOURCE="" -CONFIG_IO_URING=y -CONFIG_IRQCHIP=y -CONFIG_IRQ_DOMAIN=y -CONFIG_IRQ_DOMAIN_HIERARCHY=y -CONFIG_IRQ_FORCED_THREADING=y -CONFIG_IRQ_TIME_ACCOUNTING=y -CONFIG_IRQ_WORK=y -# CONFIG_LEDS_BRIGHTNESS_HW_CHANGED is not set -CONFIG_LIBFDT=y -CONFIG_LOCK_DEBUGGING_SUPPORT=y -CONFIG_LOCK_SPIN_ON_OWNER=y -CONFIG_LTO_NONE=y -CONFIG_LZO_COMPRESS=y -CONFIG_LZO_DECOMPRESS=y -# CONFIG_MACH_MT2701 is not set -# CONFIG_MACH_MT6589 is not set -# CONFIG_MACH_MT6592 is not set -# CONFIG_MACH_MT7623 is not set -CONFIG_MACH_MT7629=y -# CONFIG_MACH_MT8127 is not set -# CONFIG_MACH_MT8135 is not set -CONFIG_MDIO_BUS=y -CONFIG_MDIO_DEVICE=y -CONFIG_MDIO_DEVRES=y -CONFIG_MEDIATEK_WATCHDOG=y -CONFIG_MEMFD_CREATE=y -CONFIG_MFD_SYSCON=y -CONFIG_MIGHT_HAVE_CACHE_L2X0=y -CONFIG_MIGRATION=y -CONFIG_MODULES_USE_ELF_REL=y -CONFIG_MTD_NAND_CORE=y -CONFIG_MTD_NAND_ECC=y -CONFIG_MTD_NAND_ECC_MEDIATEK=y -CONFIG_MTD_NAND_ECC_SW_HAMMING=y -CONFIG_MTD_NAND_MTK_BMT=y -CONFIG_MTD_RAW_NAND=y -CONFIG_MTD_SPI_NAND=y -CONFIG_MTD_SPI_NOR=y -CONFIG_MTD_SPLIT_FIRMWARE=y -CONFIG_MTD_SPLIT_FIT_FW=y -CONFIG_MTD_UBI=y -CONFIG_MTD_UBI_BEB_LIMIT=20 -CONFIG_MTD_UBI_BLOCK=y -CONFIG_MTD_UBI_WL_THRESHOLD=4096 -# CONFIG_MTK_CMDQ is not set -# CONFIG_MTK_EFUSE is not set -CONFIG_MTK_INFRACFG=y -# CONFIG_MTK_PMIC_WRAP is not set -CONFIG_MTK_SCPSYS=y -CONFIG_MTK_SCPSYS_PM_DOMAINS=y -CONFIG_MTK_TIMER=y -CONFIG_MUTEX_SPIN_ON_OWNER=y -CONFIG_NEED_DMA_MAP_STATE=y -CONFIG_NETFILTER=y -CONFIG_NET_DEVLINK=y -CONFIG_NET_DSA=y -CONFIG_NET_DSA_MT7530=y -CONFIG_NET_DSA_MT7530_MDIO=y -# CONFIG_NET_DSA_MT7530_MMIO is not set -CONFIG_NET_DSA_TAG_MTK=y -CONFIG_NET_FLOW_LIMIT=y -CONFIG_NET_MEDIATEK_SOC=y -CONFIG_NET_MEDIATEK_SOC_WED=y -CONFIG_NET_SELFTESTS=y -CONFIG_NET_SOCK_MSG=y -CONFIG_NET_SWITCHDEV=y -CONFIG_NET_VENDOR_MEDIATEK=y -CONFIG_NLS=y -CONFIG_NO_HZ_COMMON=y -CONFIG_NO_HZ_IDLE=y -CONFIG_NR_CPUS=2 -CONFIG_NVMEM=y -CONFIG_NVMEM_SYSFS=y -CONFIG_OF=y -CONFIG_OF_ADDRESS=y -CONFIG_OF_EARLY_FLATTREE=y -CONFIG_OF_FLATTREE=y -CONFIG_OF_GPIO=y -CONFIG_OF_IRQ=y -CONFIG_OF_KOBJ=y -CONFIG_OF_MDIO=y -CONFIG_OLD_SIGACTION=y -CONFIG_OLD_SIGSUSPEND3=y -CONFIG_OUTER_CACHE=y -CONFIG_OUTER_CACHE_SYNC=y -CONFIG_PADATA=y -CONFIG_PAGE_OFFSET=0xC0000000 -CONFIG_PCI=y -CONFIG_PCIEAER=y -CONFIG_PCIEPORTBUS=y -CONFIG_PCIE_MEDIATEK=y -CONFIG_PCIE_PME=y -CONFIG_PCI_DOMAINS=y -CONFIG_PCI_DOMAINS_GENERIC=y -CONFIG_PCI_MSI=y -CONFIG_PCI_MSI_IRQ_DOMAIN=y -CONFIG_PERF_USE_VMALLOC=y -CONFIG_PGTABLE_LEVELS=2 -CONFIG_PHYLIB=y -CONFIG_PHYLINK=y -CONFIG_PHY_MTK_TPHY=y -# CONFIG_PHY_MTK_UFS is not set -# CONFIG_PHY_MTK_XSPHY is not set -CONFIG_PINCTRL=y -CONFIG_PINCTRL_MT7629=y -# CONFIG_PINCTRL_MT7986 is not set -CONFIG_PINCTRL_MTK_MOORE=y -CONFIG_PINCTRL_MTK_V2=y -CONFIG_PM=y -CONFIG_PM_CLK=y -CONFIG_PM_GENERIC_DOMAINS=y -CONFIG_PM_GENERIC_DOMAINS_OF=y -CONFIG_PTP_1588_CLOCK_OPTIONAL=y -CONFIG_PWM=y -CONFIG_PWM_MEDIATEK=y -# CONFIG_PWM_MTK_DISP is not set -CONFIG_PWM_SYSFS=y -CONFIG_RAS=y -CONFIG_RATIONAL=y -CONFIG_REGMAP=y -CONFIG_REGMAP_MMIO=y -CONFIG_RESET_CONTROLLER=y -CONFIG_RFS_ACCEL=y -CONFIG_RPS=y -# CONFIG_RTL8367S_GSW is not set -CONFIG_RWSEM_SPIN_ON_OWNER=y -CONFIG_SCSI=y -CONFIG_SCSI_COMMON=y -CONFIG_SERIAL_8250_FSL=y -CONFIG_SERIAL_8250_MT6577=y -CONFIG_SERIAL_8250_NR_UARTS=3 -CONFIG_SERIAL_8250_RUNTIME_UARTS=3 -CONFIG_SERIAL_MCTRL_GPIO=y -CONFIG_SERIAL_OF_PLATFORM=y -CONFIG_SGL_ALLOC=y -CONFIG_SG_POOL=y -CONFIG_SMP=y -CONFIG_SMP_ON_UP=y -CONFIG_SOCK_RX_QUEUE_MAPPING=y -CONFIG_SPARSE_IRQ=y -CONFIG_SPI=y -CONFIG_SPI_MASTER=y -CONFIG_SPI_MEM=y -CONFIG_SPI_MT65XX=y -CONFIG_SPI_MTK_NOR=y -CONFIG_SPI_MTK_SNFI=y -CONFIG_SRCU=y -CONFIG_STACKTRACE=y -# CONFIG_SWAP is not set -CONFIG_SWCONFIG=y -CONFIG_SWPHY=y -CONFIG_SWP_EMULATE=y -CONFIG_SYS_SUPPORTS_APM_EMULATION=y -CONFIG_TICK_CPU_ACCOUNTING=y -CONFIG_TIMER_OF=y -CONFIG_TIMER_PROBE=y -CONFIG_TREE_RCU=y -CONFIG_TREE_SRCU=y -CONFIG_UBIFS_FS=y -CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h" -CONFIG_UNWINDER_ARM=y -CONFIG_USB=y -CONFIG_USB_COMMON=y -CONFIG_USB_SUPPORT=y -CONFIG_USB_XHCI_HCD=y -CONFIG_USB_XHCI_MTK=y -# CONFIG_USB_XHCI_PLATFORM is not set -CONFIG_USE_OF=y -# CONFIG_VFP is not set -CONFIG_WATCHDOG_CORE=y -# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set -CONFIG_XPS=y -CONFIG_XXHASH=y -CONFIG_XZ_DEC_ARM=y -CONFIG_XZ_DEC_BCJ=y -CONFIG_ZBOOT_ROM_BSS=0 -CONFIG_ZBOOT_ROM_TEXT=0 -CONFIG_ZLIB_DEFLATE=y -CONFIG_ZLIB_INFLATE=y -CONFIG_ZSTD_COMPRESS=y -CONFIG_ZSTD_DECOMPRESS=y diff --git a/target/linux/mediatek/mt7629/config-6.1 b/target/linux/mediatek/mt7629/config-6.1 deleted file mode 100644 index c0c501e59..000000000 --- a/target/linux/mediatek/mt7629/config-6.1 +++ /dev/null @@ -1,349 +0,0 @@ -CONFIG_ALIGNMENT_TRAP=y -CONFIG_ARCH_32BIT_OFF_T=y -CONFIG_ARCH_FORCE_MAX_ORDER=11 -CONFIG_ARCH_HIBERNATION_POSSIBLE=y -CONFIG_ARCH_KEEP_MEMBLOCK=y -CONFIG_ARCH_MEDIATEK=y -CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y -CONFIG_ARCH_MULTIPLATFORM=y -CONFIG_ARCH_MULTI_V6_V7=y -CONFIG_ARCH_MULTI_V7=y -CONFIG_ARCH_NR_GPIO=0 -CONFIG_ARCH_OPTIONAL_KERNEL_RWX=y -CONFIG_ARCH_OPTIONAL_KERNEL_RWX_DEFAULT=y -CONFIG_ARCH_SELECT_MEMORY_MODEL=y -CONFIG_ARCH_SPARSEMEM_ENABLE=y -CONFIG_ARCH_SUSPEND_POSSIBLE=y -CONFIG_ARM=y -CONFIG_ARM_ARCH_TIMER=y -CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y -CONFIG_ARM_GIC=y -CONFIG_ARM_HAS_GROUP_RELOCS=y -CONFIG_ARM_HEAVY_MB=y -CONFIG_ARM_L1_CACHE_SHIFT=6 -CONFIG_ARM_L1_CACHE_SHIFT_6=y -CONFIG_ARM_PATCH_IDIV=y -CONFIG_ARM_PATCH_PHYS_VIRT=y -CONFIG_ARM_THUMB=y -CONFIG_ARM_UNWIND=y -CONFIG_ARM_VIRT_EXT=y -CONFIG_ATAGS=y -CONFIG_AUTO_ZRELADDR=y -CONFIG_BINFMT_FLAT_ARGVP_ENVP_ON_STACK=y -CONFIG_BLK_DEV_SD=y -CONFIG_BLK_MQ_PCI=y -CONFIG_BLK_PM=y -CONFIG_BSD_PROCESS_ACCT=y -CONFIG_BSD_PROCESS_ACCT_V3=y -CONFIG_CACHE_L2X0=y -CONFIG_CC_HAVE_STACKPROTECTOR_TLS=y -CONFIG_CC_IMPLICIT_FALLTHROUGH="-Wimplicit-fallthrough=5" -CONFIG_CC_NO_ARRAY_BOUNDS=y -# CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE is not set -CONFIG_CC_OPTIMIZE_FOR_SIZE=y -CONFIG_CHR_DEV_SCH=y -CONFIG_CLKSRC_MMIO=y -CONFIG_CLONE_BACKWARDS=y -CONFIG_CMDLINE="rootfstype=squashfs,jffs2" -CONFIG_CMDLINE_FROM_BOOTLOADER=y -CONFIG_CMDLINE_OVERRIDE=y -CONFIG_COMMON_CLK=y -CONFIG_COMMON_CLK_MEDIATEK=y -# CONFIG_COMMON_CLK_MT2701 is not set -# CONFIG_COMMON_CLK_MT6795 is not set -# CONFIG_COMMON_CLK_MT7622 is not set -CONFIG_COMMON_CLK_MT7629=y -CONFIG_COMMON_CLK_MT7629_ETHSYS=y -CONFIG_COMMON_CLK_MT7629_HIFSYS=y -# CONFIG_COMMON_CLK_MT7981 is not set -# CONFIG_COMMON_CLK_MT7986 is not set -# CONFIG_COMMON_CLK_MT7988 is not set -# CONFIG_COMMON_CLK_MT8135 is not set -# CONFIG_COMMON_CLK_MT8173 is not set -# CONFIG_COMMON_CLK_MT8365 is not set -# CONFIG_COMMON_CLK_MT8516 is not set -CONFIG_COMPACT_UNEVICTABLE_DEFAULT=1 -CONFIG_COMPAT_32BIT_TIME=y -CONFIG_CONTEXT_TRACKING=y -CONFIG_CONTEXT_TRACKING_IDLE=y -CONFIG_CPU_32v6K=y -CONFIG_CPU_32v7=y -CONFIG_CPU_ABRT_EV7=y -CONFIG_CPU_CACHE_V7=y -CONFIG_CPU_CACHE_VIPT=y -CONFIG_CPU_COPY_V6=y -CONFIG_CPU_CP15=y -CONFIG_CPU_CP15_MMU=y -CONFIG_CPU_HAS_ASID=y -CONFIG_CPU_IDLE=y -CONFIG_CPU_IDLE_GOV_MENU=y -CONFIG_CPU_LITTLE_ENDIAN=y -CONFIG_CPU_PABRT_V7=y -CONFIG_CPU_PM=y -CONFIG_CPU_RMAP=y -CONFIG_CPU_SPECTRE=y -CONFIG_CPU_THUMB_CAPABLE=y -CONFIG_CPU_TLB_V7=y -CONFIG_CPU_V7=y -CONFIG_CRC16=y -CONFIG_CRYPTO_DEFLATE=y -CONFIG_CRYPTO_HASH_INFO=y -CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y -CONFIG_CRYPTO_LIB_SHA1=y -CONFIG_CRYPTO_LIB_UTILS=y -CONFIG_CRYPTO_LZO=y -CONFIG_CRYPTO_RNG2=y -CONFIG_CRYPTO_ZSTD=y -CONFIG_CURRENT_POINTER_IN_TPIDRURO=y -CONFIG_DCACHE_WORD_ACCESS=y -CONFIG_DEBUG_INFO=y -CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S" -CONFIG_DEBUG_MISC=y -CONFIG_DEFAULT_HOSTNAME="(mt7629)" -CONFIG_DIMLIB=y -CONFIG_DMA_OPS=y -CONFIG_DTC=y -CONFIG_EDAC_ATOMIC_SCRUB=y -CONFIG_EDAC_SUPPORT=y -CONFIG_EINT_MTK=y -CONFIG_EXCLUSIVE_SYSTEM_RAM=y -CONFIG_FIXED_PHY=y -CONFIG_FIX_EARLYCON_MEM=y -CONFIG_FRAME_WARN=1024 -CONFIG_FWNODE_MDIO=y -CONFIG_FW_LOADER_PAGED_BUF=y -CONFIG_FW_LOADER_SYSFS=y -CONFIG_GCC11_NO_ARRAY_BOUNDS=y -CONFIG_GENERIC_ALLOCATOR=y -CONFIG_GENERIC_ARCH_TOPOLOGY=y -CONFIG_GENERIC_BUG=y -CONFIG_GENERIC_CLOCKEVENTS=y -CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y -CONFIG_GENERIC_CPU_AUTOPROBE=y -CONFIG_GENERIC_CPU_VULNERABILITIES=y -CONFIG_GENERIC_EARLY_IOREMAP=y -CONFIG_GENERIC_GETTIMEOFDAY=y -CONFIG_GENERIC_IDLE_POLL_SETUP=y -CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y -CONFIG_GENERIC_IRQ_MIGRATION=y -CONFIG_GENERIC_IRQ_MULTI_HANDLER=y -CONFIG_GENERIC_IRQ_SHOW=y -CONFIG_GENERIC_IRQ_SHOW_LEVEL=y -CONFIG_GENERIC_LIB_DEVMEM_IS_ALLOWED=y -CONFIG_GENERIC_MSI_IRQ=y -CONFIG_GENERIC_MSI_IRQ_DOMAIN=y -CONFIG_GENERIC_PCI_IOMAP=y -CONFIG_GENERIC_PHY=y -CONFIG_GENERIC_PINCONF=y -CONFIG_GENERIC_PINCTRL_GROUPS=y -CONFIG_GENERIC_PINMUX_FUNCTIONS=y -CONFIG_GENERIC_SCHED_CLOCK=y -CONFIG_GENERIC_SMP_IDLE_THREAD=y -CONFIG_GENERIC_STRNCPY_FROM_USER=y -CONFIG_GENERIC_STRNLEN_USER=y -CONFIG_GENERIC_TIME_VSYSCALL=y -CONFIG_GENERIC_VDSO_32=y -CONFIG_GPIO_CDEV=y -CONFIG_GRO_CELLS=y -CONFIG_HARDEN_BRANCH_PREDICTOR=y -CONFIG_HARDIRQS_SW_RESEND=y -CONFIG_HAS_DMA=y -CONFIG_HAS_IOMEM=y -CONFIG_HAS_IOPORT_MAP=y -CONFIG_HAVE_SMP=y -CONFIG_HOTPLUG_CPU=y -CONFIG_HW_RANDOM=y -CONFIG_HW_RANDOM_MTK=y -CONFIG_HZ_FIXED=0 -CONFIG_INITRAMFS_SOURCE="" -CONFIG_IRQCHIP=y -CONFIG_IRQSTACKS=y -CONFIG_IRQ_DOMAIN=y -CONFIG_IRQ_DOMAIN_HIERARCHY=y -CONFIG_IRQ_FORCED_THREADING=y -CONFIG_IRQ_TIME_ACCOUNTING=y -CONFIG_IRQ_WORK=y -# CONFIG_LEDS_BRIGHTNESS_HW_CHANGED is not set -CONFIG_LIBFDT=y -CONFIG_LOCK_DEBUGGING_SUPPORT=y -CONFIG_LOCK_SPIN_ON_OWNER=y -CONFIG_LZO_COMPRESS=y -CONFIG_LZO_DECOMPRESS=y -# CONFIG_MACH_MT2701 is not set -# CONFIG_MACH_MT6589 is not set -# CONFIG_MACH_MT6592 is not set -# CONFIG_MACH_MT7623 is not set -CONFIG_MACH_MT7629=y -# CONFIG_MACH_MT8127 is not set -# CONFIG_MACH_MT8135 is not set -CONFIG_MDIO_BUS=y -CONFIG_MDIO_DEVICE=y -CONFIG_MDIO_DEVRES=y -CONFIG_MEDIATEK_GE_PHY=y -CONFIG_MEDIATEK_WATCHDOG=y -CONFIG_MEMFD_CREATE=y -CONFIG_MFD_SYSCON=y -CONFIG_MIGHT_HAVE_CACHE_L2X0=y -CONFIG_MIGRATION=y -CONFIG_MODULES_USE_ELF_REL=y -CONFIG_MTD_NAND_CORE=y -CONFIG_MTD_NAND_ECC=y -CONFIG_MTD_NAND_ECC_MEDIATEK=y -CONFIG_MTD_NAND_ECC_SW_HAMMING=y -CONFIG_MTD_NAND_MTK_BMT=y -CONFIG_MTD_RAW_NAND=y -CONFIG_MTD_SPI_NAND=y -CONFIG_MTD_SPI_NOR=y -CONFIG_MTD_SPLIT_FIRMWARE=y -CONFIG_MTD_SPLIT_FIT_FW=y -CONFIG_MTD_UBI=y -CONFIG_MTD_UBI_BEB_LIMIT=20 -CONFIG_MTD_UBI_BLOCK=y -CONFIG_MTD_UBI_WL_THRESHOLD=4096 -# CONFIG_MTK_CMDQ is not set -CONFIG_MTK_INFRACFG=y -# CONFIG_MTK_PMIC_WRAP is not set -CONFIG_MTK_SCPSYS=y -CONFIG_MTK_SCPSYS_PM_DOMAINS=y -CONFIG_MTK_TIMER=y -CONFIG_MUTEX_SPIN_ON_OWNER=y -CONFIG_NEED_DMA_MAP_STATE=y -CONFIG_NETFILTER=y -CONFIG_NET_DEVLINK=y -CONFIG_NET_DSA=y -CONFIG_NET_DSA_MT7530=y -CONFIG_NET_DSA_MT7530_MDIO=y -# CONFIG_NET_DSA_MT7530_MMIO is not set -CONFIG_NET_DSA_TAG_MTK=y -CONFIG_NET_FLOW_LIMIT=y -CONFIG_NET_MEDIATEK_SOC=y -CONFIG_NET_MEDIATEK_SOC_WED=y -CONFIG_NET_SELFTESTS=y -CONFIG_NET_SWITCHDEV=y -CONFIG_NET_VENDOR_MEDIATEK=y -CONFIG_NLS=y -CONFIG_NO_HZ_COMMON=y -CONFIG_NO_HZ_IDLE=y -CONFIG_NR_CPUS=2 -CONFIG_NVMEM=y -# CONFIG_NVMEM_MTK_EFUSE is not set -CONFIG_NVMEM_SYSFS=y -CONFIG_OF=y -CONFIG_OF_ADDRESS=y -CONFIG_OF_EARLY_FLATTREE=y -CONFIG_OF_FLATTREE=y -CONFIG_OF_GPIO=y -CONFIG_OF_IRQ=y -CONFIG_OF_KOBJ=y -CONFIG_OF_MDIO=y -CONFIG_OLD_SIGACTION=y -CONFIG_OLD_SIGSUSPEND3=y -CONFIG_OUTER_CACHE=y -CONFIG_OUTER_CACHE_SYNC=y -CONFIG_PADATA=y -CONFIG_PAGE_OFFSET=0xC0000000 -CONFIG_PAGE_POOL=y -CONFIG_PAGE_POOL_STATS=y -CONFIG_PAGE_SIZE_LESS_THAN_256KB=y -CONFIG_PAGE_SIZE_LESS_THAN_64KB=y -CONFIG_PCI=y -CONFIG_PCIEAER=y -CONFIG_PCIEPORTBUS=y -CONFIG_PCIE_MEDIATEK=y -CONFIG_PCIE_PME=y -CONFIG_PCI_DOMAINS=y -CONFIG_PCI_DOMAINS_GENERIC=y -CONFIG_PCI_MSI=y -CONFIG_PCI_MSI_IRQ_DOMAIN=y -CONFIG_PCS_MTK_LYNXI=y -CONFIG_PERF_USE_VMALLOC=y -CONFIG_PGTABLE_LEVELS=2 -CONFIG_PHYLIB=y -CONFIG_PHYLINK=y -# CONFIG_PHY_MTK_DP is not set -# CONFIG_PHY_MTK_PCIE is not set -CONFIG_PHY_MTK_TPHY=y -# CONFIG_PHY_MTK_UFS is not set -# CONFIG_PHY_MTK_XSPHY is not set -CONFIG_PINCTRL=y -CONFIG_PINCTRL_MT7629=y -CONFIG_PINCTRL_MTK_MOORE=y -CONFIG_PINCTRL_MTK_V2=y -CONFIG_PM=y -CONFIG_PM_CLK=y -CONFIG_PM_GENERIC_DOMAINS=y -CONFIG_PM_GENERIC_DOMAINS_OF=y -CONFIG_PREEMPT_NONE_BUILD=y -CONFIG_PTP_1588_CLOCK_OPTIONAL=y -CONFIG_PWM=y -CONFIG_PWM_MEDIATEK=y -# CONFIG_PWM_MTK_DISP is not set -CONFIG_PWM_SYSFS=y -CONFIG_RANDSTRUCT_NONE=y -CONFIG_RAS=y -CONFIG_RATIONAL=y -CONFIG_REGMAP=y -CONFIG_REGMAP_MMIO=y -CONFIG_RESET_CONTROLLER=y -CONFIG_RFS_ACCEL=y -CONFIG_RPS=y -# CONFIG_RTL8367S_GSW is not set -CONFIG_RWSEM_SPIN_ON_OWNER=y -CONFIG_SCSI=y -CONFIG_SCSI_COMMON=y -CONFIG_SERIAL_8250_FSL=y -CONFIG_SERIAL_8250_MT6577=y -CONFIG_SERIAL_8250_NR_UARTS=3 -CONFIG_SERIAL_8250_RUNTIME_UARTS=3 -CONFIG_SERIAL_MCTRL_GPIO=y -CONFIG_SERIAL_OF_PLATFORM=y -CONFIG_SGL_ALLOC=y -CONFIG_SG_POOL=y -CONFIG_SMP=y -CONFIG_SMP_ON_UP=y -CONFIG_SOCK_RX_QUEUE_MAPPING=y -CONFIG_SOFTIRQ_ON_OWN_STACK=y -CONFIG_SPARSE_IRQ=y -CONFIG_SPI=y -CONFIG_SPI_MASTER=y -CONFIG_SPI_MEM=y -CONFIG_SPI_MT65XX=y -CONFIG_SPI_MTK_NOR=y -CONFIG_SPI_MTK_SNFI=y -CONFIG_SRCU=y -CONFIG_STACKTRACE=y -# CONFIG_SWAP is not set -CONFIG_SWCONFIG=y -CONFIG_SWPHY=y -CONFIG_SWP_EMULATE=y -CONFIG_SYS_SUPPORTS_APM_EMULATION=y -CONFIG_THREAD_INFO_IN_TASK=y -CONFIG_TICK_CPU_ACCOUNTING=y -CONFIG_TIMER_OF=y -CONFIG_TIMER_PROBE=y -CONFIG_TREE_RCU=y -CONFIG_TREE_SRCU=y -CONFIG_UBIFS_FS=y -CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h" -CONFIG_UNWINDER_ARM=y -CONFIG_USB=y -CONFIG_USB_COMMON=y -CONFIG_USB_SUPPORT=y -CONFIG_USB_XHCI_HCD=y -CONFIG_USB_XHCI_MTK=y -# CONFIG_USB_XHCI_PLATFORM is not set -CONFIG_USE_OF=y -# CONFIG_VFP is not set -CONFIG_WATCHDOG_CORE=y -# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set -CONFIG_XPS=y -CONFIG_XXHASH=y -CONFIG_XZ_DEC_ARM=y -CONFIG_XZ_DEC_BCJ=y -CONFIG_ZBOOT_ROM_BSS=0 -CONFIG_ZBOOT_ROM_TEXT=0 -CONFIG_ZLIB_DEFLATE=y -CONFIG_ZLIB_INFLATE=y -CONFIG_ZSTD_COMMON=y -CONFIG_ZSTD_COMPRESS=y -CONFIG_ZSTD_DECOMPRESS=y diff --git a/target/linux/mediatek/patches-5.15/100-dts-update-mt7622-rfb1.patch b/target/linux/mediatek/patches-5.15/100-dts-update-mt7622-rfb1.patch deleted file mode 100644 index 7029b2cbf..000000000 --- a/target/linux/mediatek/patches-5.15/100-dts-update-mt7622-rfb1.patch +++ /dev/null @@ -1,119 +0,0 @@ ---- a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts -@@ -1,7 +1,6 @@ - /* -- * Copyright (c) 2017 MediaTek Inc. -- * Author: Ming Huang -- * Sean Wang -+ * Copyright (c) 2018 MediaTek Inc. -+ * Author: Ryder Lee - * - * SPDX-License-Identifier: (GPL-2.0 OR MIT) - */ -@@ -23,7 +22,7 @@ - - chosen { - stdout-path = "serial0:115200n8"; -- bootargs = "earlycon=uart8250,mmio32,0x11002000 swiotlb=512"; -+ bootargs = "earlycon=uart8250,mmio32,0x11002000 console=ttyS0,115200n1 swiotlb=512"; - }; - - cpus { -@@ -40,23 +39,22 @@ - - gpio-keys { - compatible = "gpio-keys"; -- poll-interval = <100>; - - factory { - label = "factory"; - linux,code = ; -- gpios = <&pio 0 0>; -+ gpios = <&pio 0 GPIO_ACTIVE_LOW>; - }; - - wps { - label = "wps"; - linux,code = ; -- gpios = <&pio 102 0>; -+ gpios = <&pio 102 GPIO_ACTIVE_LOW>; - }; - }; - - memory@40000000 { -- reg = <0 0x40000000 0 0x20000000>; -+ reg = <0 0x40000000 0 0x40000000>; - device_type = "memory"; - }; - -@@ -133,22 +131,22 @@ - - port@0 { - reg = <0>; -- label = "lan0"; -+ label = "lan1"; - }; - - port@1 { - reg = <1>; -- label = "lan1"; -+ label = "lan2"; - }; - - port@2 { - reg = <2>; -- label = "lan2"; -+ label = "lan3"; - }; - - port@3 { - reg = <3>; -- label = "lan3"; -+ label = "lan4"; - }; - - port@4 { -@@ -237,15 +235,28 @@ - - &pcie { - pinctrl-names = "default"; -- pinctrl-0 = <&pcie0_pins>; -+ pinctrl-0 = <&pcie0_pins>, <&pcie1_pins>; - status = "okay"; - - pcie@0,0 { - status = "okay"; - }; -+ -+ pcie@1,0 { -+ status = "okay"; -+ }; - }; - - &pio { -+ /* Attention: GPIO 90 is used to switch between PCIe@1,0 and -+ * SATA functions. i.e. output-high: PCIe, output-low: SATA -+ */ -+ asm_sel { -+ gpio-hog; -+ gpios = <90 GPIO_ACTIVE_HIGH>; -+ output-high; -+ }; -+ - /* eMMC is shared pin with parallel NAND */ - emmc_pins_default: emmc-pins-default { - mux { -@@ -522,11 +533,11 @@ - }; - - &sata { -- status = "okay"; -+ status = "disabled"; - }; - - &sata_phy { -- status = "okay"; -+ status = "disabled"; - }; - - &spi0 { diff --git a/target/linux/mediatek/patches-5.15/101-dts-update-mt7629-rfb.patch b/target/linux/mediatek/patches-5.15/101-dts-update-mt7629-rfb.patch deleted file mode 100644 index 254b5f9eb..000000000 --- a/target/linux/mediatek/patches-5.15/101-dts-update-mt7629-rfb.patch +++ /dev/null @@ -1,60 +0,0 @@ ---- a/arch/arm/boot/dts/mt7629-rfb.dts -+++ b/arch/arm/boot/dts/mt7629-rfb.dts -@@ -18,6 +18,7 @@ - - chosen { - stdout-path = "serial0:115200n8"; -+ bootargs = "earlycon=uart8250,mmio32,0x11002000 console=ttyS0,115200n8"; - }; - - gpio-keys { -@@ -70,6 +71,10 @@ - compatible = "mediatek,eth-mac"; - reg = <0>; - phy-mode = "2500base-x"; -+ -+ nvmem-cells = <&macaddr_factory_2a>; -+ nvmem-cell-names = "mac-address"; -+ - fixed-link { - speed = <2500>; - full-duplex; -@@ -82,6 +87,9 @@ - reg = <1>; - phy-mode = "gmii"; - phy-handle = <&phy0>; -+ -+ nvmem-cells = <&macaddr_factory_24>; -+ nvmem-cell-names = "mac-address"; - }; - - mdio: mdio-bus { -@@ -133,8 +141,9 @@ - }; - - partition@b0000 { -- label = "kernel"; -+ label = "firmware"; - reg = <0xb0000 0xb50000>; -+ compatible = "denx,fit"; - }; - }; - }; -@@ -272,3 +281,17 @@ - pinctrl-0 = <&watchdog_pins>; - status = "okay"; - }; -+ -+&factory { -+ compatible = "nvmem-cells"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ macaddr_factory_24: macaddr@24 { -+ reg = <0x24 0x6>; -+ }; -+ -+ macaddr_factory_2a: macaddr@2a { -+ reg = <0x2a 0x6>; -+ }; -+}; diff --git a/target/linux/mediatek/patches-5.15/103-mt7623-enable-arch-timer.patch b/target/linux/mediatek/patches-5.15/103-mt7623-enable-arch-timer.patch deleted file mode 100644 index 04df7b927..000000000 --- a/target/linux/mediatek/patches-5.15/103-mt7623-enable-arch-timer.patch +++ /dev/null @@ -1,20 +0,0 @@ -From d6a596012150960f0f3a214d31bbac4b607dbd1e Mon Sep 17 00:00:00 2001 -From: Chuanhong Guo -Date: Fri, 29 Apr 2022 10:40:56 +0800 -Subject: [PATCH] arm: mediatek: select arch timer for mt7623 - -Signed-off-by: Chuanhong Guo ---- - arch/arm/mach-mediatek/Kconfig | 1 + - 1 file changed, 1 insertion(+) - ---- a/arch/arm/mach-mediatek/Kconfig -+++ b/arch/arm/mach-mediatek/Kconfig -@@ -26,6 +26,7 @@ config MACH_MT6592 - config MACH_MT7623 - bool "MediaTek MT7623 SoCs support" - default ARCH_MEDIATEK -+ select HAVE_ARM_ARCH_TIMER - - config MACH_MT7629 - bool "MediaTek MT7629 SoCs support" diff --git a/target/linux/mediatek/patches-5.15/104-mt7622-add-snor-irq.patch b/target/linux/mediatek/patches-5.15/104-mt7622-add-snor-irq.patch deleted file mode 100644 index 88aab4129..000000000 --- a/target/linux/mediatek/patches-5.15/104-mt7622-add-snor-irq.patch +++ /dev/null @@ -1,10 +0,0 @@ ---- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi -+++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi -@@ -556,6 +556,7 @@ - compatible = "mediatek,mt7622-nor", - "mediatek,mt8173-nor"; - reg = <0 0x11014000 0 0xe0>; -+ interrupts = ; - clocks = <&pericfg CLK_PERI_FLASH_PD>, - <&topckgen CLK_TOP_FLASH_SEL>; - clock-names = "spi", "sf"; diff --git a/target/linux/mediatek/patches-5.15/105-dts-mt7622-enable-pstore.patch b/target/linux/mediatek/patches-5.15/105-dts-mt7622-enable-pstore.patch deleted file mode 100644 index da42c0772..000000000 --- a/target/linux/mediatek/patches-5.15/105-dts-mt7622-enable-pstore.patch +++ /dev/null @@ -1,25 +0,0 @@ ---- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi -+++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi -@@ -111,7 +111,7 @@ - }; - - psci { -- compatible = "arm,psci-0.2"; -+ compatible = "arm,psci-1.0"; - method = "smc"; - }; - -@@ -127,6 +127,13 @@ - #size-cells = <2>; - ranges; - -+ /* 64 KiB reserved for ramoops/pstore */ -+ ramoops@42ff0000 { -+ compatible = "ramoops"; -+ reg = <0 0x42ff0000 0 0x10000>; -+ record-size = <0x1000>; -+ }; -+ - /* 192 KiB reserved for ARM Trusted Firmware (BL31) */ - secmon_reserved: secmon@43000000 { - reg = <0 0x43000000 0 0x30000>; diff --git a/target/linux/mediatek/patches-5.15/110-dts-fix-bpi2-console.patch b/target/linux/mediatek/patches-5.15/110-dts-fix-bpi2-console.patch deleted file mode 100644 index 8dc53d298..000000000 --- a/target/linux/mediatek/patches-5.15/110-dts-fix-bpi2-console.patch +++ /dev/null @@ -1,10 +0,0 @@ ---- a/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts -+++ b/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts -@@ -19,6 +19,7 @@ - - chosen { - stdout-path = "serial2:115200n8"; -+ bootargs = "console=ttyS2,115200n8 console=tty1"; - }; - - connector { diff --git a/target/linux/mediatek/patches-5.15/111-dts-fix-bpi64-console.patch b/target/linux/mediatek/patches-5.15/111-dts-fix-bpi64-console.patch deleted file mode 100644 index 07a2eae24..000000000 --- a/target/linux/mediatek/patches-5.15/111-dts-fix-bpi64-console.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts -@@ -22,7 +22,7 @@ - - chosen { - stdout-path = "serial0:115200n8"; -- bootargs = "earlycon=uart8250,mmio32,0x11002000 swiotlb=512"; -+ bootargs = "earlycon=uart8250,mmio32,0x11002000 console=ttyS0,115200n1 swiotlb=512"; - }; - - cpus { diff --git a/target/linux/mediatek/patches-5.15/112-dts-fix-bpi64-lan-names.patch b/target/linux/mediatek/patches-5.15/112-dts-fix-bpi64-lan-names.patch deleted file mode 100644 index e88913c30..000000000 --- a/target/linux/mediatek/patches-5.15/112-dts-fix-bpi64-lan-names.patch +++ /dev/null @@ -1,37 +0,0 @@ ---- a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts -@@ -18,6 +18,7 @@ - - aliases { - serial0 = &uart0; -+ ethernet0 = &gmac0; - }; - - chosen { -@@ -161,22 +162,22 @@ - - port@1 { - reg = <1>; -- label = "lan0"; -+ label = "lan1"; - }; - - port@2 { - reg = <2>; -- label = "lan1"; -+ label = "lan2"; - }; - - port@3 { - reg = <3>; -- label = "lan2"; -+ label = "lan3"; - }; - - port@4 { - reg = <4>; -- label = "lan3"; -+ label = "lan4"; - }; - - port@6 { diff --git a/target/linux/mediatek/patches-5.15/113-dts-fix-bpi64-leds-and-buttons.patch b/target/linux/mediatek/patches-5.15/113-dts-fix-bpi64-leds-and-buttons.patch deleted file mode 100644 index f728b9656..000000000 --- a/target/linux/mediatek/patches-5.15/113-dts-fix-bpi64-leds-and-buttons.patch +++ /dev/null @@ -1,56 +0,0 @@ ---- a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts -@@ -19,6 +19,10 @@ - aliases { - serial0 = &uart0; - ethernet0 = &gmac0; -+ led-boot = &led_system_green; -+ led-failsafe = &led_system_blue; -+ led-running = &led_system_green; -+ led-upgrade = &led_system_blue; - }; - - chosen { -@@ -42,8 +46,8 @@ - compatible = "gpio-keys"; - - factory { -- label = "factory"; -- linux,code = ; -+ label = "reset"; -+ linux,code = ; - gpios = <&pio 0 GPIO_ACTIVE_HIGH>; - }; - -@@ -57,17 +61,25 @@ - leds { - compatible = "gpio-leds"; - -- green { -- label = "bpi-r64:pio:green"; -- gpios = <&pio 89 GPIO_ACTIVE_HIGH>; -+ led_system_blue: blue { -+ label = "bpi-r64:pio:blue"; -+ gpios = <&pio 85 GPIO_ACTIVE_HIGH>; - default-state = "off"; - }; - -- red { -- label = "bpi-r64:pio:red"; -- gpios = <&pio 88 GPIO_ACTIVE_HIGH>; -+ led_system_green: green { -+ label = "bpi-r64:pio:green"; -+ gpios = <&pio 89 GPIO_ACTIVE_HIGH>; - default-state = "off"; - }; -+ -+/* -+ * red { -+ * label = "bpi-r64:pio:red"; -+ * gpios = <&pio 88 GPIO_ACTIVE_HIGH>; -+ * default-state = "off"; -+ * }; -+ */ - }; - - memory@40000000 { diff --git a/target/linux/mediatek/patches-5.15/114-dts-bpi64-disable-rtc.patch b/target/linux/mediatek/patches-5.15/114-dts-bpi64-disable-rtc.patch deleted file mode 100644 index 8e19168ac..000000000 --- a/target/linux/mediatek/patches-5.15/114-dts-bpi64-disable-rtc.patch +++ /dev/null @@ -1,21 +0,0 @@ ---- a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts -@@ -565,12 +565,16 @@ - status = "okay"; - }; - -+&rtc { -+ status = "disabled"; -+}; -+ - &sata { -- status = "disable"; -+ status = "disabled"; - }; - - &sata_phy { -- status = "disable"; -+ status = "disabled"; - }; - - &spi0 { diff --git a/target/linux/mediatek/patches-5.15/115-dts-bpi64-add-snand-support.patch b/target/linux/mediatek/patches-5.15/115-dts-bpi64-add-snand-support.patch deleted file mode 100644 index 508dd2b57..000000000 --- a/target/linux/mediatek/patches-5.15/115-dts-bpi64-add-snand-support.patch +++ /dev/null @@ -1,50 +0,0 @@ ---- a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts -@@ -260,14 +260,42 @@ - status = "disabled"; - }; - --&nor_flash { -- pinctrl-names = "default"; -- pinctrl-0 = <&spi_nor_pins>; -- status = "disabled"; -+&bch { -+ status = "okay"; -+}; - -+&snfi { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&serial_nand_pins>; -+ status = "okay"; - flash@0 { -- compatible = "jedec,spi-nor"; -+ compatible = "spi-nand"; - reg = <0>; -+ spi-tx-bus-width = <4>; -+ spi-rx-bus-width = <4>; -+ nand-ecc-engine = <&snfi>; -+ partitions { -+ compatible = "fixed-partitions"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ partition@0 { -+ label = "bl2"; -+ reg = <0x0 0x80000>; -+ read-only; -+ }; -+ -+ partition@80000 { -+ label = "fip"; -+ reg = <0x80000 0x200000>; -+ read-only; -+ }; -+ -+ partition@280000 { -+ label = "ubi"; -+ reg = <0x280000 0x7d80000>; -+ }; -+ }; - }; - }; - diff --git a/target/linux/mediatek/patches-5.15/120-01-v5.18-mtd-nand-ecc-Add-infrastructure-to-support-hardware-.patch b/target/linux/mediatek/patches-5.15/120-01-v5.18-mtd-nand-ecc-Add-infrastructure-to-support-hardware-.patch deleted file mode 100644 index 7fb62e740..000000000 --- a/target/linux/mediatek/patches-5.15/120-01-v5.18-mtd-nand-ecc-Add-infrastructure-to-support-hardware-.patch +++ /dev/null @@ -1,214 +0,0 @@ -From ad4944aa0b02cb043afe20bc2a018c161e65c992 Mon Sep 17 00:00:00 2001 -From: Miquel Raynal -Date: Thu, 16 Dec 2021 12:16:38 +0100 -Subject: [PATCH 01/15] mtd: nand: ecc: Add infrastructure to support hardware - engines - -Add the necessary helpers to register/unregister hardware ECC engines -that will be called from ECC engine drivers. - -Also add helpers to get the right engine from the user -perspective. Keep a reference of the in use ECC engine in order to -prevent modules to be unloaded. Put the reference when the engine gets -retired. - -A static list of hardware (only) ECC engines is setup to keep track of -the registered engines. - -Signed-off-by: Miquel Raynal -Link: https://lore.kernel.org/linux-mtd/20211216111654.238086-13-miquel.raynal@bootlin.com -(cherry picked from commit 96489c1c0b53131b0e1ec33e2060538379ad6152) ---- - drivers/mtd/nand/core.c | 10 +++-- - drivers/mtd/nand/ecc.c | 88 ++++++++++++++++++++++++++++++++++++++++ - include/linux/mtd/nand.h | 28 +++++++++++++ - 3 files changed, 123 insertions(+), 3 deletions(-) - ---- a/drivers/mtd/nand/core.c -+++ b/drivers/mtd/nand/core.c -@@ -232,7 +232,9 @@ static int nanddev_get_ecc_engine(struct - nand->ecc.engine = nand_ecc_get_on_die_hw_engine(nand); - break; - case NAND_ECC_ENGINE_TYPE_ON_HOST: -- pr_err("On-host hardware ECC engines not supported yet\n"); -+ nand->ecc.engine = nand_ecc_get_on_host_hw_engine(nand); -+ if (PTR_ERR(nand->ecc.engine) == -EPROBE_DEFER) -+ return -EPROBE_DEFER; - break; - default: - pr_err("Missing ECC engine type\n"); -@@ -252,7 +254,7 @@ static int nanddev_put_ecc_engine(struct - { - switch (nand->ecc.ctx.conf.engine_type) { - case NAND_ECC_ENGINE_TYPE_ON_HOST: -- pr_err("On-host hardware ECC engines not supported yet\n"); -+ nand_ecc_put_on_host_hw_engine(nand); - break; - case NAND_ECC_ENGINE_TYPE_NONE: - case NAND_ECC_ENGINE_TYPE_SOFT: -@@ -297,7 +299,9 @@ int nanddev_ecc_engine_init(struct nand_ - /* Look for the ECC engine to use */ - ret = nanddev_get_ecc_engine(nand); - if (ret) { -- pr_err("No ECC engine found\n"); -+ if (ret != -EPROBE_DEFER) -+ pr_err("No ECC engine found\n"); -+ - return ret; - } - ---- a/drivers/mtd/nand/ecc.c -+++ b/drivers/mtd/nand/ecc.c -@@ -96,6 +96,12 @@ - #include - #include - #include -+#include -+#include -+#include -+ -+static LIST_HEAD(on_host_hw_engines); -+static DEFINE_MUTEX(on_host_hw_engines_mutex); - - /** - * nand_ecc_init_ctx - Init the ECC engine context -@@ -611,6 +617,88 @@ struct nand_ecc_engine *nand_ecc_get_on_ - } - EXPORT_SYMBOL(nand_ecc_get_on_die_hw_engine); - -+int nand_ecc_register_on_host_hw_engine(struct nand_ecc_engine *engine) -+{ -+ struct nand_ecc_engine *item; -+ -+ if (!engine) -+ return -EINVAL; -+ -+ /* Prevent multiple registrations of one engine */ -+ list_for_each_entry(item, &on_host_hw_engines, node) -+ if (item == engine) -+ return 0; -+ -+ mutex_lock(&on_host_hw_engines_mutex); -+ list_add_tail(&engine->node, &on_host_hw_engines); -+ mutex_unlock(&on_host_hw_engines_mutex); -+ -+ return 0; -+} -+EXPORT_SYMBOL(nand_ecc_register_on_host_hw_engine); -+ -+int nand_ecc_unregister_on_host_hw_engine(struct nand_ecc_engine *engine) -+{ -+ if (!engine) -+ return -EINVAL; -+ -+ mutex_lock(&on_host_hw_engines_mutex); -+ list_del(&engine->node); -+ mutex_unlock(&on_host_hw_engines_mutex); -+ -+ return 0; -+} -+EXPORT_SYMBOL(nand_ecc_unregister_on_host_hw_engine); -+ -+static struct nand_ecc_engine *nand_ecc_match_on_host_hw_engine(struct device *dev) -+{ -+ struct nand_ecc_engine *item; -+ -+ list_for_each_entry(item, &on_host_hw_engines, node) -+ if (item->dev == dev) -+ return item; -+ -+ return NULL; -+} -+ -+struct nand_ecc_engine *nand_ecc_get_on_host_hw_engine(struct nand_device *nand) -+{ -+ struct nand_ecc_engine *engine = NULL; -+ struct device *dev = &nand->mtd.dev; -+ struct platform_device *pdev; -+ struct device_node *np; -+ -+ if (list_empty(&on_host_hw_engines)) -+ return NULL; -+ -+ /* Check for an explicit nand-ecc-engine property */ -+ np = of_parse_phandle(dev->of_node, "nand-ecc-engine", 0); -+ if (np) { -+ pdev = of_find_device_by_node(np); -+ if (!pdev) -+ return ERR_PTR(-EPROBE_DEFER); -+ -+ engine = nand_ecc_match_on_host_hw_engine(&pdev->dev); -+ platform_device_put(pdev); -+ of_node_put(np); -+ -+ if (!engine) -+ return ERR_PTR(-EPROBE_DEFER); -+ } -+ -+ if (engine) -+ get_device(engine->dev); -+ -+ return engine; -+} -+EXPORT_SYMBOL(nand_ecc_get_on_host_hw_engine); -+ -+void nand_ecc_put_on_host_hw_engine(struct nand_device *nand) -+{ -+ put_device(nand->ecc.engine->dev); -+} -+EXPORT_SYMBOL(nand_ecc_put_on_host_hw_engine); -+ - MODULE_LICENSE("GPL"); - MODULE_AUTHOR("Miquel Raynal "); - MODULE_DESCRIPTION("Generic ECC engine"); ---- a/include/linux/mtd/nand.h -+++ b/include/linux/mtd/nand.h -@@ -264,11 +264,35 @@ struct nand_ecc_engine_ops { - }; - - /** -+ * enum nand_ecc_engine_integration - How the NAND ECC engine is integrated -+ * @NAND_ECC_ENGINE_INTEGRATION_INVALID: Invalid value -+ * @NAND_ECC_ENGINE_INTEGRATION_PIPELINED: Pipelined engine, performs on-the-fly -+ * correction, does not need to copy -+ * data around -+ * @NAND_ECC_ENGINE_INTEGRATION_EXTERNAL: External engine, needs to bring the -+ * data into its own area before use -+ */ -+enum nand_ecc_engine_integration { -+ NAND_ECC_ENGINE_INTEGRATION_INVALID, -+ NAND_ECC_ENGINE_INTEGRATION_PIPELINED, -+ NAND_ECC_ENGINE_INTEGRATION_EXTERNAL, -+}; -+ -+/** - * struct nand_ecc_engine - ECC engine abstraction for NAND devices -+ * @dev: Host device -+ * @node: Private field for registration time - * @ops: ECC engine operations -+ * @integration: How the engine is integrated with the host -+ * (only relevant on %NAND_ECC_ENGINE_TYPE_ON_HOST engines) -+ * @priv: Private data - */ - struct nand_ecc_engine { -+ struct device *dev; -+ struct list_head node; - struct nand_ecc_engine_ops *ops; -+ enum nand_ecc_engine_integration integration; -+ void *priv; - }; - - void of_get_nand_ecc_user_config(struct nand_device *nand); -@@ -279,8 +303,12 @@ int nand_ecc_prepare_io_req(struct nand_ - int nand_ecc_finish_io_req(struct nand_device *nand, - struct nand_page_io_req *req); - bool nand_ecc_is_strong_enough(struct nand_device *nand); -+int nand_ecc_register_on_host_hw_engine(struct nand_ecc_engine *engine); -+int nand_ecc_unregister_on_host_hw_engine(struct nand_ecc_engine *engine); - struct nand_ecc_engine *nand_ecc_get_sw_engine(struct nand_device *nand); - struct nand_ecc_engine *nand_ecc_get_on_die_hw_engine(struct nand_device *nand); -+struct nand_ecc_engine *nand_ecc_get_on_host_hw_engine(struct nand_device *nand); -+void nand_ecc_put_on_host_hw_engine(struct nand_device *nand); - - #if IS_ENABLED(CONFIG_MTD_NAND_ECC_SW_HAMMING) - struct nand_ecc_engine *nand_ecc_sw_hamming_get_engine(void); diff --git a/target/linux/mediatek/patches-5.15/120-02-v5.18-mtd-nand-Add-a-new-helper-to-retrieve-the-ECC-contex.patch b/target/linux/mediatek/patches-5.15/120-02-v5.18-mtd-nand-Add-a-new-helper-to-retrieve-the-ECC-contex.patch deleted file mode 100644 index 61a39ee0e..000000000 --- a/target/linux/mediatek/patches-5.15/120-02-v5.18-mtd-nand-Add-a-new-helper-to-retrieve-the-ECC-contex.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 840b2f8dd2d0579e517140e1f9bbc482eaf4ed07 Mon Sep 17 00:00:00 2001 -From: Miquel Raynal -Date: Thu, 16 Dec 2021 12:16:39 +0100 -Subject: [PATCH 02/15] mtd: nand: Add a new helper to retrieve the ECC context - -Introduce nand_to_ecc_ctx() which will allow to easily jump to the -private pointer of an ECC context given a NAND device. This is very -handy, from the prepare or finish ECC hook, to get the internal context -out of the NAND device object. - -Signed-off-by: Miquel Raynal -Link: https://lore.kernel.org/linux-mtd/20211216111654.238086-14-miquel.raynal@bootlin.com -(cherry picked from commit cda32a618debd3fad8e42757b198719ae180f8f4) ---- - include/linux/mtd/nand.h | 5 +++++ - 1 file changed, 5 insertions(+) - ---- a/include/linux/mtd/nand.h -+++ b/include/linux/mtd/nand.h -@@ -990,6 +990,11 @@ int nanddev_markbad(struct nand_device * - int nanddev_ecc_engine_init(struct nand_device *nand); - void nanddev_ecc_engine_cleanup(struct nand_device *nand); - -+static inline void *nand_to_ecc_ctx(struct nand_device *nand) -+{ -+ return nand->ecc.ctx.priv; -+} -+ - /* BBT related functions */ - enum nand_bbt_block_status { - NAND_BBT_BLOCK_STATUS_UNKNOWN, diff --git a/target/linux/mediatek/patches-5.15/120-03-v5.18-mtd-nand-ecc-Provide-a-helper-to-retrieve-a-pileline.patch b/target/linux/mediatek/patches-5.15/120-03-v5.18-mtd-nand-ecc-Provide-a-helper-to-retrieve-a-pileline.patch deleted file mode 100644 index 29b62880a..000000000 --- a/target/linux/mediatek/patches-5.15/120-03-v5.18-mtd-nand-ecc-Provide-a-helper-to-retrieve-a-pileline.patch +++ /dev/null @@ -1,73 +0,0 @@ -From 784866bc4f9f25e0494b77750f95af2a2619e498 Mon Sep 17 00:00:00 2001 -From: Miquel Raynal -Date: Thu, 16 Dec 2021 12:16:41 +0100 -Subject: [PATCH 03/15] mtd: nand: ecc: Provide a helper to retrieve a - pilelined engine device - -In a pipelined engine situation, we might either have the host which -internally has support for error correction, or have it using an -external hardware block for this purpose. In the former case, the host -is also the ECC engine. In the latter case, it is not. In order to get -the right pointers on the right devices (for example: in order to devm_* -allocate variables), let's introduce this helper which can safely be -called by pipelined ECC engines in order to retrieve the right device -structure. - -Signed-off-by: Miquel Raynal -Link: https://lore.kernel.org/linux-mtd/20211216111654.238086-16-miquel.raynal@bootlin.com -(cherry picked from commit 5145abeb0649acf810a32e63bd762e617a9b3309) ---- - drivers/mtd/nand/ecc.c | 31 +++++++++++++++++++++++++++++++ - include/linux/mtd/nand.h | 1 + - 2 files changed, 32 insertions(+) - ---- a/drivers/mtd/nand/ecc.c -+++ b/drivers/mtd/nand/ecc.c -@@ -699,6 +699,37 @@ void nand_ecc_put_on_host_hw_engine(stru - } - EXPORT_SYMBOL(nand_ecc_put_on_host_hw_engine); - -+/* -+ * In the case of a pipelined engine, the device registering the ECC -+ * engine is not necessarily the ECC engine itself but may be a host controller. -+ * It is then useful to provide a helper to retrieve the right device object -+ * which actually represents the ECC engine. -+ */ -+struct device *nand_ecc_get_engine_dev(struct device *host) -+{ -+ struct platform_device *ecc_pdev; -+ struct device_node *np; -+ -+ /* -+ * If the device node contains this property, it means we need to follow -+ * it in order to get the right ECC engine device we are looking for. -+ */ -+ np = of_parse_phandle(host->of_node, "nand-ecc-engine", 0); -+ if (!np) -+ return host; -+ -+ ecc_pdev = of_find_device_by_node(np); -+ if (!ecc_pdev) { -+ of_node_put(np); -+ return NULL; -+ } -+ -+ platform_device_put(ecc_pdev); -+ of_node_put(np); -+ -+ return &ecc_pdev->dev; -+} -+ - MODULE_LICENSE("GPL"); - MODULE_AUTHOR("Miquel Raynal "); - MODULE_DESCRIPTION("Generic ECC engine"); ---- a/include/linux/mtd/nand.h -+++ b/include/linux/mtd/nand.h -@@ -309,6 +309,7 @@ struct nand_ecc_engine *nand_ecc_get_sw_ - struct nand_ecc_engine *nand_ecc_get_on_die_hw_engine(struct nand_device *nand); - struct nand_ecc_engine *nand_ecc_get_on_host_hw_engine(struct nand_device *nand); - void nand_ecc_put_on_host_hw_engine(struct nand_device *nand); -+struct device *nand_ecc_get_engine_dev(struct device *host); - - #if IS_ENABLED(CONFIG_MTD_NAND_ECC_SW_HAMMING) - struct nand_ecc_engine *nand_ecc_sw_hamming_get_engine(void); diff --git a/target/linux/mediatek/patches-5.15/120-04-v5.18-spi-spi-mem-Introduce-a-capability-structure.patch b/target/linux/mediatek/patches-5.15/120-04-v5.18-spi-spi-mem-Introduce-a-capability-structure.patch deleted file mode 100644 index 1e7f572dd..000000000 --- a/target/linux/mediatek/patches-5.15/120-04-v5.18-spi-spi-mem-Introduce-a-capability-structure.patch +++ /dev/null @@ -1,71 +0,0 @@ -From 3e45577e70cbf8fdc5c13033114989794a3797d5 Mon Sep 17 00:00:00 2001 -From: Miquel Raynal -Date: Thu, 27 Jan 2022 10:17:56 +0100 -Subject: [PATCH 04/15] spi: spi-mem: Introduce a capability structure - -Create a spi_controller_mem_caps structure and put it within the -spi_controller structure close to the spi_controller_mem_ops -strucure. So far the only field in this structure is the support for dtr -operations, but soon we will add another parameter. - -Also create a helper to parse the capabilities and check if the -requested capability has been set or not. - -Signed-off-by: Miquel Raynal -Reviewed-by: Pratyush Yadav -Reviewed-by: Boris Brezillon -Reviewed-by: Tudor Ambarus -Reviewed-by: Mark Brown -Link: https://lore.kernel.org/linux-mtd/20220127091808.1043392-2-miquel.raynal@bootlin.com -(cherry picked from commit 4a3cc7fb6e63bcfdedec25364738f1493345bd20) ---- - include/linux/spi/spi-mem.h | 11 +++++++++++ - include/linux/spi/spi.h | 3 +++ - 2 files changed, 14 insertions(+) - ---- a/include/linux/spi/spi-mem.h -+++ b/include/linux/spi/spi-mem.h -@@ -286,6 +286,17 @@ struct spi_controller_mem_ops { - }; - - /** -+ * struct spi_controller_mem_caps - SPI memory controller capabilities -+ * @dtr: Supports DTR operations -+ */ -+struct spi_controller_mem_caps { -+ bool dtr; -+}; -+ -+#define spi_mem_controller_is_capable(ctlr, cap) \ -+ ((ctlr)->mem_caps && (ctlr)->mem_caps->cap) -+ -+/** - * struct spi_mem_driver - SPI memory driver - * @spidrv: inherit from a SPI driver - * @probe: probe a SPI memory. Usually where detection/initialization takes ---- a/include/linux/spi/spi.h -+++ b/include/linux/spi/spi.h -@@ -23,6 +23,7 @@ struct software_node; - struct spi_controller; - struct spi_transfer; - struct spi_controller_mem_ops; -+struct spi_controller_mem_caps; - - /* - * INTERFACES between SPI master-side drivers and SPI slave protocol handlers, -@@ -419,6 +420,7 @@ extern struct spi_device *spi_new_ancill - * @mem_ops: optimized/dedicated operations for interactions with SPI memory. - * This field is optional and should only be implemented if the - * controller has native support for memory like operations. -+ * @mem_caps: controller capabilities for the handling of memory operations. - * @unprepare_message: undo any work done by prepare_message(). - * @slave_abort: abort the ongoing transfer request on an SPI slave controller - * @cs_gpios: LEGACY: array of GPIO descs to use as chip select lines; one per -@@ -643,6 +645,7 @@ struct spi_controller { - - /* Optimized handlers for SPI memory-like operations. */ - const struct spi_controller_mem_ops *mem_ops; -+ const struct spi_controller_mem_caps *mem_caps; - - /* gpio chip select */ - int *cs_gpios; diff --git a/target/linux/mediatek/patches-5.15/120-05-v5.18-spi-spi-mem-Check-the-controller-extra-capabilities.patch b/target/linux/mediatek/patches-5.15/120-05-v5.18-spi-spi-mem-Check-the-controller-extra-capabilities.patch deleted file mode 100644 index 9f01fdb83..000000000 --- a/target/linux/mediatek/patches-5.15/120-05-v5.18-spi-spi-mem-Check-the-controller-extra-capabilities.patch +++ /dev/null @@ -1,51 +0,0 @@ -From c9cae7e1e5c87d0aa76b7bededa5191a0c8cf25a Mon Sep 17 00:00:00 2001 -From: Miquel Raynal -Date: Thu, 27 Jan 2022 10:17:57 +0100 -Subject: [PATCH 05/15] spi: spi-mem: Check the controller extra capabilities - -Controllers can now provide a spi-mem capabilities structure. Let's make -use of it in spi_mem_controller_default_supports_op(). As we want to -check for DTR operations as well as normal operations in a single -helper, let's pull the necessary checks from spi_mem_dtr_supports_op() -for now. - -However, because no controller provide these extra capabilities, this -change has no effect so far. - -Signed-off-by: Miquel Raynal -Reviewed-by: Pratyush Yadav -Reviewed-by: Boris Brezillon -Reviewed-by: Tudor Ambarus -Link: https://lore.kernel.org/linux-mtd/20220127091808.1043392-3-miquel.raynal@bootlin.com -(cherry picked from commit cb7e96ee81edaa48c67d84c14df2cbe464391c37) ---- - drivers/spi/spi-mem.c | 17 +++++++++++++---- - 1 file changed, 13 insertions(+), 4 deletions(-) - ---- a/drivers/spi/spi-mem.c -+++ b/drivers/spi/spi-mem.c -@@ -173,11 +173,20 @@ EXPORT_SYMBOL_GPL(spi_mem_dtr_supports_o - bool spi_mem_default_supports_op(struct spi_mem *mem, - const struct spi_mem_op *op) - { -- if (op->cmd.dtr || op->addr.dtr || op->dummy.dtr || op->data.dtr) -- return false; -+ struct spi_controller *ctlr = mem->spi->controller; -+ bool op_is_dtr = -+ op->cmd.dtr || op->addr.dtr || op->dummy.dtr || op->data.dtr; - -- if (op->cmd.nbytes != 1) -- return false; -+ if (op_is_dtr) { -+ if (!spi_mem_controller_is_capable(ctlr, dtr)) -+ return false; -+ -+ if (op->cmd.nbytes != 2) -+ return false; -+ } else { -+ if (op->cmd.nbytes != 1) -+ return false; -+ } - - return spi_mem_check_buswidth(mem, op); - } diff --git a/target/linux/mediatek/patches-5.15/120-06-v5.18-spi-spi-mem-Kill-the-spi_mem_dtr_supports_op-helper.patch b/target/linux/mediatek/patches-5.15/120-06-v5.18-spi-spi-mem-Kill-the-spi_mem_dtr_supports_op-helper.patch deleted file mode 100644 index c313a455b..000000000 --- a/target/linux/mediatek/patches-5.15/120-06-v5.18-spi-spi-mem-Kill-the-spi_mem_dtr_supports_op-helper.patch +++ /dev/null @@ -1,111 +0,0 @@ -From 2e5fba82e4aeb72d71230eef2541881615aaf7cf Mon Sep 17 00:00:00 2001 -From: Miquel Raynal -Date: Thu, 27 Jan 2022 10:18:00 +0100 -Subject: [PATCH 06/15] spi: spi-mem: Kill the spi_mem_dtr_supports_op() helper - -Now that spi_mem_default_supports_op() has access to the static -controller capabilities (relating to memory operations), and now that -these capabilities have been filled by the relevant controllers, there -is no need for a specific helper checking only DTR operations, so let's -just kill spi_mem_dtr_supports_op() and simply use -spi_mem_default_supports_op() instead. - -Signed-off-by: Miquel Raynal -Reviewed-by: Pratyush Yadav -Reviewed-by: Boris Brezillon -Reviewed-by: Tudor Ambarus -Link: https://lore.kernel.org/linux-mtd/20220127091808.1043392-6-miquel.raynal@bootlin.com -(cherry picked from commit 9a15efc5d5e6b5beaed0883e5bdcd0b1384c1b20) ---- - drivers/spi/spi-cadence-quadspi.c | 5 +---- - drivers/spi/spi-mem.c | 10 ---------- - drivers/spi/spi-mxic.c | 10 +--------- - include/linux/spi/spi-mem.h | 11 ----------- - 4 files changed, 2 insertions(+), 34 deletions(-) - ---- a/drivers/spi/spi-cadence-quadspi.c -+++ b/drivers/spi/spi-cadence-quadspi.c -@@ -1249,10 +1249,7 @@ static bool cqspi_supports_mem_op(struct - return false; - } - -- if (all_true) -- return spi_mem_dtr_supports_op(mem, op); -- else -- return spi_mem_default_supports_op(mem, op); -+ return spi_mem_default_supports_op(mem, op); - } - - static int cqspi_of_get_flash_pdata(struct platform_device *pdev, ---- a/drivers/spi/spi-mem.c -+++ b/drivers/spi/spi-mem.c -@@ -160,16 +160,6 @@ static bool spi_mem_check_buswidth(struc - return true; - } - --bool spi_mem_dtr_supports_op(struct spi_mem *mem, -- const struct spi_mem_op *op) --{ -- if (op->cmd.nbytes != 2) -- return false; -- -- return spi_mem_check_buswidth(mem, op); --} --EXPORT_SYMBOL_GPL(spi_mem_dtr_supports_op); -- - bool spi_mem_default_supports_op(struct spi_mem *mem, - const struct spi_mem_op *op) - { ---- a/drivers/spi/spi-mxic.c -+++ b/drivers/spi/spi-mxic.c -@@ -331,8 +331,6 @@ static int mxic_spi_data_xfer(struct mxi - static bool mxic_spi_mem_supports_op(struct spi_mem *mem, - const struct spi_mem_op *op) - { -- bool all_false; -- - if (op->data.buswidth > 8 || op->addr.buswidth > 8 || - op->dummy.buswidth > 8 || op->cmd.buswidth > 8) - return false; -@@ -344,13 +342,7 @@ static bool mxic_spi_mem_supports_op(str - if (op->addr.nbytes > 7) - return false; - -- all_false = !op->cmd.dtr && !op->addr.dtr && !op->dummy.dtr && -- !op->data.dtr; -- -- if (all_false) -- return spi_mem_default_supports_op(mem, op); -- else -- return spi_mem_dtr_supports_op(mem, op); -+ return spi_mem_default_supports_op(mem, op); - } - - static int mxic_spi_mem_exec_op(struct spi_mem *mem, ---- a/include/linux/spi/spi-mem.h -+++ b/include/linux/spi/spi-mem.h -@@ -330,10 +330,6 @@ void spi_controller_dma_unmap_mem_op_dat - - bool spi_mem_default_supports_op(struct spi_mem *mem, - const struct spi_mem_op *op); -- --bool spi_mem_dtr_supports_op(struct spi_mem *mem, -- const struct spi_mem_op *op); -- - #else - static inline int - spi_controller_dma_map_mem_op_data(struct spi_controller *ctlr, -@@ -356,13 +352,6 @@ bool spi_mem_default_supports_op(struct - { - return false; - } -- --static inline --bool spi_mem_dtr_supports_op(struct spi_mem *mem, -- const struct spi_mem_op *op) --{ -- return false; --} - #endif /* CONFIG_SPI_MEM */ - - int spi_mem_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op); diff --git a/target/linux/mediatek/patches-5.15/120-07-v5.18-spi-spi-mem-Add-an-ecc-parameter-to-the-spi_mem_op-s.patch b/target/linux/mediatek/patches-5.15/120-07-v5.18-spi-spi-mem-Add-an-ecc-parameter-to-the-spi_mem_op-s.patch deleted file mode 100644 index 6d7e47650..000000000 --- a/target/linux/mediatek/patches-5.15/120-07-v5.18-spi-spi-mem-Add-an-ecc-parameter-to-the-spi_mem_op-s.patch +++ /dev/null @@ -1,72 +0,0 @@ -From 9e7eb0ea442ecb1c3fe443289e288694f10c5148 Mon Sep 17 00:00:00 2001 -From: Miquel Raynal -Date: Thu, 27 Jan 2022 10:18:01 +0100 -Subject: [PATCH 07/15] spi: spi-mem: Add an ecc parameter to the spi_mem_op - structure - -Soon the SPI-NAND core will need a way to request a SPI controller to -enable ECC support for a given operation. This is because of the -pipelined integration of certain ECC engines, which are directly managed -by the SPI controller itself. - -Introduce a spi_mem_op additional field for this purpose: ecc. - -So far this field is left unset and checked to be false by all -the SPI controller drivers in their ->supports_op() hook, as they all -call spi_mem_default_supports_op(). - -Signed-off-by: Miquel Raynal -Acked-by: Pratyush Yadav -Reviewed-by: Boris Brezillon -Reviewed-by: Tudor Ambarus -Link: https://lore.kernel.org/linux-mtd/20220127091808.1043392-7-miquel.raynal@bootlin.com -(cherry picked from commit a433c2cbd75ab76f277364f44e76f32c7df306e7) ---- - drivers/spi/spi-mem.c | 5 +++++ - include/linux/spi/spi-mem.h | 4 ++++ - 2 files changed, 9 insertions(+) - ---- a/drivers/spi/spi-mem.c -+++ b/drivers/spi/spi-mem.c -@@ -178,6 +178,11 @@ bool spi_mem_default_supports_op(struct - return false; - } - -+ if (op->data.ecc) { -+ if (!spi_mem_controller_is_capable(ctlr, ecc)) -+ return false; -+ } -+ - return spi_mem_check_buswidth(mem, op); - } - EXPORT_SYMBOL_GPL(spi_mem_default_supports_op); ---- a/include/linux/spi/spi-mem.h -+++ b/include/linux/spi/spi-mem.h -@@ -89,6 +89,7 @@ enum spi_mem_data_dir { - * @dummy.dtr: whether the dummy bytes should be sent in DTR mode or not - * @data.buswidth: number of IO lanes used to send/receive the data - * @data.dtr: whether the data should be sent in DTR mode or not -+ * @data.ecc: whether error correction is required or not - * @data.dir: direction of the transfer - * @data.nbytes: number of data bytes to send/receive. Can be zero if the - * operation does not involve transferring data -@@ -119,6 +120,7 @@ struct spi_mem_op { - struct { - u8 buswidth; - u8 dtr : 1; -+ u8 ecc : 1; - enum spi_mem_data_dir dir; - unsigned int nbytes; - union { -@@ -288,9 +290,11 @@ struct spi_controller_mem_ops { - /** - * struct spi_controller_mem_caps - SPI memory controller capabilities - * @dtr: Supports DTR operations -+ * @ecc: Supports operations with error correction - */ - struct spi_controller_mem_caps { - bool dtr; -+ bool ecc; - }; - - #define spi_mem_controller_is_capable(ctlr, cap) \ diff --git a/target/linux/mediatek/patches-5.15/120-08-v5.18-mtd-spinand-Delay-a-little-bit-the-dirmap-creation.patch b/target/linux/mediatek/patches-5.15/120-08-v5.18-mtd-spinand-Delay-a-little-bit-the-dirmap-creation.patch deleted file mode 100644 index 192b1221e..000000000 --- a/target/linux/mediatek/patches-5.15/120-08-v5.18-mtd-spinand-Delay-a-little-bit-the-dirmap-creation.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 94ef3c35b935a63f6c156957c92f6cf33c9a8dae Mon Sep 17 00:00:00 2001 -From: Miquel Raynal -Date: Thu, 27 Jan 2022 10:18:02 +0100 -Subject: [PATCH 08/15] mtd: spinand: Delay a little bit the dirmap creation - -As we will soon tweak the dirmap creation to act a little bit -differently depending on the picked ECC engine, we need to initialize -dirmaps after ECC engines. This should not have any effect as dirmaps -are not yet used at this point. - -Signed-off-by: Miquel Raynal -Reviewed-by: Boris Brezillon -Link: https://lore.kernel.org/linux-mtd/20220127091808.1043392-8-miquel.raynal@bootlin.com -(cherry picked from commit dc4c2cbf0be2d4a8e2a65013ea2815bb2c8ba949) ---- - drivers/mtd/nand/spi/core.c | 16 ++++++++-------- - 1 file changed, 8 insertions(+), 8 deletions(-) - ---- a/drivers/mtd/nand/spi/core.c -+++ b/drivers/mtd/nand/spi/core.c -@@ -1210,14 +1210,6 @@ static int spinand_init(struct spinand_d - if (ret) - goto err_free_bufs; - -- ret = spinand_create_dirmaps(spinand); -- if (ret) { -- dev_err(dev, -- "Failed to create direct mappings for read/write operations (err = %d)\n", -- ret); -- goto err_manuf_cleanup; -- } -- - ret = nanddev_init(nand, &spinand_ops, THIS_MODULE); - if (ret) - goto err_manuf_cleanup; -@@ -1252,6 +1244,14 @@ static int spinand_init(struct spinand_d - mtd->ecc_strength = nanddev_get_ecc_conf(nand)->strength; - mtd->ecc_step_size = nanddev_get_ecc_conf(nand)->step_size; - -+ ret = spinand_create_dirmaps(spinand); -+ if (ret) { -+ dev_err(dev, -+ "Failed to create direct mappings for read/write operations (err = %d)\n", -+ ret); -+ goto err_cleanup_ecc_engine; -+ } -+ - return 0; - - err_cleanup_ecc_engine: diff --git a/target/linux/mediatek/patches-5.15/120-09-v5.18-mtd-spinand-Create-direct-mapping-descriptors-for-EC.patch b/target/linux/mediatek/patches-5.15/120-09-v5.18-mtd-spinand-Create-direct-mapping-descriptors-for-EC.patch deleted file mode 100644 index 86df0270d..000000000 --- a/target/linux/mediatek/patches-5.15/120-09-v5.18-mtd-spinand-Create-direct-mapping-descriptors-for-EC.patch +++ /dev/null @@ -1,98 +0,0 @@ -From eb4a2d282c3c5752211d69be6dff2674119e5583 Mon Sep 17 00:00:00 2001 -From: Miquel Raynal -Date: Thu, 27 Jan 2022 10:18:03 +0100 -Subject: [PATCH 09/15] mtd: spinand: Create direct mapping descriptors for ECC - operations - -In order for pipelined ECC engines to be able to enable/disable the ECC -engine only when needed and avoid races when future parallel-operations -will be supported, we need to provide the information about the use of -the ECC engine in the direct mapping hooks. As direct mapping -configurations are meant to be static, it is best to create two new -mappings: one for regular 'raw' accesses and one for accesses involving -correction. It is up to the driver to use or not the new ECC enable -boolean contained in the spi-mem operation. - -As dirmaps are not free (they consume a few pages of MMIO address space) -and because these extra entries are only meant to be used by pipelined -engines, let's limit their use to this specific type of engine and save -a bit of memory with all the other setups. - -Signed-off-by: Miquel Raynal -Reviewed-by: Boris Brezillon -Link: https://lore.kernel.org/linux-mtd/20220127091808.1043392-9-miquel.raynal@bootlin.com -(cherry picked from commit f9d7c7265bcff7d9a17425a8cddf702e8fe159c2) ---- - drivers/mtd/nand/spi/core.c | 35 +++++++++++++++++++++++++++++++++-- - include/linux/mtd/spinand.h | 2 ++ - 2 files changed, 35 insertions(+), 2 deletions(-) - ---- a/drivers/mtd/nand/spi/core.c -+++ b/drivers/mtd/nand/spi/core.c -@@ -381,7 +381,10 @@ static int spinand_read_from_cache_op(st - } - } - -- rdesc = spinand->dirmaps[req->pos.plane].rdesc; -+ if (req->mode == MTD_OPS_RAW) -+ rdesc = spinand->dirmaps[req->pos.plane].rdesc; -+ else -+ rdesc = spinand->dirmaps[req->pos.plane].rdesc_ecc; - - while (nbytes) { - ret = spi_mem_dirmap_read(rdesc, column, nbytes, buf); -@@ -452,7 +455,10 @@ static int spinand_write_to_cache_op(str - req->ooblen); - } - -- wdesc = spinand->dirmaps[req->pos.plane].wdesc; -+ if (req->mode == MTD_OPS_RAW) -+ wdesc = spinand->dirmaps[req->pos.plane].wdesc; -+ else -+ wdesc = spinand->dirmaps[req->pos.plane].wdesc_ecc; - - while (nbytes) { - ret = spi_mem_dirmap_write(wdesc, column, nbytes, buf); -@@ -865,6 +871,31 @@ static int spinand_create_dirmap(struct - - spinand->dirmaps[plane].rdesc = desc; - -+ if (nand->ecc.engine->integration != NAND_ECC_ENGINE_INTEGRATION_PIPELINED) { -+ spinand->dirmaps[plane].wdesc_ecc = spinand->dirmaps[plane].wdesc; -+ spinand->dirmaps[plane].rdesc_ecc = spinand->dirmaps[plane].rdesc; -+ -+ return 0; -+ } -+ -+ info.op_tmpl = *spinand->op_templates.update_cache; -+ info.op_tmpl.data.ecc = true; -+ desc = devm_spi_mem_dirmap_create(&spinand->spimem->spi->dev, -+ spinand->spimem, &info); -+ if (IS_ERR(desc)) -+ return PTR_ERR(desc); -+ -+ spinand->dirmaps[plane].wdesc_ecc = desc; -+ -+ 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); -+ if (IS_ERR(desc)) -+ return PTR_ERR(desc); -+ -+ spinand->dirmaps[plane].rdesc_ecc = desc; -+ - return 0; - } - ---- a/include/linux/mtd/spinand.h -+++ b/include/linux/mtd/spinand.h -@@ -391,6 +391,8 @@ struct spinand_info { - struct spinand_dirmap { - struct spi_mem_dirmap_desc *wdesc; - struct spi_mem_dirmap_desc *rdesc; -+ struct spi_mem_dirmap_desc *wdesc_ecc; -+ struct spi_mem_dirmap_desc *rdesc_ecc; - }; - - /** diff --git a/target/linux/mediatek/patches-5.15/120-11-v5.19-mtd-nand-make-mtk_ecc.c-a-separated-module.patch b/target/linux/mediatek/patches-5.15/120-11-v5.19-mtd-nand-make-mtk_ecc.c-a-separated-module.patch deleted file mode 100644 index fd9098eae..000000000 --- a/target/linux/mediatek/patches-5.15/120-11-v5.19-mtd-nand-make-mtk_ecc.c-a-separated-module.patch +++ /dev/null @@ -1,1383 +0,0 @@ -From ebb9653d4a87c64fb679e4c339e867556dada719 Mon Sep 17 00:00:00 2001 -From: Chuanhong Guo -Date: Tue, 22 Mar 2022 18:44:21 +0800 -Subject: [PATCH 11/15] mtd: nand: make mtk_ecc.c a separated module - -this code will be used in mediatek snfi spi-mem controller with -pipelined ECC engine. - -Signed-off-by: Chuanhong Guo -(cherry picked from commit 316f47cec4ce5b81aa8006de202d8769c117a52d) ---- - drivers/mtd/nand/Kconfig | 7 +++++++ - drivers/mtd/nand/Makefile | 1 + - drivers/mtd/nand/{raw/mtk_ecc.c => ecc-mtk.c} | 3 +-- - drivers/mtd/nand/raw/Kconfig | 1 + - drivers/mtd/nand/raw/Makefile | 2 +- - drivers/mtd/nand/raw/mtk_nand.c | 2 +- - .../nand/raw/mtk_ecc.h => include/linux/mtd/nand-ecc-mtk.h | 0 - 7 files changed, 12 insertions(+), 4 deletions(-) - rename drivers/mtd/nand/{raw/mtk_ecc.c => ecc-mtk.c} (99%) - rename drivers/mtd/nand/raw/mtk_ecc.h => include/linux/mtd/nand-ecc-mtk.h (100%) - ---- a/drivers/mtd/nand/Kconfig -+++ b/drivers/mtd/nand/Kconfig -@@ -50,6 +50,13 @@ config MTD_NAND_MTK_BMT - bool "Support MediaTek NAND Bad-block Management Table" - default n - -+config MTD_NAND_ECC_MEDIATEK -+ tristate "Mediatek hardware ECC engine" -+ depends on HAS_IOMEM -+ select MTD_NAND_ECC -+ help -+ This enables support for the hardware ECC engine from Mediatek. -+ - endmenu - - endmenu ---- a/drivers/mtd/nand/Makefile -+++ b/drivers/mtd/nand/Makefile -@@ -3,6 +3,7 @@ - nandcore-objs := core.o bbt.o - obj-$(CONFIG_MTD_NAND_CORE) += nandcore.o - obj-$(CONFIG_MTD_NAND_MTK_BMT) += mtk_bmt.o mtk_bmt_v2.o mtk_bmt_bbt.o mtk_bmt_nmbm.o -+obj-$(CONFIG_MTD_NAND_ECC_MEDIATEK) += ecc-mtk.o - - obj-y += onenand/ - obj-y += raw/ ---- a/drivers/mtd/nand/raw/mtk_ecc.c -+++ /dev/null -@@ -1,599 +0,0 @@ --// SPDX-License-Identifier: GPL-2.0 OR MIT --/* -- * MTK ECC controller driver. -- * Copyright (C) 2016 MediaTek Inc. -- * Authors: Xiaolei Li -- * Jorge Ramirez-Ortiz -- */ -- --#include --#include --#include --#include --#include --#include --#include --#include --#include -- --#include "mtk_ecc.h" -- --#define ECC_IDLE_MASK BIT(0) --#define ECC_IRQ_EN BIT(0) --#define ECC_PG_IRQ_SEL BIT(1) --#define ECC_OP_ENABLE (1) --#define ECC_OP_DISABLE (0) -- --#define ECC_ENCCON (0x00) --#define ECC_ENCCNFG (0x04) --#define ECC_MS_SHIFT (16) --#define ECC_ENCDIADDR (0x08) --#define ECC_ENCIDLE (0x0C) --#define ECC_DECCON (0x100) --#define ECC_DECCNFG (0x104) --#define DEC_EMPTY_EN BIT(31) --#define DEC_CNFG_CORRECT (0x3 << 12) --#define ECC_DECIDLE (0x10C) --#define ECC_DECENUM0 (0x114) -- --#define ECC_TIMEOUT (500000) -- --#define ECC_IDLE_REG(op) ((op) == ECC_ENCODE ? ECC_ENCIDLE : ECC_DECIDLE) --#define ECC_CTL_REG(op) ((op) == ECC_ENCODE ? ECC_ENCCON : ECC_DECCON) -- --struct mtk_ecc_caps { -- u32 err_mask; -- u32 err_shift; -- const u8 *ecc_strength; -- const u32 *ecc_regs; -- u8 num_ecc_strength; -- u8 ecc_mode_shift; -- u32 parity_bits; -- int pg_irq_sel; --}; -- --struct mtk_ecc { -- struct device *dev; -- const struct mtk_ecc_caps *caps; -- void __iomem *regs; -- struct clk *clk; -- -- struct completion done; -- struct mutex lock; -- u32 sectors; -- -- u8 *eccdata; --}; -- --/* ecc strength that each IP supports */ --static const u8 ecc_strength_mt2701[] = { -- 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 28, 32, 36, -- 40, 44, 48, 52, 56, 60 --}; -- --static const u8 ecc_strength_mt2712[] = { -- 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 28, 32, 36, -- 40, 44, 48, 52, 56, 60, 68, 72, 80 --}; -- --static const u8 ecc_strength_mt7622[] = { -- 4, 6, 8, 10, 12 --}; -- --enum mtk_ecc_regs { -- ECC_ENCPAR00, -- ECC_ENCIRQ_EN, -- ECC_ENCIRQ_STA, -- ECC_DECDONE, -- ECC_DECIRQ_EN, -- ECC_DECIRQ_STA, --}; -- --static int mt2701_ecc_regs[] = { -- [ECC_ENCPAR00] = 0x10, -- [ECC_ENCIRQ_EN] = 0x80, -- [ECC_ENCIRQ_STA] = 0x84, -- [ECC_DECDONE] = 0x124, -- [ECC_DECIRQ_EN] = 0x200, -- [ECC_DECIRQ_STA] = 0x204, --}; -- --static int mt2712_ecc_regs[] = { -- [ECC_ENCPAR00] = 0x300, -- [ECC_ENCIRQ_EN] = 0x80, -- [ECC_ENCIRQ_STA] = 0x84, -- [ECC_DECDONE] = 0x124, -- [ECC_DECIRQ_EN] = 0x200, -- [ECC_DECIRQ_STA] = 0x204, --}; -- --static int mt7622_ecc_regs[] = { -- [ECC_ENCPAR00] = 0x10, -- [ECC_ENCIRQ_EN] = 0x30, -- [ECC_ENCIRQ_STA] = 0x34, -- [ECC_DECDONE] = 0x11c, -- [ECC_DECIRQ_EN] = 0x140, -- [ECC_DECIRQ_STA] = 0x144, --}; -- --static inline void mtk_ecc_wait_idle(struct mtk_ecc *ecc, -- enum mtk_ecc_operation op) --{ -- struct device *dev = ecc->dev; -- u32 val; -- int ret; -- -- ret = readl_poll_timeout_atomic(ecc->regs + ECC_IDLE_REG(op), val, -- val & ECC_IDLE_MASK, -- 10, ECC_TIMEOUT); -- if (ret) -- dev_warn(dev, "%s NOT idle\n", -- op == ECC_ENCODE ? "encoder" : "decoder"); --} -- --static irqreturn_t mtk_ecc_irq(int irq, void *id) --{ -- struct mtk_ecc *ecc = id; -- u32 dec, enc; -- -- dec = readw(ecc->regs + ecc->caps->ecc_regs[ECC_DECIRQ_STA]) -- & ECC_IRQ_EN; -- if (dec) { -- dec = readw(ecc->regs + ecc->caps->ecc_regs[ECC_DECDONE]); -- if (dec & ecc->sectors) { -- /* -- * Clear decode IRQ status once again to ensure that -- * there will be no extra IRQ. -- */ -- readw(ecc->regs + ecc->caps->ecc_regs[ECC_DECIRQ_STA]); -- ecc->sectors = 0; -- complete(&ecc->done); -- } else { -- return IRQ_HANDLED; -- } -- } else { -- enc = readl(ecc->regs + ecc->caps->ecc_regs[ECC_ENCIRQ_STA]) -- & ECC_IRQ_EN; -- if (enc) -- complete(&ecc->done); -- else -- return IRQ_NONE; -- } -- -- return IRQ_HANDLED; --} -- --static int mtk_ecc_config(struct mtk_ecc *ecc, struct mtk_ecc_config *config) --{ -- u32 ecc_bit, dec_sz, enc_sz; -- u32 reg, i; -- -- for (i = 0; i < ecc->caps->num_ecc_strength; i++) { -- if (ecc->caps->ecc_strength[i] == config->strength) -- break; -- } -- -- if (i == ecc->caps->num_ecc_strength) { -- dev_err(ecc->dev, "invalid ecc strength %d\n", -- config->strength); -- return -EINVAL; -- } -- -- ecc_bit = i; -- -- if (config->op == ECC_ENCODE) { -- /* configure ECC encoder (in bits) */ -- enc_sz = config->len << 3; -- -- reg = ecc_bit | (config->mode << ecc->caps->ecc_mode_shift); -- reg |= (enc_sz << ECC_MS_SHIFT); -- writel(reg, ecc->regs + ECC_ENCCNFG); -- -- if (config->mode != ECC_NFI_MODE) -- writel(lower_32_bits(config->addr), -- ecc->regs + ECC_ENCDIADDR); -- -- } else { -- /* configure ECC decoder (in bits) */ -- dec_sz = (config->len << 3) + -- config->strength * ecc->caps->parity_bits; -- -- reg = ecc_bit | (config->mode << ecc->caps->ecc_mode_shift); -- reg |= (dec_sz << ECC_MS_SHIFT) | DEC_CNFG_CORRECT; -- reg |= DEC_EMPTY_EN; -- writel(reg, ecc->regs + ECC_DECCNFG); -- -- if (config->sectors) -- ecc->sectors = 1 << (config->sectors - 1); -- } -- -- return 0; --} -- --void mtk_ecc_get_stats(struct mtk_ecc *ecc, struct mtk_ecc_stats *stats, -- int sectors) --{ -- u32 offset, i, err; -- u32 bitflips = 0; -- -- stats->corrected = 0; -- stats->failed = 0; -- -- for (i = 0; i < sectors; i++) { -- offset = (i >> 2) << 2; -- err = readl(ecc->regs + ECC_DECENUM0 + offset); -- err = err >> ((i % 4) * ecc->caps->err_shift); -- err &= ecc->caps->err_mask; -- if (err == ecc->caps->err_mask) { -- /* uncorrectable errors */ -- stats->failed++; -- continue; -- } -- -- stats->corrected += err; -- bitflips = max_t(u32, bitflips, err); -- } -- -- stats->bitflips = bitflips; --} --EXPORT_SYMBOL(mtk_ecc_get_stats); -- --void mtk_ecc_release(struct mtk_ecc *ecc) --{ -- clk_disable_unprepare(ecc->clk); -- put_device(ecc->dev); --} --EXPORT_SYMBOL(mtk_ecc_release); -- --static void mtk_ecc_hw_init(struct mtk_ecc *ecc) --{ -- mtk_ecc_wait_idle(ecc, ECC_ENCODE); -- writew(ECC_OP_DISABLE, ecc->regs + ECC_ENCCON); -- -- mtk_ecc_wait_idle(ecc, ECC_DECODE); -- writel(ECC_OP_DISABLE, ecc->regs + ECC_DECCON); --} -- --static struct mtk_ecc *mtk_ecc_get(struct device_node *np) --{ -- struct platform_device *pdev; -- struct mtk_ecc *ecc; -- -- pdev = of_find_device_by_node(np); -- if (!pdev) -- return ERR_PTR(-EPROBE_DEFER); -- -- ecc = platform_get_drvdata(pdev); -- if (!ecc) { -- put_device(&pdev->dev); -- return ERR_PTR(-EPROBE_DEFER); -- } -- -- clk_prepare_enable(ecc->clk); -- mtk_ecc_hw_init(ecc); -- -- return ecc; --} -- --struct mtk_ecc *of_mtk_ecc_get(struct device_node *of_node) --{ -- struct mtk_ecc *ecc = NULL; -- struct device_node *np; -- -- np = of_parse_phandle(of_node, "ecc-engine", 0); -- if (np) { -- ecc = mtk_ecc_get(np); -- of_node_put(np); -- } -- -- return ecc; --} --EXPORT_SYMBOL(of_mtk_ecc_get); -- --int mtk_ecc_enable(struct mtk_ecc *ecc, struct mtk_ecc_config *config) --{ -- enum mtk_ecc_operation op = config->op; -- u16 reg_val; -- int ret; -- -- ret = mutex_lock_interruptible(&ecc->lock); -- if (ret) { -- dev_err(ecc->dev, "interrupted when attempting to lock\n"); -- return ret; -- } -- -- mtk_ecc_wait_idle(ecc, op); -- -- ret = mtk_ecc_config(ecc, config); -- if (ret) { -- mutex_unlock(&ecc->lock); -- return ret; -- } -- -- if (config->mode != ECC_NFI_MODE || op != ECC_ENCODE) { -- init_completion(&ecc->done); -- reg_val = ECC_IRQ_EN; -- /* -- * For ECC_NFI_MODE, if ecc->caps->pg_irq_sel is 1, then it -- * means this chip can only generate one ecc irq during page -- * read / write. If is 0, generate one ecc irq each ecc step. -- */ -- if (ecc->caps->pg_irq_sel && config->mode == ECC_NFI_MODE) -- reg_val |= ECC_PG_IRQ_SEL; -- if (op == ECC_ENCODE) -- writew(reg_val, ecc->regs + -- ecc->caps->ecc_regs[ECC_ENCIRQ_EN]); -- else -- writew(reg_val, ecc->regs + -- ecc->caps->ecc_regs[ECC_DECIRQ_EN]); -- } -- -- writew(ECC_OP_ENABLE, ecc->regs + ECC_CTL_REG(op)); -- -- return 0; --} --EXPORT_SYMBOL(mtk_ecc_enable); -- --void mtk_ecc_disable(struct mtk_ecc *ecc) --{ -- enum mtk_ecc_operation op = ECC_ENCODE; -- -- /* find out the running operation */ -- if (readw(ecc->regs + ECC_CTL_REG(op)) != ECC_OP_ENABLE) -- op = ECC_DECODE; -- -- /* disable it */ -- mtk_ecc_wait_idle(ecc, op); -- if (op == ECC_DECODE) { -- /* -- * Clear decode IRQ status in case there is a timeout to wait -- * decode IRQ. -- */ -- readw(ecc->regs + ecc->caps->ecc_regs[ECC_DECDONE]); -- writew(0, ecc->regs + ecc->caps->ecc_regs[ECC_DECIRQ_EN]); -- } else { -- writew(0, ecc->regs + ecc->caps->ecc_regs[ECC_ENCIRQ_EN]); -- } -- -- writew(ECC_OP_DISABLE, ecc->regs + ECC_CTL_REG(op)); -- -- mutex_unlock(&ecc->lock); --} --EXPORT_SYMBOL(mtk_ecc_disable); -- --int mtk_ecc_wait_done(struct mtk_ecc *ecc, enum mtk_ecc_operation op) --{ -- int ret; -- -- ret = wait_for_completion_timeout(&ecc->done, msecs_to_jiffies(500)); -- if (!ret) { -- dev_err(ecc->dev, "%s timeout - interrupt did not arrive)\n", -- (op == ECC_ENCODE) ? "encoder" : "decoder"); -- return -ETIMEDOUT; -- } -- -- return 0; --} --EXPORT_SYMBOL(mtk_ecc_wait_done); -- --int mtk_ecc_encode(struct mtk_ecc *ecc, struct mtk_ecc_config *config, -- u8 *data, u32 bytes) --{ -- dma_addr_t addr; -- u32 len; -- int ret; -- -- addr = dma_map_single(ecc->dev, data, bytes, DMA_TO_DEVICE); -- ret = dma_mapping_error(ecc->dev, addr); -- if (ret) { -- dev_err(ecc->dev, "dma mapping error\n"); -- return -EINVAL; -- } -- -- config->op = ECC_ENCODE; -- config->addr = addr; -- ret = mtk_ecc_enable(ecc, config); -- if (ret) { -- dma_unmap_single(ecc->dev, addr, bytes, DMA_TO_DEVICE); -- return ret; -- } -- -- ret = mtk_ecc_wait_done(ecc, ECC_ENCODE); -- if (ret) -- goto timeout; -- -- mtk_ecc_wait_idle(ecc, ECC_ENCODE); -- -- /* Program ECC bytes to OOB: per sector oob = FDM + ECC + SPARE */ -- len = (config->strength * ecc->caps->parity_bits + 7) >> 3; -- -- /* write the parity bytes generated by the ECC back to temp buffer */ -- __ioread32_copy(ecc->eccdata, -- ecc->regs + ecc->caps->ecc_regs[ECC_ENCPAR00], -- round_up(len, 4)); -- -- /* copy into possibly unaligned OOB region with actual length */ -- memcpy(data + bytes, ecc->eccdata, len); --timeout: -- -- dma_unmap_single(ecc->dev, addr, bytes, DMA_TO_DEVICE); -- mtk_ecc_disable(ecc); -- -- return ret; --} --EXPORT_SYMBOL(mtk_ecc_encode); -- --void mtk_ecc_adjust_strength(struct mtk_ecc *ecc, u32 *p) --{ -- const u8 *ecc_strength = ecc->caps->ecc_strength; -- int i; -- -- for (i = 0; i < ecc->caps->num_ecc_strength; i++) { -- if (*p <= ecc_strength[i]) { -- if (!i) -- *p = ecc_strength[i]; -- else if (*p != ecc_strength[i]) -- *p = ecc_strength[i - 1]; -- return; -- } -- } -- -- *p = ecc_strength[ecc->caps->num_ecc_strength - 1]; --} --EXPORT_SYMBOL(mtk_ecc_adjust_strength); -- --unsigned int mtk_ecc_get_parity_bits(struct mtk_ecc *ecc) --{ -- return ecc->caps->parity_bits; --} --EXPORT_SYMBOL(mtk_ecc_get_parity_bits); -- --static const struct mtk_ecc_caps mtk_ecc_caps_mt2701 = { -- .err_mask = 0x3f, -- .err_shift = 8, -- .ecc_strength = ecc_strength_mt2701, -- .ecc_regs = mt2701_ecc_regs, -- .num_ecc_strength = 20, -- .ecc_mode_shift = 5, -- .parity_bits = 14, -- .pg_irq_sel = 0, --}; -- --static const struct mtk_ecc_caps mtk_ecc_caps_mt2712 = { -- .err_mask = 0x7f, -- .err_shift = 8, -- .ecc_strength = ecc_strength_mt2712, -- .ecc_regs = mt2712_ecc_regs, -- .num_ecc_strength = 23, -- .ecc_mode_shift = 5, -- .parity_bits = 14, -- .pg_irq_sel = 1, --}; -- --static const struct mtk_ecc_caps mtk_ecc_caps_mt7622 = { -- .err_mask = 0x1f, -- .err_shift = 5, -- .ecc_strength = ecc_strength_mt7622, -- .ecc_regs = mt7622_ecc_regs, -- .num_ecc_strength = 5, -- .ecc_mode_shift = 4, -- .parity_bits = 13, -- .pg_irq_sel = 0, --}; -- --static const struct of_device_id mtk_ecc_dt_match[] = { -- { -- .compatible = "mediatek,mt2701-ecc", -- .data = &mtk_ecc_caps_mt2701, -- }, { -- .compatible = "mediatek,mt2712-ecc", -- .data = &mtk_ecc_caps_mt2712, -- }, { -- .compatible = "mediatek,mt7622-ecc", -- .data = &mtk_ecc_caps_mt7622, -- }, -- {}, --}; -- --static int mtk_ecc_probe(struct platform_device *pdev) --{ -- struct device *dev = &pdev->dev; -- struct mtk_ecc *ecc; -- struct resource *res; -- u32 max_eccdata_size; -- int irq, ret; -- -- ecc = devm_kzalloc(dev, sizeof(*ecc), GFP_KERNEL); -- if (!ecc) -- return -ENOMEM; -- -- ecc->caps = of_device_get_match_data(dev); -- -- max_eccdata_size = ecc->caps->num_ecc_strength - 1; -- max_eccdata_size = ecc->caps->ecc_strength[max_eccdata_size]; -- max_eccdata_size = (max_eccdata_size * ecc->caps->parity_bits + 7) >> 3; -- max_eccdata_size = round_up(max_eccdata_size, 4); -- ecc->eccdata = devm_kzalloc(dev, max_eccdata_size, GFP_KERNEL); -- if (!ecc->eccdata) -- return -ENOMEM; -- -- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -- ecc->regs = devm_ioremap_resource(dev, res); -- if (IS_ERR(ecc->regs)) -- return PTR_ERR(ecc->regs); -- -- ecc->clk = devm_clk_get(dev, NULL); -- if (IS_ERR(ecc->clk)) { -- dev_err(dev, "failed to get clock: %ld\n", PTR_ERR(ecc->clk)); -- return PTR_ERR(ecc->clk); -- } -- -- irq = platform_get_irq(pdev, 0); -- if (irq < 0) -- return irq; -- -- ret = dma_set_mask(dev, DMA_BIT_MASK(32)); -- if (ret) { -- dev_err(dev, "failed to set DMA mask\n"); -- return ret; -- } -- -- ret = devm_request_irq(dev, irq, mtk_ecc_irq, 0x0, "mtk-ecc", ecc); -- if (ret) { -- dev_err(dev, "failed to request irq\n"); -- return -EINVAL; -- } -- -- ecc->dev = dev; -- mutex_init(&ecc->lock); -- platform_set_drvdata(pdev, ecc); -- dev_info(dev, "probed\n"); -- -- return 0; --} -- --#ifdef CONFIG_PM_SLEEP --static int mtk_ecc_suspend(struct device *dev) --{ -- struct mtk_ecc *ecc = dev_get_drvdata(dev); -- -- clk_disable_unprepare(ecc->clk); -- -- return 0; --} -- --static int mtk_ecc_resume(struct device *dev) --{ -- struct mtk_ecc *ecc = dev_get_drvdata(dev); -- int ret; -- -- ret = clk_prepare_enable(ecc->clk); -- if (ret) { -- dev_err(dev, "failed to enable clk\n"); -- return ret; -- } -- -- return 0; --} -- --static SIMPLE_DEV_PM_OPS(mtk_ecc_pm_ops, mtk_ecc_suspend, mtk_ecc_resume); --#endif -- --MODULE_DEVICE_TABLE(of, mtk_ecc_dt_match); -- --static struct platform_driver mtk_ecc_driver = { -- .probe = mtk_ecc_probe, -- .driver = { -- .name = "mtk-ecc", -- .of_match_table = of_match_ptr(mtk_ecc_dt_match), --#ifdef CONFIG_PM_SLEEP -- .pm = &mtk_ecc_pm_ops, --#endif -- }, --}; -- --module_platform_driver(mtk_ecc_driver); -- --MODULE_AUTHOR("Xiaolei Li "); --MODULE_DESCRIPTION("MTK Nand ECC Driver"); --MODULE_LICENSE("Dual MIT/GPL"); ---- /dev/null -+++ b/drivers/mtd/nand/ecc-mtk.c -@@ -0,0 +1,598 @@ -+// SPDX-License-Identifier: GPL-2.0 OR MIT -+/* -+ * MTK ECC controller driver. -+ * Copyright (C) 2016 MediaTek Inc. -+ * Authors: Xiaolei Li -+ * Jorge Ramirez-Ortiz -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define ECC_IDLE_MASK BIT(0) -+#define ECC_IRQ_EN BIT(0) -+#define ECC_PG_IRQ_SEL BIT(1) -+#define ECC_OP_ENABLE (1) -+#define ECC_OP_DISABLE (0) -+ -+#define ECC_ENCCON (0x00) -+#define ECC_ENCCNFG (0x04) -+#define ECC_MS_SHIFT (16) -+#define ECC_ENCDIADDR (0x08) -+#define ECC_ENCIDLE (0x0C) -+#define ECC_DECCON (0x100) -+#define ECC_DECCNFG (0x104) -+#define DEC_EMPTY_EN BIT(31) -+#define DEC_CNFG_CORRECT (0x3 << 12) -+#define ECC_DECIDLE (0x10C) -+#define ECC_DECENUM0 (0x114) -+ -+#define ECC_TIMEOUT (500000) -+ -+#define ECC_IDLE_REG(op) ((op) == ECC_ENCODE ? ECC_ENCIDLE : ECC_DECIDLE) -+#define ECC_CTL_REG(op) ((op) == ECC_ENCODE ? ECC_ENCCON : ECC_DECCON) -+ -+struct mtk_ecc_caps { -+ u32 err_mask; -+ u32 err_shift; -+ const u8 *ecc_strength; -+ const u32 *ecc_regs; -+ u8 num_ecc_strength; -+ u8 ecc_mode_shift; -+ u32 parity_bits; -+ int pg_irq_sel; -+}; -+ -+struct mtk_ecc { -+ struct device *dev; -+ const struct mtk_ecc_caps *caps; -+ void __iomem *regs; -+ struct clk *clk; -+ -+ struct completion done; -+ struct mutex lock; -+ u32 sectors; -+ -+ u8 *eccdata; -+}; -+ -+/* ecc strength that each IP supports */ -+static const u8 ecc_strength_mt2701[] = { -+ 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 28, 32, 36, -+ 40, 44, 48, 52, 56, 60 -+}; -+ -+static const u8 ecc_strength_mt2712[] = { -+ 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 28, 32, 36, -+ 40, 44, 48, 52, 56, 60, 68, 72, 80 -+}; -+ -+static const u8 ecc_strength_mt7622[] = { -+ 4, 6, 8, 10, 12 -+}; -+ -+enum mtk_ecc_regs { -+ ECC_ENCPAR00, -+ ECC_ENCIRQ_EN, -+ ECC_ENCIRQ_STA, -+ ECC_DECDONE, -+ ECC_DECIRQ_EN, -+ ECC_DECIRQ_STA, -+}; -+ -+static int mt2701_ecc_regs[] = { -+ [ECC_ENCPAR00] = 0x10, -+ [ECC_ENCIRQ_EN] = 0x80, -+ [ECC_ENCIRQ_STA] = 0x84, -+ [ECC_DECDONE] = 0x124, -+ [ECC_DECIRQ_EN] = 0x200, -+ [ECC_DECIRQ_STA] = 0x204, -+}; -+ -+static int mt2712_ecc_regs[] = { -+ [ECC_ENCPAR00] = 0x300, -+ [ECC_ENCIRQ_EN] = 0x80, -+ [ECC_ENCIRQ_STA] = 0x84, -+ [ECC_DECDONE] = 0x124, -+ [ECC_DECIRQ_EN] = 0x200, -+ [ECC_DECIRQ_STA] = 0x204, -+}; -+ -+static int mt7622_ecc_regs[] = { -+ [ECC_ENCPAR00] = 0x10, -+ [ECC_ENCIRQ_EN] = 0x30, -+ [ECC_ENCIRQ_STA] = 0x34, -+ [ECC_DECDONE] = 0x11c, -+ [ECC_DECIRQ_EN] = 0x140, -+ [ECC_DECIRQ_STA] = 0x144, -+}; -+ -+static inline void mtk_ecc_wait_idle(struct mtk_ecc *ecc, -+ enum mtk_ecc_operation op) -+{ -+ struct device *dev = ecc->dev; -+ u32 val; -+ int ret; -+ -+ ret = readl_poll_timeout_atomic(ecc->regs + ECC_IDLE_REG(op), val, -+ val & ECC_IDLE_MASK, -+ 10, ECC_TIMEOUT); -+ if (ret) -+ dev_warn(dev, "%s NOT idle\n", -+ op == ECC_ENCODE ? "encoder" : "decoder"); -+} -+ -+static irqreturn_t mtk_ecc_irq(int irq, void *id) -+{ -+ struct mtk_ecc *ecc = id; -+ u32 dec, enc; -+ -+ dec = readw(ecc->regs + ecc->caps->ecc_regs[ECC_DECIRQ_STA]) -+ & ECC_IRQ_EN; -+ if (dec) { -+ dec = readw(ecc->regs + ecc->caps->ecc_regs[ECC_DECDONE]); -+ if (dec & ecc->sectors) { -+ /* -+ * Clear decode IRQ status once again to ensure that -+ * there will be no extra IRQ. -+ */ -+ readw(ecc->regs + ecc->caps->ecc_regs[ECC_DECIRQ_STA]); -+ ecc->sectors = 0; -+ complete(&ecc->done); -+ } else { -+ return IRQ_HANDLED; -+ } -+ } else { -+ enc = readl(ecc->regs + ecc->caps->ecc_regs[ECC_ENCIRQ_STA]) -+ & ECC_IRQ_EN; -+ if (enc) -+ complete(&ecc->done); -+ else -+ return IRQ_NONE; -+ } -+ -+ return IRQ_HANDLED; -+} -+ -+static int mtk_ecc_config(struct mtk_ecc *ecc, struct mtk_ecc_config *config) -+{ -+ u32 ecc_bit, dec_sz, enc_sz; -+ u32 reg, i; -+ -+ for (i = 0; i < ecc->caps->num_ecc_strength; i++) { -+ if (ecc->caps->ecc_strength[i] == config->strength) -+ break; -+ } -+ -+ if (i == ecc->caps->num_ecc_strength) { -+ dev_err(ecc->dev, "invalid ecc strength %d\n", -+ config->strength); -+ return -EINVAL; -+ } -+ -+ ecc_bit = i; -+ -+ if (config->op == ECC_ENCODE) { -+ /* configure ECC encoder (in bits) */ -+ enc_sz = config->len << 3; -+ -+ reg = ecc_bit | (config->mode << ecc->caps->ecc_mode_shift); -+ reg |= (enc_sz << ECC_MS_SHIFT); -+ writel(reg, ecc->regs + ECC_ENCCNFG); -+ -+ if (config->mode != ECC_NFI_MODE) -+ writel(lower_32_bits(config->addr), -+ ecc->regs + ECC_ENCDIADDR); -+ -+ } else { -+ /* configure ECC decoder (in bits) */ -+ dec_sz = (config->len << 3) + -+ config->strength * ecc->caps->parity_bits; -+ -+ reg = ecc_bit | (config->mode << ecc->caps->ecc_mode_shift); -+ reg |= (dec_sz << ECC_MS_SHIFT) | DEC_CNFG_CORRECT; -+ reg |= DEC_EMPTY_EN; -+ writel(reg, ecc->regs + ECC_DECCNFG); -+ -+ if (config->sectors) -+ ecc->sectors = 1 << (config->sectors - 1); -+ } -+ -+ return 0; -+} -+ -+void mtk_ecc_get_stats(struct mtk_ecc *ecc, struct mtk_ecc_stats *stats, -+ int sectors) -+{ -+ u32 offset, i, err; -+ u32 bitflips = 0; -+ -+ stats->corrected = 0; -+ stats->failed = 0; -+ -+ for (i = 0; i < sectors; i++) { -+ offset = (i >> 2) << 2; -+ err = readl(ecc->regs + ECC_DECENUM0 + offset); -+ err = err >> ((i % 4) * ecc->caps->err_shift); -+ err &= ecc->caps->err_mask; -+ if (err == ecc->caps->err_mask) { -+ /* uncorrectable errors */ -+ stats->failed++; -+ continue; -+ } -+ -+ stats->corrected += err; -+ bitflips = max_t(u32, bitflips, err); -+ } -+ -+ stats->bitflips = bitflips; -+} -+EXPORT_SYMBOL(mtk_ecc_get_stats); -+ -+void mtk_ecc_release(struct mtk_ecc *ecc) -+{ -+ clk_disable_unprepare(ecc->clk); -+ put_device(ecc->dev); -+} -+EXPORT_SYMBOL(mtk_ecc_release); -+ -+static void mtk_ecc_hw_init(struct mtk_ecc *ecc) -+{ -+ mtk_ecc_wait_idle(ecc, ECC_ENCODE); -+ writew(ECC_OP_DISABLE, ecc->regs + ECC_ENCCON); -+ -+ mtk_ecc_wait_idle(ecc, ECC_DECODE); -+ writel(ECC_OP_DISABLE, ecc->regs + ECC_DECCON); -+} -+ -+static struct mtk_ecc *mtk_ecc_get(struct device_node *np) -+{ -+ struct platform_device *pdev; -+ struct mtk_ecc *ecc; -+ -+ pdev = of_find_device_by_node(np); -+ if (!pdev) -+ return ERR_PTR(-EPROBE_DEFER); -+ -+ ecc = platform_get_drvdata(pdev); -+ if (!ecc) { -+ put_device(&pdev->dev); -+ return ERR_PTR(-EPROBE_DEFER); -+ } -+ -+ clk_prepare_enable(ecc->clk); -+ mtk_ecc_hw_init(ecc); -+ -+ return ecc; -+} -+ -+struct mtk_ecc *of_mtk_ecc_get(struct device_node *of_node) -+{ -+ struct mtk_ecc *ecc = NULL; -+ struct device_node *np; -+ -+ np = of_parse_phandle(of_node, "ecc-engine", 0); -+ if (np) { -+ ecc = mtk_ecc_get(np); -+ of_node_put(np); -+ } -+ -+ return ecc; -+} -+EXPORT_SYMBOL(of_mtk_ecc_get); -+ -+int mtk_ecc_enable(struct mtk_ecc *ecc, struct mtk_ecc_config *config) -+{ -+ enum mtk_ecc_operation op = config->op; -+ u16 reg_val; -+ int ret; -+ -+ ret = mutex_lock_interruptible(&ecc->lock); -+ if (ret) { -+ dev_err(ecc->dev, "interrupted when attempting to lock\n"); -+ return ret; -+ } -+ -+ mtk_ecc_wait_idle(ecc, op); -+ -+ ret = mtk_ecc_config(ecc, config); -+ if (ret) { -+ mutex_unlock(&ecc->lock); -+ return ret; -+ } -+ -+ if (config->mode != ECC_NFI_MODE || op != ECC_ENCODE) { -+ init_completion(&ecc->done); -+ reg_val = ECC_IRQ_EN; -+ /* -+ * For ECC_NFI_MODE, if ecc->caps->pg_irq_sel is 1, then it -+ * means this chip can only generate one ecc irq during page -+ * read / write. If is 0, generate one ecc irq each ecc step. -+ */ -+ if (ecc->caps->pg_irq_sel && config->mode == ECC_NFI_MODE) -+ reg_val |= ECC_PG_IRQ_SEL; -+ if (op == ECC_ENCODE) -+ writew(reg_val, ecc->regs + -+ ecc->caps->ecc_regs[ECC_ENCIRQ_EN]); -+ else -+ writew(reg_val, ecc->regs + -+ ecc->caps->ecc_regs[ECC_DECIRQ_EN]); -+ } -+ -+ writew(ECC_OP_ENABLE, ecc->regs + ECC_CTL_REG(op)); -+ -+ return 0; -+} -+EXPORT_SYMBOL(mtk_ecc_enable); -+ -+void mtk_ecc_disable(struct mtk_ecc *ecc) -+{ -+ enum mtk_ecc_operation op = ECC_ENCODE; -+ -+ /* find out the running operation */ -+ if (readw(ecc->regs + ECC_CTL_REG(op)) != ECC_OP_ENABLE) -+ op = ECC_DECODE; -+ -+ /* disable it */ -+ mtk_ecc_wait_idle(ecc, op); -+ if (op == ECC_DECODE) { -+ /* -+ * Clear decode IRQ status in case there is a timeout to wait -+ * decode IRQ. -+ */ -+ readw(ecc->regs + ecc->caps->ecc_regs[ECC_DECDONE]); -+ writew(0, ecc->regs + ecc->caps->ecc_regs[ECC_DECIRQ_EN]); -+ } else { -+ writew(0, ecc->regs + ecc->caps->ecc_regs[ECC_ENCIRQ_EN]); -+ } -+ -+ writew(ECC_OP_DISABLE, ecc->regs + ECC_CTL_REG(op)); -+ -+ mutex_unlock(&ecc->lock); -+} -+EXPORT_SYMBOL(mtk_ecc_disable); -+ -+int mtk_ecc_wait_done(struct mtk_ecc *ecc, enum mtk_ecc_operation op) -+{ -+ int ret; -+ -+ ret = wait_for_completion_timeout(&ecc->done, msecs_to_jiffies(500)); -+ if (!ret) { -+ dev_err(ecc->dev, "%s timeout - interrupt did not arrive)\n", -+ (op == ECC_ENCODE) ? "encoder" : "decoder"); -+ return -ETIMEDOUT; -+ } -+ -+ return 0; -+} -+EXPORT_SYMBOL(mtk_ecc_wait_done); -+ -+int mtk_ecc_encode(struct mtk_ecc *ecc, struct mtk_ecc_config *config, -+ u8 *data, u32 bytes) -+{ -+ dma_addr_t addr; -+ u32 len; -+ int ret; -+ -+ addr = dma_map_single(ecc->dev, data, bytes, DMA_TO_DEVICE); -+ ret = dma_mapping_error(ecc->dev, addr); -+ if (ret) { -+ dev_err(ecc->dev, "dma mapping error\n"); -+ return -EINVAL; -+ } -+ -+ config->op = ECC_ENCODE; -+ config->addr = addr; -+ ret = mtk_ecc_enable(ecc, config); -+ if (ret) { -+ dma_unmap_single(ecc->dev, addr, bytes, DMA_TO_DEVICE); -+ return ret; -+ } -+ -+ ret = mtk_ecc_wait_done(ecc, ECC_ENCODE); -+ if (ret) -+ goto timeout; -+ -+ mtk_ecc_wait_idle(ecc, ECC_ENCODE); -+ -+ /* Program ECC bytes to OOB: per sector oob = FDM + ECC + SPARE */ -+ len = (config->strength * ecc->caps->parity_bits + 7) >> 3; -+ -+ /* write the parity bytes generated by the ECC back to temp buffer */ -+ __ioread32_copy(ecc->eccdata, -+ ecc->regs + ecc->caps->ecc_regs[ECC_ENCPAR00], -+ round_up(len, 4)); -+ -+ /* copy into possibly unaligned OOB region with actual length */ -+ memcpy(data + bytes, ecc->eccdata, len); -+timeout: -+ -+ dma_unmap_single(ecc->dev, addr, bytes, DMA_TO_DEVICE); -+ mtk_ecc_disable(ecc); -+ -+ return ret; -+} -+EXPORT_SYMBOL(mtk_ecc_encode); -+ -+void mtk_ecc_adjust_strength(struct mtk_ecc *ecc, u32 *p) -+{ -+ const u8 *ecc_strength = ecc->caps->ecc_strength; -+ int i; -+ -+ for (i = 0; i < ecc->caps->num_ecc_strength; i++) { -+ if (*p <= ecc_strength[i]) { -+ if (!i) -+ *p = ecc_strength[i]; -+ else if (*p != ecc_strength[i]) -+ *p = ecc_strength[i - 1]; -+ return; -+ } -+ } -+ -+ *p = ecc_strength[ecc->caps->num_ecc_strength - 1]; -+} -+EXPORT_SYMBOL(mtk_ecc_adjust_strength); -+ -+unsigned int mtk_ecc_get_parity_bits(struct mtk_ecc *ecc) -+{ -+ return ecc->caps->parity_bits; -+} -+EXPORT_SYMBOL(mtk_ecc_get_parity_bits); -+ -+static const struct mtk_ecc_caps mtk_ecc_caps_mt2701 = { -+ .err_mask = 0x3f, -+ .err_shift = 8, -+ .ecc_strength = ecc_strength_mt2701, -+ .ecc_regs = mt2701_ecc_regs, -+ .num_ecc_strength = 20, -+ .ecc_mode_shift = 5, -+ .parity_bits = 14, -+ .pg_irq_sel = 0, -+}; -+ -+static const struct mtk_ecc_caps mtk_ecc_caps_mt2712 = { -+ .err_mask = 0x7f, -+ .err_shift = 8, -+ .ecc_strength = ecc_strength_mt2712, -+ .ecc_regs = mt2712_ecc_regs, -+ .num_ecc_strength = 23, -+ .ecc_mode_shift = 5, -+ .parity_bits = 14, -+ .pg_irq_sel = 1, -+}; -+ -+static const struct mtk_ecc_caps mtk_ecc_caps_mt7622 = { -+ .err_mask = 0x1f, -+ .err_shift = 5, -+ .ecc_strength = ecc_strength_mt7622, -+ .ecc_regs = mt7622_ecc_regs, -+ .num_ecc_strength = 5, -+ .ecc_mode_shift = 4, -+ .parity_bits = 13, -+ .pg_irq_sel = 0, -+}; -+ -+static const struct of_device_id mtk_ecc_dt_match[] = { -+ { -+ .compatible = "mediatek,mt2701-ecc", -+ .data = &mtk_ecc_caps_mt2701, -+ }, { -+ .compatible = "mediatek,mt2712-ecc", -+ .data = &mtk_ecc_caps_mt2712, -+ }, { -+ .compatible = "mediatek,mt7622-ecc", -+ .data = &mtk_ecc_caps_mt7622, -+ }, -+ {}, -+}; -+ -+static int mtk_ecc_probe(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ struct mtk_ecc *ecc; -+ struct resource *res; -+ u32 max_eccdata_size; -+ int irq, ret; -+ -+ ecc = devm_kzalloc(dev, sizeof(*ecc), GFP_KERNEL); -+ if (!ecc) -+ return -ENOMEM; -+ -+ ecc->caps = of_device_get_match_data(dev); -+ -+ max_eccdata_size = ecc->caps->num_ecc_strength - 1; -+ max_eccdata_size = ecc->caps->ecc_strength[max_eccdata_size]; -+ max_eccdata_size = (max_eccdata_size * ecc->caps->parity_bits + 7) >> 3; -+ max_eccdata_size = round_up(max_eccdata_size, 4); -+ ecc->eccdata = devm_kzalloc(dev, max_eccdata_size, GFP_KERNEL); -+ if (!ecc->eccdata) -+ return -ENOMEM; -+ -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ ecc->regs = devm_ioremap_resource(dev, res); -+ if (IS_ERR(ecc->regs)) -+ return PTR_ERR(ecc->regs); -+ -+ ecc->clk = devm_clk_get(dev, NULL); -+ if (IS_ERR(ecc->clk)) { -+ dev_err(dev, "failed to get clock: %ld\n", PTR_ERR(ecc->clk)); -+ return PTR_ERR(ecc->clk); -+ } -+ -+ irq = platform_get_irq(pdev, 0); -+ if (irq < 0) -+ return irq; -+ -+ ret = dma_set_mask(dev, DMA_BIT_MASK(32)); -+ if (ret) { -+ dev_err(dev, "failed to set DMA mask\n"); -+ return ret; -+ } -+ -+ ret = devm_request_irq(dev, irq, mtk_ecc_irq, 0x0, "mtk-ecc", ecc); -+ if (ret) { -+ dev_err(dev, "failed to request irq\n"); -+ return -EINVAL; -+ } -+ -+ ecc->dev = dev; -+ mutex_init(&ecc->lock); -+ platform_set_drvdata(pdev, ecc); -+ dev_info(dev, "probed\n"); -+ -+ return 0; -+} -+ -+#ifdef CONFIG_PM_SLEEP -+static int mtk_ecc_suspend(struct device *dev) -+{ -+ struct mtk_ecc *ecc = dev_get_drvdata(dev); -+ -+ clk_disable_unprepare(ecc->clk); -+ -+ return 0; -+} -+ -+static int mtk_ecc_resume(struct device *dev) -+{ -+ struct mtk_ecc *ecc = dev_get_drvdata(dev); -+ int ret; -+ -+ ret = clk_prepare_enable(ecc->clk); -+ if (ret) { -+ dev_err(dev, "failed to enable clk\n"); -+ return ret; -+ } -+ -+ return 0; -+} -+ -+static SIMPLE_DEV_PM_OPS(mtk_ecc_pm_ops, mtk_ecc_suspend, mtk_ecc_resume); -+#endif -+ -+MODULE_DEVICE_TABLE(of, mtk_ecc_dt_match); -+ -+static struct platform_driver mtk_ecc_driver = { -+ .probe = mtk_ecc_probe, -+ .driver = { -+ .name = "mtk-ecc", -+ .of_match_table = of_match_ptr(mtk_ecc_dt_match), -+#ifdef CONFIG_PM_SLEEP -+ .pm = &mtk_ecc_pm_ops, -+#endif -+ }, -+}; -+ -+module_platform_driver(mtk_ecc_driver); -+ -+MODULE_AUTHOR("Xiaolei Li "); -+MODULE_DESCRIPTION("MTK Nand ECC Driver"); -+MODULE_LICENSE("Dual MIT/GPL"); ---- a/drivers/mtd/nand/raw/Kconfig -+++ b/drivers/mtd/nand/raw/Kconfig -@@ -360,6 +360,7 @@ config MTD_NAND_QCOM - - config MTD_NAND_MTK - tristate "MTK NAND controller" -+ depends on MTD_NAND_ECC_MEDIATEK - depends on ARCH_MEDIATEK || COMPILE_TEST - depends on HAS_IOMEM - help ---- a/drivers/mtd/nand/raw/Makefile -+++ b/drivers/mtd/nand/raw/Makefile -@@ -48,7 +48,7 @@ obj-$(CONFIG_MTD_NAND_SUNXI) += sunxi_n - obj-$(CONFIG_MTD_NAND_HISI504) += hisi504_nand.o - obj-$(CONFIG_MTD_NAND_BRCMNAND) += brcmnand/ - obj-$(CONFIG_MTD_NAND_QCOM) += qcom_nandc.o --obj-$(CONFIG_MTD_NAND_MTK) += mtk_ecc.o mtk_nand.o -+obj-$(CONFIG_MTD_NAND_MTK) += mtk_nand.o - obj-$(CONFIG_MTD_NAND_MXIC) += mxic_nand.o - obj-$(CONFIG_MTD_NAND_TEGRA) += tegra_nand.o - obj-$(CONFIG_MTD_NAND_STM32_FMC2) += stm32_fmc2_nand.o ---- a/drivers/mtd/nand/raw/mtk_nand.c -+++ b/drivers/mtd/nand/raw/mtk_nand.c -@@ -17,7 +17,7 @@ - #include - #include - #include --#include "mtk_ecc.h" -+#include - - /* NAND controller register definition */ - #define NFI_CNFG (0x00) ---- a/drivers/mtd/nand/raw/mtk_ecc.h -+++ /dev/null -@@ -1,47 +0,0 @@ --/* SPDX-License-Identifier: GPL-2.0 OR MIT */ --/* -- * MTK SDG1 ECC controller -- * -- * Copyright (c) 2016 Mediatek -- * Authors: Xiaolei Li -- * Jorge Ramirez-Ortiz -- */ -- --#ifndef __DRIVERS_MTD_NAND_MTK_ECC_H__ --#define __DRIVERS_MTD_NAND_MTK_ECC_H__ -- --#include -- --enum mtk_ecc_mode {ECC_DMA_MODE = 0, ECC_NFI_MODE = 1}; --enum mtk_ecc_operation {ECC_ENCODE, ECC_DECODE}; -- --struct device_node; --struct mtk_ecc; -- --struct mtk_ecc_stats { -- u32 corrected; -- u32 bitflips; -- u32 failed; --}; -- --struct mtk_ecc_config { -- enum mtk_ecc_operation op; -- enum mtk_ecc_mode mode; -- dma_addr_t addr; -- u32 strength; -- u32 sectors; -- u32 len; --}; -- --int mtk_ecc_encode(struct mtk_ecc *, struct mtk_ecc_config *, u8 *, u32); --void mtk_ecc_get_stats(struct mtk_ecc *, struct mtk_ecc_stats *, int); --int mtk_ecc_wait_done(struct mtk_ecc *, enum mtk_ecc_operation); --int mtk_ecc_enable(struct mtk_ecc *, struct mtk_ecc_config *); --void mtk_ecc_disable(struct mtk_ecc *); --void mtk_ecc_adjust_strength(struct mtk_ecc *ecc, u32 *p); --unsigned int mtk_ecc_get_parity_bits(struct mtk_ecc *ecc); -- --struct mtk_ecc *of_mtk_ecc_get(struct device_node *); --void mtk_ecc_release(struct mtk_ecc *); -- --#endif ---- /dev/null -+++ b/include/linux/mtd/nand-ecc-mtk.h -@@ -0,0 +1,47 @@ -+/* SPDX-License-Identifier: GPL-2.0 OR MIT */ -+/* -+ * MTK SDG1 ECC controller -+ * -+ * Copyright (c) 2016 Mediatek -+ * Authors: Xiaolei Li -+ * Jorge Ramirez-Ortiz -+ */ -+ -+#ifndef __DRIVERS_MTD_NAND_MTK_ECC_H__ -+#define __DRIVERS_MTD_NAND_MTK_ECC_H__ -+ -+#include -+ -+enum mtk_ecc_mode {ECC_DMA_MODE = 0, ECC_NFI_MODE = 1}; -+enum mtk_ecc_operation {ECC_ENCODE, ECC_DECODE}; -+ -+struct device_node; -+struct mtk_ecc; -+ -+struct mtk_ecc_stats { -+ u32 corrected; -+ u32 bitflips; -+ u32 failed; -+}; -+ -+struct mtk_ecc_config { -+ enum mtk_ecc_operation op; -+ enum mtk_ecc_mode mode; -+ dma_addr_t addr; -+ u32 strength; -+ u32 sectors; -+ u32 len; -+}; -+ -+int mtk_ecc_encode(struct mtk_ecc *, struct mtk_ecc_config *, u8 *, u32); -+void mtk_ecc_get_stats(struct mtk_ecc *, struct mtk_ecc_stats *, int); -+int mtk_ecc_wait_done(struct mtk_ecc *, enum mtk_ecc_operation); -+int mtk_ecc_enable(struct mtk_ecc *, struct mtk_ecc_config *); -+void mtk_ecc_disable(struct mtk_ecc *); -+void mtk_ecc_adjust_strength(struct mtk_ecc *ecc, u32 *p); -+unsigned int mtk_ecc_get_parity_bits(struct mtk_ecc *ecc); -+ -+struct mtk_ecc *of_mtk_ecc_get(struct device_node *); -+void mtk_ecc_release(struct mtk_ecc *); -+ -+#endif diff --git a/target/linux/mediatek/patches-5.15/120-12-v5.19-spi-add-driver-for-MTK-SPI-NAND-Flash-Interface.patch b/target/linux/mediatek/patches-5.15/120-12-v5.19-spi-add-driver-for-MTK-SPI-NAND-Flash-Interface.patch deleted file mode 100644 index ed2090501..000000000 --- a/target/linux/mediatek/patches-5.15/120-12-v5.19-spi-add-driver-for-MTK-SPI-NAND-Flash-Interface.patch +++ /dev/null @@ -1,1537 +0,0 @@ -From 8170bafa8936e9fbfdce992932a63bd20eca3bc3 Mon Sep 17 00:00:00 2001 -From: Chuanhong Guo -Date: Sat, 2 Apr 2022 10:16:11 +0800 -Subject: [PATCH v6 2/5] spi: add driver for MTK SPI NAND Flash Interface - -This driver implements support for the SPI-NAND mode of MTK NAND Flash -Interface as a SPI-MEM controller with pipelined ECC capability. - -Signed-off-by: Chuanhong Guo -Tested-by: Daniel Golle ---- -Change since v1: - fix CI warnings - -Changes since v2: - use streamed DMA api to avoid an extra memory copy during read - make ECC engine config a per-nand context - take user-requested ECC strength into account - -Change since v3: none -Changes since v4: - fix missing OOB write - print page format with dev_dbg - replace uint*_t copied from vendor driver with u* - -Changes since v5: - add missing nfi mode register configuration in probe - fix an off-by-one bug in mtk_snand_mac_io - - drivers/spi/Kconfig | 10 + - drivers/spi/Makefile | 1 + - drivers/spi/spi-mtk-snfi.c | 1470 ++++++++++++++++++++++++++++++++++++ - 3 files changed, 1481 insertions(+) - create mode 100644 drivers/spi/spi-mtk-snfi.c - ---- a/drivers/spi/Kconfig -+++ b/drivers/spi/Kconfig -@@ -529,6 +529,16 @@ config SPI_MTK_NOR - SPI interface as well as several SPI NOR specific instructions - via SPI MEM interface. - -+config SPI_MTK_SNFI -+ tristate "MediaTek SPI NAND Flash Interface" -+ depends on ARCH_MEDIATEK || COMPILE_TEST -+ depends on MTD_NAND_ECC_MEDIATEK -+ help -+ This enables support for SPI-NAND mode on the MediaTek NAND -+ Flash Interface found on MediaTek ARM SoCs. This controller -+ is implemented as a SPI-MEM controller with pipelined ECC -+ capcability. -+ - config SPI_NPCM_FIU - tristate "Nuvoton NPCM FLASH Interface Unit" - depends on ARCH_NPCM || COMPILE_TEST ---- a/drivers/spi/Makefile -+++ b/drivers/spi/Makefile -@@ -71,6 +71,7 @@ obj-$(CONFIG_SPI_MPC52xx) += spi-mpc52x - obj-$(CONFIG_SPI_MT65XX) += spi-mt65xx.o - obj-$(CONFIG_SPI_MT7621) += spi-mt7621.o - obj-$(CONFIG_SPI_MTK_NOR) += spi-mtk-nor.o -+obj-$(CONFIG_SPI_MTK_SNFI) += spi-mtk-snfi.o - obj-$(CONFIG_SPI_MXIC) += spi-mxic.o - obj-$(CONFIG_SPI_MXS) += spi-mxs.o - obj-$(CONFIG_SPI_NPCM_FIU) += spi-npcm-fiu.o ---- /dev/null -+++ b/drivers/spi/spi-mtk-snfi.c -@@ -0,0 +1,1470 @@ -+// SPDX-License-Identifier: GPL-2.0 -+// -+// Driver for the SPI-NAND mode of Mediatek NAND Flash Interface -+// -+// Copyright (c) 2022 Chuanhong Guo -+// -+// This driver is based on the SPI-NAND mtd driver from Mediatek SDK: -+// -+// Copyright (C) 2020 MediaTek Inc. -+// Author: Weijie Gao -+// -+// This controller organize the page data as several interleaved sectors -+// like the following: (sizeof(FDM + ECC) = snf->nfi_cfg.spare_size) -+// +---------+------+------+---------+------+------+-----+ -+// | Sector1 | FDM1 | ECC1 | Sector2 | FDM2 | ECC2 | ... | -+// +---------+------+------+---------+------+------+-----+ -+// With auto-format turned on, DMA only returns this part: -+// +---------+---------+-----+ -+// | Sector1 | Sector2 | ... | -+// +---------+---------+-----+ -+// The FDM data will be filled to the registers, and ECC parity data isn't -+// accessible. -+// With auto-format off, all ((Sector+FDM+ECC)*nsectors) will be read over DMA -+// in it's original order shown in the first table. ECC can't be turned on when -+// auto-format is off. -+// -+// However, Linux SPI-NAND driver expects the data returned as: -+// +------+-----+ -+// | Page | OOB | -+// +------+-----+ -+// where the page data is continuously stored instead of interleaved. -+// So we assume all instructions matching the page_op template between ECC -+// prepare_io_req and finish_io_req are for page cache r/w. -+// Here's how this spi-mem driver operates when reading: -+// 1. Always set snf->autofmt = true in prepare_io_req (even when ECC is off). -+// 2. Perform page ops and let the controller fill the DMA bounce buffer with -+// de-interleaved sector data and set FDM registers. -+// 3. Return the data as: -+// +---------+---------+-----+------+------+-----+ -+// | Sector1 | Sector2 | ... | FDM1 | FDM2 | ... | -+// +---------+---------+-----+------+------+-----+ -+// 4. For other matching spi_mem ops outside a prepare/finish_io_req pair, -+// read the data with auto-format off into the bounce buffer and copy -+// needed data to the buffer specified in the request. -+// -+// Write requests operates in a similar manner. -+// As a limitation of this strategy, we won't be able to access any ECC parity -+// data at all in Linux. -+// -+// Here's the bad block mark situation on MTK chips: -+// In older chips like mt7622, MTK uses the first FDM byte in the first sector -+// as the bad block mark. After de-interleaving, this byte appears at [pagesize] -+// in the returned data, which is the BBM position expected by kernel. However, -+// the conventional bad block mark is the first byte of the OOB, which is part -+// of the last sector data in the interleaved layout. Instead of fixing their -+// hardware, MTK decided to address this inconsistency in software. On these -+// later chips, the BootROM expects the following: -+// 1. The [pagesize] byte on a nand page is used as BBM, which will appear at -+// (page_size - (nsectors - 1) * spare_size) in the DMA buffer. -+// 2. The original byte stored at that position in the DMA buffer will be stored -+// as the first byte of the FDM section in the last sector. -+// We can't disagree with the BootROM, so after de-interleaving, we need to -+// perform the following swaps in read: -+// 1. Store the BBM at [page_size - (nsectors - 1) * spare_size] to [page_size], -+// which is the expected BBM position by kernel. -+// 2. Store the page data byte at [pagesize + (nsectors-1) * fdm] back to -+// [page_size - (nsectors - 1) * spare_size] -+// Similarly, when writing, we need to perform swaps in the other direction. -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+// NFI registers -+#define NFI_CNFG 0x000 -+#define CNFG_OP_MODE_S 12 -+#define CNFG_OP_MODE_CUST 6 -+#define CNFG_OP_MODE_PROGRAM 3 -+#define CNFG_AUTO_FMT_EN BIT(9) -+#define CNFG_HW_ECC_EN BIT(8) -+#define CNFG_DMA_BURST_EN BIT(2) -+#define CNFG_READ_MODE BIT(1) -+#define CNFG_DMA_MODE BIT(0) -+ -+#define NFI_PAGEFMT 0x0004 -+#define NFI_SPARE_SIZE_LS_S 16 -+#define NFI_FDM_ECC_NUM_S 12 -+#define NFI_FDM_NUM_S 8 -+#define NFI_SPARE_SIZE_S 4 -+#define NFI_SEC_SEL_512 BIT(2) -+#define NFI_PAGE_SIZE_S 0 -+#define NFI_PAGE_SIZE_512_2K 0 -+#define NFI_PAGE_SIZE_2K_4K 1 -+#define NFI_PAGE_SIZE_4K_8K 2 -+#define NFI_PAGE_SIZE_8K_16K 3 -+ -+#define NFI_CON 0x008 -+#define CON_SEC_NUM_S 12 -+#define CON_BWR BIT(9) -+#define CON_BRD BIT(8) -+#define CON_NFI_RST BIT(1) -+#define CON_FIFO_FLUSH BIT(0) -+ -+#define NFI_INTR_EN 0x010 -+#define NFI_INTR_STA 0x014 -+#define NFI_IRQ_INTR_EN BIT(31) -+#define NFI_IRQ_CUS_READ BIT(8) -+#define NFI_IRQ_CUS_PG BIT(7) -+ -+#define NFI_CMD 0x020 -+#define NFI_CMD_DUMMY_READ 0x00 -+#define NFI_CMD_DUMMY_WRITE 0x80 -+ -+#define NFI_STRDATA 0x040 -+#define STR_DATA BIT(0) -+ -+#define NFI_STA 0x060 -+#define NFI_NAND_FSM GENMASK(28, 24) -+#define NFI_FSM GENMASK(19, 16) -+#define READ_EMPTY BIT(12) -+ -+#define NFI_FIFOSTA 0x064 -+#define FIFO_WR_REMAIN_S 8 -+#define FIFO_RD_REMAIN_S 0 -+ -+#define NFI_ADDRCNTR 0x070 -+#define SEC_CNTR GENMASK(16, 12) -+#define SEC_CNTR_S 12 -+#define NFI_SEC_CNTR(val) (((val)&SEC_CNTR) >> SEC_CNTR_S) -+ -+#define NFI_STRADDR 0x080 -+ -+#define NFI_BYTELEN 0x084 -+#define BUS_SEC_CNTR(val) (((val)&SEC_CNTR) >> SEC_CNTR_S) -+ -+#define NFI_FDM0L 0x0a0 -+#define NFI_FDM0M 0x0a4 -+#define NFI_FDML(n) (NFI_FDM0L + (n)*8) -+#define NFI_FDMM(n) (NFI_FDM0M + (n)*8) -+ -+#define NFI_DEBUG_CON1 0x220 -+#define WBUF_EN BIT(2) -+ -+#define NFI_MASTERSTA 0x224 -+#define MAS_ADDR GENMASK(11, 9) -+#define MAS_RD GENMASK(8, 6) -+#define MAS_WR GENMASK(5, 3) -+#define MAS_RDDLY GENMASK(2, 0) -+#define NFI_MASTERSTA_MASK_7622 (MAS_ADDR | MAS_RD | MAS_WR | MAS_RDDLY) -+ -+// SNFI registers -+#define SNF_MAC_CTL 0x500 -+#define MAC_XIO_SEL BIT(4) -+#define SF_MAC_EN BIT(3) -+#define SF_TRIG BIT(2) -+#define WIP_READY BIT(1) -+#define WIP BIT(0) -+ -+#define SNF_MAC_OUTL 0x504 -+#define SNF_MAC_INL 0x508 -+ -+#define SNF_RD_CTL2 0x510 -+#define DATA_READ_DUMMY_S 8 -+#define DATA_READ_MAX_DUMMY 0xf -+#define DATA_READ_CMD_S 0 -+ -+#define SNF_RD_CTL3 0x514 -+ -+#define SNF_PG_CTL1 0x524 -+#define PG_LOAD_CMD_S 8 -+ -+#define SNF_PG_CTL2 0x528 -+ -+#define SNF_MISC_CTL 0x538 -+#define SW_RST BIT(28) -+#define FIFO_RD_LTC_S 25 -+#define PG_LOAD_X4_EN BIT(20) -+#define DATA_READ_MODE_S 16 -+#define DATA_READ_MODE GENMASK(18, 16) -+#define DATA_READ_MODE_X1 0 -+#define DATA_READ_MODE_X2 1 -+#define DATA_READ_MODE_X4 2 -+#define DATA_READ_MODE_DUAL 5 -+#define DATA_READ_MODE_QUAD 6 -+#define PG_LOAD_CUSTOM_EN BIT(7) -+#define DATARD_CUSTOM_EN BIT(6) -+#define CS_DESELECT_CYC_S 0 -+ -+#define SNF_MISC_CTL2 0x53c -+#define PROGRAM_LOAD_BYTE_NUM_S 16 -+#define READ_DATA_BYTE_NUM_S 11 -+ -+#define SNF_DLY_CTL3 0x548 -+#define SFCK_SAM_DLY_S 0 -+ -+#define SNF_STA_CTL1 0x550 -+#define CUS_PG_DONE BIT(28) -+#define CUS_READ_DONE BIT(27) -+#define SPI_STATE_S 0 -+#define SPI_STATE GENMASK(3, 0) -+ -+#define SNF_CFG 0x55c -+#define SPI_MODE BIT(0) -+ -+#define SNF_GPRAM 0x800 -+#define SNF_GPRAM_SIZE 0xa0 -+ -+#define SNFI_POLL_INTERVAL 1000000 -+ -+static const u8 mt7622_spare_sizes[] = { 16, 26, 27, 28 }; -+ -+struct mtk_snand_caps { -+ u16 sector_size; -+ u16 max_sectors; -+ u16 fdm_size; -+ u16 fdm_ecc_size; -+ u16 fifo_size; -+ -+ bool bbm_swap; -+ bool empty_page_check; -+ u32 mastersta_mask; -+ -+ const u8 *spare_sizes; -+ u32 num_spare_size; -+}; -+ -+static const struct mtk_snand_caps mt7622_snand_caps = { -+ .sector_size = 512, -+ .max_sectors = 8, -+ .fdm_size = 8, -+ .fdm_ecc_size = 1, -+ .fifo_size = 32, -+ .bbm_swap = false, -+ .empty_page_check = false, -+ .mastersta_mask = NFI_MASTERSTA_MASK_7622, -+ .spare_sizes = mt7622_spare_sizes, -+ .num_spare_size = ARRAY_SIZE(mt7622_spare_sizes) -+}; -+ -+static const struct mtk_snand_caps mt7629_snand_caps = { -+ .sector_size = 512, -+ .max_sectors = 8, -+ .fdm_size = 8, -+ .fdm_ecc_size = 1, -+ .fifo_size = 32, -+ .bbm_swap = true, -+ .empty_page_check = false, -+ .mastersta_mask = NFI_MASTERSTA_MASK_7622, -+ .spare_sizes = mt7622_spare_sizes, -+ .num_spare_size = ARRAY_SIZE(mt7622_spare_sizes) -+}; -+ -+struct mtk_snand_conf { -+ size_t page_size; -+ size_t oob_size; -+ u8 nsectors; -+ u8 spare_size; -+}; -+ -+struct mtk_snand { -+ struct spi_controller *ctlr; -+ struct device *dev; -+ struct clk *nfi_clk; -+ struct clk *pad_clk; -+ void __iomem *nfi_base; -+ int irq; -+ struct completion op_done; -+ const struct mtk_snand_caps *caps; -+ struct mtk_ecc_config *ecc_cfg; -+ struct mtk_ecc *ecc; -+ struct mtk_snand_conf nfi_cfg; -+ struct mtk_ecc_stats ecc_stats; -+ struct nand_ecc_engine ecc_eng; -+ bool autofmt; -+ u8 *buf; -+ size_t buf_len; -+}; -+ -+static struct mtk_snand *nand_to_mtk_snand(struct nand_device *nand) -+{ -+ struct nand_ecc_engine *eng = nand->ecc.engine; -+ -+ return container_of(eng, struct mtk_snand, ecc_eng); -+} -+ -+static inline int snand_prepare_bouncebuf(struct mtk_snand *snf, size_t size) -+{ -+ if (snf->buf_len >= size) -+ return 0; -+ kfree(snf->buf); -+ snf->buf = kmalloc(size, GFP_KERNEL); -+ if (!snf->buf) -+ return -ENOMEM; -+ snf->buf_len = size; -+ memset(snf->buf, 0xff, snf->buf_len); -+ return 0; -+} -+ -+static inline u32 nfi_read32(struct mtk_snand *snf, u32 reg) -+{ -+ return readl(snf->nfi_base + reg); -+} -+ -+static inline void nfi_write32(struct mtk_snand *snf, u32 reg, u32 val) -+{ -+ writel(val, snf->nfi_base + reg); -+} -+ -+static inline void nfi_write16(struct mtk_snand *snf, u32 reg, u16 val) -+{ -+ writew(val, snf->nfi_base + reg); -+} -+ -+static inline void nfi_rmw32(struct mtk_snand *snf, u32 reg, u32 clr, u32 set) -+{ -+ u32 val; -+ -+ val = readl(snf->nfi_base + reg); -+ val &= ~clr; -+ val |= set; -+ writel(val, snf->nfi_base + reg); -+} -+ -+static void nfi_read_data(struct mtk_snand *snf, u32 reg, u8 *data, u32 len) -+{ -+ u32 i, val = 0, es = sizeof(u32); -+ -+ for (i = reg; i < reg + len; i++) { -+ if (i == reg || i % es == 0) -+ val = nfi_read32(snf, i & ~(es - 1)); -+ -+ *data++ = (u8)(val >> (8 * (i % es))); -+ } -+} -+ -+static int mtk_nfi_reset(struct mtk_snand *snf) -+{ -+ u32 val, fifo_mask; -+ int ret; -+ -+ nfi_write32(snf, NFI_CON, CON_FIFO_FLUSH | CON_NFI_RST); -+ -+ ret = readw_poll_timeout(snf->nfi_base + NFI_MASTERSTA, val, -+ !(val & snf->caps->mastersta_mask), 0, -+ SNFI_POLL_INTERVAL); -+ if (ret) { -+ dev_err(snf->dev, "NFI master is still busy after reset\n"); -+ return ret; -+ } -+ -+ ret = readl_poll_timeout(snf->nfi_base + NFI_STA, val, -+ !(val & (NFI_FSM | NFI_NAND_FSM)), 0, -+ SNFI_POLL_INTERVAL); -+ if (ret) { -+ dev_err(snf->dev, "Failed to reset NFI\n"); -+ return ret; -+ } -+ -+ fifo_mask = ((snf->caps->fifo_size - 1) << FIFO_RD_REMAIN_S) | -+ ((snf->caps->fifo_size - 1) << FIFO_WR_REMAIN_S); -+ ret = readw_poll_timeout(snf->nfi_base + NFI_FIFOSTA, val, -+ !(val & fifo_mask), 0, SNFI_POLL_INTERVAL); -+ if (ret) { -+ dev_err(snf->dev, "NFI FIFOs are not empty\n"); -+ return ret; -+ } -+ -+ return 0; -+} -+ -+static int mtk_snand_mac_reset(struct mtk_snand *snf) -+{ -+ int ret; -+ u32 val; -+ -+ nfi_rmw32(snf, SNF_MISC_CTL, 0, SW_RST); -+ -+ ret = readl_poll_timeout(snf->nfi_base + SNF_STA_CTL1, val, -+ !(val & SPI_STATE), 0, SNFI_POLL_INTERVAL); -+ if (ret) -+ dev_err(snf->dev, "Failed to reset SNFI MAC\n"); -+ -+ nfi_write32(snf, SNF_MISC_CTL, -+ (2 << FIFO_RD_LTC_S) | (10 << CS_DESELECT_CYC_S)); -+ -+ return ret; -+} -+ -+static int mtk_snand_mac_trigger(struct mtk_snand *snf, u32 outlen, u32 inlen) -+{ -+ int ret; -+ u32 val; -+ -+ nfi_write32(snf, SNF_MAC_CTL, SF_MAC_EN); -+ nfi_write32(snf, SNF_MAC_OUTL, outlen); -+ nfi_write32(snf, SNF_MAC_INL, inlen); -+ -+ nfi_write32(snf, SNF_MAC_CTL, SF_MAC_EN | SF_TRIG); -+ -+ ret = readl_poll_timeout(snf->nfi_base + SNF_MAC_CTL, val, -+ val & WIP_READY, 0, SNFI_POLL_INTERVAL); -+ if (ret) { -+ dev_err(snf->dev, "Timed out waiting for WIP_READY\n"); -+ goto cleanup; -+ } -+ -+ ret = readl_poll_timeout(snf->nfi_base + SNF_MAC_CTL, val, !(val & WIP), -+ 0, SNFI_POLL_INTERVAL); -+ if (ret) -+ dev_err(snf->dev, "Timed out waiting for WIP cleared\n"); -+ -+cleanup: -+ nfi_write32(snf, SNF_MAC_CTL, 0); -+ -+ return ret; -+} -+ -+static int mtk_snand_mac_io(struct mtk_snand *snf, const struct spi_mem_op *op) -+{ -+ u32 rx_len = 0; -+ u32 reg_offs = 0; -+ u32 val = 0; -+ const u8 *tx_buf = NULL; -+ u8 *rx_buf = NULL; -+ int i, ret; -+ u8 b; -+ -+ if (op->data.dir == SPI_MEM_DATA_IN) { -+ rx_len = op->data.nbytes; -+ rx_buf = op->data.buf.in; -+ } else { -+ tx_buf = op->data.buf.out; -+ } -+ -+ mtk_snand_mac_reset(snf); -+ -+ for (i = 0; i < op->cmd.nbytes; i++, reg_offs++) { -+ b = (op->cmd.opcode >> ((op->cmd.nbytes - i - 1) * 8)) & 0xff; -+ val |= b << (8 * (reg_offs % 4)); -+ if (reg_offs % 4 == 3) { -+ nfi_write32(snf, SNF_GPRAM + reg_offs - 3, val); -+ val = 0; -+ } -+ } -+ -+ for (i = 0; i < op->addr.nbytes; i++, reg_offs++) { -+ b = (op->addr.val >> ((op->addr.nbytes - i - 1) * 8)) & 0xff; -+ val |= b << (8 * (reg_offs % 4)); -+ if (reg_offs % 4 == 3) { -+ nfi_write32(snf, SNF_GPRAM + reg_offs - 3, val); -+ val = 0; -+ } -+ } -+ -+ for (i = 0; i < op->dummy.nbytes; i++, reg_offs++) { -+ if (reg_offs % 4 == 3) { -+ nfi_write32(snf, SNF_GPRAM + reg_offs - 3, val); -+ val = 0; -+ } -+ } -+ -+ if (op->data.dir == SPI_MEM_DATA_OUT) { -+ for (i = 0; i < op->data.nbytes; i++, reg_offs++) { -+ val |= tx_buf[i] << (8 * (reg_offs % 4)); -+ if (reg_offs % 4 == 3) { -+ nfi_write32(snf, SNF_GPRAM + reg_offs - 3, val); -+ val = 0; -+ } -+ } -+ } -+ -+ if (reg_offs % 4) -+ nfi_write32(snf, SNF_GPRAM + (reg_offs & ~3), val); -+ -+ for (i = 0; i < reg_offs; i += 4) -+ dev_dbg(snf->dev, "%d: %08X", i, -+ nfi_read32(snf, SNF_GPRAM + i)); -+ -+ dev_dbg(snf->dev, "SNF TX: %u RX: %u", reg_offs, rx_len); -+ -+ ret = mtk_snand_mac_trigger(snf, reg_offs, rx_len); -+ if (ret) -+ return ret; -+ -+ if (!rx_len) -+ return 0; -+ -+ nfi_read_data(snf, SNF_GPRAM + reg_offs, rx_buf, rx_len); -+ return 0; -+} -+ -+static int mtk_snand_setup_pagefmt(struct mtk_snand *snf, u32 page_size, -+ u32 oob_size) -+{ -+ int spare_idx = -1; -+ u32 spare_size, spare_size_shift, pagesize_idx; -+ u32 sector_size_512; -+ u8 nsectors; -+ int i; -+ -+ // skip if it's already configured as required. -+ if (snf->nfi_cfg.page_size == page_size && -+ snf->nfi_cfg.oob_size == oob_size) -+ return 0; -+ -+ nsectors = page_size / snf->caps->sector_size; -+ if (nsectors > snf->caps->max_sectors) { -+ dev_err(snf->dev, "too many sectors required.\n"); -+ goto err; -+ } -+ -+ if (snf->caps->sector_size == 512) { -+ sector_size_512 = NFI_SEC_SEL_512; -+ spare_size_shift = NFI_SPARE_SIZE_S; -+ } else { -+ sector_size_512 = 0; -+ spare_size_shift = NFI_SPARE_SIZE_LS_S; -+ } -+ -+ switch (page_size) { -+ case SZ_512: -+ pagesize_idx = NFI_PAGE_SIZE_512_2K; -+ break; -+ case SZ_2K: -+ if (snf->caps->sector_size == 512) -+ pagesize_idx = NFI_PAGE_SIZE_2K_4K; -+ else -+ pagesize_idx = NFI_PAGE_SIZE_512_2K; -+ break; -+ case SZ_4K: -+ if (snf->caps->sector_size == 512) -+ pagesize_idx = NFI_PAGE_SIZE_4K_8K; -+ else -+ pagesize_idx = NFI_PAGE_SIZE_2K_4K; -+ break; -+ case SZ_8K: -+ if (snf->caps->sector_size == 512) -+ pagesize_idx = NFI_PAGE_SIZE_8K_16K; -+ else -+ pagesize_idx = NFI_PAGE_SIZE_4K_8K; -+ break; -+ case SZ_16K: -+ pagesize_idx = NFI_PAGE_SIZE_8K_16K; -+ break; -+ default: -+ dev_err(snf->dev, "unsupported page size.\n"); -+ goto err; -+ } -+ -+ spare_size = oob_size / nsectors; -+ // If we're using the 1KB sector size, HW will automatically double the -+ // spare size. We should only use half of the value in this case. -+ if (snf->caps->sector_size == 1024) -+ spare_size /= 2; -+ -+ for (i = snf->caps->num_spare_size - 1; i >= 0; i--) { -+ if (snf->caps->spare_sizes[i] <= spare_size) { -+ spare_size = snf->caps->spare_sizes[i]; -+ if (snf->caps->sector_size == 1024) -+ spare_size *= 2; -+ spare_idx = i; -+ break; -+ } -+ } -+ -+ if (spare_idx < 0) { -+ dev_err(snf->dev, "unsupported spare size: %u\n", spare_size); -+ goto err; -+ } -+ -+ nfi_write32(snf, NFI_PAGEFMT, -+ (snf->caps->fdm_ecc_size << NFI_FDM_ECC_NUM_S) | -+ (snf->caps->fdm_size << NFI_FDM_NUM_S) | -+ (spare_idx << spare_size_shift) | -+ (pagesize_idx << NFI_PAGE_SIZE_S) | -+ sector_size_512); -+ -+ snf->nfi_cfg.page_size = page_size; -+ snf->nfi_cfg.oob_size = oob_size; -+ snf->nfi_cfg.nsectors = nsectors; -+ snf->nfi_cfg.spare_size = spare_size; -+ -+ dev_dbg(snf->dev, "page format: (%u + %u) * %u\n", -+ snf->caps->sector_size, spare_size, nsectors); -+ return snand_prepare_bouncebuf(snf, page_size + oob_size); -+err: -+ dev_err(snf->dev, "page size %u + %u is not supported\n", page_size, -+ oob_size); -+ return -EOPNOTSUPP; -+} -+ -+static int mtk_snand_ooblayout_ecc(struct mtd_info *mtd, int section, -+ struct mtd_oob_region *oobecc) -+{ -+ // ECC area is not accessible -+ return -ERANGE; -+} -+ -+static int mtk_snand_ooblayout_free(struct mtd_info *mtd, int section, -+ struct mtd_oob_region *oobfree) -+{ -+ struct nand_device *nand = mtd_to_nanddev(mtd); -+ struct mtk_snand *ms = nand_to_mtk_snand(nand); -+ -+ if (section >= ms->nfi_cfg.nsectors) -+ return -ERANGE; -+ -+ oobfree->length = ms->caps->fdm_size - 1; -+ oobfree->offset = section * ms->caps->fdm_size + 1; -+ return 0; -+} -+ -+static const struct mtd_ooblayout_ops mtk_snand_ooblayout = { -+ .ecc = mtk_snand_ooblayout_ecc, -+ .free = mtk_snand_ooblayout_free, -+}; -+ -+static int mtk_snand_ecc_init_ctx(struct nand_device *nand) -+{ -+ struct mtk_snand *snf = nand_to_mtk_snand(nand); -+ struct nand_ecc_props *conf = &nand->ecc.ctx.conf; -+ struct nand_ecc_props *reqs = &nand->ecc.requirements; -+ struct nand_ecc_props *user = &nand->ecc.user_conf; -+ struct mtd_info *mtd = nanddev_to_mtd(nand); -+ int step_size = 0, strength = 0, desired_correction = 0, steps; -+ bool ecc_user = false; -+ int ret; -+ u32 parity_bits, max_ecc_bytes; -+ struct mtk_ecc_config *ecc_cfg; -+ -+ ret = mtk_snand_setup_pagefmt(snf, nand->memorg.pagesize, -+ nand->memorg.oobsize); -+ if (ret) -+ return ret; -+ -+ ecc_cfg = kzalloc(sizeof(*ecc_cfg), GFP_KERNEL); -+ if (!ecc_cfg) -+ return -ENOMEM; -+ -+ nand->ecc.ctx.priv = ecc_cfg; -+ -+ if (user->step_size && user->strength) { -+ step_size = user->step_size; -+ strength = user->strength; -+ ecc_user = true; -+ } else if (reqs->step_size && reqs->strength) { -+ step_size = reqs->step_size; -+ strength = reqs->strength; -+ } -+ -+ if (step_size && strength) { -+ steps = mtd->writesize / step_size; -+ desired_correction = steps * strength; -+ strength = desired_correction / snf->nfi_cfg.nsectors; -+ } -+ -+ ecc_cfg->mode = ECC_NFI_MODE; -+ ecc_cfg->sectors = snf->nfi_cfg.nsectors; -+ ecc_cfg->len = snf->caps->sector_size + snf->caps->fdm_ecc_size; -+ -+ // calculate the max possible strength under current page format -+ parity_bits = mtk_ecc_get_parity_bits(snf->ecc); -+ max_ecc_bytes = snf->nfi_cfg.spare_size - snf->caps->fdm_size; -+ ecc_cfg->strength = max_ecc_bytes * 8 / parity_bits; -+ mtk_ecc_adjust_strength(snf->ecc, &ecc_cfg->strength); -+ -+ // if there's a user requested strength, find the minimum strength that -+ // meets the requirement. Otherwise use the maximum strength which is -+ // expected by BootROM. -+ if (ecc_user && strength) { -+ u32 s_next = ecc_cfg->strength - 1; -+ -+ while (1) { -+ mtk_ecc_adjust_strength(snf->ecc, &s_next); -+ if (s_next >= ecc_cfg->strength) -+ break; -+ if (s_next < strength) -+ break; -+ s_next = ecc_cfg->strength - 1; -+ } -+ } -+ -+ mtd_set_ooblayout(mtd, &mtk_snand_ooblayout); -+ -+ conf->step_size = snf->caps->sector_size; -+ conf->strength = ecc_cfg->strength; -+ -+ if (ecc_cfg->strength < strength) -+ dev_warn(snf->dev, "unable to fulfill ECC of %u bits.\n", -+ strength); -+ dev_info(snf->dev, "ECC strength: %u bits per %u bytes\n", -+ ecc_cfg->strength, snf->caps->sector_size); -+ -+ return 0; -+} -+ -+static void mtk_snand_ecc_cleanup_ctx(struct nand_device *nand) -+{ -+ struct mtk_ecc_config *ecc_cfg = nand_to_ecc_ctx(nand); -+ -+ kfree(ecc_cfg); -+} -+ -+static int mtk_snand_ecc_prepare_io_req(struct nand_device *nand, -+ struct nand_page_io_req *req) -+{ -+ struct mtk_snand *snf = nand_to_mtk_snand(nand); -+ struct mtk_ecc_config *ecc_cfg = nand_to_ecc_ctx(nand); -+ int ret; -+ -+ ret = mtk_snand_setup_pagefmt(snf, nand->memorg.pagesize, -+ nand->memorg.oobsize); -+ if (ret) -+ return ret; -+ snf->autofmt = true; -+ snf->ecc_cfg = ecc_cfg; -+ return 0; -+} -+ -+static int mtk_snand_ecc_finish_io_req(struct nand_device *nand, -+ struct nand_page_io_req *req) -+{ -+ struct mtk_snand *snf = nand_to_mtk_snand(nand); -+ struct mtd_info *mtd = nanddev_to_mtd(nand); -+ -+ snf->ecc_cfg = NULL; -+ snf->autofmt = false; -+ if ((req->mode == MTD_OPS_RAW) || (req->type != NAND_PAGE_READ)) -+ return 0; -+ -+ if (snf->ecc_stats.failed) -+ mtd->ecc_stats.failed += snf->ecc_stats.failed; -+ mtd->ecc_stats.corrected += snf->ecc_stats.corrected; -+ return snf->ecc_stats.failed ? -EBADMSG : snf->ecc_stats.bitflips; -+} -+ -+static struct nand_ecc_engine_ops mtk_snfi_ecc_engine_ops = { -+ .init_ctx = mtk_snand_ecc_init_ctx, -+ .cleanup_ctx = mtk_snand_ecc_cleanup_ctx, -+ .prepare_io_req = mtk_snand_ecc_prepare_io_req, -+ .finish_io_req = mtk_snand_ecc_finish_io_req, -+}; -+ -+static void mtk_snand_read_fdm(struct mtk_snand *snf, u8 *buf) -+{ -+ u32 vall, valm; -+ u8 *oobptr = buf; -+ int i, j; -+ -+ for (i = 0; i < snf->nfi_cfg.nsectors; i++) { -+ vall = nfi_read32(snf, NFI_FDML(i)); -+ valm = nfi_read32(snf, NFI_FDMM(i)); -+ -+ for (j = 0; j < snf->caps->fdm_size; j++) -+ oobptr[j] = (j >= 4 ? valm : vall) >> ((j % 4) * 8); -+ -+ oobptr += snf->caps->fdm_size; -+ } -+} -+ -+static void mtk_snand_write_fdm(struct mtk_snand *snf, const u8 *buf) -+{ -+ u32 fdm_size = snf->caps->fdm_size; -+ const u8 *oobptr = buf; -+ u32 vall, valm; -+ int i, j; -+ -+ for (i = 0; i < snf->nfi_cfg.nsectors; i++) { -+ vall = 0; -+ valm = 0; -+ -+ for (j = 0; j < 8; j++) { -+ if (j < 4) -+ vall |= (j < fdm_size ? oobptr[j] : 0xff) -+ << (j * 8); -+ else -+ valm |= (j < fdm_size ? oobptr[j] : 0xff) -+ << ((j - 4) * 8); -+ } -+ -+ nfi_write32(snf, NFI_FDML(i), vall); -+ nfi_write32(snf, NFI_FDMM(i), valm); -+ -+ oobptr += fdm_size; -+ } -+} -+ -+static void mtk_snand_bm_swap(struct mtk_snand *snf, u8 *buf) -+{ -+ u32 buf_bbm_pos, fdm_bbm_pos; -+ -+ if (!snf->caps->bbm_swap || snf->nfi_cfg.nsectors == 1) -+ return; -+ -+ // swap [pagesize] byte on nand with the first fdm byte -+ // in the last sector. -+ buf_bbm_pos = snf->nfi_cfg.page_size - -+ (snf->nfi_cfg.nsectors - 1) * snf->nfi_cfg.spare_size; -+ fdm_bbm_pos = snf->nfi_cfg.page_size + -+ (snf->nfi_cfg.nsectors - 1) * snf->caps->fdm_size; -+ -+ swap(snf->buf[fdm_bbm_pos], buf[buf_bbm_pos]); -+} -+ -+static void mtk_snand_fdm_bm_swap(struct mtk_snand *snf) -+{ -+ u32 fdm_bbm_pos1, fdm_bbm_pos2; -+ -+ if (!snf->caps->bbm_swap || snf->nfi_cfg.nsectors == 1) -+ return; -+ -+ // swap the first fdm byte in the first and the last sector. -+ fdm_bbm_pos1 = snf->nfi_cfg.page_size; -+ fdm_bbm_pos2 = snf->nfi_cfg.page_size + -+ (snf->nfi_cfg.nsectors - 1) * snf->caps->fdm_size; -+ swap(snf->buf[fdm_bbm_pos1], snf->buf[fdm_bbm_pos2]); -+} -+ -+static int mtk_snand_read_page_cache(struct mtk_snand *snf, -+ const struct spi_mem_op *op) -+{ -+ u8 *buf = snf->buf; -+ u8 *buf_fdm = buf + snf->nfi_cfg.page_size; -+ // the address part to be sent by the controller -+ u32 op_addr = op->addr.val; -+ // where to start copying data from bounce buffer -+ u32 rd_offset = 0; -+ u32 dummy_clk = (op->dummy.nbytes * BITS_PER_BYTE / op->dummy.buswidth); -+ u32 op_mode = 0; -+ u32 dma_len = snf->buf_len; -+ int ret = 0; -+ u32 rd_mode, rd_bytes, val; -+ dma_addr_t buf_dma; -+ -+ if (snf->autofmt) { -+ u32 last_bit; -+ u32 mask; -+ -+ dma_len = snf->nfi_cfg.page_size; -+ op_mode = CNFG_AUTO_FMT_EN; -+ if (op->data.ecc) -+ op_mode |= CNFG_HW_ECC_EN; -+ // extract the plane bit: -+ // Find the highest bit set in (pagesize+oobsize). -+ // Bits higher than that in op->addr are kept and sent over SPI -+ // Lower bits are used as an offset for copying data from DMA -+ // bounce buffer. -+ last_bit = fls(snf->nfi_cfg.page_size + snf->nfi_cfg.oob_size); -+ mask = (1 << last_bit) - 1; -+ rd_offset = op_addr & mask; -+ op_addr &= ~mask; -+ -+ // check if we can dma to the caller memory -+ if (rd_offset == 0 && op->data.nbytes >= snf->nfi_cfg.page_size) -+ buf = op->data.buf.in; -+ } -+ mtk_snand_mac_reset(snf); -+ mtk_nfi_reset(snf); -+ -+ // command and dummy cycles -+ nfi_write32(snf, SNF_RD_CTL2, -+ (dummy_clk << DATA_READ_DUMMY_S) | -+ (op->cmd.opcode << DATA_READ_CMD_S)); -+ -+ // read address -+ nfi_write32(snf, SNF_RD_CTL3, op_addr); -+ -+ // Set read op_mode -+ if (op->data.buswidth == 4) -+ rd_mode = op->addr.buswidth == 4 ? DATA_READ_MODE_QUAD : -+ DATA_READ_MODE_X4; -+ else if (op->data.buswidth == 2) -+ rd_mode = op->addr.buswidth == 2 ? DATA_READ_MODE_DUAL : -+ DATA_READ_MODE_X2; -+ else -+ rd_mode = DATA_READ_MODE_X1; -+ rd_mode <<= DATA_READ_MODE_S; -+ nfi_rmw32(snf, SNF_MISC_CTL, DATA_READ_MODE, -+ rd_mode | DATARD_CUSTOM_EN); -+ -+ // Set bytes to read -+ rd_bytes = (snf->nfi_cfg.spare_size + snf->caps->sector_size) * -+ snf->nfi_cfg.nsectors; -+ nfi_write32(snf, SNF_MISC_CTL2, -+ (rd_bytes << PROGRAM_LOAD_BYTE_NUM_S) | rd_bytes); -+ -+ // NFI read prepare -+ nfi_write16(snf, NFI_CNFG, -+ (CNFG_OP_MODE_CUST << CNFG_OP_MODE_S) | CNFG_DMA_BURST_EN | -+ CNFG_READ_MODE | CNFG_DMA_MODE | op_mode); -+ -+ nfi_write32(snf, NFI_CON, (snf->nfi_cfg.nsectors << CON_SEC_NUM_S)); -+ -+ buf_dma = dma_map_single(snf->dev, buf, dma_len, DMA_FROM_DEVICE); -+ if (dma_mapping_error(snf->dev, buf_dma)) { -+ dev_err(snf->dev, "DMA mapping failed.\n"); -+ goto cleanup; -+ } -+ nfi_write32(snf, NFI_STRADDR, buf_dma); -+ if (op->data.ecc) { -+ snf->ecc_cfg->op = ECC_DECODE; -+ ret = mtk_ecc_enable(snf->ecc, snf->ecc_cfg); -+ if (ret) -+ goto cleanup_dma; -+ } -+ // Prepare for custom read interrupt -+ nfi_write32(snf, NFI_INTR_EN, NFI_IRQ_INTR_EN | NFI_IRQ_CUS_READ); -+ reinit_completion(&snf->op_done); -+ -+ // Trigger NFI into custom mode -+ nfi_write16(snf, NFI_CMD, NFI_CMD_DUMMY_READ); -+ -+ // Start DMA read -+ nfi_rmw32(snf, NFI_CON, 0, CON_BRD); -+ nfi_write16(snf, NFI_STRDATA, STR_DATA); -+ -+ if (!wait_for_completion_timeout( -+ &snf->op_done, usecs_to_jiffies(SNFI_POLL_INTERVAL))) { -+ dev_err(snf->dev, "DMA timed out for reading from cache.\n"); -+ ret = -ETIMEDOUT; -+ goto cleanup; -+ } -+ -+ // Wait for BUS_SEC_CNTR returning expected value -+ ret = readl_poll_timeout(snf->nfi_base + NFI_BYTELEN, val, -+ BUS_SEC_CNTR(val) >= snf->nfi_cfg.nsectors, 0, -+ SNFI_POLL_INTERVAL); -+ if (ret) { -+ dev_err(snf->dev, "Timed out waiting for BUS_SEC_CNTR\n"); -+ goto cleanup2; -+ } -+ -+ // Wait for bus becoming idle -+ ret = readl_poll_timeout(snf->nfi_base + NFI_MASTERSTA, val, -+ !(val & snf->caps->mastersta_mask), 0, -+ SNFI_POLL_INTERVAL); -+ if (ret) { -+ dev_err(snf->dev, "Timed out waiting for bus becoming idle\n"); -+ goto cleanup2; -+ } -+ -+ if (op->data.ecc) { -+ ret = mtk_ecc_wait_done(snf->ecc, ECC_DECODE); -+ if (ret) { -+ dev_err(snf->dev, "wait ecc done timeout\n"); -+ goto cleanup2; -+ } -+ // save status before disabling ecc -+ mtk_ecc_get_stats(snf->ecc, &snf->ecc_stats, -+ snf->nfi_cfg.nsectors); -+ } -+ -+ dma_unmap_single(snf->dev, buf_dma, dma_len, DMA_FROM_DEVICE); -+ -+ if (snf->autofmt) { -+ mtk_snand_read_fdm(snf, buf_fdm); -+ if (snf->caps->bbm_swap) { -+ mtk_snand_bm_swap(snf, buf); -+ mtk_snand_fdm_bm_swap(snf); -+ } -+ } -+ -+ // copy data back -+ if (nfi_read32(snf, NFI_STA) & READ_EMPTY) { -+ memset(op->data.buf.in, 0xff, op->data.nbytes); -+ snf->ecc_stats.bitflips = 0; -+ snf->ecc_stats.failed = 0; -+ snf->ecc_stats.corrected = 0; -+ } else { -+ if (buf == op->data.buf.in) { -+ u32 cap_len = snf->buf_len - snf->nfi_cfg.page_size; -+ u32 req_left = op->data.nbytes - snf->nfi_cfg.page_size; -+ -+ if (req_left) -+ memcpy(op->data.buf.in + snf->nfi_cfg.page_size, -+ buf_fdm, -+ cap_len < req_left ? cap_len : req_left); -+ } else if (rd_offset < snf->buf_len) { -+ u32 cap_len = snf->buf_len - rd_offset; -+ -+ if (op->data.nbytes < cap_len) -+ cap_len = op->data.nbytes; -+ memcpy(op->data.buf.in, snf->buf + rd_offset, cap_len); -+ } -+ } -+cleanup2: -+ if (op->data.ecc) -+ mtk_ecc_disable(snf->ecc); -+cleanup_dma: -+ // unmap dma only if any error happens. (otherwise it's done before -+ // data copying) -+ if (ret) -+ dma_unmap_single(snf->dev, buf_dma, dma_len, DMA_FROM_DEVICE); -+cleanup: -+ // Stop read -+ nfi_write32(snf, NFI_CON, 0); -+ nfi_write16(snf, NFI_CNFG, 0); -+ -+ // Clear SNF done flag -+ nfi_rmw32(snf, SNF_STA_CTL1, 0, CUS_READ_DONE); -+ nfi_write32(snf, SNF_STA_CTL1, 0); -+ -+ // Disable interrupt -+ nfi_read32(snf, NFI_INTR_STA); -+ nfi_write32(snf, NFI_INTR_EN, 0); -+ -+ nfi_rmw32(snf, SNF_MISC_CTL, DATARD_CUSTOM_EN, 0); -+ return ret; -+} -+ -+static int mtk_snand_write_page_cache(struct mtk_snand *snf, -+ const struct spi_mem_op *op) -+{ -+ // the address part to be sent by the controller -+ u32 op_addr = op->addr.val; -+ // where to start copying data from bounce buffer -+ u32 wr_offset = 0; -+ u32 op_mode = 0; -+ int ret = 0; -+ u32 wr_mode = 0; -+ u32 dma_len = snf->buf_len; -+ u32 wr_bytes, val; -+ size_t cap_len; -+ dma_addr_t buf_dma; -+ -+ if (snf->autofmt) { -+ u32 last_bit; -+ u32 mask; -+ -+ dma_len = snf->nfi_cfg.page_size; -+ op_mode = CNFG_AUTO_FMT_EN; -+ if (op->data.ecc) -+ op_mode |= CNFG_HW_ECC_EN; -+ -+ last_bit = fls(snf->nfi_cfg.page_size + snf->nfi_cfg.oob_size); -+ mask = (1 << last_bit) - 1; -+ wr_offset = op_addr & mask; -+ op_addr &= ~mask; -+ } -+ mtk_snand_mac_reset(snf); -+ mtk_nfi_reset(snf); -+ -+ if (wr_offset) -+ memset(snf->buf, 0xff, wr_offset); -+ -+ cap_len = snf->buf_len - wr_offset; -+ if (op->data.nbytes < cap_len) -+ cap_len = op->data.nbytes; -+ memcpy(snf->buf + wr_offset, op->data.buf.out, cap_len); -+ if (snf->autofmt) { -+ if (snf->caps->bbm_swap) { -+ mtk_snand_fdm_bm_swap(snf); -+ mtk_snand_bm_swap(snf, snf->buf); -+ } -+ mtk_snand_write_fdm(snf, snf->buf + snf->nfi_cfg.page_size); -+ } -+ -+ // Command -+ nfi_write32(snf, SNF_PG_CTL1, (op->cmd.opcode << PG_LOAD_CMD_S)); -+ -+ // write address -+ nfi_write32(snf, SNF_PG_CTL2, op_addr); -+ -+ // Set read op_mode -+ if (op->data.buswidth == 4) -+ wr_mode = PG_LOAD_X4_EN; -+ -+ nfi_rmw32(snf, SNF_MISC_CTL, PG_LOAD_X4_EN, -+ wr_mode | PG_LOAD_CUSTOM_EN); -+ -+ // Set bytes to write -+ wr_bytes = (snf->nfi_cfg.spare_size + snf->caps->sector_size) * -+ snf->nfi_cfg.nsectors; -+ nfi_write32(snf, SNF_MISC_CTL2, -+ (wr_bytes << PROGRAM_LOAD_BYTE_NUM_S) | wr_bytes); -+ -+ // NFI write prepare -+ nfi_write16(snf, NFI_CNFG, -+ (CNFG_OP_MODE_PROGRAM << CNFG_OP_MODE_S) | -+ CNFG_DMA_BURST_EN | CNFG_DMA_MODE | op_mode); -+ -+ nfi_write32(snf, NFI_CON, (snf->nfi_cfg.nsectors << CON_SEC_NUM_S)); -+ buf_dma = dma_map_single(snf->dev, snf->buf, dma_len, DMA_TO_DEVICE); -+ if (dma_mapping_error(snf->dev, buf_dma)) { -+ dev_err(snf->dev, "DMA mapping failed.\n"); -+ goto cleanup; -+ } -+ nfi_write32(snf, NFI_STRADDR, buf_dma); -+ if (op->data.ecc) { -+ snf->ecc_cfg->op = ECC_ENCODE; -+ ret = mtk_ecc_enable(snf->ecc, snf->ecc_cfg); -+ if (ret) -+ goto cleanup_dma; -+ } -+ // Prepare for custom write interrupt -+ nfi_write32(snf, NFI_INTR_EN, NFI_IRQ_INTR_EN | NFI_IRQ_CUS_PG); -+ reinit_completion(&snf->op_done); -+ ; -+ -+ // Trigger NFI into custom mode -+ nfi_write16(snf, NFI_CMD, NFI_CMD_DUMMY_WRITE); -+ -+ // Start DMA write -+ nfi_rmw32(snf, NFI_CON, 0, CON_BWR); -+ nfi_write16(snf, NFI_STRDATA, STR_DATA); -+ -+ if (!wait_for_completion_timeout( -+ &snf->op_done, usecs_to_jiffies(SNFI_POLL_INTERVAL))) { -+ dev_err(snf->dev, "DMA timed out for program load.\n"); -+ ret = -ETIMEDOUT; -+ goto cleanup_ecc; -+ } -+ -+ // Wait for NFI_SEC_CNTR returning expected value -+ ret = readl_poll_timeout(snf->nfi_base + NFI_ADDRCNTR, val, -+ NFI_SEC_CNTR(val) >= snf->nfi_cfg.nsectors, 0, -+ SNFI_POLL_INTERVAL); -+ if (ret) -+ dev_err(snf->dev, "Timed out waiting for NFI_SEC_CNTR\n"); -+ -+cleanup_ecc: -+ if (op->data.ecc) -+ mtk_ecc_disable(snf->ecc); -+cleanup_dma: -+ dma_unmap_single(snf->dev, buf_dma, dma_len, DMA_TO_DEVICE); -+cleanup: -+ // Stop write -+ nfi_write32(snf, NFI_CON, 0); -+ nfi_write16(snf, NFI_CNFG, 0); -+ -+ // Clear SNF done flag -+ nfi_rmw32(snf, SNF_STA_CTL1, 0, CUS_PG_DONE); -+ nfi_write32(snf, SNF_STA_CTL1, 0); -+ -+ // Disable interrupt -+ nfi_read32(snf, NFI_INTR_STA); -+ nfi_write32(snf, NFI_INTR_EN, 0); -+ -+ nfi_rmw32(snf, SNF_MISC_CTL, PG_LOAD_CUSTOM_EN, 0); -+ -+ return ret; -+} -+ -+/** -+ * mtk_snand_is_page_ops() - check if the op is a controller supported page op. -+ * @op spi-mem op to check -+ * -+ * Check whether op can be executed with read_from_cache or program_load -+ * mode in the controller. -+ * This controller can execute typical Read From Cache and Program Load -+ * instructions found on SPI-NAND with 2-byte address. -+ * DTR and cmd buswidth & nbytes should be checked before calling this. -+ * -+ * Return: true if the op matches the instruction template -+ */ -+static bool mtk_snand_is_page_ops(const struct spi_mem_op *op) -+{ -+ if (op->addr.nbytes != 2) -+ return false; -+ -+ if (op->addr.buswidth != 1 && op->addr.buswidth != 2 && -+ op->addr.buswidth != 4) -+ return false; -+ -+ // match read from page instructions -+ if (op->data.dir == SPI_MEM_DATA_IN) { -+ // check dummy cycle first -+ if (op->dummy.nbytes * BITS_PER_BYTE / op->dummy.buswidth > -+ DATA_READ_MAX_DUMMY) -+ return false; -+ // quad io / quad out -+ if ((op->addr.buswidth == 4 || op->addr.buswidth == 1) && -+ op->data.buswidth == 4) -+ return true; -+ -+ // dual io / dual out -+ if ((op->addr.buswidth == 2 || op->addr.buswidth == 1) && -+ op->data.buswidth == 2) -+ return true; -+ -+ // standard spi -+ if (op->addr.buswidth == 1 && op->data.buswidth == 1) -+ return true; -+ } else if (op->data.dir == SPI_MEM_DATA_OUT) { -+ // check dummy cycle first -+ if (op->dummy.nbytes) -+ return false; -+ // program load quad out -+ if (op->addr.buswidth == 1 && op->data.buswidth == 4) -+ return true; -+ // standard spi -+ if (op->addr.buswidth == 1 && op->data.buswidth == 1) -+ return true; -+ } -+ return false; -+} -+ -+static bool mtk_snand_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 (mtk_snand_is_page_ops(op)) -+ return true; -+ return ((op->addr.nbytes == 0 || op->addr.buswidth == 1) && -+ (op->dummy.nbytes == 0 || op->dummy.buswidth == 1) && -+ (op->data.nbytes == 0 || op->data.buswidth == 1)); -+} -+ -+static int mtk_snand_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op) -+{ -+ struct mtk_snand *ms = spi_controller_get_devdata(mem->spi->master); -+ // page ops transfer size must be exactly ((sector_size + spare_size) * -+ // nsectors). Limit the op size if the caller requests more than that. -+ // exec_op will read more than needed and discard the leftover if the -+ // caller requests less data. -+ if (mtk_snand_is_page_ops(op)) { -+ size_t l; -+ // skip adjust_op_size for page ops -+ if (ms->autofmt) -+ return 0; -+ l = ms->caps->sector_size + ms->nfi_cfg.spare_size; -+ l *= ms->nfi_cfg.nsectors; -+ if (op->data.nbytes > l) -+ op->data.nbytes = l; -+ } else { -+ size_t hl = op->cmd.nbytes + op->addr.nbytes + op->dummy.nbytes; -+ -+ if (hl >= SNF_GPRAM_SIZE) -+ return -EOPNOTSUPP; -+ if (op->data.nbytes > SNF_GPRAM_SIZE - hl) -+ op->data.nbytes = SNF_GPRAM_SIZE - hl; -+ } -+ return 0; -+} -+ -+static int mtk_snand_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) -+{ -+ struct mtk_snand *ms = spi_controller_get_devdata(mem->spi->master); -+ -+ dev_dbg(ms->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 (mtk_snand_is_page_ops(op)) { -+ if (op->data.dir == SPI_MEM_DATA_IN) -+ return mtk_snand_read_page_cache(ms, op); -+ else -+ return mtk_snand_write_page_cache(ms, op); -+ } else { -+ return mtk_snand_mac_io(ms, op); -+ } -+} -+ -+static const struct spi_controller_mem_ops mtk_snand_mem_ops = { -+ .adjust_op_size = mtk_snand_adjust_op_size, -+ .supports_op = mtk_snand_supports_op, -+ .exec_op = mtk_snand_exec_op, -+}; -+ -+static const struct spi_controller_mem_caps mtk_snand_mem_caps = { -+ .ecc = true, -+}; -+ -+static irqreturn_t mtk_snand_irq(int irq, void *id) -+{ -+ struct mtk_snand *snf = id; -+ u32 sta, ien; -+ -+ sta = nfi_read32(snf, NFI_INTR_STA); -+ ien = nfi_read32(snf, NFI_INTR_EN); -+ -+ if (!(sta & ien)) -+ return IRQ_NONE; -+ -+ nfi_write32(snf, NFI_INTR_EN, 0); -+ complete(&snf->op_done); -+ return IRQ_HANDLED; -+} -+ -+static const struct of_device_id mtk_snand_ids[] = { -+ { .compatible = "mediatek,mt7622-snand", .data = &mt7622_snand_caps }, -+ { .compatible = "mediatek,mt7629-snand", .data = &mt7629_snand_caps }, -+ {}, -+}; -+ -+MODULE_DEVICE_TABLE(of, mtk_snand_ids); -+ -+static int mtk_snand_enable_clk(struct mtk_snand *ms) -+{ -+ int ret; -+ -+ ret = clk_prepare_enable(ms->nfi_clk); -+ if (ret) { -+ dev_err(ms->dev, "unable to enable nfi clk\n"); -+ return ret; -+ } -+ ret = clk_prepare_enable(ms->pad_clk); -+ if (ret) { -+ dev_err(ms->dev, "unable to enable pad clk\n"); -+ goto err1; -+ } -+ return 0; -+err1: -+ clk_disable_unprepare(ms->nfi_clk); -+ return ret; -+} -+ -+static void mtk_snand_disable_clk(struct mtk_snand *ms) -+{ -+ clk_disable_unprepare(ms->pad_clk); -+ clk_disable_unprepare(ms->nfi_clk); -+} -+ -+static int mtk_snand_probe(struct platform_device *pdev) -+{ -+ struct device_node *np = pdev->dev.of_node; -+ const struct of_device_id *dev_id; -+ struct spi_controller *ctlr; -+ struct mtk_snand *ms; -+ int ret; -+ -+ dev_id = of_match_node(mtk_snand_ids, np); -+ if (!dev_id) -+ return -EINVAL; -+ -+ ctlr = devm_spi_alloc_master(&pdev->dev, sizeof(*ms)); -+ if (!ctlr) -+ return -ENOMEM; -+ platform_set_drvdata(pdev, ctlr); -+ -+ ms = spi_controller_get_devdata(ctlr); -+ -+ ms->ctlr = ctlr; -+ ms->caps = dev_id->data; -+ -+ ms->ecc = of_mtk_ecc_get(np); -+ if (IS_ERR(ms->ecc)) -+ return PTR_ERR(ms->ecc); -+ else if (!ms->ecc) -+ return -ENODEV; -+ -+ ms->nfi_base = devm_platform_ioremap_resource(pdev, 0); -+ if (IS_ERR(ms->nfi_base)) { -+ ret = PTR_ERR(ms->nfi_base); -+ goto release_ecc; -+ } -+ -+ ms->dev = &pdev->dev; -+ -+ ms->nfi_clk = devm_clk_get(&pdev->dev, "nfi_clk"); -+ if (IS_ERR(ms->nfi_clk)) { -+ ret = PTR_ERR(ms->nfi_clk); -+ dev_err(&pdev->dev, "unable to get nfi_clk, err = %d\n", ret); -+ goto release_ecc; -+ } -+ -+ ms->pad_clk = devm_clk_get(&pdev->dev, "pad_clk"); -+ if (IS_ERR(ms->pad_clk)) { -+ ret = PTR_ERR(ms->pad_clk); -+ dev_err(&pdev->dev, "unable to get pad_clk, err = %d\n", ret); -+ goto release_ecc; -+ } -+ -+ ret = mtk_snand_enable_clk(ms); -+ if (ret) -+ goto release_ecc; -+ -+ init_completion(&ms->op_done); -+ -+ ms->irq = platform_get_irq(pdev, 0); -+ if (ms->irq < 0) { -+ ret = ms->irq; -+ goto disable_clk; -+ } -+ ret = devm_request_irq(ms->dev, ms->irq, mtk_snand_irq, 0x0, -+ "mtk-snand", ms); -+ if (ret) { -+ dev_err(ms->dev, "failed to request snfi irq\n"); -+ goto disable_clk; -+ } -+ -+ ret = dma_set_mask(ms->dev, DMA_BIT_MASK(32)); -+ if (ret) { -+ dev_err(ms->dev, "failed to set dma mask\n"); -+ goto disable_clk; -+ } -+ -+ // switch to SNFI mode -+ nfi_write32(ms, SNF_CFG, SPI_MODE); -+ -+ // setup an initial page format for ops matching page_cache_op template -+ // before ECC is called. -+ ret = mtk_snand_setup_pagefmt(ms, ms->caps->sector_size, -+ ms->caps->spare_sizes[0]); -+ if (ret) { -+ dev_err(ms->dev, "failed to set initial page format\n"); -+ goto disable_clk; -+ } -+ -+ // setup ECC engine -+ ms->ecc_eng.dev = &pdev->dev; -+ ms->ecc_eng.integration = NAND_ECC_ENGINE_INTEGRATION_PIPELINED; -+ ms->ecc_eng.ops = &mtk_snfi_ecc_engine_ops; -+ ms->ecc_eng.priv = ms; -+ -+ ret = nand_ecc_register_on_host_hw_engine(&ms->ecc_eng); -+ if (ret) { -+ dev_err(&pdev->dev, "failed to register ecc engine.\n"); -+ goto disable_clk; -+ } -+ -+ ctlr->num_chipselect = 1; -+ ctlr->mem_ops = &mtk_snand_mem_ops; -+ ctlr->mem_caps = &mtk_snand_mem_caps; -+ ctlr->bits_per_word_mask = SPI_BPW_MASK(8); -+ ctlr->mode_bits = SPI_RX_DUAL | SPI_RX_QUAD | SPI_TX_DUAL | SPI_TX_QUAD; -+ ctlr->dev.of_node = pdev->dev.of_node; -+ ret = spi_register_controller(ctlr); -+ if (ret) { -+ dev_err(&pdev->dev, "spi_register_controller failed.\n"); -+ goto disable_clk; -+ } -+ -+ return 0; -+disable_clk: -+ mtk_snand_disable_clk(ms); -+release_ecc: -+ mtk_ecc_release(ms->ecc); -+ return ret; -+} -+ -+static int mtk_snand_remove(struct platform_device *pdev) -+{ -+ struct spi_controller *ctlr = platform_get_drvdata(pdev); -+ struct mtk_snand *ms = spi_controller_get_devdata(ctlr); -+ -+ spi_unregister_controller(ctlr); -+ mtk_snand_disable_clk(ms); -+ mtk_ecc_release(ms->ecc); -+ kfree(ms->buf); -+ return 0; -+} -+ -+static struct platform_driver mtk_snand_driver = { -+ .probe = mtk_snand_probe, -+ .remove = mtk_snand_remove, -+ .driver = { -+ .name = "mtk-snand", -+ .of_match_table = mtk_snand_ids, -+ }, -+}; -+ -+module_platform_driver(mtk_snand_driver); -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Chuanhong Guo "); -+MODULE_DESCRIPTION("MeidaTek SPI-NAND Flash Controller Driver"); diff --git a/target/linux/mediatek/patches-5.15/120-13-v5.19-mtd-nand-mtk-ecc-also-parse-nand-ecc-engine-if-avail.patch b/target/linux/mediatek/patches-5.15/120-13-v5.19-mtd-nand-mtk-ecc-also-parse-nand-ecc-engine-if-avail.patch deleted file mode 100644 index 01d9d1208..000000000 --- a/target/linux/mediatek/patches-5.15/120-13-v5.19-mtd-nand-mtk-ecc-also-parse-nand-ecc-engine-if-avail.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 433b76fa0f3ca2865841abc21538dd8077ca3edd Mon Sep 17 00:00:00 2001 -From: Chuanhong Guo -Date: Mon, 4 Apr 2022 00:05:38 +0800 -Subject: [PATCH 13/15] mtd: nand: mtk-ecc: also parse nand-ecc-engine if - available - -The recently added ECC engine support introduced a generic property -named nand-ecc-engine for ecc engine phandle. This patch adds support -for this new property. - -Signed-off-by: Chuanhong Guo -(cherry picked from commit a41f25feb6e47c1c4d8d3279ae990ccbd8dfab54) ---- - drivers/mtd/nand/ecc-mtk.c | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - ---- a/drivers/mtd/nand/ecc-mtk.c -+++ b/drivers/mtd/nand/ecc-mtk.c -@@ -279,7 +279,10 @@ struct mtk_ecc *of_mtk_ecc_get(struct de - struct mtk_ecc *ecc = NULL; - struct device_node *np; - -- np = of_parse_phandle(of_node, "ecc-engine", 0); -+ np = of_parse_phandle(of_node, "nand-ecc-engine", 0); -+ /* for backward compatibility */ -+ if (!np) -+ np = of_parse_phandle(of_node, "ecc-engine", 0); - if (np) { - ecc = mtk_ecc_get(np); - of_node_put(np); diff --git a/target/linux/mediatek/patches-5.15/120-14-v5.19-arm64-dts-mediatek-add-mtk-snfi-for-mt7622.patch b/target/linux/mediatek/patches-5.15/120-14-v5.19-arm64-dts-mediatek-add-mtk-snfi-for-mt7622.patch deleted file mode 100644 index 56548f3ac..000000000 --- a/target/linux/mediatek/patches-5.15/120-14-v5.19-arm64-dts-mediatek-add-mtk-snfi-for-mt7622.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 9ba7c246063ae43baf2e53ccc8c8b5f8d025aaaa Mon Sep 17 00:00:00 2001 -From: Chuanhong Guo -Date: Sun, 3 Apr 2022 10:19:29 +0800 -Subject: [PATCH 15/15] arm64: dts: mediatek: add mtk-snfi for mt7622 - -This patch adds a device-tree node for the MTK SPI-NAND Flash Interface -for MT7622 device tree. - -Signed-off-by: Chuanhong Guo -(cherry picked from commit 2e022641709011ef0843d0416b0f264b5fc217af) ---- - arch/arm64/boot/dts/mediatek/mt7622.dtsi | 12 ++++++++++++ - 1 file changed, 12 insertions(+) - ---- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi -+++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi -@@ -550,6 +550,18 @@ - status = "disabled"; - }; - -+ snfi: spi@1100d000 { -+ compatible = "mediatek,mt7622-snand"; -+ reg = <0 0x1100d000 0 0x1000>; -+ interrupts = ; -+ clocks = <&pericfg CLK_PERI_NFI_PD>, <&pericfg CLK_PERI_SNFI_PD>; -+ clock-names = "nfi_clk", "pad_clk"; -+ nand-ecc-engine = <&bch>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "disabled"; -+ }; -+ - bch: ecc@1100e000 { - compatible = "mediatek,mt7622-ecc"; - reg = <0 0x1100e000 0 0x1000>; diff --git a/target/linux/mediatek/patches-5.15/121-hack-spi-nand-1b-bbm.patch b/target/linux/mediatek/patches-5.15/121-hack-spi-nand-1b-bbm.patch deleted file mode 100644 index 770a7ff9b..000000000 --- a/target/linux/mediatek/patches-5.15/121-hack-spi-nand-1b-bbm.patch +++ /dev/null @@ -1,20 +0,0 @@ ---- a/drivers/mtd/nand/spi/core.c -+++ b/drivers/mtd/nand/spi/core.c -@@ -714,7 +714,7 @@ static int spinand_mtd_write(struct mtd_ - static bool spinand_isbad(struct nand_device *nand, const struct nand_pos *pos) - { - struct spinand_device *spinand = nand_to_spinand(nand); -- u8 marker[2] = { }; -+ u8 marker[1] = { }; - struct nand_page_io_req req = { - .pos = *pos, - .ooblen = sizeof(marker), -@@ -725,7 +725,7 @@ static bool spinand_isbad(struct nand_de - - spinand_select_target(spinand, pos->target); - spinand_read_page(spinand, &req); -- if (marker[0] != 0xff || marker[1] != 0xff) -+ if (marker[0] != 0xff) - return true; - - return false; diff --git a/target/linux/mediatek/patches-5.15/130-dts-mt7629-add-snand-support.patch b/target/linux/mediatek/patches-5.15/130-dts-mt7629-add-snand-support.patch deleted file mode 100644 index be0018a38..000000000 --- a/target/linux/mediatek/patches-5.15/130-dts-mt7629-add-snand-support.patch +++ /dev/null @@ -1,94 +0,0 @@ -From c813fbe806257c574240770ef716fbee19f7dbfa Mon Sep 17 00:00:00 2001 -From: Xiangsheng Hou -Date: Thu, 6 Jun 2019 16:29:04 +0800 -Subject: [PATCH] spi: spi-mem: Mediatek: Add SPI Nand support for MT7629 - -Signed-off-by: Xiangsheng Hou ---- - arch/arm/boot/dts/mt7629-rfb.dts | 45 ++++++++++++++++++++++++++++++++ - arch/arm/boot/dts/mt7629.dtsi | 22 ++++++++++++++++ - 3 files changed, 79 insertions(+) - ---- a/arch/arm/boot/dts/mt7629.dtsi -+++ b/arch/arm/boot/dts/mt7629.dtsi -@@ -272,6 +272,27 @@ - status = "disabled"; - }; - -+ snfi: spi@1100d000 { -+ compatible = "mediatek,mt7629-snand"; -+ reg = <0x1100d000 0x1000>; -+ interrupts = ; -+ clocks = <&pericfg CLK_PERI_NFI_PD>, <&pericfg CLK_PERI_SNFI_PD>; -+ clock-names = "nfi_clk", "pad_clk"; -+ nand-ecc-engine = <&bch>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "disabled"; -+ }; -+ -+ bch: ecc@1100e000 { -+ compatible = "mediatek,mt7622-ecc"; -+ reg = <0x1100e000 0x1000>; -+ interrupts = ; -+ clocks = <&pericfg CLK_PERI_NFIECC_PD>; -+ clock-names = "nfiecc_clk"; -+ status = "disabled"; -+ }; -+ - spi: spi@1100a000 { - compatible = "mediatek,mt7629-spi", - "mediatek,mt7622-spi"; ---- a/arch/arm/boot/dts/mt7629-rfb.dts -+++ b/arch/arm/boot/dts/mt7629-rfb.dts -@@ -254,6 +254,50 @@ - }; - }; - -+&bch { -+ status = "okay"; -+}; -+ -+&snfi { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&serial_nand_pins>; -+ status = "okay"; -+ flash@0 { -+ compatible = "spi-nand"; -+ reg = <0>; -+ spi-tx-bus-width = <4>; -+ spi-rx-bus-width = <4>; -+ nand-ecc-engine = <&snfi>; -+ -+ partitions { -+ compatible = "fixed-partitions"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ partition@0 { -+ label = "Bootloader"; -+ reg = <0x00000 0x0100000>; -+ read-only; -+ }; -+ -+ partition@100000 { -+ label = "Config"; -+ reg = <0x100000 0x0040000>; -+ }; -+ -+ partition@140000 { -+ label = "factory"; -+ reg = <0x140000 0x0080000>; -+ }; -+ -+ partition@1c0000 { -+ label = "firmware"; -+ reg = <0x1c0000 0x1000000>; -+ }; -+ }; -+ }; -+}; -+ - &spi { - pinctrl-names = "default"; - pinctrl-0 = <&spi_pins>; diff --git a/target/linux/mediatek/patches-5.15/131-dts-mt7622-add-snand-support.patch b/target/linux/mediatek/patches-5.15/131-dts-mt7622-add-snand-support.patch deleted file mode 100644 index 966c8ba52..000000000 --- a/target/linux/mediatek/patches-5.15/131-dts-mt7622-add-snand-support.patch +++ /dev/null @@ -1,68 +0,0 @@ ---- a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts -@@ -540,6 +540,65 @@ - status = "disabled"; - }; - -+&bch { -+ status = "okay"; -+}; -+ -+&snfi { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&serial_nand_pins>; -+ status = "okay"; -+ flash@0 { -+ compatible = "spi-nand"; -+ reg = <0>; -+ spi-tx-bus-width = <4>; -+ spi-rx-bus-width = <4>; -+ nand-ecc-engine = <&snfi>; -+ -+ partitions { -+ compatible = "fixed-partitions"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ partition@0 { -+ label = "Preloader"; -+ reg = <0x00000 0x0080000>; -+ read-only; -+ }; -+ -+ partition@80000 { -+ label = "ATF"; -+ reg = <0x80000 0x0040000>; -+ }; -+ -+ partition@c0000 { -+ label = "Bootloader"; -+ reg = <0xc0000 0x0080000>; -+ }; -+ -+ partition@140000 { -+ label = "Config"; -+ reg = <0x140000 0x0080000>; -+ }; -+ -+ partition@1c0000 { -+ label = "Factory"; -+ reg = <0x1c0000 0x0100000>; -+ }; -+ -+ partition@200000 { -+ label = "firmware"; -+ reg = <0x2c0000 0x2000000>; -+ }; -+ -+ partition@2200000 { -+ label = "User_data"; -+ reg = <0x22c0000 0x4000000>; -+ }; -+ }; -+ }; -+}; -+ - &spi0 { - pinctrl-names = "default"; - pinctrl-0 = <&spic0_pins>; diff --git a/target/linux/mediatek/patches-5.15/140-dts-fix-wmac-support-for-mt7622-rfb1.patch b/target/linux/mediatek/patches-5.15/140-dts-fix-wmac-support-for-mt7622-rfb1.patch deleted file mode 100644 index a8964421b..000000000 --- a/target/linux/mediatek/patches-5.15/140-dts-fix-wmac-support-for-mt7622-rfb1.patch +++ /dev/null @@ -1,18 +0,0 @@ ---- a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts -@@ -581,7 +581,7 @@ - reg = <0x140000 0x0080000>; - }; - -- partition@1c0000 { -+ factory: partition@1c0000 { - label = "Factory"; - reg = <0x1c0000 0x0100000>; - }; -@@ -642,5 +642,6 @@ - &wmac { - pinctrl-names = "default"; - pinctrl-0 = <&wmac_pins>; -+ mediatek,mtd-eeprom = <&factory 0x0000>; - status = "okay"; - }; diff --git a/target/linux/mediatek/patches-5.15/150-dts-mt7623-eip97-inside-secure-support.patch b/target/linux/mediatek/patches-5.15/150-dts-mt7623-eip97-inside-secure-support.patch deleted file mode 100644 index 5b63bf422..000000000 --- a/target/linux/mediatek/patches-5.15/150-dts-mt7623-eip97-inside-secure-support.patch +++ /dev/null @@ -1,24 +0,0 @@ ---- a/arch/arm/boot/dts/mt7623.dtsi -+++ b/arch/arm/boot/dts/mt7623.dtsi -@@ -951,17 +951,15 @@ - }; - - crypto: crypto@1b240000 { -- compatible = "mediatek,eip97-crypto"; -+ compatible = "inside-secure,safexcel-eip97"; - reg = <0 0x1b240000 0 0x20000>; - interrupts = , - , - , -- , -- ; -+ ; -+ interrupt-names = "ring0", "ring1", "ring2", "ring3"; - clocks = <ðsys CLK_ETHSYS_CRYPTO>; -- clock-names = "cryp"; -- power-domains = <&scpsys MT2701_POWER_DOMAIN_ETH>; -- status = "disabled"; -+ status = "okay"; - }; - - bdpsys: syscon@1c000000 { diff --git a/target/linux/mediatek/patches-5.15/160-dts-mt7623-bpi-r2-earlycon.patch b/target/linux/mediatek/patches-5.15/160-dts-mt7623-bpi-r2-earlycon.patch deleted file mode 100644 index 091cffc3c..000000000 --- a/target/linux/mediatek/patches-5.15/160-dts-mt7623-bpi-r2-earlycon.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts -+++ b/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts -@@ -19,7 +19,7 @@ - - chosen { - stdout-path = "serial2:115200n8"; -- bootargs = "console=ttyS2,115200n8 console=tty1"; -+ bootargs = "earlycon=uart8250,mmio32,0x11004000 console=ttyS2,115200n8 console=tty1"; - }; - - connector { diff --git a/target/linux/mediatek/patches-5.15/161-dts-mt7623-bpi-r2-mmc-device-order.patch b/target/linux/mediatek/patches-5.15/161-dts-mt7623-bpi-r2-mmc-device-order.patch deleted file mode 100644 index d1bafc152..000000000 --- a/target/linux/mediatek/patches-5.15/161-dts-mt7623-bpi-r2-mmc-device-order.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts -+++ b/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts -@@ -15,6 +15,8 @@ - - aliases { - serial2 = &uart2; -+ mmc0 = &mmc0; -+ mmc1 = &mmc1; - }; - - chosen { diff --git a/target/linux/mediatek/patches-5.15/162-dts-mt7623-bpi-r2-led-aliases.patch b/target/linux/mediatek/patches-5.15/162-dts-mt7623-bpi-r2-led-aliases.patch deleted file mode 100644 index f6745add5..000000000 --- a/target/linux/mediatek/patches-5.15/162-dts-mt7623-bpi-r2-led-aliases.patch +++ /dev/null @@ -1,29 +0,0 @@ ---- a/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts -+++ b/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts -@@ -17,6 +17,10 @@ - serial2 = &uart2; - mmc0 = &mmc0; - mmc1 = &mmc1; -+ led-boot = &led_system_green; -+ led-failsafe = &led_system_blue; -+ led-running = &led_system_green; -+ led-upgrade = &led_system_blue; - }; - - chosen { -@@ -112,13 +116,13 @@ - pinctrl-names = "default"; - pinctrl-0 = <&led_pins_a>; - -- blue { -+ led_system_blue: blue { - label = "bpi-r2:pio:blue"; - gpios = <&pio 240 GPIO_ACTIVE_LOW>; - default-state = "off"; - }; - -- green { -+ led_system_green: green { - label = "bpi-r2:pio:green"; - gpios = <&pio 241 GPIO_ACTIVE_LOW>; - default-state = "off"; diff --git a/target/linux/mediatek/patches-5.15/163-dts-mt7623-bpi-r2-ethernet-alias.patch b/target/linux/mediatek/patches-5.15/163-dts-mt7623-bpi-r2-ethernet-alias.patch deleted file mode 100644 index b1dd75a41..000000000 --- a/target/linux/mediatek/patches-5.15/163-dts-mt7623-bpi-r2-ethernet-alias.patch +++ /dev/null @@ -1,10 +0,0 @@ ---- a/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts -+++ b/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts -@@ -15,6 +15,7 @@ - - aliases { - serial2 = &uart2; -+ ethernet0 = &gmac0; - mmc0 = &mmc0; - mmc1 = &mmc1; - led-boot = &led_system_green; diff --git a/target/linux/mediatek/patches-5.15/173-arm-dts-mt7623-add-musb-device-nodes.patch b/target/linux/mediatek/patches-5.15/173-arm-dts-mt7623-add-musb-device-nodes.patch deleted file mode 100644 index ba1d1fe20..000000000 --- a/target/linux/mediatek/patches-5.15/173-arm-dts-mt7623-add-musb-device-nodes.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 21d106f15262f5a2ef7531636e0703ee61c33c61 Mon Sep 17 00:00:00 2001 -From: Sungbo Eo -Date: Sun, 8 Aug 2021 21:38:40 +0900 -Subject: [PATCH 2/2] arm: dts: mt7623: add musb device nodes - -MT7623 has an musb controller that is compatible with the one from MT2701. - -Signed-off-by: Sungbo Eo ---- - arch/arm/boot/dts/mt7623.dtsi | 34 ++++++++++++++++++++++++++++++++++ - arch/arm/boot/dts/mt7623a.dtsi | 4 ++++ - 2 files changed, 38 insertions(+) - ---- a/arch/arm/boot/dts/mt7623.dtsi -+++ b/arch/arm/boot/dts/mt7623.dtsi -@@ -585,6 +585,40 @@ - status = "disabled"; - }; - -+ usb0: usb@11200000 { -+ compatible = "mediatek,mt7623-musb", -+ "mediatek,mtk-musb"; -+ reg = <0 0x11200000 0 0x1000>; -+ interrupts = ; -+ interrupt-names = "mc"; -+ phys = <&u2port2 PHY_TYPE_USB2>; -+ dr_mode = "otg"; -+ clocks = <&pericfg CLK_PERI_USB0>, -+ <&pericfg CLK_PERI_USB0_MCU>, -+ <&pericfg CLK_PERI_USB_SLV>; -+ clock-names = "main","mcu","univpll"; -+ power-domains = <&scpsys MT2701_POWER_DOMAIN_IFR_MSC>; -+ status = "disabled"; -+ }; -+ -+ u2phy1: t-phy@11210000 { -+ compatible = "mediatek,mt7623-tphy", -+ "mediatek,generic-tphy-v1"; -+ reg = <0 0x11210000 0 0x0800>; -+ #address-cells = <2>; -+ #size-cells = <2>; -+ ranges; -+ status = "disabled"; -+ -+ u2port2: usb-phy@11210800 { -+ reg = <0 0x11210800 0 0x0100>; -+ clocks = <&topckgen CLK_TOP_USB_PHY48M>; -+ clock-names = "ref"; -+ #phy-cells = <1>; -+ status = "okay"; -+ }; -+ }; -+ - audsys: clock-controller@11220000 { - compatible = "mediatek,mt7623-audsys", - "mediatek,mt2701-audsys", ---- a/arch/arm/boot/dts/mt7623a.dtsi -+++ b/arch/arm/boot/dts/mt7623a.dtsi -@@ -35,6 +35,10 @@ - clock-names = "ethif"; - }; - -+&usb0 { -+ power-domains = <&scpsys MT7623A_POWER_DOMAIN_IFR_MSC>; -+}; -+ - &usb1 { - power-domains = <&scpsys MT7623A_POWER_DOMAIN_HIF>; - }; diff --git a/target/linux/mediatek/patches-5.15/180-dts-mt7622-bpi-r64-add-mt7531-irq.patch b/target/linux/mediatek/patches-5.15/180-dts-mt7622-bpi-r64-add-mt7531-irq.patch deleted file mode 100644 index fabee390c..000000000 --- a/target/linux/mediatek/patches-5.15/180-dts-mt7622-bpi-r64-add-mt7531-irq.patch +++ /dev/null @@ -1,13 +0,0 @@ ---- a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts -@@ -161,6 +161,10 @@ - switch@0 { - compatible = "mediatek,mt7531"; - reg = <0>; -+ interrupt-controller; -+ #interrupt-cells = <1>; -+ interrupt-parent = <&pio>; -+ interrupts = <53 IRQ_TYPE_LEVEL_HIGH>; - reset-gpios = <&pio 54 0>; - - ports { diff --git a/target/linux/mediatek/patches-5.15/190-arm64-dts-mediatek-mt7622-fix-GICv2-range.patch b/target/linux/mediatek/patches-5.15/190-arm64-dts-mediatek-mt7622-fix-GICv2-range.patch deleted file mode 100644 index 8b41000a6..000000000 --- a/target/linux/mediatek/patches-5.15/190-arm64-dts-mediatek-mt7622-fix-GICv2-range.patch +++ /dev/null @@ -1,106 +0,0 @@ -From patchwork Tue Apr 26 19:51:36 2022 -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 7bit -X-Patchwork-Submitter: Daniel Golle -X-Patchwork-Id: 12827872 -Return-Path: - -X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on - aws-us-west-2-korg-lkml-1.web.codeaurora.org -Received: from bombadil.infradead.org (bombadil.infradead.org - [198.137.202.133]) - (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) - (No client certificate requested) - by smtp.lore.kernel.org (Postfix) with ESMTPS id BACF3C433EF - for ; - Tue, 26 Apr 2022 19:53:05 +0000 (UTC) -DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; - d=lists.infradead.org; s=bombadil.20210309; h=Sender: - Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: - List-Archive:List-Unsubscribe:List-Id:MIME-Version:Message-ID:Subject:Cc:To: - From:Date:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: - Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:References: - List-Owner; bh=OWGSxvlKoyPWz6b629RNINucULo6oOdFssAIiJETWRg=; b=T0HEjee0FX3hlb - x5jl7xLK5sKM0pkE2oRgwzthbFlNg8ST1j/2GkgcgT0S2Bi0vRfFxHeu/RKzS9RmiVnKJnPGL8ctg - WoBLyO5i+NcmosGoy6MmoOjGTNhj/+3q3Z1jRLBSJ4ySSP22X77YeuJTmVzySPUllQhWvDhjMVCR9 - QBRmQdc6gCAg3IYGEbWwS2TG+UHveDCeZRWxMzrwI8UPadNCRFROwugmiQ3mdU41lHCTDpnlfuRJh - o1igLKfMBLz+D8rFYvDh7FfkcKkY6lNoswA2HKUun1MEzgoyQKmITPnG2maX/BvJJuj/B3ZJShh4k - AZHmXoQxq1mrsm2FxfnQ==; -Received: from localhost ([::1] helo=bombadil.infradead.org) - by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) - id 1njRE5-00G05D-9z; Tue, 26 Apr 2022 19:51:57 +0000 -Received: from fudo.makrotopia.org ([2a07:2ec0:3002::71]) - by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) - id 1njRE1-00G03h-9H; Tue, 26 Apr 2022 19:51:55 +0000 -Received: from local - by fudo.makrotopia.org with esmtpsa (TLS1.3:TLS_AES_256_GCM_SHA384:256) - (Exim 4.94.2) (envelope-from ) - id 1njRDu-0006aF-4F; Tue, 26 Apr 2022 21:51:46 +0200 -Date: Tue, 26 Apr 2022 20:51:36 +0100 -From: Daniel Golle -To: devicetree@vger.kernel.org, linux-mediatek@lists.infradead.org, - linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org -Cc: Rob Herring , - Krzysztof Kozlowski , - Matthias Brugger -Subject: [PATCH] arm64: dts: mediatek: mt7622: fix GICv2 range -Message-ID: -MIME-Version: 1.0 -Content-Disposition: inline -X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 -X-CRM114-CacheID: sfid-20220426_125153_359242_EA3D452C -X-CRM114-Status: GOOD ( 12.45 ) -X-BeenThere: linux-arm-kernel@lists.infradead.org -X-Mailman-Version: 2.1.34 -Precedence: list -List-Id: -List-Unsubscribe: - , - -List-Archive: -List-Post: -List-Help: -List-Subscribe: - , - -Sender: "linux-arm-kernel" -Errors-To: - linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org - -With the current range specified for the CPU interface there is an -error message at boot: - -GIC: GICv2 detected, but range too small and irqchip.gicv2_force_probe not set - -Setting irqchip.gicv2_force_probe=1 in bootargs results in: - -GIC: Aliased GICv2 at 0x0000000010320000, trying to find the canonical range over 128kB -GIC: Adjusting CPU interface base to 0x000000001032f000 -GIC: Using split EOI/Deactivate mode - -Using the adjusted CPU interface base and 8K size results in only the -final line remaining and fully working system as well as /proc/interrupts -showing additional IPI3,4,5,6: - -IPI3: 0 0 CPU stop (for crash dump) interrupts -IPI4: 0 0 Timer broadcast interrupts -IPI5: 0 0 IRQ work interrupts -IPI6: 0 0 CPU wake-up interrupts - -Signed-off-by: Daniel Golle ---- - arch/arm64/boot/dts/mediatek/mt7622.dtsi | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi -+++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi -@@ -337,7 +337,7 @@ - #interrupt-cells = <3>; - interrupt-parent = <&gic>; - reg = <0 0x10310000 0 0x1000>, -- <0 0x10320000 0 0x1000>, -+ <0 0x1032f000 0 0x2000>, - <0 0x10340000 0 0x2000>, - <0 0x10360000 0 0x2000>; - }; diff --git a/target/linux/mediatek/patches-5.15/191-v5.19-arm64-dts-mt7622-specify-the-L2-cache-topology.patch b/target/linux/mediatek/patches-5.15/191-v5.19-arm64-dts-mt7622-specify-the-L2-cache-topology.patch deleted file mode 100644 index 8851fefbb..000000000 --- a/target/linux/mediatek/patches-5.15/191-v5.19-arm64-dts-mt7622-specify-the-L2-cache-topology.patch +++ /dev/null @@ -1,132 +0,0 @@ -From patchwork Thu Apr 28 22:57:55 2022 -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 7bit -X-Patchwork-Submitter: Rui Salvaterra -X-Patchwork-Id: 12831311 -Return-Path: - -X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on - aws-us-west-2-korg-lkml-1.web.codeaurora.org -Received: from bombadil.infradead.org (bombadil.infradead.org - [198.137.202.133]) - (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) - (No client certificate requested) - by smtp.lore.kernel.org (Postfix) with ESMTPS id 49367C433EF - for ; - Thu, 28 Apr 2022 22:59:15 +0000 (UTC) -DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; - d=lists.infradead.org; s=bombadil.20210309; h=Sender: - Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: - List-Archive:List-Unsubscribe:List-Id:MIME-Version:Message-Id:Date:Subject:Cc - :To:From:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: - Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:References: - List-Owner; bh=SerBW8MOw68wFFCbuq25LJzAcmqCfKMO2cFJxwFvZ+M=; b=nN4CYEO6VOGVbq - GSvQPGoya0L2IzQ/ZfknzQ853lY97zEPJk14ndK+TGQ+8ySjBSTu0xKgxlBoJj5G+DGubgRP1eZRJ - bktFqX2tohnrRavlceRxgVA3YFGBhjXE7AC0YzGC7auH2S6nSPUrH7cTVuaeIacIoV1AXPazc2hRU - u8RaJl1XHQwuhdZOsFBH99M5an3Zsmq0tsoIOYwB+gQaI307ZkqscxzcXFiCYCHlDvZlhHlW/WbdG - J+3iUnfq1KJWI2kE7TkPXMYaJzbEgG+LDrgYr3deADArCfCmnzbf0U29EZd6cR5D19GMVqGFDvsTX - H69W8qxVzJ+mR2HQd3GQ==; -Received: from localhost ([::1] helo=bombadil.infradead.org) - by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) - id 1nkD5T-008uVi-54; Thu, 28 Apr 2022 22:58:15 +0000 -Received: from mail-ed1-x533.google.com ([2a00:1450:4864:20::533]) - by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) - id 1nkD5P-008uUW-Px; Thu, 28 Apr 2022 22:58:13 +0000 -Received: by mail-ed1-x533.google.com with SMTP id p18so7146795edr.7; - Thu, 28 Apr 2022 15:58:08 -0700 (PDT) -DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; - h=from:to:cc:subject:date:message-id:mime-version - :content-transfer-encoding; - bh=R5/7OCxhqk5o9giaTDUQztGpi5IgQbeepSeYSbhWdII=; - b=BZQqEcfqgYTQ01yTJ3p6tPu0vaoYxHxTZYXAPCQDyng2F9JErAwf+wBYyeCYL3jbyn - fu7P7HVw2JjagdSunf6J7t0o3nqtfHGPh/ZLJHzYdg1s5shotJ5wMbZpAHCMdC4+K+BV - uL4JNuQnZmCRBiUFM+rtrpfaTepwEclOBBGoL9iE+tm/pWzx/WIR5WB9W8CutqsrDxF5 - 8r5IwxNz3GLYfDgZMejyxQ0BjUIeQeCMTqhf73P19V3Bgg4MUbJ2q163D/OWSpHCbJdH - OfKEAdrVw4U7Rx0/SOnvPBxeiyCVH2uAkdPiFk+O3ZvsaiODty7uqGGjbN4chYEWRdp+ - 7WBQ== -X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; - d=1e100.net; s=20210112; - h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version - :content-transfer-encoding; - bh=R5/7OCxhqk5o9giaTDUQztGpi5IgQbeepSeYSbhWdII=; - b=mvuzYrIKVAnpUgnlEa+S84XOruFt2VxxK25dib+Az/UPt4CzDO0h1u3SckfcmsFT4h - lUKka66CkdkHCJWC5JqKwSD0lbgtu2KWEsvtCWVDS+S6XKuAu99o2kvNyHC+/xW07dKL - zB7WAkyG53lrX0KH7fZ46uzHoRKWATW/idDhXBA49B+vaPqHKroSOn5JBKsu/hDwsQdf - zWA5tmOJweFjVZYe0ChD8OUDYOv+6RYlGqVvsQ5quMKJDBoC7KC8YMqvHc3K6DbQbnvZ - vJyXlcHgHSpadLRgg6wIY+ZyJyZsGqVyRD1TmcByRxSrUTGc3VSQeXUcUPv+3JFk9Esu - PqoA== -X-Gm-Message-State: AOAM530veLoWc1JsDUuaRxe8Wi4N5UaD7cH5c9nhGlW7j5aj9gwvCDya - /uqAd6FaNeLuB5hEWmAEXXugS+7njg== -X-Google-Smtp-Source: - ABdhPJyLbUuBj/1YYm+3qmglf7zy9b/YbbcMub3/HL40okdVxkr6/TVxIZulAoEV9PjbfrGkO2N3Bw== -X-Received: by 2002:a05:6402:2920:b0:425:d7c7:41f with SMTP id - ee32-20020a056402292000b00425d7c7041fmr29248373edb.370.1651186687432; - Thu, 28 Apr 2022 15:58:07 -0700 (PDT) -Received: from crystalwell.adg.lan (a109-49-0-175.cpe.netcabo.pt. - [109.49.0.175]) by smtp.gmail.com with ESMTPSA id - a25-20020a056402169900b0042617ba63c8sm2219102edv.82.2022.04.28.15.58.06 - (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); - Thu, 28 Apr 2022 15:58:06 -0700 (PDT) -From: Rui Salvaterra -To: linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, - linux-kernel@vger.kernel.org -Cc: matthias.bgg@gmail.com, ryder.lee@mediatek.com, daniel@makrotopia.org, - Rui Salvaterra -Subject: [PATCH] arm64: dts: mt7622: specify the L2 cache topology -Date: Thu, 28 Apr 2022 23:57:55 +0100 -Message-Id: <20220428225755.785153-1-rsalvaterra@gmail.com> -X-Mailer: git-send-email 2.36.0 -MIME-Version: 1.0 -X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 -X-CRM114-CacheID: sfid-20220428_155811_895571_B63D2806 -X-CRM114-Status: GOOD ( 10.27 ) -X-BeenThere: linux-arm-kernel@lists.infradead.org -X-Mailman-Version: 2.1.34 -Precedence: list -List-Id: -List-Unsubscribe: - , - -List-Archive: -List-Post: -List-Help: -List-Subscribe: - , - -Sender: "linux-arm-kernel" -Errors-To: - linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org - -On an MT7622 system, the kernel complains of not being able to detect the cache -hierarchy of CPU 0. Specify the shared L2 cache node in the device tree, in -order to fix this. - -Signed-off-by: Rui Salvaterra ---- - arch/arm64/boot/dts/mediatek/mt7622.dtsi | 7 +++++++ - 1 file changed, 7 insertions(+) - ---- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi -+++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi -@@ -80,6 +80,7 @@ - enable-method = "psci"; - clock-frequency = <1300000000>; - cci-control-port = <&cci_control2>; -+ next-level-cache = <&L2>; - }; - - cpu1: cpu@1 { -@@ -94,6 +95,12 @@ - enable-method = "psci"; - clock-frequency = <1300000000>; - cci-control-port = <&cci_control2>; -+ next-level-cache = <&L2>; -+ }; -+ -+ L2: l2-cache { -+ compatible = "cache"; -+ cache-level = <2>; - }; - }; - diff --git a/target/linux/mediatek/patches-5.15/192-v5.19-arm64-dts-mt7622-specify-the-number-of-DMA-requests.patch b/target/linux/mediatek/patches-5.15/192-v5.19-arm64-dts-mt7622-specify-the-number-of-DMA-requests.patch deleted file mode 100644 index 506a65266..000000000 --- a/target/linux/mediatek/patches-5.15/192-v5.19-arm64-dts-mt7622-specify-the-number-of-DMA-requests.patch +++ /dev/null @@ -1,122 +0,0 @@ -From patchwork Fri Apr 29 08:42:25 2022 -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 7bit -X-Patchwork-Submitter: Rui Salvaterra -X-Patchwork-Id: 12831649 -Return-Path: - -X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on - aws-us-west-2-korg-lkml-1.web.codeaurora.org -Received: from bombadil.infradead.org (bombadil.infradead.org - [198.137.202.133]) - (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) - (No client certificate requested) - by smtp.lore.kernel.org (Postfix) with ESMTPS id 386E2C433FE - for ; - Fri, 29 Apr 2022 08:43:49 +0000 (UTC) -DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; - d=lists.infradead.org; s=bombadil.20210309; h=Sender: - Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: - List-Archive:List-Unsubscribe:List-Id:MIME-Version:Message-Id:Date:Subject:Cc - :To:From:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: - Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:References: - List-Owner; bh=8o7lZT3r9rAaTm8HKh4V0xpz9VW91LuZAYfrXGv0Xic=; b=bS+249v3+UY+qs - bxuupjLqBetRQqMAaPjTn6GKQJtca75PMdLf3okoQban7PNqWO9WOgCJWgY2eyzOSjxHBPr1dsGzy - 6c3CZBbMy8pXl/zf80YRmikPFXehOzAvOpZjco4QUCCqXNsJM9FKzAqYIaZDSlLOTmADDepsh481G - k/h/g39ztzn09LVqwF2Bh0DopIbHiq/BepTeU8jFt5GTj3EGPTdCU7Vq7mf2pP6P6oPk6vswKVYaQ - opq96BDGIEpeKViuMWt07vdJX2meQBHhY/Rte/aAO5pdLpusY2OPvEKv0/49swpAEsNYIYFcgtCtm - vaKUqN85QlQznqd/NaHw==; -Received: from localhost ([::1] helo=bombadil.infradead.org) - by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) - id 1nkMD3-00AFVb-Co; Fri, 29 Apr 2022 08:42:42 +0000 -Received: from mail-ed1-x534.google.com ([2a00:1450:4864:20::534]) - by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) - id 1nkMCy-00AFSn-Rp; Fri, 29 Apr 2022 08:42:38 +0000 -Received: by mail-ed1-x534.google.com with SMTP id be20so8231068edb.12; - Fri, 29 Apr 2022 01:42:33 -0700 (PDT) -DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; - h=from:to:cc:subject:date:message-id:mime-version - :content-transfer-encoding; - bh=XJkVawFXvwQH7kz0CHPfmxuFkQ6+ipcLhCSvCaul0jQ=; - b=HSFxl4yM5hEns1ZYq8D5pL88/nYNfulhELpJyhaF8XIrymlck2o40/lATRsLIEWMyb - 8MiL8d5eAOEMSb7rUrqWodLDPZld7ZzCvoVt6XQeVmJLkAw0teNdQXvlCZgu/3Q6MwUw - Wx+QkzqUjCODOLk224RVZGvnKY9YRu/WmZEnWqBjzQIF90DLNXyni+yS7XbUn8CnPbdM - M3s/Ty7YsgPGsibKem1EI6yma15sXRNi1Vz1o0ArcPpsB/6x/ym8sCQemxSvrmer5ps9 - wrBnmlH558mrlj7rSHK9l5SmsGlkJiXB3DTLSrnynxHTY9gX9lSBsQxxjiqu1sEMvDVY - toUA== -X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; - d=1e100.net; s=20210112; - h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version - :content-transfer-encoding; - bh=XJkVawFXvwQH7kz0CHPfmxuFkQ6+ipcLhCSvCaul0jQ=; - b=LtdsZ9M/Im1hyxdJYYHttN4wtxcqRThm/H/oV8driFRB4KuwxO2iP2OqycVsS1sN2y - quWFM6L8v0KaUZRUR85rRRr8JX9P84kqTu4szOEuSIQQ/aUDUbJxVi7rICLPZ890DqTY - APplzuMhuNr6unYQO5Lxrj5IHHtrsmKP8ttR7VVWPNHpJseXc1kQ+HDLgylQLHVsb/5U - 8KpUG0LvxhvqsNU6HbTwLD/Q/88ELP5MfoWHUocYXKPrBJ8K6rCHsmjH6z6tFLfXgce7 - 619waAHXFhCBCflRbAC+D9VemoNe5wJlu9mzyQ4Xavbo8NZgDobVFWOTEQ1iRdua/oRT - tbxw== -X-Gm-Message-State: AOAM532GrwQ/whp0buK64HysYJy6aLBD/xGE/8Dr7NSW150Jds7jTjor - eVhdzOGjuWywij/s3mwA9XfPjST+Cg== -X-Google-Smtp-Source: - ABdhPJxU9goI5zXE0GQP90hO7TH0IDw++6UHpkGFSUH/chvzvE0L/pQF0XqDkdwzbbTmxsOBUMGcZg== -X-Received: by 2002:a05:6402:84c:b0:423:e5a2:3655 with SMTP id - b12-20020a056402084c00b00423e5a23655mr40374113edz.28.1651221752304; - Fri, 29 Apr 2022 01:42:32 -0700 (PDT) -Received: from crystalwell.adg.lan (a109-49-0-175.cpe.netcabo.pt. - [109.49.0.175]) by smtp.gmail.com with ESMTPSA id - el10-20020a170907284a00b006f3ef214e32sm429064ejc.152.2022.04.29.01.42.31 - (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); - Fri, 29 Apr 2022 01:42:31 -0700 (PDT) -From: Rui Salvaterra -To: linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, - linux-kernel@vger.kernel.org -Cc: matthias.bgg@gmail.com, ryder.lee@mediatek.com, daniel@makrotopia.org, - Rui Salvaterra -Subject: [PATCH] arm64: dts: mt7622: specify the number of DMA requests -Date: Fri, 29 Apr 2022 09:42:25 +0100 -Message-Id: <20220429084225.298213-1-rsalvaterra@gmail.com> -X-Mailer: git-send-email 2.36.0 -MIME-Version: 1.0 -X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 -X-CRM114-CacheID: sfid-20220429_014236_944696_097D1E73 -X-CRM114-Status: UNSURE ( 8.85 ) -X-CRM114-Notice: Please train this message. -X-BeenThere: linux-arm-kernel@lists.infradead.org -X-Mailman-Version: 2.1.34 -Precedence: list -List-Id: -List-Unsubscribe: - , - -List-Archive: -List-Post: -List-Help: -List-Subscribe: - , - -Sender: "linux-arm-kernel" -Errors-To: - linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org - -The MT7622 device tree never bothered to specify the number of virtual DMA -channels for the HSDMA controller, always falling back to the default value of -3. Make this value explicit, in order to avoid the following dmesg notification: - -mtk_hsdma 1b007000.dma-controller: Using 3 as missing dma-requests property - -Signed-off-by: Rui Salvaterra ---- - arch/arm64/boot/dts/mediatek/mt7622.dtsi | 1 + - 1 file changed, 1 insertion(+) - ---- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi -+++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi -@@ -938,6 +938,7 @@ - clock-names = "hsdma"; - power-domains = <&scpsys MT7622_POWER_DOMAIN_ETHSYS>; - #dma-cells = <1>; -+ dma-requests = <3>; - }; - - pcie_mirror: pcie-mirror@10000400 { diff --git a/target/linux/mediatek/patches-5.15/193-dts-mt7623-thermal_zone_fix.patch b/target/linux/mediatek/patches-5.15/193-dts-mt7623-thermal_zone_fix.patch deleted file mode 100644 index 1cfb53d62..000000000 --- a/target/linux/mediatek/patches-5.15/193-dts-mt7623-thermal_zone_fix.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 824d56e753a588fcfd650db1822e34a02a48bb77 Mon Sep 17 00:00:00 2001 -From: Bruno Umuarama -Date: Thu, 13 Oct 2022 21:18:21 +0000 -Subject: [PATCH] mediatek: mt7623: fix thermal zone -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Raising the temperatures for passive and active trips. @VA1DER -proposed at issue 9396 to remove passive trip. This commit relates to -his suggestion. - -Without this patch. the CPU will be throttled all the way down to 98MHz -if the temperature rises even a degree above the trip point, and it was -further discovered that if the internal temperature of the device is -above the first trip point temperature when it boots then it will start -in a throttled state and even -$ echo disabled > /sys/class/thermal/thermal_zone0/mode -will have no effect. - -The patch increases the passive trip point and active cooling map. The -throttling temperature will then be at 77°C and 82°C, which is still a -low enough temperature for ARM devices to not be in the real danger -zone, and gives some operational headroom. - -Signed-off-by: Bruno Umuarama ---- - arch/arm/boot/dts/mt7623.dtsi | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/arch/arm/boot/dts/mt7623.dtsi -+++ b/arch/arm/boot/dts/mt7623.dtsi -@@ -160,13 +160,13 @@ - - trips { - cpu_passive: cpu-passive { -- temperature = <57000>; -+ temperature = <77000>; - hysteresis = <2000>; - type = "passive"; - }; - - cpu_active: cpu-active { -- temperature = <67000>; -+ temperature = <82000>; - hysteresis = <2000>; - type = "active"; - }; diff --git a/target/linux/mediatek/patches-5.15/194-dts-mt7968a-add-ramoops.patch b/target/linux/mediatek/patches-5.15/194-dts-mt7968a-add-ramoops.patch deleted file mode 100644 index 161c1e751..000000000 --- a/target/linux/mediatek/patches-5.15/194-dts-mt7968a-add-ramoops.patch +++ /dev/null @@ -1,17 +0,0 @@ ---- a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi -+++ b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi -@@ -68,6 +68,14 @@ - #address-cells = <2>; - #size-cells = <2>; - ranges; -+ -+ /* 64 KiB reserved for ramoops/pstore */ -+ ramoops@42ff0000 { -+ compatible = "ramoops"; -+ reg = <0 0x42ff0000 0 0x10000>; -+ record-size = <0x1000>; -+ }; -+ - /* 192 KiB reserved for ARM Trusted Firmware (BL31) */ - secmon_reserved: secmon@43000000 { - reg = <0 0x43000000 0 0x30000>; diff --git a/target/linux/mediatek/patches-5.15/195-dts-mt7986a-bpi-r3-leds-port-names-and-wifi-eeprom.patch b/target/linux/mediatek/patches-5.15/195-dts-mt7986a-bpi-r3-leds-port-names-and-wifi-eeprom.patch deleted file mode 100644 index 336920baf..000000000 --- a/target/linux/mediatek/patches-5.15/195-dts-mt7986a-bpi-r3-leds-port-names-and-wifi-eeprom.patch +++ /dev/null @@ -1,196 +0,0 @@ ---- a/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts -@@ -23,6 +23,10 @@ - serial0 = &uart0; - ethernet0 = &gmac0; - ethernet1 = &gmac1; -+ led-boot = &green_led; -+ led-failsafe = &green_led; -+ led-running = &green_led; -+ led-upgrade = &blue_led; - }; - - chosen { -@@ -419,27 +423,27 @@ - - port@1 { - reg = <1>; -- label = "lan0"; -+ label = "lan1"; - }; - - port@2 { - reg = <2>; -- label = "lan1"; -+ label = "lan2"; - }; - - port@3 { - reg = <3>; -- label = "lan2"; -+ label = "lan3"; - }; - - port@4 { - reg = <4>; -- label = "lan3"; -+ label = "lan4"; - }; - - port5: port@5 { - reg = <5>; -- label = "lan4"; -+ label = "sfp2"; - phy-mode = "2500base-x"; - sfp = <&sfp2>; - managed = "in-band-status"; -@@ -490,9 +494,137 @@ - - &wifi { - status = "okay"; -- pinctrl-names = "default", "dbdc"; -+ pinctrl-names = "default"; - pinctrl-0 = <&wf_2g_5g_pins>, <&wf_led_pins>; -- pinctrl-1 = <&wf_dbdc_pins>, <&wf_led_pins>; -+ -+ mediatek,eeprom-data = <0x86790900 0x000c4326 0x60000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x01000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000800 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x24649090 0x00280000 0x05100000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00021e00 0x021e0002 0x1e00021e 0x00022800 0x02280002 0x28000228 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00008080 0x8080fdf7 -+ 0x0903150d 0x80808080 0x80808080 0x05050d0d 0x1313c6c6 0xc3c3c200 0x00c200c2 0x00008182 -+ 0x8585c2c2 0x82828282 0x858500c2 0xc2000081 0x82858587 0x87c2c200 0x81818285 0x858787c2 -+ 0xc2000081 0x82858587 0x87c2c200 0x00818285 0x858787c2 0xc2000081 0x82858587 0x87c4c4c2 -+ 0xc100c300 0xc3c3c100 0x818383c3 0xc3c3c100 0x81838300 0xc2c2c2c0 0x81828484 0x000000c3 -+ 0xc3c3c100 0x81838386 0x86c3c3c3 0xc1008183 0x838686c2 0xc2c2c081 0x82848486 0x86c3c3c3 -+ 0xc1008183 0x838686c3 0xc3c3c100 0x81838386 0x86c3c3c3 0xc1008183 0x83868622 0x28002228 -+ 0x00222800 0x22280000 0xdddddddd 0xdddddddd 0xddbbbbbb 0xccccccdd 0xdddddddd 0xdddddddd -+ 0xeeeeeecc 0xccccdddd 0xdddddddd 0x004a5662 0x0000004a 0x56620000 0x004a5662 0x0000004a -+ 0x56620000 0x88888888 0x33333326 0x26262626 0x26262600 0x33333326 0x26262626 0x26262600 -+ 0x33333326 0x26262626 0x26262600 0x33333326 0x26262626 0x26262600 0x00000000 0xf0f0cc00 -+ 0x00000000 0x0000aaaa 0xaabbbbbb 0xcccccccc 0xccccbbbb 0xbbbbbbbb 0xbbbbbbaa 0xaaaabbbb -+ 0xbbaaaaaa 0x999999aa 0xaaaabbbb 0xbbcccccc 0x00000000 0x0000aaaa 0xaa000000 0xbbbbbbbb -+ 0xbbbbaaaa 0xaa999999 0xaaaaaaaa 0xaaaaaaaa 0xaaaaaaaa 0xaaaaaaaa 0xaaaabbbb 0xbbbbbbbb -+ 0x00000000 0x00000000 0x00000000 0x99999999 0x9999aaaa 0xaaaaaaaa 0x999999aa 0xaaaaaaaa -+ 0xaaaaaaaa 0xaaaaaaaa 0xaaaabbbb 0xbbbbbbbb 0x00000000 0x0000eeee 0xeeffffff 0xcccccccc -+ 0xccccdddd 0xddbbbbbb 0xccccccbb 0xbbbbbbbb 0xbbbbbbbb 0xbbbbbbbb 0xbbbbcccc 0xccdddddd -+ 0x00516200 0x686e0051 0x6200686e 0x00516200 0x686e0051 0x6200686e 0x00516200 0x686e0051 -+ 0x6200686e 0x00516200 0x686e0051 0x6200686e 0x00516200 0x686e0051 0x6200686e 0x00516200 -+ 0x686e0051 0x6200686e 0x00516200 0x686e0051 0x6200686e 0x00516200 0x686e0051 0x6200686e -+ 0x00516200 0x686e0051 0x6200686e 0x00516200 0x686e0051 0x6200686e 0x00516200 0x686e0051 -+ 0x6200686e 0x00516200 0x686e0051 0x6200686e 0x00516200 0x686e0051 0x6200686e 0x00516200 -+ 0x686e0051 0x6200686e 0x00516200 0x686e0051 0x6200686e 0x00516200 0x686e0051 0x6200686e -+ 0x88888888 0x88888888 0x88888888 0x88888888 0x88888888 0x88888888 0x88888888 0x88888888 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000001 0x06000100 0x01050002 0x00ff0300 -+ 0xf900fe03 0x00000000 0x00000000 0x0000009b 0x6e370000 0x00000000 0x00fc0009 0x0a00fe00 -+ 0x060700fe 0x00070800 0x05000b0a 0x00000000 0x00000000 0x000000e2 0x96460000 0x00000000 -+ 0x000400f7 0xf8000300 0xfcfe0003 0x00fbfc00 0xee00e3f2 0x00000000 0x00000000 0x00000011 -+ 0xbb550000 0x00000000 0x000600f6 0xfc000300 0xfbfe0004 0x00fafe00 0xf600ecf2 0x00000000 -+ 0x00000000 0x0000001f 0xbf580000 0x00000000 0x000600f5 0xf6000400 0xf8f90004 0x00f7f800 -+ 0xf700f0f4 0x00000000 0x00000000 0x00000024 0xbe570000 0x00000000 0x000800f8 0xfe000600 -+ 0xf8fd0007 0x00f9fe00 0xf500f0f4 0x00000000 0x00000000 0x0000002d 0xd6610000 0x00000000 -+ 0x000400f7 0xfc000500 0xf7fc0005 0x00f7fc00 0xf900f5f8 0x00000000 0x00000000 0x00000026 -+ 0xd96e0000 0x00000000 0x000400f7 0xf9000600 0xf5f70005 0x00f5f800 0xf900f4f7 0x00000000 -+ 0x00000000 0x0000001b 0xce690000 0x00000000 0x000300f8 0xf8000600 0xf6f60004 0x00f6f700 -+ 0xf900f4f7 0x00000000 0x00000000 0x00000018 0xd8720000 0x00000000 0x00000000 0x02404002 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0xc1c2c1c2 0x41c341c3 0x3fc13fc1 0x40c13fc2 0x3fc240c1 0x41c040c0 0x3fc23fc2 0x40c13fc2 -+ 0x3fc140c0 0x41c040c0 0x3fc33fc3 0x40c23fc2 0x3fc240c1 0x41c040c0 0x3fc23fc2 0x40c23fc2 -+ 0x3fc140c1 0x41c040c0 0x00000000 0x00000000 0x41c741c7 0xc1c7c1c7 0x00000000 0x00000000 -+ 0x3fc03fc0 0x3fc03fc0 0x3fc03fc0 0x3fc03fc0 0x3fc03fc0 0x3fc03fc0 0x3fc03fc0 0x3fc03fc0 -+ 0x3fc03fc0 0x3fc03fc0 0x3fc03fc0 0x3fc03fc0 0x3fc03fc0 0x3fc03fc0 0x3fc03fc0 0x3fc03fc0 -+ 0x00a0ce00 0x00000000 0xb6840000 0x00000000 0x00000000 0x00000000 0x18181818 0x18181818 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x004b5763 0x0000004b 0x57630000 0x004b5763 0x0000004b 0x57630000 0x88888888 0x08474759 -+ 0x69780849 0x49596d7a 0x0849495a 0x6d790848 0x48596c78 0x08484858 0x6a780848 0x48586a78 -+ 0x08484858 0x6c78084a 0x4a5b6d79 0x08474759 0x697a0848 0x48596b79 0x08484859 0x6c7a0848 -+ 0x48586c79 0x08484857 0x68770848 0x48576877 0x08484857 0x6a77084a 0x4a5a6a77 0x08464659 -+ 0x69790848 0x48586b79 0x08484858 0x6c7a0848 0x48596c79 0x08484857 0x68770848 0x48576877 -+ 0x08494958 0x6d7a084b 0x4b5c6c77 0x0847475a 0x6a7b0849 0x495a6e7c 0x0849495a 0x6e7c0849 -+ 0x495b6e7c 0x08494959 0x6a7a0849 0x49596a7a 0x084a4a5a 0x6f7d084b 0x4b5c6e7b 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x85848484 -+ 0xc3c4c4c5 0xc4c3c33f 0xc3c3c2c2 0xc2c2c03f 0xc3c3c3c4 0xc4c4c33f 0xc2c2c2c2 0xc1c3c1c1 -+ 0xc0c08282 0x83848686 0x88880000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00001111 0x00000000 -+ 0x8080f703 0x10808080 0x80050d13 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x000000a4 0xce000000 0x0000b684 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000>; - - led { - led-active-low; ---- a/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-nor.dtso -+++ b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-nor.dtso -@@ -55,6 +55,7 @@ - partition@c00000 { - label = "fit"; - reg = <0xc00000 0x1400000>; -+ compatible = "denx,fit"; - }; - }; - }; diff --git a/target/linux/mediatek/patches-5.15/200-phy-phy-mtk-tphy-Add-hifsys-support.patch b/target/linux/mediatek/patches-5.15/200-phy-phy-mtk-tphy-Add-hifsys-support.patch deleted file mode 100644 index cfb0556d1..000000000 --- a/target/linux/mediatek/patches-5.15/200-phy-phy-mtk-tphy-Add-hifsys-support.patch +++ /dev/null @@ -1,66 +0,0 @@ -From 28f9a5e2a3f5441ab5594669ed82da11e32277a9 Mon Sep 17 00:00:00 2001 -From: Kristian Evensen -Date: Mon, 30 Apr 2018 14:38:01 +0200 -Subject: [PATCH] phy: phy-mtk-tphy: Add hifsys-support - ---- - drivers/phy/mediatek/phy-mtk-tphy.c | 20 ++++++++++++++++++++ - 1 file changed, 20 insertions(+) - ---- a/drivers/phy/mediatek/phy-mtk-tphy.c -+++ b/drivers/phy/mediatek/phy-mtk-tphy.c -@@ -18,6 +18,8 @@ - #include - #include - #include -+#include -+#include - - /* version V1 sub-banks offset base address */ - /* banks shared by multiple phys */ -@@ -311,6 +313,9 @@ - - #define TPHY_CLKS_CNT 2 - -+#define HIF_SYSCFG1 0x14 -+#define HIF_SYSCFG1_PHY2_MASK (0x3 << 20) -+ - enum mtk_phy_version { - MTK_PHY_V1 = 1, - MTK_PHY_V2, -@@ -377,6 +382,7 @@ struct mtk_tphy { - void __iomem *sif_base; /* only shared sif */ - const struct mtk_phy_pdata *pdata; - struct mtk_phy_instance **phys; -+ struct regmap *hif; - int nphys; - int src_ref_clk; /* MHZ, reference clock for slew rate calibrate */ - int src_coef; /* coefficient for slew rate calibrate */ -@@ -730,6 +736,10 @@ static void pcie_phy_instance_init(struc - if (tphy->pdata->version != MTK_PHY_V1) - return; - -+ if (tphy->hif) -+ regmap_update_bits(tphy->hif, HIF_SYSCFG1, -+ HIF_SYSCFG1_PHY2_MASK, 0); -+ - tmp = readl(u3_banks->phya + U3P_U3_PHYA_DA_REG0); - tmp &= ~(P3A_RG_XTAL_EXT_PE1H | P3A_RG_XTAL_EXT_PE2H); - tmp |= P3A_RG_XTAL_EXT_PE1H_VAL(0x2) | P3A_RG_XTAL_EXT_PE2H_VAL(0x2); -@@ -1437,6 +1447,16 @@ static int mtk_tphy_probe(struct platfor - &tphy->src_coef); - } - -+ if (of_find_property(np, "mediatek,phy-switch", NULL)) { -+ tphy->hif = syscon_regmap_lookup_by_phandle(np, -+ "mediatek,phy-switch"); -+ if (IS_ERR(tphy->hif)) { -+ dev_err(&pdev->dev, -+ "missing \"mediatek,phy-switch\" phandle\n"); -+ return PTR_ERR(tphy->hif); -+ } -+ } -+ - port = 0; - for_each_child_of_node(np, child_np) { - struct mtk_phy_instance *instance; diff --git a/target/linux/mediatek/patches-5.15/210-v6.1-pinctrl-mediatek-add-support-for-MT7986-SoC.patch b/target/linux/mediatek/patches-5.15/210-v6.1-pinctrl-mediatek-add-support-for-MT7986-SoC.patch deleted file mode 100644 index 0761e1da1..000000000 --- a/target/linux/mediatek/patches-5.15/210-v6.1-pinctrl-mediatek-add-support-for-MT7986-SoC.patch +++ /dev/null @@ -1,26 +0,0 @@ ---- a/drivers/pinctrl/mediatek/Kconfig -+++ b/drivers/pinctrl/mediatek/Kconfig -@@ -120,6 +120,13 @@ config PINCTRL_MT7622 - default ARM64 && ARCH_MEDIATEK - select PINCTRL_MTK_MOORE - -+config PINCTRL_MT7986 -+ bool "Mediatek MT7986 pin control" -+ depends on OF -+ depends on ARM64 || COMPILE_TEST -+ default ARM64 && ARCH_MEDIATEK -+ select PINCTRL_MTK_MOORE -+ - config PINCTRL_MT8167 - bool "Mediatek MT8167 pin control" - depends on OF ---- a/drivers/pinctrl/mediatek/Makefile -+++ b/drivers/pinctrl/mediatek/Makefile -@@ -17,6 +17,7 @@ obj-$(CONFIG_PINCTRL_MT6797) += pinctrl- - obj-$(CONFIG_PINCTRL_MT7622) += pinctrl-mt7622.o - obj-$(CONFIG_PINCTRL_MT7623) += pinctrl-mt7623.o - obj-$(CONFIG_PINCTRL_MT7629) += pinctrl-mt7629.o -+obj-$(CONFIG_PINCTRL_MT7986) += pinctrl-mt7986.o - obj-$(CONFIG_PINCTRL_MT8167) += pinctrl-mt8167.o - obj-$(CONFIG_PINCTRL_MT8173) += pinctrl-mt8173.o - obj-$(CONFIG_PINCTRL_MT8183) += pinctrl-mt8183.o diff --git a/target/linux/mediatek/patches-5.15/211-v5.16-clk-mediatek-Add-API-for-clock-resource-recycle.patch b/target/linux/mediatek/patches-5.15/211-v5.16-clk-mediatek-Add-API-for-clock-resource-recycle.patch deleted file mode 100644 index 15de8aa3d..000000000 --- a/target/linux/mediatek/patches-5.15/211-v5.16-clk-mediatek-Add-API-for-clock-resource-recycle.patch +++ /dev/null @@ -1,28 +0,0 @@ ---- a/drivers/clk/mediatek/clk-mtk.c -+++ b/drivers/clk/mediatek/clk-mtk.c -@@ -43,6 +43,15 @@ err_out: - return NULL; - } - -+void mtk_free_clk_data(struct clk_onecell_data *clk_data) -+{ -+ if (!clk_data) -+ return; -+ -+ kfree(clk_data->clks); -+ kfree(clk_data); -+} -+ - void mtk_clk_register_fixed_clks(const struct mtk_fixed_clk *clks, - int num, struct clk_onecell_data *clk_data) - { ---- a/drivers/clk/mediatek/clk-mtk.h -+++ b/drivers/clk/mediatek/clk-mtk.h -@@ -202,6 +202,7 @@ void mtk_clk_register_dividers(const str - struct clk_onecell_data *clk_data); - - struct clk_onecell_data *mtk_alloc_clk_data(unsigned int clk_num); -+void mtk_free_clk_data(struct clk_onecell_data *clk_data); - - #define HAVE_RST_BAR BIT(0) - #define PLL_AO BIT(1) diff --git a/target/linux/mediatek/patches-5.15/212-v5.17-clk-mediatek-add-mt7986-clock-support.patch b/target/linux/mediatek/patches-5.15/212-v5.17-clk-mediatek-add-mt7986-clock-support.patch deleted file mode 100644 index 8e2365a49..000000000 --- a/target/linux/mediatek/patches-5.15/212-v5.17-clk-mediatek-add-mt7986-clock-support.patch +++ /dev/null @@ -1,39 +0,0 @@ ---- a/drivers/clk/mediatek/Kconfig -+++ b/drivers/clk/mediatek/Kconfig -@@ -344,6 +344,23 @@ config COMMON_CLK_MT7629_HIFSYS - This driver supports MediaTek MT7629 HIFSYS clocks providing - to PCI-E and USB. - -+config COMMON_CLK_MT7986 -+ bool "Clock driver for MediaTek MT7986" -+ depends on ARCH_MEDIATEK || COMPILE_TEST -+ select COMMON_CLK_MEDIATEK -+ default ARCH_MEDIATEK -+ help -+ This driver supports MediaTek MT7986 basic clocks and clocks -+ required for various periperals found on MediaTek. -+ -+config COMMON_CLK_MT7986_ETHSYS -+ bool "Clock driver for MediaTek MT7986 ETHSYS" -+ depends on COMMON_CLK_MT7986 -+ default COMMON_CLK_MT7986 -+ help -+ This driver add support for clocks for Ethernet and SGMII -+ required on MediaTek MT7986 SoC. -+ - config COMMON_CLK_MT8135 - bool "Clock driver for MediaTek MT8135" - depends on (ARCH_MEDIATEK && ARM) || COMPILE_TEST ---- a/drivers/clk/mediatek/Makefile -+++ b/drivers/clk/mediatek/Makefile -@@ -46,6 +46,10 @@ obj-$(CONFIG_COMMON_CLK_MT7622_AUDSYS) + - obj-$(CONFIG_COMMON_CLK_MT7629) += clk-mt7629.o - obj-$(CONFIG_COMMON_CLK_MT7629_ETHSYS) += clk-mt7629-eth.o - obj-$(CONFIG_COMMON_CLK_MT7629_HIFSYS) += clk-mt7629-hif.o -+obj-$(CONFIG_COMMON_CLK_MT7986) += clk-mt7986-apmixed.o -+obj-$(CONFIG_COMMON_CLK_MT7986) += clk-mt7986-topckgen.o -+obj-$(CONFIG_COMMON_CLK_MT7986) += clk-mt7986-infracfg.o -+obj-$(CONFIG_COMMON_CLK_MT7986_ETHSYS) += clk-mt7986-eth.o - obj-$(CONFIG_COMMON_CLK_MT8135) += clk-mt8135.o - obj-$(CONFIG_COMMON_CLK_MT8167) += clk-mt8167.o - obj-$(CONFIG_COMMON_CLK_MT8167_AUDSYS) += clk-mt8167-aud.o diff --git a/target/linux/mediatek/patches-5.15/213-spi-mediatek-add-mt7986-spi-support.patch b/target/linux/mediatek/patches-5.15/213-spi-mediatek-add-mt7986-spi-support.patch deleted file mode 100644 index 2d6fc55ae..000000000 --- a/target/linux/mediatek/patches-5.15/213-spi-mediatek-add-mt7986-spi-support.patch +++ /dev/null @@ -1,917 +0,0 @@ -From 7d99750f96fc6904d54affebdc8c9b0bfae1e9e8 Mon Sep 17 00:00:00 2001 -From: Sam Shih -Date: Sun, 17 Apr 2022 11:40:22 +0800 -Subject: [PATCH] spi: mediatek: backport document and driver to support mt7986 - spi design - -this patch add the support of ipm design and upgrade devicetree binding - -The patch is comming from following threads -- https://lore.kernel.org/all/20220315032411.2826-1-leilk.liu@mediatek.com/ -- https://lore.kernel.org/all/20220401071616.8874-1-leilk.liu@mediatek.com/ - -Signed-off-by: Sam Shih ---- - .../bindings/spi/mediatek,spi-mt65xx.yaml | 111 ++++ - drivers/spi/spi-mt65xx.c | 509 ++++++++++++++++-- - 2 files changed, 572 insertions(+), 48 deletions(-) - create mode 100644 Documentation/devicetree/bindings/spi/mediatek,spi-mt65xx.yaml - ---- /dev/null -+++ b/Documentation/devicetree/bindings/spi/mediatek,spi-mt65xx.yaml -@@ -0,0 +1,111 @@ -+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) -+%YAML 1.2 -+--- -+$id: http://devicetree.org/schemas/spi/mediatek,spi-mt65xx.yaml# -+$schema: http://devicetree.org/meta-schemas/core.yaml# -+ -+title: SPI Bus controller for MediaTek ARM SoCs -+ -+maintainers: -+ - Leilk Liu -+ -+allOf: -+ - $ref: "/schemas/spi/spi-controller.yaml#" -+ -+properties: -+ compatible: -+ oneOf: -+ - items: -+ - enum: -+ - mediatek,mt7629-spi -+ - const: mediatek,mt7622-spi -+ - items: -+ - enum: -+ - mediatek,mt8516-spi -+ - const: mediatek,mt2712-spi -+ - items: -+ - enum: -+ - mediatek,mt6779-spi -+ - mediatek,mt8186-spi -+ - mediatek,mt8192-spi -+ - mediatek,mt8195-spi -+ - const: mediatek,mt6765-spi -+ - items: -+ - enum: -+ - mediatek,mt7986-spi-ipm -+ - const: mediatek,spi-ipm -+ - items: -+ - enum: -+ - mediatek,mt2701-spi -+ - mediatek,mt2712-spi -+ - mediatek,mt6589-spi -+ - mediatek,mt6765-spi -+ - mediatek,mt6893-spi -+ - mediatek,mt7622-spi -+ - mediatek,mt8135-spi -+ - mediatek,mt8173-spi -+ - mediatek,mt8183-spi -+ -+ reg: -+ maxItems: 1 -+ -+ interrupts: -+ maxItems: 1 -+ -+ clocks: -+ minItems: 3 -+ items: -+ - description: clock used for the parent clock -+ - description: clock used for the muxes clock -+ - description: clock used for the clock gate -+ - description: clock used for the AHB bus, this clock is optional -+ -+ clock-names: -+ minItems: 3 -+ items: -+ - const: parent-clk -+ - const: sel-clk -+ - const: spi-clk -+ - const: hclk -+ -+ mediatek,pad-select: -+ $ref: /schemas/types.yaml#/definitions/uint32-array -+ minItems: 1 -+ maxItems: 4 -+ items: -+ enum: [0, 1, 2, 3] -+ description: -+ specify which pins group(ck/mi/mo/cs) spi controller used. -+ This is an array. -+ -+required: -+ - compatible -+ - reg -+ - interrupts -+ - clocks -+ - clock-names -+ - '#address-cells' -+ - '#size-cells' -+ -+unevaluatedProperties: false -+ -+examples: -+ - | -+ #include -+ #include -+ #include -+ #include -+ -+ spi@1100a000 { -+ compatible = "mediatek,mt8173-spi"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ reg = <0x1100a000 0x1000>; -+ interrupts = ; -+ clocks = <&topckgen CLK_TOP_SYSPLL3_D2>, -+ <&topckgen CLK_TOP_SPI_SEL>, -+ <&pericfg CLK_PERI_SPI0>; -+ clock-names = "parent-clk", "sel-clk", "spi-clk"; -+ cs-gpios = <&pio 105 GPIO_ACTIVE_LOW>, <&pio 72 GPIO_ACTIVE_LOW>; -+ mediatek,pad-select = <1>, <0>; -+ }; ---- a/drivers/spi/spi-mt65xx.c -+++ b/drivers/spi/spi-mt65xx.c -@@ -12,11 +12,12 @@ - #include - #include - #include --#include -+#include - #include - #include - #include - #include -+#include - #include - - #define SPI_CFG0_REG 0x0000 -@@ -31,6 +32,7 @@ - #define SPI_CFG2_REG 0x0028 - #define SPI_TX_SRC_REG_64 0x002c - #define SPI_RX_DST_REG_64 0x0030 -+#define SPI_CFG3_IPM_REG 0x0040 - - #define SPI_CFG0_SCK_HIGH_OFFSET 0 - #define SPI_CFG0_SCK_LOW_OFFSET 8 -@@ -51,6 +53,7 @@ - #define SPI_CFG1_CS_IDLE_MASK 0xff - #define SPI_CFG1_PACKET_LOOP_MASK 0xff00 - #define SPI_CFG1_PACKET_LENGTH_MASK 0x3ff0000 -+#define SPI_CFG1_IPM_PACKET_LENGTH_MASK GENMASK(31, 16) - #define SPI_CFG2_SCK_HIGH_OFFSET 0 - #define SPI_CFG2_SCK_LOW_OFFSET 16 - -@@ -71,6 +74,24 @@ - #define SPI_CMD_TX_ENDIAN BIT(15) - #define SPI_CMD_FINISH_IE BIT(16) - #define SPI_CMD_PAUSE_IE BIT(17) -+#define SPI_CMD_IPM_NONIDLE_MODE BIT(19) -+#define SPI_CMD_IPM_SPIM_LOOP BIT(21) -+#define SPI_CMD_IPM_GET_TICKDLY_OFFSET 22 -+ -+#define SPI_CMD_IPM_GET_TICKDLY_MASK GENMASK(24, 22) -+ -+#define PIN_MODE_CFG(x) ((x) / 2) -+ -+#define SPI_CFG3_IPM_HALF_DUPLEX_DIR BIT(2) -+#define SPI_CFG3_IPM_HALF_DUPLEX_EN BIT(3) -+#define SPI_CFG3_IPM_XMODE_EN BIT(4) -+#define SPI_CFG3_IPM_NODATA_FLAG BIT(5) -+#define SPI_CFG3_IPM_CMD_BYTELEN_OFFSET 8 -+#define SPI_CFG3_IPM_ADDR_BYTELEN_OFFSET 12 -+ -+#define SPI_CFG3_IPM_CMD_PIN_MODE_MASK GENMASK(1, 0) -+#define SPI_CFG3_IPM_CMD_BYTELEN_MASK GENMASK(11, 8) -+#define SPI_CFG3_IPM_ADDR_BYTELEN_MASK GENMASK(15, 12) - - #define MT8173_SPI_MAX_PAD_SEL 3 - -@@ -81,6 +102,9 @@ - - #define MTK_SPI_MAX_FIFO_SIZE 32U - #define MTK_SPI_PACKET_SIZE 1024 -+#define MTK_SPI_IPM_PACKET_SIZE SZ_64K -+#define MTK_SPI_IPM_PACKET_LOOP SZ_256 -+ - #define MTK_SPI_32BITS_MASK (0xffffffff) - - #define DMA_ADDR_EXT_BITS (36) -@@ -96,6 +120,8 @@ struct mtk_spi_compatible { - bool dma_ext; - /* some IC no need unprepare SPI clk */ - bool no_need_unprepare; -+ /* IPM design adjust and extend register to support more features */ -+ bool ipm_design; - }; - - struct mtk_spi { -@@ -103,7 +129,7 @@ struct mtk_spi { - u32 state; - int pad_num; - u32 *pad_sel; -- struct clk *parent_clk, *sel_clk, *spi_clk; -+ struct clk *parent_clk, *sel_clk, *spi_clk, *spi_hclk; - struct spi_transfer *cur_transfer; - u32 xfer_len; - u32 num_xfered; -@@ -111,6 +137,11 @@ struct mtk_spi { - u32 tx_sgl_len, rx_sgl_len; - const struct mtk_spi_compatible *dev_comp; - u32 spi_clk_hz; -+ struct completion spimem_done; -+ bool use_spimem; -+ struct device *dev; -+ dma_addr_t tx_dma; -+ dma_addr_t rx_dma; - }; - - static const struct mtk_spi_compatible mtk_common_compat; -@@ -119,6 +150,12 @@ static const struct mtk_spi_compatible m - .must_tx = true, - }; - -+static const struct mtk_spi_compatible mtk_ipm_compat = { -+ .enhance_timing = true, -+ .dma_ext = true, -+ .ipm_design = true, -+}; -+ - static const struct mtk_spi_compatible mt6765_compat = { - .need_pad_sel = true, - .must_tx = true, -@@ -160,6 +197,9 @@ static const struct mtk_chip_config mtk_ - }; - - static const struct of_device_id mtk_spi_of_match[] = { -+ { .compatible = "mediatek,spi-ipm", -+ .data = (void *)&mtk_ipm_compat, -+ }, - { .compatible = "mediatek,mt2701-spi", - .data = (void *)&mtk_common_compat, - }, -@@ -278,12 +318,11 @@ static int mtk_spi_set_hw_cs_timing(stru - return 0; - } - --static int mtk_spi_prepare_message(struct spi_master *master, -- struct spi_message *msg) -+static int mtk_spi_hw_init(struct spi_master *master, -+ struct spi_device *spi) - { - u16 cpha, cpol; - u32 reg_val; -- struct spi_device *spi = msg->spi; - struct mtk_chip_config *chip_config = spi->controller_data; - struct mtk_spi *mdata = spi_master_get_devdata(master); - -@@ -291,6 +330,15 @@ static int mtk_spi_prepare_message(struc - cpol = spi->mode & SPI_CPOL ? 1 : 0; - - reg_val = readl(mdata->base + SPI_CMD_REG); -+ if (mdata->dev_comp->ipm_design) { -+ /* SPI transfer without idle time until packet length done */ -+ reg_val |= SPI_CMD_IPM_NONIDLE_MODE; -+ if (spi->mode & SPI_LOOP) -+ reg_val |= SPI_CMD_IPM_SPIM_LOOP; -+ else -+ reg_val &= ~SPI_CMD_IPM_SPIM_LOOP; -+ } -+ - if (cpha) - reg_val |= SPI_CMD_CPHA; - else -@@ -348,23 +396,39 @@ static int mtk_spi_prepare_message(struc - mdata->base + SPI_PAD_SEL_REG); - - /* tick delay */ -- reg_val = readl(mdata->base + SPI_CFG1_REG); - if (mdata->dev_comp->enhance_timing) { -- reg_val &= ~SPI_CFG1_GET_TICK_DLY_MASK; -- reg_val |= ((chip_config->tick_delay & 0x7) -- << SPI_CFG1_GET_TICK_DLY_OFFSET); -+ if (mdata->dev_comp->ipm_design) { -+ reg_val = readl(mdata->base + SPI_CMD_REG); -+ reg_val &= ~SPI_CMD_IPM_GET_TICKDLY_MASK; -+ reg_val |= ((chip_config->tick_delay & 0x7) -+ << SPI_CMD_IPM_GET_TICKDLY_OFFSET); -+ writel(reg_val, mdata->base + SPI_CMD_REG); -+ } else { -+ reg_val = readl(mdata->base + SPI_CFG1_REG); -+ reg_val &= ~SPI_CFG1_GET_TICK_DLY_MASK; -+ reg_val |= ((chip_config->tick_delay & 0x7) -+ << SPI_CFG1_GET_TICK_DLY_OFFSET); -+ writel(reg_val, mdata->base + SPI_CFG1_REG); -+ } - } else { -+ reg_val = readl(mdata->base + SPI_CFG1_REG); - reg_val &= ~SPI_CFG1_GET_TICK_DLY_MASK_V1; - reg_val |= ((chip_config->tick_delay & 0x3) - << SPI_CFG1_GET_TICK_DLY_OFFSET_V1); -+ writel(reg_val, mdata->base + SPI_CFG1_REG); - } -- writel(reg_val, mdata->base + SPI_CFG1_REG); - - /* set hw cs timing */ - mtk_spi_set_hw_cs_timing(spi); - return 0; - } - -+static int mtk_spi_prepare_message(struct spi_master *master, -+ struct spi_message *msg) -+{ -+ return mtk_spi_hw_init(master, msg->spi); -+} -+ - static void mtk_spi_set_cs(struct spi_device *spi, bool enable) - { - u32 reg_val; -@@ -386,13 +450,13 @@ static void mtk_spi_set_cs(struct spi_de - } - - static void mtk_spi_prepare_transfer(struct spi_master *master, -- struct spi_transfer *xfer) -+ u32 speed_hz) - { - u32 div, sck_time, reg_val; - struct mtk_spi *mdata = spi_master_get_devdata(master); - -- if (xfer->speed_hz < mdata->spi_clk_hz / 2) -- div = DIV_ROUND_UP(mdata->spi_clk_hz, xfer->speed_hz); -+ if (speed_hz < mdata->spi_clk_hz / 2) -+ div = DIV_ROUND_UP(mdata->spi_clk_hz, speed_hz); - else - div = 1; - -@@ -423,12 +487,24 @@ static void mtk_spi_setup_packet(struct - u32 packet_size, packet_loop, reg_val; - struct mtk_spi *mdata = spi_master_get_devdata(master); - -- packet_size = min_t(u32, mdata->xfer_len, MTK_SPI_PACKET_SIZE); -+ if (mdata->dev_comp->ipm_design) -+ packet_size = min_t(u32, -+ mdata->xfer_len, -+ MTK_SPI_IPM_PACKET_SIZE); -+ else -+ packet_size = min_t(u32, -+ mdata->xfer_len, -+ MTK_SPI_PACKET_SIZE); -+ - packet_loop = mdata->xfer_len / packet_size; - - reg_val = readl(mdata->base + SPI_CFG1_REG); -- reg_val &= ~(SPI_CFG1_PACKET_LENGTH_MASK | SPI_CFG1_PACKET_LOOP_MASK); -+ if (mdata->dev_comp->ipm_design) -+ reg_val &= ~SPI_CFG1_IPM_PACKET_LENGTH_MASK; -+ else -+ reg_val &= ~SPI_CFG1_PACKET_LENGTH_MASK; - reg_val |= (packet_size - 1) << SPI_CFG1_PACKET_LENGTH_OFFSET; -+ reg_val &= ~SPI_CFG1_PACKET_LOOP_MASK; - reg_val |= (packet_loop - 1) << SPI_CFG1_PACKET_LOOP_OFFSET; - writel(reg_val, mdata->base + SPI_CFG1_REG); - } -@@ -523,7 +599,7 @@ static int mtk_spi_fifo_transfer(struct - mdata->cur_transfer = xfer; - mdata->xfer_len = min(MTK_SPI_MAX_FIFO_SIZE, xfer->len); - mdata->num_xfered = 0; -- mtk_spi_prepare_transfer(master, xfer); -+ mtk_spi_prepare_transfer(master, xfer->speed_hz); - mtk_spi_setup_packet(master); - - if (xfer->tx_buf) { -@@ -556,7 +632,7 @@ static int mtk_spi_dma_transfer(struct s - mdata->cur_transfer = xfer; - mdata->num_xfered = 0; - -- mtk_spi_prepare_transfer(master, xfer); -+ mtk_spi_prepare_transfer(master, xfer->speed_hz); - - cmd = readl(mdata->base + SPI_CMD_REG); - if (xfer->tx_buf) -@@ -591,6 +667,19 @@ static int mtk_spi_transfer_one(struct s - struct spi_device *spi, - struct spi_transfer *xfer) - { -+ struct mtk_spi *mdata = spi_master_get_devdata(spi->master); -+ u32 reg_val = 0; -+ -+ /* prepare xfer direction and duplex mode */ -+ if (mdata->dev_comp->ipm_design) { -+ if (!xfer->tx_buf || !xfer->rx_buf) { -+ reg_val |= SPI_CFG3_IPM_HALF_DUPLEX_EN; -+ if (xfer->rx_buf) -+ reg_val |= SPI_CFG3_IPM_HALF_DUPLEX_DIR; -+ } -+ writel(reg_val, mdata->base + SPI_CFG3_IPM_REG); -+ } -+ - if (master->can_dma(master, spi, xfer)) - return mtk_spi_dma_transfer(master, spi, xfer); - else -@@ -614,8 +703,9 @@ static int mtk_spi_setup(struct spi_devi - if (!spi->controller_data) - spi->controller_data = (void *)&mtk_default_chip_info; - -- if (mdata->dev_comp->need_pad_sel && gpio_is_valid(spi->cs_gpio)) -- gpio_direction_output(spi->cs_gpio, !(spi->mode & SPI_CS_HIGH)); -+ if (mdata->dev_comp->need_pad_sel && spi->cs_gpiod) -+ /* CS de-asserted, gpiolib will handle inversion */ -+ gpiod_direction_output(spi->cs_gpiod, 0); - - return 0; - } -@@ -633,6 +723,12 @@ static irqreturn_t mtk_spi_interrupt(int - else - mdata->state = MTK_SPI_IDLE; - -+ /* SPI-MEM ops */ -+ if (mdata->use_spimem) { -+ complete(&mdata->spimem_done); -+ return IRQ_HANDLED; -+ } -+ - if (!master->can_dma(master, NULL, trans)) { - if (trans->rx_buf) { - cnt = mdata->xfer_len / 4; -@@ -718,6 +814,274 @@ static irqreturn_t mtk_spi_interrupt(int - return IRQ_HANDLED; - } - -+static int mtk_spi_mem_adjust_op_size(struct spi_mem *mem, -+ struct spi_mem_op *op) -+{ -+ int opcode_len; -+ -+ if (op->data.dir != SPI_MEM_NO_DATA) { -+ opcode_len = 1 + op->addr.nbytes + op->dummy.nbytes; -+ if (opcode_len + op->data.nbytes > MTK_SPI_IPM_PACKET_SIZE) { -+ op->data.nbytes = MTK_SPI_IPM_PACKET_SIZE - opcode_len; -+ /* force data buffer dma-aligned. */ -+ op->data.nbytes -= op->data.nbytes % 4; -+ } -+ } -+ -+ return 0; -+} -+ -+static bool mtk_spi_mem_supports_op(struct spi_mem *mem, -+ const struct spi_mem_op *op) -+{ -+ if (!spi_mem_default_supports_op(mem, op)) -+ return false; -+ -+ if (op->addr.nbytes && op->dummy.nbytes && -+ op->addr.buswidth != op->dummy.buswidth) -+ return false; -+ -+ if (op->addr.nbytes + op->dummy.nbytes > 16) -+ return false; -+ -+ if (op->data.nbytes > MTK_SPI_IPM_PACKET_SIZE) { -+ if (op->data.nbytes / MTK_SPI_IPM_PACKET_SIZE > -+ MTK_SPI_IPM_PACKET_LOOP || -+ op->data.nbytes % MTK_SPI_IPM_PACKET_SIZE != 0) -+ return false; -+ } -+ -+ return true; -+} -+ -+static void mtk_spi_mem_setup_dma_xfer(struct spi_master *master, -+ const struct spi_mem_op *op) -+{ -+ struct mtk_spi *mdata = spi_master_get_devdata(master); -+ -+ writel((u32)(mdata->tx_dma & MTK_SPI_32BITS_MASK), -+ mdata->base + SPI_TX_SRC_REG); -+#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT -+ if (mdata->dev_comp->dma_ext) -+ writel((u32)(mdata->tx_dma >> 32), -+ mdata->base + SPI_TX_SRC_REG_64); -+#endif -+ -+ if (op->data.dir == SPI_MEM_DATA_IN) { -+ writel((u32)(mdata->rx_dma & MTK_SPI_32BITS_MASK), -+ mdata->base + SPI_RX_DST_REG); -+#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT -+ if (mdata->dev_comp->dma_ext) -+ writel((u32)(mdata->rx_dma >> 32), -+ mdata->base + SPI_RX_DST_REG_64); -+#endif -+ } -+} -+ -+static int mtk_spi_transfer_wait(struct spi_mem *mem, -+ const struct spi_mem_op *op) -+{ -+ struct mtk_spi *mdata = spi_master_get_devdata(mem->spi->master); -+ /* -+ * For each byte we wait for 8 cycles of the SPI clock. -+ * Since speed is defined in Hz and we want milliseconds, -+ * so it should be 8 * 1000. -+ */ -+ u64 ms = 8000LL; -+ -+ if (op->data.dir == SPI_MEM_NO_DATA) -+ ms *= 32; /* prevent we may get 0 for short transfers. */ -+ else -+ ms *= op->data.nbytes; -+ ms = div_u64(ms, mem->spi->max_speed_hz); -+ ms += ms + 1000; /* 1s tolerance */ -+ -+ if (ms > UINT_MAX) -+ ms = UINT_MAX; -+ -+ if (!wait_for_completion_timeout(&mdata->spimem_done, -+ msecs_to_jiffies(ms))) { -+ dev_err(mdata->dev, "spi-mem transfer timeout\n"); -+ return -ETIMEDOUT; -+ } -+ -+ return 0; -+} -+ -+static int mtk_spi_mem_exec_op(struct spi_mem *mem, -+ const struct spi_mem_op *op) -+{ -+ struct mtk_spi *mdata = spi_master_get_devdata(mem->spi->master); -+ u32 reg_val, nio, tx_size; -+ char *tx_tmp_buf, *rx_tmp_buf; -+ int ret = 0; -+ -+ mdata->use_spimem = true; -+ reinit_completion(&mdata->spimem_done); -+ -+ mtk_spi_reset(mdata); -+ mtk_spi_hw_init(mem->spi->master, mem->spi); -+ mtk_spi_prepare_transfer(mem->spi->master, mem->spi->max_speed_hz); -+ -+ reg_val = readl(mdata->base + SPI_CFG3_IPM_REG); -+ /* opcode byte len */ -+ reg_val &= ~SPI_CFG3_IPM_CMD_BYTELEN_MASK; -+ reg_val |= 1 << SPI_CFG3_IPM_CMD_BYTELEN_OFFSET; -+ -+ /* addr & dummy byte len */ -+ reg_val &= ~SPI_CFG3_IPM_ADDR_BYTELEN_MASK; -+ if (op->addr.nbytes || op->dummy.nbytes) -+ reg_val |= (op->addr.nbytes + op->dummy.nbytes) << -+ SPI_CFG3_IPM_ADDR_BYTELEN_OFFSET; -+ -+ /* data byte len */ -+ if (op->data.dir == SPI_MEM_NO_DATA) { -+ reg_val |= SPI_CFG3_IPM_NODATA_FLAG; -+ writel(0, mdata->base + SPI_CFG1_REG); -+ } else { -+ reg_val &= ~SPI_CFG3_IPM_NODATA_FLAG; -+ mdata->xfer_len = op->data.nbytes; -+ mtk_spi_setup_packet(mem->spi->master); -+ } -+ -+ if (op->addr.nbytes || op->dummy.nbytes) { -+ if (op->addr.buswidth == 1 || op->dummy.buswidth == 1) -+ reg_val |= SPI_CFG3_IPM_XMODE_EN; -+ else -+ reg_val &= ~SPI_CFG3_IPM_XMODE_EN; -+ } -+ -+ if (op->addr.buswidth == 2 || -+ op->dummy.buswidth == 2 || -+ op->data.buswidth == 2) -+ nio = 2; -+ else if (op->addr.buswidth == 4 || -+ op->dummy.buswidth == 4 || -+ op->data.buswidth == 4) -+ nio = 4; -+ else -+ nio = 1; -+ -+ reg_val &= ~SPI_CFG3_IPM_CMD_PIN_MODE_MASK; -+ reg_val |= PIN_MODE_CFG(nio); -+ -+ reg_val |= SPI_CFG3_IPM_HALF_DUPLEX_EN; -+ if (op->data.dir == SPI_MEM_DATA_IN) -+ reg_val |= SPI_CFG3_IPM_HALF_DUPLEX_DIR; -+ else -+ reg_val &= ~SPI_CFG3_IPM_HALF_DUPLEX_DIR; -+ writel(reg_val, mdata->base + SPI_CFG3_IPM_REG); -+ -+ tx_size = 1 + op->addr.nbytes + op->dummy.nbytes; -+ if (op->data.dir == SPI_MEM_DATA_OUT) -+ tx_size += op->data.nbytes; -+ -+ tx_size = max_t(u32, tx_size, 32); -+ -+ tx_tmp_buf = kzalloc(tx_size, GFP_KERNEL | GFP_DMA); -+ if (!tx_tmp_buf) { -+ mdata->use_spimem = false; -+ return -ENOMEM; -+ } -+ -+ tx_tmp_buf[0] = op->cmd.opcode; -+ -+ if (op->addr.nbytes) { -+ int i; -+ -+ for (i = 0; i < op->addr.nbytes; i++) -+ tx_tmp_buf[i + 1] = op->addr.val >> -+ (8 * (op->addr.nbytes - i - 1)); -+ } -+ -+ if (op->dummy.nbytes) -+ memset(tx_tmp_buf + op->addr.nbytes + 1, -+ 0xff, -+ op->dummy.nbytes); -+ -+ if (op->data.nbytes && op->data.dir == SPI_MEM_DATA_OUT) -+ memcpy(tx_tmp_buf + op->dummy.nbytes + op->addr.nbytes + 1, -+ op->data.buf.out, -+ op->data.nbytes); -+ -+ mdata->tx_dma = dma_map_single(mdata->dev, tx_tmp_buf, -+ tx_size, DMA_TO_DEVICE); -+ if (dma_mapping_error(mdata->dev, mdata->tx_dma)) { -+ ret = -ENOMEM; -+ goto err_exit; -+ } -+ -+ if (op->data.dir == SPI_MEM_DATA_IN) { -+ if (!IS_ALIGNED((size_t)op->data.buf.in, 4)) { -+ rx_tmp_buf = kzalloc(op->data.nbytes, -+ GFP_KERNEL | GFP_DMA); -+ if (!rx_tmp_buf) { -+ ret = -ENOMEM; -+ goto unmap_tx_dma; -+ } -+ } else { -+ rx_tmp_buf = op->data.buf.in; -+ } -+ -+ mdata->rx_dma = dma_map_single(mdata->dev, -+ rx_tmp_buf, -+ op->data.nbytes, -+ DMA_FROM_DEVICE); -+ if (dma_mapping_error(mdata->dev, mdata->rx_dma)) { -+ ret = -ENOMEM; -+ goto kfree_rx_tmp_buf; -+ } -+ } -+ -+ reg_val = readl(mdata->base + SPI_CMD_REG); -+ reg_val |= SPI_CMD_TX_DMA; -+ if (op->data.dir == SPI_MEM_DATA_IN) -+ reg_val |= SPI_CMD_RX_DMA; -+ writel(reg_val, mdata->base + SPI_CMD_REG); -+ -+ mtk_spi_mem_setup_dma_xfer(mem->spi->master, op); -+ -+ mtk_spi_enable_transfer(mem->spi->master); -+ -+ /* Wait for the interrupt. */ -+ ret = mtk_spi_transfer_wait(mem, op); -+ if (ret) -+ goto unmap_rx_dma; -+ -+ /* spi disable dma */ -+ reg_val = readl(mdata->base + SPI_CMD_REG); -+ reg_val &= ~SPI_CMD_TX_DMA; -+ if (op->data.dir == SPI_MEM_DATA_IN) -+ reg_val &= ~SPI_CMD_RX_DMA; -+ writel(reg_val, mdata->base + SPI_CMD_REG); -+ -+unmap_rx_dma: -+ if (op->data.dir == SPI_MEM_DATA_IN) { -+ dma_unmap_single(mdata->dev, mdata->rx_dma, -+ op->data.nbytes, DMA_FROM_DEVICE); -+ if (!IS_ALIGNED((size_t)op->data.buf.in, 4)) -+ memcpy(op->data.buf.in, rx_tmp_buf, op->data.nbytes); -+ } -+kfree_rx_tmp_buf: -+ if (op->data.dir == SPI_MEM_DATA_IN && -+ !IS_ALIGNED((size_t)op->data.buf.in, 4)) -+ kfree(rx_tmp_buf); -+unmap_tx_dma: -+ dma_unmap_single(mdata->dev, mdata->tx_dma, -+ tx_size, DMA_TO_DEVICE); -+err_exit: -+ kfree(tx_tmp_buf); -+ mdata->use_spimem = false; -+ -+ return ret; -+} -+ -+static const struct spi_controller_mem_ops mtk_spi_mem_ops = { -+ .adjust_op_size = mtk_spi_mem_adjust_op_size, -+ .supports_op = mtk_spi_mem_supports_op, -+ .exec_op = mtk_spi_mem_exec_op, -+}; -+ - static int mtk_spi_probe(struct platform_device *pdev) - { - struct spi_master *master; -@@ -741,6 +1105,7 @@ static int mtk_spi_probe(struct platform - master->can_dma = mtk_spi_can_dma; - master->setup = mtk_spi_setup; - master->set_cs_timing = mtk_spi_set_hw_cs_timing; -+ master->use_gpio_descriptors = true; - - of_id = of_match_node(mtk_spi_of_match, pdev->dev.of_node); - if (!of_id) { -@@ -757,6 +1122,14 @@ static int mtk_spi_probe(struct platform - - if (mdata->dev_comp->must_tx) - master->flags = SPI_MASTER_MUST_TX; -+ if (mdata->dev_comp->ipm_design) -+ master->mode_bits |= SPI_LOOP; -+ -+ if (mdata->dev_comp->ipm_design) { -+ mdata->dev = &pdev->dev; -+ master->mem_ops = &mtk_spi_mem_ops; -+ init_completion(&mdata->spimem_done); -+ } - - if (mdata->dev_comp->need_pad_sel) { - mdata->pad_num = of_property_count_u32_elems( -@@ -833,25 +1206,40 @@ static int mtk_spi_probe(struct platform - goto err_put_master; - } - -+ mdata->spi_hclk = devm_clk_get_optional(&pdev->dev, "hclk"); -+ if (IS_ERR(mdata->spi_hclk)) { -+ ret = PTR_ERR(mdata->spi_hclk); -+ dev_err(&pdev->dev, "failed to get hclk: %d\n", ret); -+ goto err_put_master; -+ } -+ -+ ret = clk_prepare_enable(mdata->spi_hclk); -+ if (ret < 0) { -+ dev_err(&pdev->dev, "failed to enable hclk (%d)\n", ret); -+ goto err_put_master; -+ } -+ - ret = clk_prepare_enable(mdata->spi_clk); - if (ret < 0) { - dev_err(&pdev->dev, "failed to enable spi_clk (%d)\n", ret); -- goto err_put_master; -+ goto err_disable_spi_hclk; - } - - ret = clk_set_parent(mdata->sel_clk, mdata->parent_clk); - if (ret < 0) { - dev_err(&pdev->dev, "failed to clk_set_parent (%d)\n", ret); -- clk_disable_unprepare(mdata->spi_clk); -- goto err_put_master; -+ goto err_disable_spi_clk; - } - - mdata->spi_clk_hz = clk_get_rate(mdata->spi_clk); - -- if (mdata->dev_comp->no_need_unprepare) -+ if (mdata->dev_comp->no_need_unprepare) { - clk_disable(mdata->spi_clk); -- else -+ clk_disable(mdata->spi_hclk); -+ } else { - clk_disable_unprepare(mdata->spi_clk); -+ clk_disable_unprepare(mdata->spi_hclk); -+ } - - pm_runtime_enable(&pdev->dev); - -@@ -864,25 +1252,12 @@ static int mtk_spi_probe(struct platform - goto err_disable_runtime_pm; - } - -- if (!master->cs_gpios && master->num_chipselect > 1) { -+ if (!master->cs_gpiods && master->num_chipselect > 1) { - dev_err(&pdev->dev, - "cs_gpios not specified and num_chipselect > 1\n"); - ret = -EINVAL; - goto err_disable_runtime_pm; - } -- -- if (master->cs_gpios) { -- for (i = 0; i < master->num_chipselect; i++) { -- ret = devm_gpio_request(&pdev->dev, -- master->cs_gpios[i], -- dev_name(&pdev->dev)); -- if (ret) { -- dev_err(&pdev->dev, -- "can't get CS GPIO %i\n", i); -- goto err_disable_runtime_pm; -- } -- } -- } - } - - if (mdata->dev_comp->dma_ext) -@@ -904,6 +1279,10 @@ static int mtk_spi_probe(struct platform - - err_disable_runtime_pm: - pm_runtime_disable(&pdev->dev); -+err_disable_spi_clk: -+ clk_disable_unprepare(mdata->spi_clk); -+err_disable_spi_hclk: -+ clk_disable_unprepare(mdata->spi_hclk); - err_put_master: - spi_master_put(master); - -@@ -922,8 +1301,10 @@ static int mtk_spi_remove(struct platfor - - mtk_spi_reset(mdata); - -- if (mdata->dev_comp->no_need_unprepare) -+ if (mdata->dev_comp->no_need_unprepare) { - clk_unprepare(mdata->spi_clk); -+ clk_unprepare(mdata->spi_hclk); -+ } - - pm_runtime_put_noidle(&pdev->dev); - pm_runtime_disable(&pdev->dev); -@@ -942,8 +1323,10 @@ static int mtk_spi_suspend(struct device - if (ret) - return ret; - -- if (!pm_runtime_suspended(dev)) -+ if (!pm_runtime_suspended(dev)) { - clk_disable_unprepare(mdata->spi_clk); -+ clk_disable_unprepare(mdata->spi_hclk); -+ } - - return ret; - } -@@ -960,11 +1343,20 @@ static int mtk_spi_resume(struct device - dev_err(dev, "failed to enable spi_clk (%d)\n", ret); - return ret; - } -+ -+ ret = clk_prepare_enable(mdata->spi_hclk); -+ if (ret < 0) { -+ dev_err(dev, "failed to enable spi_hclk (%d)\n", ret); -+ clk_disable_unprepare(mdata->spi_clk); -+ return ret; -+ } - } - - ret = spi_master_resume(master); -- if (ret < 0) -+ if (ret < 0) { - clk_disable_unprepare(mdata->spi_clk); -+ clk_disable_unprepare(mdata->spi_hclk); -+ } - - return ret; - } -@@ -976,10 +1368,13 @@ static int mtk_spi_runtime_suspend(struc - struct spi_master *master = dev_get_drvdata(dev); - struct mtk_spi *mdata = spi_master_get_devdata(master); - -- if (mdata->dev_comp->no_need_unprepare) -+ if (mdata->dev_comp->no_need_unprepare) { - clk_disable(mdata->spi_clk); -- else -+ clk_disable(mdata->spi_hclk); -+ } else { - clk_disable_unprepare(mdata->spi_clk); -+ clk_disable_unprepare(mdata->spi_hclk); -+ } - - return 0; - } -@@ -990,13 +1385,31 @@ static int mtk_spi_runtime_resume(struct - struct mtk_spi *mdata = spi_master_get_devdata(master); - int ret; - -- if (mdata->dev_comp->no_need_unprepare) -+ if (mdata->dev_comp->no_need_unprepare) { - ret = clk_enable(mdata->spi_clk); -- else -+ if (ret < 0) { -+ dev_err(dev, "failed to enable spi_clk (%d)\n", ret); -+ return ret; -+ } -+ ret = clk_enable(mdata->spi_hclk); -+ if (ret < 0) { -+ dev_err(dev, "failed to enable spi_hclk (%d)\n", ret); -+ clk_disable(mdata->spi_clk); -+ return ret; -+ } -+ } else { - ret = clk_prepare_enable(mdata->spi_clk); -- if (ret < 0) { -- dev_err(dev, "failed to enable spi_clk (%d)\n", ret); -- return ret; -+ if (ret < 0) { -+ dev_err(dev, "failed to prepare_enable spi_clk (%d)\n", ret); -+ return ret; -+ } -+ -+ ret = clk_prepare_enable(mdata->spi_hclk); -+ if (ret < 0) { -+ dev_err(dev, "failed to prepare_enable spi_hclk (%d)\n", ret); -+ clk_disable_unprepare(mdata->spi_clk); -+ return ret; -+ } - } - - return 0; diff --git a/target/linux/mediatek/patches-5.15/214-v6.3-clk-mediatek-add-mt7981-clock-support.patch b/target/linux/mediatek/patches-5.15/214-v6.3-clk-mediatek-add-mt7981-clock-support.patch deleted file mode 100644 index 631eb0409..000000000 --- a/target/linux/mediatek/patches-5.15/214-v6.3-clk-mediatek-add-mt7981-clock-support.patch +++ /dev/null @@ -1,39 +0,0 @@ ---- a/drivers/clk/mediatek/Kconfig -+++ b/drivers/clk/mediatek/Kconfig -@@ -344,6 +344,23 @@ config COMMON_CLK_MT7629_HIFSYS - This driver supports MediaTek MT7629 HIFSYS clocks providing - to PCI-E and USB. - -+config COMMON_CLK_MT7981 -+ bool "Clock driver for MediaTek MT7981" -+ depends on ARCH_MEDIATEK || COMPILE_TEST -+ select COMMON_CLK_MEDIATEK -+ default ARCH_MEDIATEK -+ help -+ This driver supports MediaTek MT7981 basic clocks and clocks -+ required for various periperals found on MediaTek. -+ -+config COMMON_CLK_MT7981_ETHSYS -+ bool "Clock driver for MediaTek MT7981 ETHSYS" -+ depends on COMMON_CLK_MT7981 -+ default COMMON_CLK_MT7981 -+ help -+ This driver add support for clocks for Ethernet and SGMII -+ required on MediaTek MT7981 SoC. -+ - config COMMON_CLK_MT7986 - bool "Clock driver for MediaTek MT7986" - depends on ARCH_MEDIATEK || COMPILE_TEST ---- a/drivers/clk/mediatek/Makefile -+++ b/drivers/clk/mediatek/Makefile -@@ -46,6 +46,10 @@ obj-$(CONFIG_COMMON_CLK_MT7622_AUDSYS) + - obj-$(CONFIG_COMMON_CLK_MT7629) += clk-mt7629.o - obj-$(CONFIG_COMMON_CLK_MT7629_ETHSYS) += clk-mt7629-eth.o - obj-$(CONFIG_COMMON_CLK_MT7629_HIFSYS) += clk-mt7629-hif.o -+obj-$(CONFIG_COMMON_CLK_MT7981) += clk-mt7981-apmixed.o -+obj-$(CONFIG_COMMON_CLK_MT7981) += clk-mt7981-topckgen.o -+obj-$(CONFIG_COMMON_CLK_MT7981) += clk-mt7981-infracfg.o -+obj-$(CONFIG_COMMON_CLK_MT7981_ETHSYS) += clk-mt7981-eth.o - obj-$(CONFIG_COMMON_CLK_MT7986) += clk-mt7986-apmixed.o - obj-$(CONFIG_COMMON_CLK_MT7986) += clk-mt7986-topckgen.o - obj-$(CONFIG_COMMON_CLK_MT7986) += clk-mt7986-infracfg.o diff --git a/target/linux/mediatek/patches-5.15/215-mtdblock-revert-warn-if-opened-on-NAND.patch b/target/linux/mediatek/patches-5.15/215-mtdblock-revert-warn-if-opened-on-NAND.patch deleted file mode 100644 index 43983339b..000000000 --- a/target/linux/mediatek/patches-5.15/215-mtdblock-revert-warn-if-opened-on-NAND.patch +++ /dev/null @@ -1,26 +0,0 @@ ---- a/drivers/mtd/mtdblock.c -+++ b/drivers/mtd/mtdblock.c -@@ -261,10 +261,6 @@ static int mtdblock_open(struct mtd_blkt - return 0; - } - -- if (mtd_type_is_nand(mbd->mtd)) -- pr_warn("%s: MTD device '%s' is NAND, please consider using UBI block devices instead.\n", -- mbd->tr->name, mbd->mtd->name); -- - /* OK, it's not open. Create cache info for it */ - mtdblk->count = 1; - mutex_init(&mtdblk->cache_mutex); ---- a/drivers/mtd/mtdblock_ro.c -+++ b/drivers/mtd/mtdblock_ro.c -@@ -46,10 +46,6 @@ static void mtdblock_add_mtd(struct mtd_ - dev->tr = tr; - dev->readonly = 1; - -- if (mtd_type_is_nand(mtd)) -- pr_warn("%s: MTD device '%s' is NAND, please consider using UBI block devices instead.\n", -- tr->name, mtd->name); -- - if (add_mtd_blktrans_dev(dev)) - kfree(dev); - } diff --git a/target/linux/mediatek/patches-5.15/215-v6.3-pinctrl-mediatek-add-support-for-MT7981-SoC.patch b/target/linux/mediatek/patches-5.15/215-v6.3-pinctrl-mediatek-add-support-for-MT7981-SoC.patch deleted file mode 100644 index ae99685df..000000000 --- a/target/linux/mediatek/patches-5.15/215-v6.3-pinctrl-mediatek-add-support-for-MT7981-SoC.patch +++ /dev/null @@ -1,26 +0,0 @@ ---- a/drivers/pinctrl/mediatek/Kconfig -+++ b/drivers/pinctrl/mediatek/Kconfig -@@ -120,6 +120,13 @@ config PINCTRL_MT7622 - default ARM64 && ARCH_MEDIATEK - select PINCTRL_MTK_MOORE - -+config PINCTRL_MT7981 -+ bool "Mediatek MT7981 pin control" -+ depends on OF -+ depends on ARM64 || COMPILE_TEST -+ default ARM64 && ARCH_MEDIATEK -+ select PINCTRL_MTK_MOORE -+ - config PINCTRL_MT7986 - bool "Mediatek MT7986 pin control" - depends on OF ---- a/drivers/pinctrl/mediatek/Makefile -+++ b/drivers/pinctrl/mediatek/Makefile -@@ -17,6 +17,7 @@ obj-$(CONFIG_PINCTRL_MT6797) += pinctrl- - obj-$(CONFIG_PINCTRL_MT7622) += pinctrl-mt7622.o - obj-$(CONFIG_PINCTRL_MT7623) += pinctrl-mt7623.o - obj-$(CONFIG_PINCTRL_MT7629) += pinctrl-mt7629.o -+obj-$(CONFIG_PINCTRL_MT7986) += pinctrl-mt7981.o - obj-$(CONFIG_PINCTRL_MT7986) += pinctrl-mt7986.o - obj-$(CONFIG_PINCTRL_MT8167) += pinctrl-mt8167.o - obj-$(CONFIG_PINCTRL_MT8173) += pinctrl-mt8173.o diff --git a/target/linux/mediatek/patches-5.15/240-pinctrl-mediatek-add-support-for-MT7988-SoC.patch b/target/linux/mediatek/patches-5.15/240-pinctrl-mediatek-add-support-for-MT7988-SoC.patch deleted file mode 100644 index cbee45bc1..000000000 --- a/target/linux/mediatek/patches-5.15/240-pinctrl-mediatek-add-support-for-MT7988-SoC.patch +++ /dev/null @@ -1,26 +0,0 @@ ---- a/drivers/pinctrl/mediatek/Kconfig -+++ b/drivers/pinctrl/mediatek/Kconfig -@@ -134,6 +134,13 @@ config PINCTRL_MT7986 - default ARM64 && ARCH_MEDIATEK - select PINCTRL_MTK_MOORE - -+config PINCTRL_MT7988 -+ bool "Mediatek MT7988 pin control" -+ depends on OF -+ depends on ARM64 || COMPILE_TEST -+ default ARCH_MEDIATEK -+ select PINCTRL_MTK_MOORE -+ - config PINCTRL_MT8167 - bool "Mediatek MT8167 pin control" - depends on OF ---- a/drivers/pinctrl/mediatek/Makefile -+++ b/drivers/pinctrl/mediatek/Makefile -@@ -19,6 +19,7 @@ obj-$(CONFIG_PINCTRL_MT7623) += pinctrl- - obj-$(CONFIG_PINCTRL_MT7629) += pinctrl-mt7629.o - obj-$(CONFIG_PINCTRL_MT7986) += pinctrl-mt7981.o - obj-$(CONFIG_PINCTRL_MT7986) += pinctrl-mt7986.o -+obj-$(CONFIG_PINCTRL_MT7988) += pinctrl-mt7988.o - obj-$(CONFIG_PINCTRL_MT8167) += pinctrl-mt8167.o - obj-$(CONFIG_PINCTRL_MT8173) += pinctrl-mt8173.o - obj-$(CONFIG_PINCTRL_MT8183) += pinctrl-mt8183.o diff --git a/target/linux/mediatek/patches-5.15/241-clk-mediatek-Add-pcw-chg-shift-control.patch b/target/linux/mediatek/patches-5.15/241-clk-mediatek-Add-pcw-chg-shift-control.patch deleted file mode 100644 index 23a5b7c91..000000000 --- a/target/linux/mediatek/patches-5.15/241-clk-mediatek-Add-pcw-chg-shift-control.patch +++ /dev/null @@ -1,24 +0,0 @@ ---- a/drivers/clk/mediatek/clk-mtk.h -+++ b/drivers/clk/mediatek/clk-mtk.h -@@ -233,6 +233,7 @@ struct mtk_pll_data { - u32 pcw_reg; - int pcw_shift; - u32 pcw_chg_reg; -+ int pcw_chg_shift; - const struct mtk_pll_div_table *div_table; - const char *parent_name; - u32 en_reg; ---- a/drivers/clk/mediatek/clk-pll.c -+++ b/drivers/clk/mediatek/clk-pll.c -@@ -137,7 +137,10 @@ static void mtk_pll_set_rate_regs(struct - pll->data->pcw_shift); - val |= pcw << pll->data->pcw_shift; - writel(val, pll->pcw_addr); -- chg = readl(pll->pcw_chg_addr) | PCW_CHG_MASK; -+ if (pll->data->pcw_chg_shift) -+ chg = readl(pll->pcw_chg_addr) | BIT(pll->data->pcw_chg_shift); -+ else -+ chg = readl(pll->pcw_chg_addr) | PCW_CHG_MASK; - writel(chg, pll->pcw_chg_addr); - if (pll->tuner_addr) - writel(val + 1, pll->tuner_addr); diff --git a/target/linux/mediatek/patches-5.15/242-clk-mediatek-add-mt7988-clock-support.patch b/target/linux/mediatek/patches-5.15/242-clk-mediatek-add-mt7988-clock-support.patch deleted file mode 100644 index bf9146352..000000000 --- a/target/linux/mediatek/patches-5.15/242-clk-mediatek-add-mt7988-clock-support.patch +++ /dev/null @@ -1,31 +0,0 @@ ---- a/drivers/clk/mediatek/Kconfig -+++ b/drivers/clk/mediatek/Kconfig -@@ -378,6 +378,15 @@ config COMMON_CLK_MT7986_ETHSYS - This driver add support for clocks for Ethernet and SGMII - required on MediaTek MT7986 SoC. - -+config COMMON_CLK_MT7988 -+ bool "Clock driver for MediaTek MT7988" -+ depends on ARCH_MEDIATEK || COMPILE_TEST -+ select COMMON_CLK_MEDIATEK -+ default ARCH_MEDIATEK -+ help -+ This driver supports MediaTek MT7988 basic clocks and clocks -+ required for various periperals found on MediaTek. -+ - config COMMON_CLK_MT8135 - bool "Clock driver for MediaTek MT8135" - depends on (ARCH_MEDIATEK && ARM) || COMPILE_TEST ---- a/drivers/clk/mediatek/Makefile -+++ b/drivers/clk/mediatek/Makefile -@@ -54,6 +54,10 @@ obj-$(CONFIG_COMMON_CLK_MT7986) += clk-m - obj-$(CONFIG_COMMON_CLK_MT7986) += clk-mt7986-topckgen.o - obj-$(CONFIG_COMMON_CLK_MT7986) += clk-mt7986-infracfg.o - obj-$(CONFIG_COMMON_CLK_MT7986_ETHSYS) += clk-mt7986-eth.o -+obj-$(CONFIG_COMMON_CLK_MT7988) += clk-mt7988-apmixed.o -+obj-$(CONFIG_COMMON_CLK_MT7988) += clk-mt7988-topckgen.o -+obj-$(CONFIG_COMMON_CLK_MT7988) += clk-mt7988-infracfg.o -+obj-$(CONFIG_COMMON_CLK_MT7988) += clk-mt7988-eth.o - obj-$(CONFIG_COMMON_CLK_MT8135) += clk-mt8135.o - obj-$(CONFIG_COMMON_CLK_MT8167) += clk-mt8167.o - obj-$(CONFIG_COMMON_CLK_MT8167_AUDSYS) += clk-mt8167-aud.o diff --git a/target/linux/mediatek/patches-5.15/320-mmc-mediatek-add-support-for-MT7986-SoC.patch b/target/linux/mediatek/patches-5.15/320-mmc-mediatek-add-support-for-MT7986-SoC.patch deleted file mode 100644 index 56ffa73c0..000000000 --- a/target/linux/mediatek/patches-5.15/320-mmc-mediatek-add-support-for-MT7986-SoC.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 1a7963e9843f6f1e4b02a30926d20b314c03e4df Mon Sep 17 00:00:00 2001 -From: Sam Shih -Date: Sat, 25 Jun 2022 02:10:13 +0800 -Subject: [PATCH] mmc: mediatek: add support for MT7986 SoC - -Adding mt7986 own characteristics and of_device_id to have support -of MT7986 SoC. - -Signed-off-by: Sam Shih -Change-Id: I07cf8406cbe8c1a7114b304f35fc3e689e512e5a ---- - drivers/mmc/host/mtk-sd.c | 14 ++++++++++++++ - 1 file changed, 14 insertions(+) - ---- a/drivers/mmc/host/mtk-sd.c -+++ b/drivers/mmc/host/mtk-sd.c -@@ -540,6 +540,19 @@ static const struct mtk_mmc_compatible m - .support_64g = false, - }; - -+static const struct mtk_mmc_compatible mt7986_compat = { -+ .clk_div_bits = 12, -+ .recheck_sdio_irq = true, -+ .hs400_tune = false, -+ .pad_tune_reg = MSDC_PAD_TUNE0, -+ .async_fifo = true, -+ .data_tune = true, -+ .busy_check = true, -+ .stop_clk_fix = true, -+ .enhance_rx = true, -+ .support_64g = true, -+}; -+ - static const struct mtk_mmc_compatible mt8516_compat = { - .clk_div_bits = 12, - .recheck_sdio_irq = true, -@@ -584,6 +597,7 @@ static const struct of_device_id msdc_of - { .compatible = "mediatek,mt2701-mmc", .data = &mt2701_compat}, - { .compatible = "mediatek,mt2712-mmc", .data = &mt2712_compat}, - { .compatible = "mediatek,mt7622-mmc", .data = &mt7622_compat}, -+ { .compatible = "mediatek,mt7986-mmc", .data = &mt7986_compat}, - { .compatible = "mediatek,mt8516-mmc", .data = &mt8516_compat}, - { .compatible = "mediatek,mt7620-mmc", .data = &mt7620_compat}, - { .compatible = "mediatek,mt6779-mmc", .data = &mt6779_compat}, diff --git a/target/linux/mediatek/patches-5.15/330-snand-mtk-bmt-support.patch b/target/linux/mediatek/patches-5.15/330-snand-mtk-bmt-support.patch deleted file mode 100644 index 48bfb0d35..000000000 --- a/target/linux/mediatek/patches-5.15/330-snand-mtk-bmt-support.patch +++ /dev/null @@ -1,34 +0,0 @@ ---- a/drivers/mtd/nand/spi/core.c -+++ b/drivers/mtd/nand/spi/core.c -@@ -19,6 +19,7 @@ - #include - #include - #include -+#include - - static int spinand_read_reg_op(struct spinand_device *spinand, u8 reg, u8 *val) - { -@@ -1332,6 +1333,7 @@ static int spinand_probe(struct spi_mem - if (ret) - return ret; - -+ mtk_bmt_attach(mtd); - ret = mtd_device_register(mtd, NULL, 0); - if (ret) - goto err_spinand_cleanup; -@@ -1339,6 +1341,7 @@ static int spinand_probe(struct spi_mem - return 0; - - err_spinand_cleanup: -+ mtk_bmt_detach(mtd); - spinand_cleanup(spinand); - - return ret; -@@ -1357,6 +1360,7 @@ static int spinand_remove(struct spi_mem - if (ret) - return ret; - -+ mtk_bmt_detach(mtd); - spinand_cleanup(spinand); - - return 0; diff --git a/target/linux/mediatek/patches-5.15/331-mt7622-rfb1-enable-bmt.patch b/target/linux/mediatek/patches-5.15/331-mt7622-rfb1-enable-bmt.patch deleted file mode 100644 index 504928cb2..000000000 --- a/target/linux/mediatek/patches-5.15/331-mt7622-rfb1-enable-bmt.patch +++ /dev/null @@ -1,10 +0,0 @@ ---- a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts -@@ -554,6 +554,7 @@ - spi-tx-bus-width = <4>; - spi-rx-bus-width = <4>; - nand-ecc-engine = <&snfi>; -+ mediatek,bmt-v2; - - partitions { - compatible = "fixed-partitions"; diff --git a/target/linux/mediatek/patches-5.15/340-mtd-spinand-Add-support-for-the-Fidelix-FM35X1GA.patch b/target/linux/mediatek/patches-5.15/340-mtd-spinand-Add-support-for-the-Fidelix-FM35X1GA.patch deleted file mode 100644 index e6d39c0f1..000000000 --- a/target/linux/mediatek/patches-5.15/340-mtd-spinand-Add-support-for-the-Fidelix-FM35X1GA.patch +++ /dev/null @@ -1,122 +0,0 @@ -From 5f49a5c9b16330e0df8f639310e4715dcad71947 Mon Sep 17 00:00:00 2001 -From: Davide Fioravanti -Date: Fri, 8 Jan 2021 15:35:24 +0100 -Subject: [PATCH] mtd: spinand: Add support for the Fidelix FM35X1GA - -Datasheet: http://www.hobos.com.cn/upload/datasheet/DS35X1GAXXX_100_rev00.pdf - -Signed-off-by: Davide Fioravanti ---- - drivers/mtd/nand/spi/Makefile | 2 +- - drivers/mtd/nand/spi/core.c | 1 + - drivers/mtd/nand/spi/fidelix.c | 76 ++++++++++++++++++++++++++++++++++ - include/linux/mtd/spinand.h | 1 + - 4 files changed, 79 insertions(+), 1 deletion(-) - create mode 100644 drivers/mtd/nand/spi/fidelix.c - ---- a/drivers/mtd/nand/spi/Makefile -+++ b/drivers/mtd/nand/spi/Makefile -@@ -1,3 +1,3 @@ - # SPDX-License-Identifier: GPL-2.0 --spinand-objs := core.o esmt.o gigadevice.o macronix.o micron.o paragon.o toshiba.o winbond.o xtx.o -+spinand-objs := core.o esmt.o fidelix.o gigadevice.o macronix.o 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 -@@ -929,6 +929,7 @@ static const struct nand_ops spinand_ops - - static const struct spinand_manufacturer *spinand_manufacturers[] = { - &esmt_c8_spinand_manufacturer, -+ &fidelix_spinand_manufacturer, - &gigadevice_spinand_manufacturer, - ¯onix_spinand_manufacturer, - µn_spinand_manufacturer, ---- /dev/null -+++ b/drivers/mtd/nand/spi/fidelix.c -@@ -0,0 +1,76 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (c) 2020 Davide Fioravanti -+ */ -+ -+#include -+#include -+#include -+ -+#define SPINAND_MFR_FIDELIX 0xE5 -+#define FIDELIX_ECCSR_MASK 0x0F -+ -+static SPINAND_OP_VARIANTS(read_cache_variants, -+ SPINAND_PAGE_READ_FROM_CACHE_X4_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(true, 0, NULL, 0), -+ SPINAND_PROG_LOAD(true, 0, NULL, 0)); -+ -+static int fm35x1ga_ooblayout_ecc(struct mtd_info *mtd, int section, -+ struct mtd_oob_region *region) -+{ -+ if (section > 3) -+ return -ERANGE; -+ -+ region->offset = (16 * section) + 8; -+ region->length = 8; -+ -+ return 0; -+} -+ -+static int fm35x1ga_ooblayout_free(struct mtd_info *mtd, int section, -+ struct mtd_oob_region *region) -+{ -+ if (section > 3) -+ return -ERANGE; -+ -+ region->offset = (16 * section) + 2; -+ region->length = 6; -+ -+ return 0; -+} -+ -+static const struct mtd_ooblayout_ops fm35x1ga_ooblayout = { -+ .ecc = fm35x1ga_ooblayout_ecc, -+ .free = fm35x1ga_ooblayout_free, -+}; -+ -+static const struct spinand_info fidelix_spinand_table[] = { -+ SPINAND_INFO("FM35X1GA", -+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x71), -+ NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1), -+ NAND_ECCREQ(4, 512), -+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants, -+ &write_cache_variants, -+ &update_cache_variants), -+ SPINAND_HAS_QE_BIT, -+ SPINAND_ECCINFO(&fm35x1ga_ooblayout, NULL)), -+}; -+ -+static const struct spinand_manufacturer_ops fidelix_spinand_manuf_ops = { -+}; -+ -+const struct spinand_manufacturer fidelix_spinand_manufacturer = { -+ .id = SPINAND_MFR_FIDELIX, -+ .name = "Fidelix", -+ .chips = fidelix_spinand_table, -+ .nchips = ARRAY_SIZE(fidelix_spinand_table), -+ .ops = &fidelix_spinand_manuf_ops, -+}; ---- a/include/linux/mtd/spinand.h -+++ b/include/linux/mtd/spinand.h -@@ -261,6 +261,7 @@ struct spinand_manufacturer { - - /* SPI NAND manufacturers */ - extern const struct spinand_manufacturer esmt_c8_spinand_manufacturer; -+extern const struct spinand_manufacturer fidelix_spinand_manufacturer; - extern const struct spinand_manufacturer gigadevice_spinand_manufacturer; - extern const struct spinand_manufacturer macronix_spinand_manufacturer; - extern const struct spinand_manufacturer micron_spinand_manufacturer; diff --git a/target/linux/mediatek/patches-5.15/350-01-cpufreq-mediatek-Cleanup-variables-and-error-handlin.patch b/target/linux/mediatek/patches-5.15/350-01-cpufreq-mediatek-Cleanup-variables-and-error-handlin.patch deleted file mode 100644 index 8fad64a57..000000000 --- a/target/linux/mediatek/patches-5.15/350-01-cpufreq-mediatek-Cleanup-variables-and-error-handlin.patch +++ /dev/null @@ -1,166 +0,0 @@ -From 7a768326fdba542144833b9198a6d0edab52fad2 Mon Sep 17 00:00:00 2001 -From: Jia-Wei Chang -Date: Fri, 8 Apr 2022 12:58:56 +0800 -Subject: [PATCH 01/21] cpufreq: mediatek: Cleanup variables and error handling - in mtk_cpu_dvfs_info_init() - -- Remove several unnecessary varaibles in mtk_cpu_dvfs_info_init(). -- Unify error message format and use dev_err_probe() if possible. - -Signed-off-by: Jia-Wei Chang -Signed-off-by: Rex-BC Chen -Reviewed-by: AngeloGioacchino Del Regno -Signed-off-by: Viresh Kumar ---- - drivers/cpufreq/mediatek-cpufreq.c | 89 ++++++++++++------------------ - 1 file changed, 34 insertions(+), 55 deletions(-) - ---- a/drivers/cpufreq/mediatek-cpufreq.c -+++ b/drivers/cpufreq/mediatek-cpufreq.c -@@ -302,96 +302,75 @@ static int mtk_cpufreq_set_target(struct - static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu) - { - struct device *cpu_dev; -- struct regulator *proc_reg = ERR_PTR(-ENODEV); -- struct regulator *sram_reg = ERR_PTR(-ENODEV); -- struct clk *cpu_clk = ERR_PTR(-ENODEV); -- struct clk *inter_clk = ERR_PTR(-ENODEV); - struct dev_pm_opp *opp; - unsigned long rate; - int ret; - - cpu_dev = get_cpu_device(cpu); - if (!cpu_dev) { -- pr_err("failed to get cpu%d device\n", cpu); -+ dev_err(cpu_dev, "failed to get cpu%d device\n", cpu); - return -ENODEV; - } -+ info->cpu_dev = cpu_dev; - -- cpu_clk = clk_get(cpu_dev, "cpu"); -- if (IS_ERR(cpu_clk)) { -- if (PTR_ERR(cpu_clk) == -EPROBE_DEFER) -- pr_warn("cpu clk for cpu%d not ready, retry.\n", cpu); -- else -- pr_err("failed to get cpu clk for cpu%d\n", cpu); -- -- ret = PTR_ERR(cpu_clk); -- return ret; -- } -- -- inter_clk = clk_get(cpu_dev, "intermediate"); -- if (IS_ERR(inter_clk)) { -- if (PTR_ERR(inter_clk) == -EPROBE_DEFER) -- pr_warn("intermediate clk for cpu%d not ready, retry.\n", -- cpu); -- else -- pr_err("failed to get intermediate clk for cpu%d\n", -- cpu); -+ info->cpu_clk = clk_get(cpu_dev, "cpu"); -+ if (IS_ERR(info->cpu_clk)) { -+ ret = PTR_ERR(info->cpu_clk); -+ return dev_err_probe(cpu_dev, ret, -+ "cpu%d: failed to get cpu clk\n", cpu); -+ } - -- ret = PTR_ERR(inter_clk); -+ info->inter_clk = clk_get(cpu_dev, "intermediate"); -+ if (IS_ERR(info->inter_clk)) { -+ ret = PTR_ERR(info->inter_clk); -+ dev_err_probe(cpu_dev, ret, -+ "cpu%d: failed to get intermediate clk\n", cpu); - goto out_free_resources; - } - -- proc_reg = regulator_get_optional(cpu_dev, "proc"); -- if (IS_ERR(proc_reg)) { -- if (PTR_ERR(proc_reg) == -EPROBE_DEFER) -- pr_warn("proc regulator for cpu%d not ready, retry.\n", -- cpu); -- else -- pr_err("failed to get proc regulator for cpu%d\n", -- cpu); -- -- ret = PTR_ERR(proc_reg); -+ info->proc_reg = regulator_get_optional(cpu_dev, "proc"); -+ if (IS_ERR(info->proc_reg)) { -+ ret = PTR_ERR(info->proc_reg); -+ dev_err_probe(cpu_dev, ret, -+ "cpu%d: failed to get proc regulator\n", cpu); - goto out_free_resources; - } - - /* Both presence and absence of sram regulator are valid cases. */ -- sram_reg = regulator_get_exclusive(cpu_dev, "sram"); -+ info->sram_reg = regulator_get_exclusive(cpu_dev, "sram"); -+ if (IS_ERR(info->sram_reg)) -+ info->sram_reg = NULL; - - /* Get OPP-sharing information from "operating-points-v2" bindings */ - ret = dev_pm_opp_of_get_sharing_cpus(cpu_dev, &info->cpus); - if (ret) { -- pr_err("failed to get OPP-sharing information for cpu%d\n", -- cpu); -+ dev_err(cpu_dev, -+ "cpu%d: failed to get OPP-sharing information\n", cpu); - goto out_free_resources; - } - - ret = dev_pm_opp_of_cpumask_add_table(&info->cpus); - if (ret) { -- pr_warn("no OPP table for cpu%d\n", cpu); -+ dev_warn(cpu_dev, "cpu%d: no OPP table\n", cpu); - goto out_free_resources; - } - - /* Search a safe voltage for intermediate frequency. */ -- rate = clk_get_rate(inter_clk); -+ rate = clk_get_rate(info->inter_clk); - opp = dev_pm_opp_find_freq_ceil(cpu_dev, &rate); - if (IS_ERR(opp)) { -- pr_err("failed to get intermediate opp for cpu%d\n", cpu); -+ dev_err(cpu_dev, "cpu%d: failed to get intermediate opp\n", cpu); - ret = PTR_ERR(opp); - goto out_free_opp_table; - } - info->intermediate_voltage = dev_pm_opp_get_voltage(opp); - dev_pm_opp_put(opp); - -- info->cpu_dev = cpu_dev; -- info->proc_reg = proc_reg; -- info->sram_reg = IS_ERR(sram_reg) ? NULL : sram_reg; -- info->cpu_clk = cpu_clk; -- info->inter_clk = inter_clk; -- - /* - * If SRAM regulator is present, software "voltage tracking" is needed - * for this CPU power domain. - */ -- info->need_voltage_tracking = !IS_ERR(sram_reg); -+ info->need_voltage_tracking = (info->sram_reg != NULL); - - return 0; - -@@ -399,14 +378,14 @@ out_free_opp_table: - dev_pm_opp_of_cpumask_remove_table(&info->cpus); - - out_free_resources: -- if (!IS_ERR(proc_reg)) -- regulator_put(proc_reg); -- if (!IS_ERR(sram_reg)) -- regulator_put(sram_reg); -- if (!IS_ERR(cpu_clk)) -- clk_put(cpu_clk); -- if (!IS_ERR(inter_clk)) -- clk_put(inter_clk); -+ if (!IS_ERR(info->proc_reg)) -+ regulator_put(info->proc_reg); -+ if (!IS_ERR(info->sram_reg)) -+ regulator_put(info->sram_reg); -+ if (!IS_ERR(info->cpu_clk)) -+ clk_put(info->cpu_clk); -+ if (!IS_ERR(info->inter_clk)) -+ clk_put(info->inter_clk); - - return ret; - } diff --git a/target/linux/mediatek/patches-5.15/350-02-cpufreq-mediatek-Remove-unused-headers.patch b/target/linux/mediatek/patches-5.15/350-02-cpufreq-mediatek-Remove-unused-headers.patch deleted file mode 100644 index eebeeb090..000000000 --- a/target/linux/mediatek/patches-5.15/350-02-cpufreq-mediatek-Remove-unused-headers.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 756104b856d4bc3121420af3ced342f5fc2b2123 Mon Sep 17 00:00:00 2001 -From: Jia-Wei Chang -Date: Fri, 8 Apr 2022 12:58:57 +0800 -Subject: [PATCH 02/21] cpufreq: mediatek: Remove unused headers - -Remove unused headers. - -Signed-off-by: Jia-Wei Chang -Reviewed-by: AngeloGioacchino Del Regno -Signed-off-by: Viresh Kumar ---- - drivers/cpufreq/mediatek-cpufreq.c | 2 -- - 1 file changed, 2 deletions(-) - ---- a/drivers/cpufreq/mediatek-cpufreq.c -+++ b/drivers/cpufreq/mediatek-cpufreq.c -@@ -13,8 +13,6 @@ - #include - #include - #include --#include --#include - - #define MIN_VOLT_SHIFT (100000) - #define MAX_VOLT_SHIFT (200000) diff --git a/target/linux/mediatek/patches-5.15/350-03-cpufreq-mediatek-Enable-clocks-and-regulators.patch b/target/linux/mediatek/patches-5.15/350-03-cpufreq-mediatek-Enable-clocks-and-regulators.patch deleted file mode 100644 index c97d5fc3d..000000000 --- a/target/linux/mediatek/patches-5.15/350-03-cpufreq-mediatek-Enable-clocks-and-regulators.patch +++ /dev/null @@ -1,117 +0,0 @@ -From 342d5545e9f40496db9ae0d31c2427dd5f369a43 Mon Sep 17 00:00:00 2001 -From: Jia-Wei Chang -Date: Fri, 8 Apr 2022 12:58:58 +0800 -Subject: [PATCH 03/21] cpufreq: mediatek: Enable clocks and regulators - -We need to enable regulators so that the max and min requested values will -be recorded. -The intermediate clock is not always enabled by CCF in different projects, -so we should enable it in the cpufreq driver. - -Signed-off-by: Andrew-sh.Cheng -Signed-off-by: Jia-Wei Chang -Signed-off-by: Rex-BC Chen -Reviewed-by: AngeloGioacchino Del Regno -Signed-off-by: Viresh Kumar ---- - drivers/cpufreq/mediatek-cpufreq.c | 50 +++++++++++++++++++++++++++--- - 1 file changed, 45 insertions(+), 5 deletions(-) - ---- a/drivers/cpufreq/mediatek-cpufreq.c -+++ b/drivers/cpufreq/mediatek-cpufreq.c -@@ -334,10 +334,23 @@ static int mtk_cpu_dvfs_info_init(struct - goto out_free_resources; - } - -+ ret = regulator_enable(info->proc_reg); -+ if (ret) { -+ dev_warn(cpu_dev, "cpu%d: failed to enable vproc\n", cpu); -+ goto out_free_resources; -+ } -+ - /* Both presence and absence of sram regulator are valid cases. */ - info->sram_reg = regulator_get_exclusive(cpu_dev, "sram"); - if (IS_ERR(info->sram_reg)) - info->sram_reg = NULL; -+ else { -+ ret = regulator_enable(info->sram_reg); -+ if (ret) { -+ dev_warn(cpu_dev, "cpu%d: failed to enable vsram\n", cpu); -+ goto out_free_resources; -+ } -+ } - - /* Get OPP-sharing information from "operating-points-v2" bindings */ - ret = dev_pm_opp_of_get_sharing_cpus(cpu_dev, &info->cpus); -@@ -353,13 +366,21 @@ static int mtk_cpu_dvfs_info_init(struct - goto out_free_resources; - } - -+ ret = clk_prepare_enable(info->cpu_clk); -+ if (ret) -+ goto out_free_opp_table; -+ -+ ret = clk_prepare_enable(info->inter_clk); -+ if (ret) -+ goto out_disable_mux_clock; -+ - /* Search a safe voltage for intermediate frequency. */ - rate = clk_get_rate(info->inter_clk); - opp = dev_pm_opp_find_freq_ceil(cpu_dev, &rate); - if (IS_ERR(opp)) { - dev_err(cpu_dev, "cpu%d: failed to get intermediate opp\n", cpu); - ret = PTR_ERR(opp); -- goto out_free_opp_table; -+ goto out_disable_inter_clock; - } - info->intermediate_voltage = dev_pm_opp_get_voltage(opp); - dev_pm_opp_put(opp); -@@ -372,10 +393,21 @@ static int mtk_cpu_dvfs_info_init(struct - - return 0; - -+out_disable_inter_clock: -+ clk_disable_unprepare(info->inter_clk); -+ -+out_disable_mux_clock: -+ clk_disable_unprepare(info->cpu_clk); -+ - out_free_opp_table: - dev_pm_opp_of_cpumask_remove_table(&info->cpus); - - out_free_resources: -+ if (regulator_is_enabled(info->proc_reg)) -+ regulator_disable(info->proc_reg); -+ if (info->sram_reg && regulator_is_enabled(info->sram_reg)) -+ regulator_disable(info->sram_reg); -+ - if (!IS_ERR(info->proc_reg)) - regulator_put(info->proc_reg); - if (!IS_ERR(info->sram_reg)) -@@ -390,14 +422,22 @@ out_free_resources: - - static void mtk_cpu_dvfs_info_release(struct mtk_cpu_dvfs_info *info) - { -- if (!IS_ERR(info->proc_reg)) -+ if (!IS_ERR(info->proc_reg)) { -+ regulator_disable(info->proc_reg); - regulator_put(info->proc_reg); -- if (!IS_ERR(info->sram_reg)) -+ } -+ if (!IS_ERR(info->sram_reg)) { -+ regulator_disable(info->sram_reg); - regulator_put(info->sram_reg); -- if (!IS_ERR(info->cpu_clk)) -+ } -+ if (!IS_ERR(info->cpu_clk)) { -+ clk_disable_unprepare(info->cpu_clk); - clk_put(info->cpu_clk); -- if (!IS_ERR(info->inter_clk)) -+ } -+ if (!IS_ERR(info->inter_clk)) { -+ clk_disable_unprepare(info->inter_clk); - clk_put(info->inter_clk); -+ } - - dev_pm_opp_of_cpumask_remove_table(&info->cpus); - } diff --git a/target/linux/mediatek/patches-5.15/350-04-cpufreq-mediatek-Use-device-print-to-show-logs.patch b/target/linux/mediatek/patches-5.15/350-04-cpufreq-mediatek-Use-device-print-to-show-logs.patch deleted file mode 100644 index 18e1da728..000000000 --- a/target/linux/mediatek/patches-5.15/350-04-cpufreq-mediatek-Use-device-print-to-show-logs.patch +++ /dev/null @@ -1,161 +0,0 @@ -From a02e2b359141035d2d6999940bc1b9f83ec88587 Mon Sep 17 00:00:00 2001 -From: Rex-BC Chen -Date: Fri, 22 Apr 2022 15:52:27 +0800 -Subject: [PATCH 04/21] cpufreq: mediatek: Use device print to show logs - -- Replace pr_* with dev_* to show logs. -- Remove usage of __func__. - -Signed-off-by: Rex-BC Chen -Reviewed-by: AngeloGioacchino Del Regno -Signed-off-by: Viresh Kumar ---- - drivers/cpufreq/mediatek-cpufreq.c | 54 ++++++++++++++++-------------- - 1 file changed, 28 insertions(+), 26 deletions(-) - ---- a/drivers/cpufreq/mediatek-cpufreq.c -+++ b/drivers/cpufreq/mediatek-cpufreq.c -@@ -67,7 +67,8 @@ static int mtk_cpufreq_voltage_tracking( - - old_vproc = regulator_get_voltage(proc_reg); - if (old_vproc < 0) { -- pr_err("%s: invalid Vproc value: %d\n", __func__, old_vproc); -+ dev_err(info->cpu_dev, -+ "invalid Vproc value: %d\n", old_vproc); - return old_vproc; - } - /* Vsram should not exceed the maximum allowed voltage of SoC. */ -@@ -83,14 +84,14 @@ static int mtk_cpufreq_voltage_tracking( - do { - old_vsram = regulator_get_voltage(sram_reg); - if (old_vsram < 0) { -- pr_err("%s: invalid Vsram value: %d\n", -- __func__, old_vsram); -+ dev_err(info->cpu_dev, -+ "invalid Vsram value: %d\n", old_vsram); - return old_vsram; - } - old_vproc = regulator_get_voltage(proc_reg); - if (old_vproc < 0) { -- pr_err("%s: invalid Vproc value: %d\n", -- __func__, old_vproc); -+ dev_err(info->cpu_dev, -+ "invalid Vproc value: %d\n", old_vproc); - return old_vproc; - } - -@@ -138,14 +139,14 @@ static int mtk_cpufreq_voltage_tracking( - do { - old_vproc = regulator_get_voltage(proc_reg); - if (old_vproc < 0) { -- pr_err("%s: invalid Vproc value: %d\n", -- __func__, old_vproc); -+ dev_err(info->cpu_dev, -+ "invalid Vproc value: %d\n", old_vproc); - return old_vproc; - } - old_vsram = regulator_get_voltage(sram_reg); - if (old_vsram < 0) { -- pr_err("%s: invalid Vsram value: %d\n", -- __func__, old_vsram); -+ dev_err(info->cpu_dev, -+ "invalid Vsram value: %d\n", old_vsram); - return old_vsram; - } - -@@ -216,7 +217,7 @@ static int mtk_cpufreq_set_target(struct - old_freq_hz = clk_get_rate(cpu_clk); - old_vproc = regulator_get_voltage(info->proc_reg); - if (old_vproc < 0) { -- pr_err("%s: invalid Vproc value: %d\n", __func__, old_vproc); -+ dev_err(cpu_dev, "invalid Vproc value: %d\n", old_vproc); - return old_vproc; - } - -@@ -224,8 +225,8 @@ static int mtk_cpufreq_set_target(struct - - opp = dev_pm_opp_find_freq_ceil(cpu_dev, &freq_hz); - if (IS_ERR(opp)) { -- pr_err("cpu%d: failed to find OPP for %ld\n", -- policy->cpu, freq_hz); -+ dev_err(cpu_dev, "cpu%d: failed to find OPP for %ld\n", -+ policy->cpu, freq_hz); - return PTR_ERR(opp); - } - vproc = dev_pm_opp_get_voltage(opp); -@@ -239,8 +240,8 @@ static int mtk_cpufreq_set_target(struct - if (old_vproc < target_vproc) { - ret = mtk_cpufreq_set_voltage(info, target_vproc); - if (ret) { -- pr_err("cpu%d: failed to scale up voltage!\n", -- policy->cpu); -+ dev_err(cpu_dev, -+ "cpu%d: failed to scale up voltage!\n", policy->cpu); - mtk_cpufreq_set_voltage(info, old_vproc); - return ret; - } -@@ -249,8 +250,8 @@ static int mtk_cpufreq_set_target(struct - /* Reparent the CPU clock to intermediate clock. */ - ret = clk_set_parent(cpu_clk, info->inter_clk); - if (ret) { -- pr_err("cpu%d: failed to re-parent cpu clock!\n", -- policy->cpu); -+ dev_err(cpu_dev, -+ "cpu%d: failed to re-parent cpu clock!\n", policy->cpu); - mtk_cpufreq_set_voltage(info, old_vproc); - WARN_ON(1); - return ret; -@@ -259,8 +260,8 @@ static int mtk_cpufreq_set_target(struct - /* Set the original PLL to target rate. */ - ret = clk_set_rate(armpll, freq_hz); - if (ret) { -- pr_err("cpu%d: failed to scale cpu clock rate!\n", -- policy->cpu); -+ dev_err(cpu_dev, -+ "cpu%d: failed to scale cpu clock rate!\n", policy->cpu); - clk_set_parent(cpu_clk, armpll); - mtk_cpufreq_set_voltage(info, old_vproc); - return ret; -@@ -269,8 +270,8 @@ static int mtk_cpufreq_set_target(struct - /* Set parent of CPU clock back to the original PLL. */ - ret = clk_set_parent(cpu_clk, armpll); - if (ret) { -- pr_err("cpu%d: failed to re-parent cpu clock!\n", -- policy->cpu); -+ dev_err(cpu_dev, -+ "cpu%d: failed to re-parent cpu clock!\n", policy->cpu); - mtk_cpufreq_set_voltage(info, inter_vproc); - WARN_ON(1); - return ret; -@@ -283,8 +284,8 @@ static int mtk_cpufreq_set_target(struct - if (vproc < inter_vproc || vproc < old_vproc) { - ret = mtk_cpufreq_set_voltage(info, vproc); - if (ret) { -- pr_err("cpu%d: failed to scale down voltage!\n", -- policy->cpu); -+ dev_err(cpu_dev, -+ "cpu%d: failed to scale down voltage!\n", policy->cpu); - clk_set_parent(cpu_clk, info->inter_clk); - clk_set_rate(armpll, old_freq_hz); - clk_set_parent(cpu_clk, armpll); -@@ -450,15 +451,16 @@ static int mtk_cpufreq_init(struct cpufr - - info = mtk_cpu_dvfs_info_lookup(policy->cpu); - if (!info) { -- pr_err("dvfs info for cpu%d is not initialized.\n", -- policy->cpu); -+ dev_err(info->cpu_dev, -+ "dvfs info for cpu%d is not initialized.\n", policy->cpu); - return -EINVAL; - } - - ret = dev_pm_opp_init_cpufreq_table(info->cpu_dev, &freq_table); - if (ret) { -- pr_err("failed to init cpufreq table for cpu%d: %d\n", -- policy->cpu, ret); -+ dev_err(info->cpu_dev, -+ "failed to init cpufreq table for cpu%d: %d\n", -+ policy->cpu, ret); - return ret; - } - diff --git a/target/linux/mediatek/patches-5.15/350-05-cpufreq-mediatek-Replace-old_-with-pre_.patch b/target/linux/mediatek/patches-5.15/350-05-cpufreq-mediatek-Replace-old_-with-pre_.patch deleted file mode 100644 index 8506f4e47..000000000 --- a/target/linux/mediatek/patches-5.15/350-05-cpufreq-mediatek-Replace-old_-with-pre_.patch +++ /dev/null @@ -1,201 +0,0 @@ -From 35832d9f9c5c1da01420d962dc56e7e61d104829 Mon Sep 17 00:00:00 2001 -From: Rex-BC Chen -Date: Fri, 22 Apr 2022 15:52:28 +0800 -Subject: [PATCH 05/21] cpufreq: mediatek: Replace old_* with pre_* - -To make driver more readable, replace old_* with pre_*. - -Signed-off-by: Rex-BC Chen -Reviewed-by: AngeloGioacchino Del Regno -Signed-off-by: Viresh Kumar ---- - drivers/cpufreq/mediatek-cpufreq.c | 84 +++++++++++++++--------------- - 1 file changed, 42 insertions(+), 42 deletions(-) - ---- a/drivers/cpufreq/mediatek-cpufreq.c -+++ b/drivers/cpufreq/mediatek-cpufreq.c -@@ -63,18 +63,18 @@ static int mtk_cpufreq_voltage_tracking( - { - struct regulator *proc_reg = info->proc_reg; - struct regulator *sram_reg = info->sram_reg; -- int old_vproc, old_vsram, new_vsram, vsram, vproc, ret; -+ int pre_vproc, pre_vsram, new_vsram, vsram, vproc, ret; - -- old_vproc = regulator_get_voltage(proc_reg); -- if (old_vproc < 0) { -+ pre_vproc = regulator_get_voltage(proc_reg); -+ if (pre_vproc < 0) { - dev_err(info->cpu_dev, -- "invalid Vproc value: %d\n", old_vproc); -- return old_vproc; -+ "invalid Vproc value: %d\n", pre_vproc); -+ return pre_vproc; - } - /* Vsram should not exceed the maximum allowed voltage of SoC. */ - new_vsram = min(new_vproc + MIN_VOLT_SHIFT, MAX_VOLT_LIMIT); - -- if (old_vproc < new_vproc) { -+ if (pre_vproc < new_vproc) { - /* - * When scaling up voltages, Vsram and Vproc scale up step - * by step. At each step, set Vsram to (Vproc + 200mV) first, -@@ -82,20 +82,20 @@ static int mtk_cpufreq_voltage_tracking( - * Keep doing it until Vsram and Vproc hit target voltages. - */ - do { -- old_vsram = regulator_get_voltage(sram_reg); -- if (old_vsram < 0) { -+ pre_vsram = regulator_get_voltage(sram_reg); -+ if (pre_vsram < 0) { - dev_err(info->cpu_dev, -- "invalid Vsram value: %d\n", old_vsram); -- return old_vsram; -+ "invalid Vsram value: %d\n", pre_vsram); -+ return pre_vsram; - } -- old_vproc = regulator_get_voltage(proc_reg); -- if (old_vproc < 0) { -+ pre_vproc = regulator_get_voltage(proc_reg); -+ if (pre_vproc < 0) { - dev_err(info->cpu_dev, -- "invalid Vproc value: %d\n", old_vproc); -- return old_vproc; -+ "invalid Vproc value: %d\n", pre_vproc); -+ return pre_vproc; - } - -- vsram = min(new_vsram, old_vproc + MAX_VOLT_SHIFT); -+ vsram = min(new_vsram, pre_vproc + MAX_VOLT_SHIFT); - - if (vsram + VOLT_TOL >= MAX_VOLT_LIMIT) { - vsram = MAX_VOLT_LIMIT; -@@ -124,12 +124,12 @@ static int mtk_cpufreq_voltage_tracking( - ret = regulator_set_voltage(proc_reg, vproc, - vproc + VOLT_TOL); - if (ret) { -- regulator_set_voltage(sram_reg, old_vsram, -- old_vsram); -+ regulator_set_voltage(sram_reg, pre_vsram, -+ pre_vsram); - return ret; - } - } while (vproc < new_vproc || vsram < new_vsram); -- } else if (old_vproc > new_vproc) { -+ } else if (pre_vproc > new_vproc) { - /* - * When scaling down voltages, Vsram and Vproc scale down step - * by step. At each step, set Vproc to (Vsram - 200mV) first, -@@ -137,20 +137,20 @@ static int mtk_cpufreq_voltage_tracking( - * Keep doing it until Vsram and Vproc hit target voltages. - */ - do { -- old_vproc = regulator_get_voltage(proc_reg); -- if (old_vproc < 0) { -+ pre_vproc = regulator_get_voltage(proc_reg); -+ if (pre_vproc < 0) { - dev_err(info->cpu_dev, -- "invalid Vproc value: %d\n", old_vproc); -- return old_vproc; -+ "invalid Vproc value: %d\n", pre_vproc); -+ return pre_vproc; - } -- old_vsram = regulator_get_voltage(sram_reg); -- if (old_vsram < 0) { -+ pre_vsram = regulator_get_voltage(sram_reg); -+ if (pre_vsram < 0) { - dev_err(info->cpu_dev, -- "invalid Vsram value: %d\n", old_vsram); -- return old_vsram; -+ "invalid Vsram value: %d\n", pre_vsram); -+ return pre_vsram; - } - -- vproc = max(new_vproc, old_vsram - MAX_VOLT_SHIFT); -+ vproc = max(new_vproc, pre_vsram - MAX_VOLT_SHIFT); - ret = regulator_set_voltage(proc_reg, vproc, - vproc + VOLT_TOL); - if (ret) -@@ -180,8 +180,8 @@ static int mtk_cpufreq_voltage_tracking( - } - - if (ret) { -- regulator_set_voltage(proc_reg, old_vproc, -- old_vproc); -+ regulator_set_voltage(proc_reg, pre_vproc, -+ pre_vproc); - return ret; - } - } while (vproc > new_vproc + VOLT_TOL || -@@ -209,16 +209,16 @@ static int mtk_cpufreq_set_target(struct - struct mtk_cpu_dvfs_info *info = policy->driver_data; - struct device *cpu_dev = info->cpu_dev; - struct dev_pm_opp *opp; -- long freq_hz, old_freq_hz; -- int vproc, old_vproc, inter_vproc, target_vproc, ret; -+ long freq_hz, pre_freq_hz; -+ int vproc, pre_vproc, inter_vproc, target_vproc, ret; - - inter_vproc = info->intermediate_voltage; - -- old_freq_hz = clk_get_rate(cpu_clk); -- old_vproc = regulator_get_voltage(info->proc_reg); -- if (old_vproc < 0) { -- dev_err(cpu_dev, "invalid Vproc value: %d\n", old_vproc); -- return old_vproc; -+ pre_freq_hz = clk_get_rate(cpu_clk); -+ pre_vproc = regulator_get_voltage(info->proc_reg); -+ if (pre_vproc < 0) { -+ dev_err(cpu_dev, "invalid Vproc value: %d\n", pre_vproc); -+ return pre_vproc; - } - - freq_hz = freq_table[index].frequency * 1000; -@@ -237,12 +237,12 @@ static int mtk_cpufreq_set_target(struct - * current voltage, scale up voltage first. - */ - target_vproc = (inter_vproc > vproc) ? inter_vproc : vproc; -- if (old_vproc < target_vproc) { -+ if (pre_vproc < target_vproc) { - ret = mtk_cpufreq_set_voltage(info, target_vproc); - if (ret) { - dev_err(cpu_dev, - "cpu%d: failed to scale up voltage!\n", policy->cpu); -- mtk_cpufreq_set_voltage(info, old_vproc); -+ mtk_cpufreq_set_voltage(info, pre_vproc); - return ret; - } - } -@@ -252,7 +252,7 @@ static int mtk_cpufreq_set_target(struct - if (ret) { - dev_err(cpu_dev, - "cpu%d: failed to re-parent cpu clock!\n", policy->cpu); -- mtk_cpufreq_set_voltage(info, old_vproc); -+ mtk_cpufreq_set_voltage(info, pre_vproc); - WARN_ON(1); - return ret; - } -@@ -263,7 +263,7 @@ static int mtk_cpufreq_set_target(struct - dev_err(cpu_dev, - "cpu%d: failed to scale cpu clock rate!\n", policy->cpu); - clk_set_parent(cpu_clk, armpll); -- mtk_cpufreq_set_voltage(info, old_vproc); -+ mtk_cpufreq_set_voltage(info, pre_vproc); - return ret; - } - -@@ -281,13 +281,13 @@ static int mtk_cpufreq_set_target(struct - * If the new voltage is lower than the intermediate voltage or the - * original voltage, scale down to the new voltage. - */ -- if (vproc < inter_vproc || vproc < old_vproc) { -+ if (vproc < inter_vproc || vproc < pre_vproc) { - ret = mtk_cpufreq_set_voltage(info, vproc); - if (ret) { - dev_err(cpu_dev, - "cpu%d: failed to scale down voltage!\n", policy->cpu); - clk_set_parent(cpu_clk, info->inter_clk); -- clk_set_rate(armpll, old_freq_hz); -+ clk_set_rate(armpll, pre_freq_hz); - clk_set_parent(cpu_clk, armpll); - return ret; - } diff --git a/target/linux/mediatek/patches-5.15/350-06-cpufreq-mediatek-Record-previous-target-vproc-value.patch b/target/linux/mediatek/patches-5.15/350-06-cpufreq-mediatek-Record-previous-target-vproc-value.patch deleted file mode 100644 index 94e6617d2..000000000 --- a/target/linux/mediatek/patches-5.15/350-06-cpufreq-mediatek-Record-previous-target-vproc-value.patch +++ /dev/null @@ -1,64 +0,0 @@ -From 34737eb8d0daa0d4183f10286a2f55d8788066bc Mon Sep 17 00:00:00 2001 -From: Jia-Wei Chang -Date: Fri, 22 Apr 2022 15:52:29 +0800 -Subject: [PATCH 06/21] cpufreq: mediatek: Record previous target vproc value - -We found the buck voltage may not be exactly the same with what we set -because CPU may share the same buck with other module. -Therefore, we need to record the previous desired value instead of reading -it from regulators. - -Signed-off-by: Andrew-sh.Cheng -Signed-off-by: Jia-Wei Chang -Signed-off-by: Rex-BC Chen -Reviewed-by: AngeloGioacchino Del Regno -Signed-off-by: Viresh Kumar ---- - drivers/cpufreq/mediatek-cpufreq.c | 20 ++++++++++++++++---- - 1 file changed, 16 insertions(+), 4 deletions(-) - ---- a/drivers/cpufreq/mediatek-cpufreq.c -+++ b/drivers/cpufreq/mediatek-cpufreq.c -@@ -40,6 +40,7 @@ struct mtk_cpu_dvfs_info { - struct list_head list_head; - int intermediate_voltage; - bool need_voltage_tracking; -+ int pre_vproc; - }; - - static struct platform_device *cpufreq_pdev; -@@ -193,11 +194,17 @@ static int mtk_cpufreq_voltage_tracking( - - static int mtk_cpufreq_set_voltage(struct mtk_cpu_dvfs_info *info, int vproc) - { -+ int ret; -+ - if (info->need_voltage_tracking) -- return mtk_cpufreq_voltage_tracking(info, vproc); -+ ret = mtk_cpufreq_voltage_tracking(info, vproc); - else -- return regulator_set_voltage(info->proc_reg, vproc, -- vproc + VOLT_TOL); -+ ret = regulator_set_voltage(info->proc_reg, vproc, -+ MAX_VOLT_LIMIT); -+ if (!ret) -+ info->pre_vproc = vproc; -+ -+ return ret; - } - - static int mtk_cpufreq_set_target(struct cpufreq_policy *policy, -@@ -215,7 +222,12 @@ static int mtk_cpufreq_set_target(struct - inter_vproc = info->intermediate_voltage; - - pre_freq_hz = clk_get_rate(cpu_clk); -- pre_vproc = regulator_get_voltage(info->proc_reg); -+ -+ if (unlikely(info->pre_vproc <= 0)) -+ pre_vproc = regulator_get_voltage(info->proc_reg); -+ else -+ pre_vproc = info->pre_vproc; -+ - if (pre_vproc < 0) { - dev_err(cpu_dev, "invalid Vproc value: %d\n", pre_vproc); - return pre_vproc; diff --git a/target/linux/mediatek/patches-5.15/350-07-cpufreq-mediatek-Make-sram-regulator-optional.patch b/target/linux/mediatek/patches-5.15/350-07-cpufreq-mediatek-Make-sram-regulator-optional.patch deleted file mode 100644 index 4b74873b1..000000000 --- a/target/linux/mediatek/patches-5.15/350-07-cpufreq-mediatek-Make-sram-regulator-optional.patch +++ /dev/null @@ -1,30 +0,0 @@ -From f6114c2bc563a8050e9dc874ad87e1448865f031 Mon Sep 17 00:00:00 2001 -From: Jia-Wei Chang -Date: Fri, 22 Apr 2022 15:52:33 +0800 -Subject: [PATCH 07/21] cpufreq: mediatek: Make sram regulator optional - -For some MediaTek SoCs, like MT8186, it's possible that the sram regulator -is shared between CPU and CCI. -We hope regulator framework can return error for error handling rather -than a dummy handler from regulator_get api. -Therefore, we choose to use regulator_get_optional. - -Signed-off-by: Jia-Wei Chang -Signed-off-by: Rex-BC Chen -Reviewed-by: AngeloGioacchino Del Regno -Signed-off-by: Viresh Kumar ---- - drivers/cpufreq/mediatek-cpufreq.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/cpufreq/mediatek-cpufreq.c -+++ b/drivers/cpufreq/mediatek-cpufreq.c -@@ -354,7 +354,7 @@ static int mtk_cpu_dvfs_info_init(struct - } - - /* Both presence and absence of sram regulator are valid cases. */ -- info->sram_reg = regulator_get_exclusive(cpu_dev, "sram"); -+ info->sram_reg = regulator_get_optional(cpu_dev, "sram"); - if (IS_ERR(info->sram_reg)) - info->sram_reg = NULL; - else { diff --git a/target/linux/mediatek/patches-5.15/350-08-cpufreq-mediatek-Fix-NULL-pointer-dereference-in-med.patch b/target/linux/mediatek/patches-5.15/350-08-cpufreq-mediatek-Fix-NULL-pointer-dereference-in-med.patch deleted file mode 100644 index f2f572a75..000000000 --- a/target/linux/mediatek/patches-5.15/350-08-cpufreq-mediatek-Fix-NULL-pointer-dereference-in-med.patch +++ /dev/null @@ -1,32 +0,0 @@ -From fa7030d8ad4638acfd9e0fac84a20716d031dc95 Mon Sep 17 00:00:00 2001 -From: Wan Jiabing -Date: Tue, 26 Apr 2022 19:17:14 +0800 -Subject: [PATCH 08/21] cpufreq: mediatek: Fix NULL pointer dereference in - mediatek-cpufreq - -Fix following coccicheck error: -drivers/cpufreq/mediatek-cpufreq.c:464:16-23: ERROR: info is NULL but dereferenced. - -Use pr_err instead of dev_err to avoid dereferring a NULL pointer. - -Fixes: f52b16ba9fe4 ("cpufreq: mediatek: Use device print to show logs") -Signed-off-by: Wan Jiabing -Reviewed-by: Matthias Brugger -Signed-off-by: Viresh Kumar ---- - drivers/cpufreq/mediatek-cpufreq.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/drivers/cpufreq/mediatek-cpufreq.c -+++ b/drivers/cpufreq/mediatek-cpufreq.c -@@ -463,8 +463,8 @@ static int mtk_cpufreq_init(struct cpufr - - info = mtk_cpu_dvfs_info_lookup(policy->cpu); - if (!info) { -- dev_err(info->cpu_dev, -- "dvfs info for cpu%d is not initialized.\n", policy->cpu); -+ pr_err("dvfs info for cpu%d is not initialized.\n", -+ policy->cpu); - return -EINVAL; - } - diff --git a/target/linux/mediatek/patches-5.15/350-09-cpufreq-mediatek-Move-voltage-limits-to-platform-dat.patch b/target/linux/mediatek/patches-5.15/350-09-cpufreq-mediatek-Move-voltage-limits-to-platform-dat.patch deleted file mode 100644 index 23b319648..000000000 --- a/target/linux/mediatek/patches-5.15/350-09-cpufreq-mediatek-Move-voltage-limits-to-platform-dat.patch +++ /dev/null @@ -1,227 +0,0 @@ -From be2354b064e6bafbbad599ae2e10569ba4f7d5a6 Mon Sep 17 00:00:00 2001 -From: Rex-BC Chen -Date: Thu, 5 May 2022 19:52:19 +0800 -Subject: [PATCH 09/21] cpufreq: mediatek: Move voltage limits to platform data - -Voltages and shifts are defined as macros originally. -There are different requirements of these values for each MediaTek SoCs. -Therefore, we add the platform data and move these values into it. - -Signed-off-by: Jia-Wei Chang -Signed-off-by: Rex-BC Chen -Reviewed-by: AngeloGioacchino Del Regno -Signed-off-by: Viresh Kumar ---- - drivers/cpufreq/mediatek-cpufreq.c | 84 +++++++++++++++++++++--------- - 1 file changed, 58 insertions(+), 26 deletions(-) - ---- a/drivers/cpufreq/mediatek-cpufreq.c -+++ b/drivers/cpufreq/mediatek-cpufreq.c -@@ -10,15 +10,21 @@ - #include - #include - #include -+#include - #include - #include - #include - --#define MIN_VOLT_SHIFT (100000) --#define MAX_VOLT_SHIFT (200000) --#define MAX_VOLT_LIMIT (1150000) - #define VOLT_TOL (10000) - -+struct mtk_cpufreq_platform_data { -+ int min_volt_shift; -+ int max_volt_shift; -+ int proc_max_volt; -+ int sram_min_volt; -+ int sram_max_volt; -+}; -+ - /* - * The struct mtk_cpu_dvfs_info holds necessary information for doing CPU DVFS - * on each CPU power/clock domain of Mediatek SoCs. Each CPU cluster in -@@ -41,6 +47,7 @@ struct mtk_cpu_dvfs_info { - int intermediate_voltage; - bool need_voltage_tracking; - int pre_vproc; -+ const struct mtk_cpufreq_platform_data *soc_data; - }; - - static struct platform_device *cpufreq_pdev; -@@ -62,6 +69,7 @@ static struct mtk_cpu_dvfs_info *mtk_cpu - static int mtk_cpufreq_voltage_tracking(struct mtk_cpu_dvfs_info *info, - int new_vproc) - { -+ const struct mtk_cpufreq_platform_data *soc_data = info->soc_data; - struct regulator *proc_reg = info->proc_reg; - struct regulator *sram_reg = info->sram_reg; - int pre_vproc, pre_vsram, new_vsram, vsram, vproc, ret; -@@ -73,7 +81,8 @@ static int mtk_cpufreq_voltage_tracking( - return pre_vproc; - } - /* Vsram should not exceed the maximum allowed voltage of SoC. */ -- new_vsram = min(new_vproc + MIN_VOLT_SHIFT, MAX_VOLT_LIMIT); -+ new_vsram = min(new_vproc + soc_data->min_volt_shift, -+ soc_data->sram_max_volt); - - if (pre_vproc < new_vproc) { - /* -@@ -96,10 +105,11 @@ static int mtk_cpufreq_voltage_tracking( - return pre_vproc; - } - -- vsram = min(new_vsram, pre_vproc + MAX_VOLT_SHIFT); -+ vsram = min(new_vsram, -+ pre_vproc + soc_data->min_volt_shift); - -- if (vsram + VOLT_TOL >= MAX_VOLT_LIMIT) { -- vsram = MAX_VOLT_LIMIT; -+ if (vsram + VOLT_TOL >= soc_data->sram_max_volt) { -+ vsram = soc_data->sram_max_volt; - - /* - * If the target Vsram hits the maximum voltage, -@@ -117,7 +127,7 @@ static int mtk_cpufreq_voltage_tracking( - ret = regulator_set_voltage(sram_reg, vsram, - vsram + VOLT_TOL); - -- vproc = vsram - MIN_VOLT_SHIFT; -+ vproc = vsram - soc_data->min_volt_shift; - } - if (ret) - return ret; -@@ -151,7 +161,8 @@ static int mtk_cpufreq_voltage_tracking( - return pre_vsram; - } - -- vproc = max(new_vproc, pre_vsram - MAX_VOLT_SHIFT); -+ vproc = max(new_vproc, -+ pre_vsram - soc_data->max_volt_shift); - ret = regulator_set_voltage(proc_reg, vproc, - vproc + VOLT_TOL); - if (ret) -@@ -160,10 +171,11 @@ static int mtk_cpufreq_voltage_tracking( - if (vproc == new_vproc) - vsram = new_vsram; - else -- vsram = max(new_vsram, vproc + MIN_VOLT_SHIFT); -+ vsram = max(new_vsram, -+ vproc + soc_data->min_volt_shift); - -- if (vsram + VOLT_TOL >= MAX_VOLT_LIMIT) { -- vsram = MAX_VOLT_LIMIT; -+ if (vsram + VOLT_TOL >= soc_data->sram_max_volt) { -+ vsram = soc_data->sram_max_volt; - - /* - * If the target Vsram hits the maximum voltage, -@@ -194,13 +206,14 @@ static int mtk_cpufreq_voltage_tracking( - - static int mtk_cpufreq_set_voltage(struct mtk_cpu_dvfs_info *info, int vproc) - { -+ const struct mtk_cpufreq_platform_data *soc_data = info->soc_data; - int ret; - - if (info->need_voltage_tracking) - ret = mtk_cpufreq_voltage_tracking(info, vproc); - else - ret = regulator_set_voltage(info->proc_reg, vproc, -- MAX_VOLT_LIMIT); -+ soc_data->proc_max_volt); - if (!ret) - info->pre_vproc = vproc; - -@@ -509,9 +522,17 @@ static struct cpufreq_driver mtk_cpufreq - - static int mtk_cpufreq_probe(struct platform_device *pdev) - { -+ const struct mtk_cpufreq_platform_data *data; - struct mtk_cpu_dvfs_info *info, *tmp; - int cpu, ret; - -+ data = dev_get_platdata(&pdev->dev); -+ if (!data) { -+ dev_err(&pdev->dev, -+ "failed to get mtk cpufreq platform data\n"); -+ return -ENODEV; -+ } -+ - for_each_possible_cpu(cpu) { - info = mtk_cpu_dvfs_info_lookup(cpu); - if (info) -@@ -523,6 +544,7 @@ static int mtk_cpufreq_probe(struct plat - goto release_dvfs_info_list; - } - -+ info->soc_data = data; - ret = mtk_cpu_dvfs_info_init(info, cpu); - if (ret) { - dev_err(&pdev->dev, -@@ -558,20 +580,27 @@ static struct platform_driver mtk_cpufre - .probe = mtk_cpufreq_probe, - }; - -+static const struct mtk_cpufreq_platform_data mt2701_platform_data = { -+ .min_volt_shift = 100000, -+ .max_volt_shift = 200000, -+ .proc_max_volt = 1150000, -+ .sram_min_volt = 0, -+ .sram_max_volt = 1150000, -+}; -+ - /* List of machines supported by this driver */ - static const struct of_device_id mtk_cpufreq_machines[] __initconst = { -- { .compatible = "mediatek,mt2701", }, -- { .compatible = "mediatek,mt2712", }, -- { .compatible = "mediatek,mt7622", }, -- { .compatible = "mediatek,mt7623", }, -- { .compatible = "mediatek,mt8167", }, -- { .compatible = "mediatek,mt817x", }, -- { .compatible = "mediatek,mt8173", }, -- { .compatible = "mediatek,mt8176", }, -- { .compatible = "mediatek,mt8183", }, -- { .compatible = "mediatek,mt8365", }, -- { .compatible = "mediatek,mt8516", }, -- -+ { .compatible = "mediatek,mt2701", .data = &mt2701_platform_data }, -+ { .compatible = "mediatek,mt2712", .data = &mt2701_platform_data }, -+ { .compatible = "mediatek,mt7622", .data = &mt2701_platform_data }, -+ { .compatible = "mediatek,mt7623", .data = &mt2701_platform_data }, -+ { .compatible = "mediatek,mt8167", .data = &mt2701_platform_data }, -+ { .compatible = "mediatek,mt817x", .data = &mt2701_platform_data }, -+ { .compatible = "mediatek,mt8173", .data = &mt2701_platform_data }, -+ { .compatible = "mediatek,mt8176", .data = &mt2701_platform_data }, -+ { .compatible = "mediatek,mt8183", .data = &mt2701_platform_data }, -+ { .compatible = "mediatek,mt8365", .data = &mt2701_platform_data }, -+ { .compatible = "mediatek,mt8516", .data = &mt2701_platform_data }, - { } - }; - MODULE_DEVICE_TABLE(of, mtk_cpufreq_machines); -@@ -580,6 +609,7 @@ static int __init mtk_cpufreq_driver_ini - { - struct device_node *np; - const struct of_device_id *match; -+ const struct mtk_cpufreq_platform_data *data; - int err; - - np = of_find_node_by_path("/"); -@@ -592,6 +622,7 @@ static int __init mtk_cpufreq_driver_ini - pr_debug("Machine is not compatible with mtk-cpufreq\n"); - return -ENODEV; - } -+ data = match->data; - - err = platform_driver_register(&mtk_cpufreq_platdrv); - if (err) -@@ -603,7 +634,8 @@ static int __init mtk_cpufreq_driver_ini - * and the device registration codes are put here to handle defer - * probing. - */ -- cpufreq_pdev = platform_device_register_simple("mtk-cpufreq", -1, NULL, 0); -+ cpufreq_pdev = platform_device_register_data(NULL, "mtk-cpufreq", -1, -+ data, sizeof(*data)); - if (IS_ERR(cpufreq_pdev)) { - pr_err("failed to register mtk-cpufreq platform device\n"); - platform_driver_unregister(&mtk_cpufreq_platdrv); diff --git a/target/linux/mediatek/patches-5.15/350-10-cpufreq-mediatek-Refine-mtk_cpufreq_voltage_tracking.patch b/target/linux/mediatek/patches-5.15/350-10-cpufreq-mediatek-Refine-mtk_cpufreq_voltage_tracking.patch deleted file mode 100644 index 0ba9471ff..000000000 --- a/target/linux/mediatek/patches-5.15/350-10-cpufreq-mediatek-Refine-mtk_cpufreq_voltage_tracking.patch +++ /dev/null @@ -1,255 +0,0 @@ -From 944b041c91f1e1cd762c39c1222f078550149486 Mon Sep 17 00:00:00 2001 -From: Jia-Wei Chang -Date: Thu, 5 May 2022 19:52:20 +0800 -Subject: [PATCH 10/21] cpufreq: mediatek: Refine - mtk_cpufreq_voltage_tracking() - -Because the difference of sram and proc should in a range of min_volt_shift -and max_volt_shift. We need to adjust the sram and proc step by step. - -We replace VOLT_TOL (voltage tolerance) with the platform data and update the -logic to determine the voltage boundary and invoking regulator_set_voltage. - -- Use 'sram_min_volt' and 'sram_max_volt' to determine the voltage boundary - of sram regulator. -- Use (sram_min_volt - min_volt_shift) and 'proc_max_volt' to determine the - voltage boundary of vproc regulator. - -Moreover, to prevent infinite loop when tracking voltage, we calculate the -maximum value for each platform data. -We assume min voltage is 0 and tracking target voltage using -min_volt_shift for each iteration. -The retry_max is 3 times of expeted iteration count. - -Signed-off-by: Jia-Wei Chang -Signed-off-by: Rex-BC Chen -Reviewed-by: AngeloGioacchino Del Regno -Signed-off-by: Viresh Kumar ---- - drivers/cpufreq/mediatek-cpufreq.c | 147 ++++++++++------------------- - 1 file changed, 51 insertions(+), 96 deletions(-) - ---- a/drivers/cpufreq/mediatek-cpufreq.c -+++ b/drivers/cpufreq/mediatek-cpufreq.c -@@ -8,6 +8,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -15,8 +16,6 @@ - #include - #include - --#define VOLT_TOL (10000) -- - struct mtk_cpufreq_platform_data { - int min_volt_shift; - int max_volt_shift; -@@ -48,6 +47,7 @@ struct mtk_cpu_dvfs_info { - bool need_voltage_tracking; - int pre_vproc; - const struct mtk_cpufreq_platform_data *soc_data; -+ int vtrack_max; - }; - - static struct platform_device *cpufreq_pdev; -@@ -73,6 +73,7 @@ static int mtk_cpufreq_voltage_tracking( - struct regulator *proc_reg = info->proc_reg; - struct regulator *sram_reg = info->sram_reg; - int pre_vproc, pre_vsram, new_vsram, vsram, vproc, ret; -+ int retry = info->vtrack_max; - - pre_vproc = regulator_get_voltage(proc_reg); - if (pre_vproc < 0) { -@@ -80,91 +81,44 @@ static int mtk_cpufreq_voltage_tracking( - "invalid Vproc value: %d\n", pre_vproc); - return pre_vproc; - } -- /* Vsram should not exceed the maximum allowed voltage of SoC. */ -- new_vsram = min(new_vproc + soc_data->min_volt_shift, -- soc_data->sram_max_volt); -- -- if (pre_vproc < new_vproc) { -- /* -- * When scaling up voltages, Vsram and Vproc scale up step -- * by step. At each step, set Vsram to (Vproc + 200mV) first, -- * then set Vproc to (Vsram - 100mV). -- * Keep doing it until Vsram and Vproc hit target voltages. -- */ -- do { -- pre_vsram = regulator_get_voltage(sram_reg); -- if (pre_vsram < 0) { -- dev_err(info->cpu_dev, -- "invalid Vsram value: %d\n", pre_vsram); -- return pre_vsram; -- } -- pre_vproc = regulator_get_voltage(proc_reg); -- if (pre_vproc < 0) { -- dev_err(info->cpu_dev, -- "invalid Vproc value: %d\n", pre_vproc); -- return pre_vproc; -- } - -- vsram = min(new_vsram, -- pre_vproc + soc_data->min_volt_shift); -+ pre_vsram = regulator_get_voltage(sram_reg); -+ if (pre_vsram < 0) { -+ dev_err(info->cpu_dev, "invalid Vsram value: %d\n", pre_vsram); -+ return pre_vsram; -+ } - -- if (vsram + VOLT_TOL >= soc_data->sram_max_volt) { -- vsram = soc_data->sram_max_volt; -+ new_vsram = clamp(new_vproc + soc_data->min_volt_shift, -+ soc_data->sram_min_volt, soc_data->sram_max_volt); -+ -+ do { -+ if (pre_vproc <= new_vproc) { -+ vsram = clamp(pre_vproc + soc_data->max_volt_shift, -+ soc_data->sram_min_volt, new_vsram); -+ ret = regulator_set_voltage(sram_reg, vsram, -+ soc_data->sram_max_volt); - -- /* -- * If the target Vsram hits the maximum voltage, -- * try to set the exact voltage value first. -- */ -- ret = regulator_set_voltage(sram_reg, vsram, -- vsram); -- if (ret) -- ret = regulator_set_voltage(sram_reg, -- vsram - VOLT_TOL, -- vsram); -+ if (ret) -+ return ret; - -+ if (vsram == soc_data->sram_max_volt || -+ new_vsram == soc_data->sram_min_volt) - vproc = new_vproc; -- } else { -- ret = regulator_set_voltage(sram_reg, vsram, -- vsram + VOLT_TOL); -- -+ else - vproc = vsram - soc_data->min_volt_shift; -- } -- if (ret) -- return ret; - - ret = regulator_set_voltage(proc_reg, vproc, -- vproc + VOLT_TOL); -+ soc_data->proc_max_volt); - if (ret) { - regulator_set_voltage(sram_reg, pre_vsram, -- pre_vsram); -+ soc_data->sram_max_volt); - return ret; - } -- } while (vproc < new_vproc || vsram < new_vsram); -- } else if (pre_vproc > new_vproc) { -- /* -- * When scaling down voltages, Vsram and Vproc scale down step -- * by step. At each step, set Vproc to (Vsram - 200mV) first, -- * then set Vproc to (Vproc + 100mV). -- * Keep doing it until Vsram and Vproc hit target voltages. -- */ -- do { -- pre_vproc = regulator_get_voltage(proc_reg); -- if (pre_vproc < 0) { -- dev_err(info->cpu_dev, -- "invalid Vproc value: %d\n", pre_vproc); -- return pre_vproc; -- } -- pre_vsram = regulator_get_voltage(sram_reg); -- if (pre_vsram < 0) { -- dev_err(info->cpu_dev, -- "invalid Vsram value: %d\n", pre_vsram); -- return pre_vsram; -- } -- -+ } else if (pre_vproc > new_vproc) { - vproc = max(new_vproc, - pre_vsram - soc_data->max_volt_shift); - ret = regulator_set_voltage(proc_reg, vproc, -- vproc + VOLT_TOL); -+ soc_data->proc_max_volt); - if (ret) - return ret; - -@@ -174,32 +128,24 @@ static int mtk_cpufreq_voltage_tracking( - vsram = max(new_vsram, - vproc + soc_data->min_volt_shift); - -- if (vsram + VOLT_TOL >= soc_data->sram_max_volt) { -- vsram = soc_data->sram_max_volt; -- -- /* -- * If the target Vsram hits the maximum voltage, -- * try to set the exact voltage value first. -- */ -- ret = regulator_set_voltage(sram_reg, vsram, -- vsram); -- if (ret) -- ret = regulator_set_voltage(sram_reg, -- vsram - VOLT_TOL, -- vsram); -- } else { -- ret = regulator_set_voltage(sram_reg, vsram, -- vsram + VOLT_TOL); -- } -- -+ ret = regulator_set_voltage(sram_reg, vsram, -+ soc_data->sram_max_volt); - if (ret) { - regulator_set_voltage(proc_reg, pre_vproc, -- pre_vproc); -+ soc_data->proc_max_volt); - return ret; - } -- } while (vproc > new_vproc + VOLT_TOL || -- vsram > new_vsram + VOLT_TOL); -- } -+ } -+ -+ pre_vproc = vproc; -+ pre_vsram = vsram; -+ -+ if (--retry < 0) { -+ dev_err(info->cpu_dev, -+ "over loop count, failed to set voltage\n"); -+ return -EINVAL; -+ } -+ } while (vproc != new_vproc || vsram != new_vsram); - - return 0; - } -@@ -261,8 +207,8 @@ static int mtk_cpufreq_set_target(struct - * If the new voltage or the intermediate voltage is higher than the - * current voltage, scale up voltage first. - */ -- target_vproc = (inter_vproc > vproc) ? inter_vproc : vproc; -- if (pre_vproc < target_vproc) { -+ target_vproc = max(inter_vproc, vproc); -+ if (pre_vproc <= target_vproc) { - ret = mtk_cpufreq_set_voltage(info, target_vproc); - if (ret) { - dev_err(cpu_dev, -@@ -417,6 +363,15 @@ static int mtk_cpu_dvfs_info_init(struct - */ - info->need_voltage_tracking = (info->sram_reg != NULL); - -+ /* -+ * We assume min voltage is 0 and tracking target voltage using -+ * min_volt_shift for each iteration. -+ * The vtrack_max is 3 times of expeted iteration count. -+ */ -+ info->vtrack_max = 3 * DIV_ROUND_UP(max(info->soc_data->sram_max_volt, -+ info->soc_data->proc_max_volt), -+ info->soc_data->min_volt_shift); -+ - return 0; - - out_disable_inter_clock: diff --git a/target/linux/mediatek/patches-5.15/350-11-cpufreq-mediatek-Add-opp-notification-support.patch b/target/linux/mediatek/patches-5.15/350-11-cpufreq-mediatek-Add-opp-notification-support.patch deleted file mode 100644 index 2cb99b907..000000000 --- a/target/linux/mediatek/patches-5.15/350-11-cpufreq-mediatek-Add-opp-notification-support.patch +++ /dev/null @@ -1,184 +0,0 @@ -From 01be227eff7e5fc01f7c8de8f6daddd5fb17ddd1 Mon Sep 17 00:00:00 2001 -From: Rex-BC Chen -Date: Thu, 5 May 2022 19:52:21 +0800 -Subject: [PATCH 11/21] cpufreq: mediatek: Add opp notification support - -From this opp notifier, cpufreq should listen to opp notification and do -proper actions when receiving events of disable and voltage adjustment. - -One of the user for this opp notifier is MediaTek SVS. -The MediaTek Smart Voltage Scaling (SVS) is a hardware which calculates -suitable SVS bank voltages to OPP voltage table. - -Signed-off-by: Andrew-sh.Cheng -Signed-off-by: Jia-Wei Chang -Signed-off-by: Rex-BC Chen -Reviewed-by: AngeloGioacchino Del Regno -[ Viresh: Renamed opp_freq as current_freq and moved its initialization ] -Signed-off-by: Viresh Kumar ---- - drivers/cpufreq/mediatek-cpufreq.c | 90 +++++++++++++++++++++++++++--- - 1 file changed, 82 insertions(+), 8 deletions(-) - ---- a/drivers/cpufreq/mediatek-cpufreq.c -+++ b/drivers/cpufreq/mediatek-cpufreq.c -@@ -46,6 +46,11 @@ struct mtk_cpu_dvfs_info { - int intermediate_voltage; - bool need_voltage_tracking; - int pre_vproc; -+ /* Avoid race condition for regulators between notify and policy */ -+ struct mutex reg_lock; -+ struct notifier_block opp_nb; -+ unsigned int opp_cpu; -+ unsigned long current_freq; - const struct mtk_cpufreq_platform_data *soc_data; - int vtrack_max; - }; -@@ -182,6 +187,8 @@ static int mtk_cpufreq_set_target(struct - - pre_freq_hz = clk_get_rate(cpu_clk); - -+ mutex_lock(&info->reg_lock); -+ - if (unlikely(info->pre_vproc <= 0)) - pre_vproc = regulator_get_voltage(info->proc_reg); - else -@@ -214,7 +221,7 @@ static int mtk_cpufreq_set_target(struct - dev_err(cpu_dev, - "cpu%d: failed to scale up voltage!\n", policy->cpu); - mtk_cpufreq_set_voltage(info, pre_vproc); -- return ret; -+ goto out; - } - } - -@@ -224,8 +231,7 @@ static int mtk_cpufreq_set_target(struct - dev_err(cpu_dev, - "cpu%d: failed to re-parent cpu clock!\n", policy->cpu); - mtk_cpufreq_set_voltage(info, pre_vproc); -- WARN_ON(1); -- return ret; -+ goto out; - } - - /* Set the original PLL to target rate. */ -@@ -235,7 +241,7 @@ static int mtk_cpufreq_set_target(struct - "cpu%d: failed to scale cpu clock rate!\n", policy->cpu); - clk_set_parent(cpu_clk, armpll); - mtk_cpufreq_set_voltage(info, pre_vproc); -- return ret; -+ goto out; - } - - /* Set parent of CPU clock back to the original PLL. */ -@@ -244,8 +250,7 @@ static int mtk_cpufreq_set_target(struct - dev_err(cpu_dev, - "cpu%d: failed to re-parent cpu clock!\n", policy->cpu); - mtk_cpufreq_set_voltage(info, inter_vproc); -- WARN_ON(1); -- return ret; -+ goto out; - } - - /* -@@ -260,15 +265,72 @@ static int mtk_cpufreq_set_target(struct - clk_set_parent(cpu_clk, info->inter_clk); - clk_set_rate(armpll, pre_freq_hz); - clk_set_parent(cpu_clk, armpll); -- return ret; -+ goto out; - } - } - -- return 0; -+ info->current_freq = freq_hz; -+ -+out: -+ mutex_unlock(&info->reg_lock); -+ -+ return ret; - } - - #define DYNAMIC_POWER "dynamic-power-coefficient" - -+static int mtk_cpufreq_opp_notifier(struct notifier_block *nb, -+ unsigned long event, void *data) -+{ -+ struct dev_pm_opp *opp = data; -+ struct dev_pm_opp *new_opp; -+ struct mtk_cpu_dvfs_info *info; -+ unsigned long freq, volt; -+ struct cpufreq_policy *policy; -+ int ret = 0; -+ -+ info = container_of(nb, struct mtk_cpu_dvfs_info, opp_nb); -+ -+ if (event == OPP_EVENT_ADJUST_VOLTAGE) { -+ freq = dev_pm_opp_get_freq(opp); -+ -+ mutex_lock(&info->reg_lock); -+ if (info->current_freq == freq) { -+ volt = dev_pm_opp_get_voltage(opp); -+ ret = mtk_cpufreq_set_voltage(info, volt); -+ if (ret) -+ dev_err(info->cpu_dev, -+ "failed to scale voltage: %d\n", ret); -+ } -+ mutex_unlock(&info->reg_lock); -+ } else if (event == OPP_EVENT_DISABLE) { -+ freq = dev_pm_opp_get_freq(opp); -+ -+ /* case of current opp item is disabled */ -+ if (info->current_freq == freq) { -+ freq = 1; -+ new_opp = dev_pm_opp_find_freq_ceil(info->cpu_dev, -+ &freq); -+ if (IS_ERR(new_opp)) { -+ dev_err(info->cpu_dev, -+ "all opp items are disabled\n"); -+ ret = PTR_ERR(new_opp); -+ return notifier_from_errno(ret); -+ } -+ -+ dev_pm_opp_put(new_opp); -+ policy = cpufreq_cpu_get(info->opp_cpu); -+ if (policy) { -+ cpufreq_driver_target(policy, freq / 1000, -+ CPUFREQ_RELATION_L); -+ cpufreq_cpu_put(policy); -+ } -+ } -+ } -+ -+ return notifier_from_errno(ret); -+} -+ - static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu) - { - struct device *cpu_dev; -@@ -357,6 +419,17 @@ static int mtk_cpu_dvfs_info_init(struct - info->intermediate_voltage = dev_pm_opp_get_voltage(opp); - dev_pm_opp_put(opp); - -+ mutex_init(&info->reg_lock); -+ info->current_freq = clk_get_rate(info->cpu_clk); -+ -+ info->opp_cpu = cpu; -+ info->opp_nb.notifier_call = mtk_cpufreq_opp_notifier; -+ ret = dev_pm_opp_register_notifier(cpu_dev, &info->opp_nb); -+ if (ret) { -+ dev_err(cpu_dev, "cpu%d: failed to register opp notifier\n", cpu); -+ goto out_disable_inter_clock; -+ } -+ - /* - * If SRAM regulator is present, software "voltage tracking" is needed - * for this CPU power domain. -@@ -421,6 +494,7 @@ static void mtk_cpu_dvfs_info_release(st - } - - dev_pm_opp_of_cpumask_remove_table(&info->cpus); -+ dev_pm_opp_unregister_notifier(info->cpu_dev, &info->opp_nb); - } - - static int mtk_cpufreq_init(struct cpufreq_policy *policy) diff --git a/target/linux/mediatek/patches-5.15/350-12-cpufreq-mediatek-Fix-potential-deadlock-problem-in-m.patch b/target/linux/mediatek/patches-5.15/350-12-cpufreq-mediatek-Fix-potential-deadlock-problem-in-m.patch deleted file mode 100644 index 76bd795c0..000000000 --- a/target/linux/mediatek/patches-5.15/350-12-cpufreq-mediatek-Fix-potential-deadlock-problem-in-m.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 6a1bd7cf4ed7a1948f564aaf16d34b7352c0029b Mon Sep 17 00:00:00 2001 -From: Wan Jiabing -Date: Tue, 10 May 2022 17:05:31 +0800 -Subject: [PATCH 12/21] cpufreq: mediatek: Fix potential deadlock problem in - mtk_cpufreq_set_target - -Fix following coccichek error: -./drivers/cpufreq/mediatek-cpufreq.c:199:2-8: preceding lock on line -./drivers/cpufreq/mediatek-cpufreq.c:208:2-8: preceding lock on line - -mutex_lock is acquired but not released before return. -Use 'goto out' to help releasing the mutex_lock. - -Fixes: c210063b40ac ("cpufreq: mediatek: Add opp notification support") -Signed-off-by: Wan Jiabing -Reviewed-by: Rex-BC Chen -Signed-off-by: Viresh Kumar ---- - drivers/cpufreq/mediatek-cpufreq.c | 6 ++++-- - 1 file changed, 4 insertions(+), 2 deletions(-) - ---- a/drivers/cpufreq/mediatek-cpufreq.c -+++ b/drivers/cpufreq/mediatek-cpufreq.c -@@ -196,7 +196,8 @@ static int mtk_cpufreq_set_target(struct - - if (pre_vproc < 0) { - dev_err(cpu_dev, "invalid Vproc value: %d\n", pre_vproc); -- return pre_vproc; -+ ret = pre_vproc; -+ goto out; - } - - freq_hz = freq_table[index].frequency * 1000; -@@ -205,7 +206,8 @@ static int mtk_cpufreq_set_target(struct - if (IS_ERR(opp)) { - dev_err(cpu_dev, "cpu%d: failed to find OPP for %ld\n", - policy->cpu, freq_hz); -- return PTR_ERR(opp); -+ ret = PTR_ERR(opp); -+ goto out; - } - vproc = dev_pm_opp_get_voltage(opp); - dev_pm_opp_put(opp); diff --git a/target/linux/mediatek/patches-5.15/350-13-cpufreq-mediatek-Link-CCI-device-to-CPU.patch b/target/linux/mediatek/patches-5.15/350-13-cpufreq-mediatek-Link-CCI-device-to-CPU.patch deleted file mode 100644 index eeaa466c3..000000000 --- a/target/linux/mediatek/patches-5.15/350-13-cpufreq-mediatek-Link-CCI-device-to-CPU.patch +++ /dev/null @@ -1,188 +0,0 @@ -From 15aaf74fb734a3e69b10d00b97b322711b81e222 Mon Sep 17 00:00:00 2001 -From: Rex-BC Chen -Date: Thu, 5 May 2022 19:52:22 +0800 -Subject: [PATCH 13/21] cpufreq: mediatek: Link CCI device to CPU - -In some MediaTek SoCs, like MT8183, CPU and CCI share the same power -supplies. Cpufreq needs to check if CCI devfreq exists and wait until -CCI devfreq ready before scaling frequency. - -Before CCI devfreq is ready, we record the voltage when booting to -kernel and use the max(cpu target voltage, booting voltage) to -prevent cpufreq adjust to the lower voltage which will cause the CCI -crash because of high frequency and low voltage. - -- Add is_ccifreq_ready() to link CCI device to CPI, and CPU will start - DVFS when CCI is ready. -- Add platform data for MT8183. - -Signed-off-by: Jia-Wei Chang -Signed-off-by: Rex-BC Chen -Reviewed-by: AngeloGioacchino Del Regno -Reviewed-by: Kevin Hilman -Signed-off-by: Viresh Kumar ---- - drivers/cpufreq/mediatek-cpufreq.c | 82 +++++++++++++++++++++++++++++- - 1 file changed, 81 insertions(+), 1 deletion(-) - ---- a/drivers/cpufreq/mediatek-cpufreq.c -+++ b/drivers/cpufreq/mediatek-cpufreq.c -@@ -22,6 +22,7 @@ struct mtk_cpufreq_platform_data { - int proc_max_volt; - int sram_min_volt; - int sram_max_volt; -+ bool ccifreq_supported; - }; - - /* -@@ -38,6 +39,7 @@ struct mtk_cpufreq_platform_data { - struct mtk_cpu_dvfs_info { - struct cpumask cpus; - struct device *cpu_dev; -+ struct device *cci_dev; - struct regulator *proc_reg; - struct regulator *sram_reg; - struct clk *cpu_clk; -@@ -45,6 +47,7 @@ struct mtk_cpu_dvfs_info { - struct list_head list_head; - int intermediate_voltage; - bool need_voltage_tracking; -+ int vproc_on_boot; - int pre_vproc; - /* Avoid race condition for regulators between notify and policy */ - struct mutex reg_lock; -@@ -53,6 +56,7 @@ struct mtk_cpu_dvfs_info { - unsigned long current_freq; - const struct mtk_cpufreq_platform_data *soc_data; - int vtrack_max; -+ bool ccifreq_bound; - }; - - static struct platform_device *cpufreq_pdev; -@@ -171,6 +175,28 @@ static int mtk_cpufreq_set_voltage(struc - return ret; - } - -+static bool is_ccifreq_ready(struct mtk_cpu_dvfs_info *info) -+{ -+ struct device_link *sup_link; -+ -+ if (info->ccifreq_bound) -+ return true; -+ -+ sup_link = device_link_add(info->cpu_dev, info->cci_dev, -+ DL_FLAG_AUTOREMOVE_CONSUMER); -+ if (!sup_link) { -+ dev_err(info->cpu_dev, "cpu%d: sup_link is NULL\n", info->opp_cpu); -+ return false; -+ } -+ -+ if (sup_link->supplier->links.status != DL_DEV_DRIVER_BOUND) -+ return false; -+ -+ info->ccifreq_bound = true; -+ -+ return true; -+} -+ - static int mtk_cpufreq_set_target(struct cpufreq_policy *policy, - unsigned int index) - { -@@ -213,6 +239,14 @@ static int mtk_cpufreq_set_target(struct - dev_pm_opp_put(opp); - - /* -+ * If MediaTek cci is supported but is not ready, we will use the value -+ * of max(target cpu voltage, booting voltage) to prevent high freqeuncy -+ * low voltage crash. -+ */ -+ if (info->soc_data->ccifreq_supported && !is_ccifreq_ready(info)) -+ vproc = max(vproc, info->vproc_on_boot); -+ -+ /* - * If the new voltage or the intermediate voltage is higher than the - * current voltage, scale up voltage first. - */ -@@ -333,6 +367,23 @@ static int mtk_cpufreq_opp_notifier(stru - return notifier_from_errno(ret); - } - -+static struct device *of_get_cci(struct device *cpu_dev) -+{ -+ struct device_node *np; -+ struct platform_device *pdev; -+ -+ np = of_parse_phandle(cpu_dev->of_node, "mediatek,cci", 0); -+ if (IS_ERR_OR_NULL(np)) -+ return NULL; -+ -+ pdev = of_find_device_by_node(np); -+ of_node_put(np); -+ if (IS_ERR_OR_NULL(pdev)) -+ return NULL; -+ -+ return &pdev->dev; -+} -+ - static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu) - { - struct device *cpu_dev; -@@ -347,6 +398,16 @@ static int mtk_cpu_dvfs_info_init(struct - } - info->cpu_dev = cpu_dev; - -+ info->ccifreq_bound = false; -+ if (info->soc_data->ccifreq_supported) { -+ info->cci_dev = of_get_cci(info->cpu_dev); -+ if (IS_ERR_OR_NULL(info->cci_dev)) { -+ ret = PTR_ERR(info->cci_dev); -+ dev_err(cpu_dev, "cpu%d: failed to get cci device\n", cpu); -+ return -ENODEV; -+ } -+ } -+ - info->cpu_clk = clk_get(cpu_dev, "cpu"); - if (IS_ERR(info->cpu_clk)) { - ret = PTR_ERR(info->cpu_clk); -@@ -410,6 +471,15 @@ static int mtk_cpu_dvfs_info_init(struct - if (ret) - goto out_disable_mux_clock; - -+ if (info->soc_data->ccifreq_supported) { -+ info->vproc_on_boot = regulator_get_voltage(info->proc_reg); -+ if (info->vproc_on_boot < 0) { -+ dev_err(info->cpu_dev, -+ "invalid Vproc value: %d\n", info->vproc_on_boot); -+ goto out_disable_inter_clock; -+ } -+ } -+ - /* Search a safe voltage for intermediate frequency. */ - rate = clk_get_rate(info->inter_clk); - opp = dev_pm_opp_find_freq_ceil(cpu_dev, &rate); -@@ -617,6 +687,16 @@ static const struct mtk_cpufreq_platform - .proc_max_volt = 1150000, - .sram_min_volt = 0, - .sram_max_volt = 1150000, -+ .ccifreq_supported = false, -+}; -+ -+static const struct mtk_cpufreq_platform_data mt8183_platform_data = { -+ .min_volt_shift = 100000, -+ .max_volt_shift = 200000, -+ .proc_max_volt = 1150000, -+ .sram_min_volt = 0, -+ .sram_max_volt = 1150000, -+ .ccifreq_supported = true, - }; - - /* List of machines supported by this driver */ -@@ -629,7 +709,7 @@ static const struct of_device_id mtk_cpu - { .compatible = "mediatek,mt817x", .data = &mt2701_platform_data }, - { .compatible = "mediatek,mt8173", .data = &mt2701_platform_data }, - { .compatible = "mediatek,mt8176", .data = &mt2701_platform_data }, -- { .compatible = "mediatek,mt8183", .data = &mt2701_platform_data }, -+ { .compatible = "mediatek,mt8183", .data = &mt8183_platform_data }, - { .compatible = "mediatek,mt8365", .data = &mt2701_platform_data }, - { .compatible = "mediatek,mt8516", .data = &mt2701_platform_data }, - { } diff --git a/target/linux/mediatek/patches-5.15/350-14-cpufreq-mediatek-Add-support-for-MT8186.patch b/target/linux/mediatek/patches-5.15/350-14-cpufreq-mediatek-Add-support-for-MT8186.patch deleted file mode 100644 index 31000cfbe..000000000 --- a/target/linux/mediatek/patches-5.15/350-14-cpufreq-mediatek-Add-support-for-MT8186.patch +++ /dev/null @@ -1,42 +0,0 @@ -From b6be0baa6615afc65c3963adab674e36af1d4d5f Mon Sep 17 00:00:00 2001 -From: Jia-Wei Chang -Date: Thu, 5 May 2022 19:52:23 +0800 -Subject: [PATCH 14/21] cpufreq: mediatek: Add support for MT8186 - -The platform data of MT8186 is different from previous MediaTek SoCs, -so we add a new compatible and platform data for it. - -Signed-off-by: Jia-Wei Chang -Signed-off-by: Rex-BC Chen -Reviewed-by: AngeloGioacchino Del Regno -Signed-off-by: Viresh Kumar ---- - drivers/cpufreq/mediatek-cpufreq.c | 10 ++++++++++ - 1 file changed, 10 insertions(+) - ---- a/drivers/cpufreq/mediatek-cpufreq.c -+++ b/drivers/cpufreq/mediatek-cpufreq.c -@@ -699,6 +699,15 @@ static const struct mtk_cpufreq_platform - .ccifreq_supported = true, - }; - -+static const struct mtk_cpufreq_platform_data mt8186_platform_data = { -+ .min_volt_shift = 100000, -+ .max_volt_shift = 250000, -+ .proc_max_volt = 1118750, -+ .sram_min_volt = 850000, -+ .sram_max_volt = 1118750, -+ .ccifreq_supported = true, -+}; -+ - /* List of machines supported by this driver */ - static const struct of_device_id mtk_cpufreq_machines[] __initconst = { - { .compatible = "mediatek,mt2701", .data = &mt2701_platform_data }, -@@ -710,6 +719,7 @@ static const struct of_device_id mtk_cpu - { .compatible = "mediatek,mt8173", .data = &mt2701_platform_data }, - { .compatible = "mediatek,mt8176", .data = &mt2701_platform_data }, - { .compatible = "mediatek,mt8183", .data = &mt8183_platform_data }, -+ { .compatible = "mediatek,mt8186", .data = &mt8186_platform_data }, - { .compatible = "mediatek,mt8365", .data = &mt2701_platform_data }, - { .compatible = "mediatek,mt8516", .data = &mt2701_platform_data }, - { } diff --git a/target/linux/mediatek/patches-5.15/350-15-cpufreq-mediatek-Handle-sram-regulator-probe-deferra.patch b/target/linux/mediatek/patches-5.15/350-15-cpufreq-mediatek-Handle-sram-regulator-probe-deferra.patch deleted file mode 100644 index c0137894c..000000000 --- a/target/linux/mediatek/patches-5.15/350-15-cpufreq-mediatek-Handle-sram-regulator-probe-deferra.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 75d19b24aa3203d6c78e4c431c2cc07157ce12fe Mon Sep 17 00:00:00 2001 -From: AngeloGioacchino Del Regno -Date: Wed, 13 Jul 2022 13:15:36 +0200 -Subject: [PATCH 15/21] cpufreq: mediatek: Handle sram regulator probe deferral - -If the regulator_get_optional() call for the SRAM regulator returns -a probe deferral, we must bail out and retry probing later: failing -to do this will produce unstabilities on platforms requiring the -handling for this regulator. - -Fixes: ffa7bdf7f344 ("cpufreq: mediatek: Make sram regulator optional") -Signed-off-by: AngeloGioacchino Del Regno -Signed-off-by: Viresh Kumar ---- - drivers/cpufreq/mediatek-cpufreq.c | 8 ++++++-- - 1 file changed, 6 insertions(+), 2 deletions(-) - ---- a/drivers/cpufreq/mediatek-cpufreq.c -+++ b/drivers/cpufreq/mediatek-cpufreq.c -@@ -439,9 +439,13 @@ static int mtk_cpu_dvfs_info_init(struct - - /* Both presence and absence of sram regulator are valid cases. */ - info->sram_reg = regulator_get_optional(cpu_dev, "sram"); -- if (IS_ERR(info->sram_reg)) -+ if (IS_ERR(info->sram_reg)) { -+ ret = PTR_ERR(info->sram_reg); -+ if (ret == -EPROBE_DEFER) -+ goto out_free_resources; -+ - info->sram_reg = NULL; -- else { -+ } else { - ret = regulator_enable(info->sram_reg); - if (ret) { - dev_warn(cpu_dev, "cpu%d: failed to enable vsram\n", cpu); diff --git a/target/linux/mediatek/patches-5.15/350-16-cpufreq-mediatek-fix-error-return-code-in-mtk_cpu_dv.patch b/target/linux/mediatek/patches-5.15/350-16-cpufreq-mediatek-fix-error-return-code-in-mtk_cpu_dv.patch deleted file mode 100644 index 45c4477ff..000000000 --- a/target/linux/mediatek/patches-5.15/350-16-cpufreq-mediatek-fix-error-return-code-in-mtk_cpu_dv.patch +++ /dev/null @@ -1,29 +0,0 @@ -From dd1174c21dacacd6c0129c1dabc5decad35c02c2 Mon Sep 17 00:00:00 2001 -From: Yang Yingliang -Date: Tue, 17 May 2022 21:34:50 +0800 -Subject: [PATCH 16/21] cpufreq: mediatek: fix error return code in - mtk_cpu_dvfs_info_init() - -If regulator_get_voltage() fails, it should return the error code in -mtk_cpu_dvfs_info_init(). - -Fixes: 0daa47325bae ("cpufreq: mediatek: Link CCI device to CPU") -Reported-by: Hulk Robot -Signed-off-by: Yang Yingliang -Reviewed-by: AngeloGioacchino Del Regno -Reviewed-by: Rex-BC Chen -Signed-off-by: Viresh Kumar ---- - drivers/cpufreq/mediatek-cpufreq.c | 1 + - 1 file changed, 1 insertion(+) - ---- a/drivers/cpufreq/mediatek-cpufreq.c -+++ b/drivers/cpufreq/mediatek-cpufreq.c -@@ -478,6 +478,7 @@ static int mtk_cpu_dvfs_info_init(struct - if (info->soc_data->ccifreq_supported) { - info->vproc_on_boot = regulator_get_voltage(info->proc_reg); - if (info->vproc_on_boot < 0) { -+ ret = info->vproc_on_boot; - dev_err(info->cpu_dev, - "invalid Vproc value: %d\n", info->vproc_on_boot); - goto out_disable_inter_clock; diff --git a/target/linux/mediatek/patches-5.15/350-17-cpufreq-mediatek-fix-passing-zero-to-PTR_ERR.patch b/target/linux/mediatek/patches-5.15/350-17-cpufreq-mediatek-fix-passing-zero-to-PTR_ERR.patch deleted file mode 100644 index 557d02b82..000000000 --- a/target/linux/mediatek/patches-5.15/350-17-cpufreq-mediatek-fix-passing-zero-to-PTR_ERR.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 230a74d459244411db91bfd678f17fcf7aedfcd0 Mon Sep 17 00:00:00 2001 -From: Jia-Wei Chang -Date: Fri, 24 Mar 2023 18:11:27 +0800 -Subject: [PATCH 17/21] cpufreq: mediatek: fix passing zero to 'PTR_ERR' - -In order to prevent passing zero to 'PTR_ERR' in -mtk_cpu_dvfs_info_init(), we fix the return value of of_get_cci() using -error pointer by explicitly casting error number. - -Signed-off-by: Jia-Wei Chang -Fixes: 0daa47325bae ("cpufreq: mediatek: Link CCI device to CPU") -Reported-by: Dan Carpenter -Reviewed-by: AngeloGioacchino Del Regno -Signed-off-by: Viresh Kumar ---- - drivers/cpufreq/mediatek-cpufreq.c | 10 +++++----- - 1 file changed, 5 insertions(+), 5 deletions(-) - ---- a/drivers/cpufreq/mediatek-cpufreq.c -+++ b/drivers/cpufreq/mediatek-cpufreq.c -@@ -373,13 +373,13 @@ static struct device *of_get_cci(struct - struct platform_device *pdev; - - np = of_parse_phandle(cpu_dev->of_node, "mediatek,cci", 0); -- if (IS_ERR_OR_NULL(np)) -- return NULL; -+ if (!np) -+ return ERR_PTR(-ENODEV); - - pdev = of_find_device_by_node(np); - of_node_put(np); -- if (IS_ERR_OR_NULL(pdev)) -- return NULL; -+ if (!pdev) -+ return ERR_PTR(-ENODEV); - - return &pdev->dev; - } -@@ -401,7 +401,7 @@ static int mtk_cpu_dvfs_info_init(struct - info->ccifreq_bound = false; - if (info->soc_data->ccifreq_supported) { - info->cci_dev = of_get_cci(info->cpu_dev); -- if (IS_ERR_OR_NULL(info->cci_dev)) { -+ if (IS_ERR(info->cci_dev)) { - ret = PTR_ERR(info->cci_dev); - dev_err(cpu_dev, "cpu%d: failed to get cci device\n", cpu); - return -ENODEV; diff --git a/target/linux/mediatek/patches-5.15/350-18-cpufreq-mediatek-fix-KP-caused-by-handler-usage-afte.patch b/target/linux/mediatek/patches-5.15/350-18-cpufreq-mediatek-fix-KP-caused-by-handler-usage-afte.patch deleted file mode 100644 index 61531d38a..000000000 --- a/target/linux/mediatek/patches-5.15/350-18-cpufreq-mediatek-fix-KP-caused-by-handler-usage-afte.patch +++ /dev/null @@ -1,149 +0,0 @@ -From fced531b7c7e18192e7982637c8e8f20c29aad64 Mon Sep 17 00:00:00 2001 -From: Jia-Wei Chang -Date: Fri, 24 Mar 2023 18:11:28 +0800 -Subject: [PATCH 18/21] cpufreq: mediatek: fix KP caused by handler usage after - regulator_put/clk_put - -Any kind of failure in mtk_cpu_dvfs_info_init() will lead to calling -regulator_put() or clk_put() and the KP will occur since the regulator/clk -handlers are used after released in mtk_cpu_dvfs_info_release(). - -To prevent the usage after regulator_put()/clk_put(), the regulator/clk -handlers are addressed in a way of "Free the Last Thing Style". - -Signed-off-by: Jia-Wei Chang -Fixes: 4b9ceb757bbb ("cpufreq: mediatek: Enable clocks and regulators") -Suggested-by: AngeloGioacchino Del Regno -Suggested-by: Dan Carpenter -Signed-off-by: Viresh Kumar ---- - drivers/cpufreq/mediatek-cpufreq.c | 62 +++++++++++++++--------------- - 1 file changed, 30 insertions(+), 32 deletions(-) - ---- a/drivers/cpufreq/mediatek-cpufreq.c -+++ b/drivers/cpufreq/mediatek-cpufreq.c -@@ -420,7 +420,7 @@ static int mtk_cpu_dvfs_info_init(struct - ret = PTR_ERR(info->inter_clk); - dev_err_probe(cpu_dev, ret, - "cpu%d: failed to get intermediate clk\n", cpu); -- goto out_free_resources; -+ goto out_free_mux_clock; - } - - info->proc_reg = regulator_get_optional(cpu_dev, "proc"); -@@ -428,13 +428,13 @@ static int mtk_cpu_dvfs_info_init(struct - ret = PTR_ERR(info->proc_reg); - dev_err_probe(cpu_dev, ret, - "cpu%d: failed to get proc regulator\n", cpu); -- goto out_free_resources; -+ goto out_free_inter_clock; - } - - ret = regulator_enable(info->proc_reg); - if (ret) { - dev_warn(cpu_dev, "cpu%d: failed to enable vproc\n", cpu); -- goto out_free_resources; -+ goto out_free_proc_reg; - } - - /* Both presence and absence of sram regulator are valid cases. */ -@@ -442,14 +442,14 @@ static int mtk_cpu_dvfs_info_init(struct - if (IS_ERR(info->sram_reg)) { - ret = PTR_ERR(info->sram_reg); - if (ret == -EPROBE_DEFER) -- goto out_free_resources; -+ goto out_disable_proc_reg; - - info->sram_reg = NULL; - } else { - ret = regulator_enable(info->sram_reg); - if (ret) { - dev_warn(cpu_dev, "cpu%d: failed to enable vsram\n", cpu); -- goto out_free_resources; -+ goto out_free_sram_reg; - } - } - -@@ -458,13 +458,13 @@ static int mtk_cpu_dvfs_info_init(struct - if (ret) { - dev_err(cpu_dev, - "cpu%d: failed to get OPP-sharing information\n", cpu); -- goto out_free_resources; -+ goto out_disable_sram_reg; - } - - ret = dev_pm_opp_of_cpumask_add_table(&info->cpus); - if (ret) { - dev_warn(cpu_dev, "cpu%d: no OPP table\n", cpu); -- goto out_free_resources; -+ goto out_disable_sram_reg; - } - - ret = clk_prepare_enable(info->cpu_clk); -@@ -533,43 +533,41 @@ out_disable_mux_clock: - out_free_opp_table: - dev_pm_opp_of_cpumask_remove_table(&info->cpus); - --out_free_resources: -- if (regulator_is_enabled(info->proc_reg)) -- regulator_disable(info->proc_reg); -- if (info->sram_reg && regulator_is_enabled(info->sram_reg)) -+out_disable_sram_reg: -+ if (info->sram_reg) - regulator_disable(info->sram_reg); - -- if (!IS_ERR(info->proc_reg)) -- regulator_put(info->proc_reg); -- if (!IS_ERR(info->sram_reg)) -+out_free_sram_reg: -+ if (info->sram_reg) - regulator_put(info->sram_reg); -- if (!IS_ERR(info->cpu_clk)) -- clk_put(info->cpu_clk); -- if (!IS_ERR(info->inter_clk)) -- clk_put(info->inter_clk); -+ -+out_disable_proc_reg: -+ regulator_disable(info->proc_reg); -+ -+out_free_proc_reg: -+ regulator_put(info->proc_reg); -+ -+out_free_inter_clock: -+ clk_put(info->inter_clk); -+ -+out_free_mux_clock: -+ clk_put(info->cpu_clk); - - return ret; - } - - static void mtk_cpu_dvfs_info_release(struct mtk_cpu_dvfs_info *info) - { -- if (!IS_ERR(info->proc_reg)) { -- regulator_disable(info->proc_reg); -- regulator_put(info->proc_reg); -- } -- if (!IS_ERR(info->sram_reg)) { -+ regulator_disable(info->proc_reg); -+ regulator_put(info->proc_reg); -+ if (info->sram_reg) { - regulator_disable(info->sram_reg); - regulator_put(info->sram_reg); - } -- if (!IS_ERR(info->cpu_clk)) { -- clk_disable_unprepare(info->cpu_clk); -- clk_put(info->cpu_clk); -- } -- if (!IS_ERR(info->inter_clk)) { -- clk_disable_unprepare(info->inter_clk); -- clk_put(info->inter_clk); -- } -- -+ clk_disable_unprepare(info->cpu_clk); -+ clk_put(info->cpu_clk); -+ clk_disable_unprepare(info->inter_clk); -+ clk_put(info->inter_clk); - dev_pm_opp_of_cpumask_remove_table(&info->cpus); - dev_pm_opp_unregister_notifier(info->cpu_dev, &info->opp_nb); - } diff --git a/target/linux/mediatek/patches-5.15/350-19-cpufreq-mediatek-raise-proc-sram-max-voltage-for-MT8.patch b/target/linux/mediatek/patches-5.15/350-19-cpufreq-mediatek-raise-proc-sram-max-voltage-for-MT8.patch deleted file mode 100644 index 2b7d229f1..000000000 --- a/target/linux/mediatek/patches-5.15/350-19-cpufreq-mediatek-raise-proc-sram-max-voltage-for-MT8.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 24bc42a2d44cb821818717a5c607270921ec5d20 Mon Sep 17 00:00:00 2001 -From: Jia-Wei Chang -Date: Fri, 24 Mar 2023 18:11:29 +0800 -Subject: [PATCH 19/21] cpufreq: mediatek: raise proc/sram max voltage for - MT8516 - -Since the upper boundary of proc/sram voltage of MT8516 is 1300 mV, -which is greater than the value of MT2701 1150 mV, we fix it by adding -the corresponding platform data and specify proc/sram_max_volt to -support MT8516. - -Signed-off-by: Jia-Wei Chang -Fixes: ead858bd128d ("cpufreq: mediatek: Move voltage limits to platform data") -Fixes: 6a17b3876bc8 ("cpufreq: mediatek: Refine mtk_cpufreq_voltage_tracking()") -Reported-by: Nick Hainke -Reviewed-by: AngeloGioacchino Del Regno -Signed-off-by: Viresh Kumar ---- - drivers/cpufreq/mediatek-cpufreq.c | 13 +++++++++++-- - 1 file changed, 11 insertions(+), 2 deletions(-) - ---- a/drivers/cpufreq/mediatek-cpufreq.c -+++ b/drivers/cpufreq/mediatek-cpufreq.c -@@ -711,20 +711,29 @@ static const struct mtk_cpufreq_platform - .ccifreq_supported = true, - }; - -+static const struct mtk_cpufreq_platform_data mt8516_platform_data = { -+ .min_volt_shift = 100000, -+ .max_volt_shift = 200000, -+ .proc_max_volt = 1310000, -+ .sram_min_volt = 0, -+ .sram_max_volt = 1310000, -+ .ccifreq_supported = false, -+}; -+ - /* List of machines supported by this driver */ - static const struct of_device_id mtk_cpufreq_machines[] __initconst = { - { .compatible = "mediatek,mt2701", .data = &mt2701_platform_data }, - { .compatible = "mediatek,mt2712", .data = &mt2701_platform_data }, - { .compatible = "mediatek,mt7622", .data = &mt2701_platform_data }, - { .compatible = "mediatek,mt7623", .data = &mt2701_platform_data }, -- { .compatible = "mediatek,mt8167", .data = &mt2701_platform_data }, -+ { .compatible = "mediatek,mt8167", .data = &mt8516_platform_data }, - { .compatible = "mediatek,mt817x", .data = &mt2701_platform_data }, - { .compatible = "mediatek,mt8173", .data = &mt2701_platform_data }, - { .compatible = "mediatek,mt8176", .data = &mt2701_platform_data }, - { .compatible = "mediatek,mt8183", .data = &mt8183_platform_data }, - { .compatible = "mediatek,mt8186", .data = &mt8186_platform_data }, - { .compatible = "mediatek,mt8365", .data = &mt2701_platform_data }, -- { .compatible = "mediatek,mt8516", .data = &mt2701_platform_data }, -+ { .compatible = "mediatek,mt8516", .data = &mt8516_platform_data }, - { } - }; - MODULE_DEVICE_TABLE(of, mtk_cpufreq_machines); diff --git a/target/linux/mediatek/patches-5.15/350-20-cpufreq-mediatek-Raise-proc-and-sram-max-voltage-for.patch b/target/linux/mediatek/patches-5.15/350-20-cpufreq-mediatek-Raise-proc-and-sram-max-voltage-for.patch deleted file mode 100644 index 2de8eb639..000000000 --- a/target/linux/mediatek/patches-5.15/350-20-cpufreq-mediatek-Raise-proc-and-sram-max-voltage-for.patch +++ /dev/null @@ -1,58 +0,0 @@ -From fe6ef09358dc0cfead9d383a8676fbe7a40fcef7 Mon Sep 17 00:00:00 2001 -From: AngeloGioacchino Del Regno -Date: Fri, 24 Mar 2023 18:11:30 +0800 -Subject: [PATCH 20/21] cpufreq: mediatek: Raise proc and sram max voltage for - MT7622/7623 - -During the addition of SRAM voltage tracking for CCI scaling, this -driver got some voltage limits set for the vtrack algorithm: these -were moved to platform data first, then enforced in a later commit -6a17b3876bc8 ("cpufreq: mediatek: Refine mtk_cpufreq_voltage_tracking()") -using these as max values for the regulator_set_voltage() calls. - -In this case, the vsram/vproc constraints for MT7622 and MT7623 -were supposed to be the same as MT2701 (and a number of other SoCs), -but that turned out to be a mistake because the aforementioned two -SoCs' maximum voltage for both VPROC and VPROC_SRAM is 1.36V. - -Fix that by adding new platform data for MT7622/7623 declaring the -right {proc,sram}_max_volt parameter. - -Fixes: ead858bd128d ("cpufreq: mediatek: Move voltage limits to platform data") -Fixes: 6a17b3876bc8 ("cpufreq: mediatek: Refine mtk_cpufreq_voltage_tracking()") -Signed-off-by: AngeloGioacchino Del Regno -Signed-off-by: Jia-Wei Chang -Signed-off-by: Viresh Kumar ---- - drivers/cpufreq/mediatek-cpufreq.c | 13 +++++++++++-- - 1 file changed, 11 insertions(+), 2 deletions(-) - ---- a/drivers/cpufreq/mediatek-cpufreq.c -+++ b/drivers/cpufreq/mediatek-cpufreq.c -@@ -693,6 +693,15 @@ static const struct mtk_cpufreq_platform - .ccifreq_supported = false, - }; - -+static const struct mtk_cpufreq_platform_data mt7622_platform_data = { -+ .min_volt_shift = 100000, -+ .max_volt_shift = 200000, -+ .proc_max_volt = 1360000, -+ .sram_min_volt = 0, -+ .sram_max_volt = 1360000, -+ .ccifreq_supported = false, -+}; -+ - static const struct mtk_cpufreq_platform_data mt8183_platform_data = { - .min_volt_shift = 100000, - .max_volt_shift = 200000, -@@ -724,8 +733,8 @@ static const struct mtk_cpufreq_platform - static const struct of_device_id mtk_cpufreq_machines[] __initconst = { - { .compatible = "mediatek,mt2701", .data = &mt2701_platform_data }, - { .compatible = "mediatek,mt2712", .data = &mt2701_platform_data }, -- { .compatible = "mediatek,mt7622", .data = &mt2701_platform_data }, -- { .compatible = "mediatek,mt7623", .data = &mt2701_platform_data }, -+ { .compatible = "mediatek,mt7622", .data = &mt7622_platform_data }, -+ { .compatible = "mediatek,mt7623", .data = &mt7622_platform_data }, - { .compatible = "mediatek,mt8167", .data = &mt8516_platform_data }, - { .compatible = "mediatek,mt817x", .data = &mt2701_platform_data }, - { .compatible = "mediatek,mt8173", .data = &mt2701_platform_data }, diff --git a/target/linux/mediatek/patches-5.15/350-21-cpufreq-mediatek-Add-support-for-MT7988.patch b/target/linux/mediatek/patches-5.15/350-21-cpufreq-mediatek-Add-support-for-MT7988.patch deleted file mode 100644 index 6acd3d607..000000000 --- a/target/linux/mediatek/patches-5.15/350-21-cpufreq-mediatek-Add-support-for-MT7988.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 4983a1517e7ddbc6f53fc07607e4ebeb51412843 Mon Sep 17 00:00:00 2001 -From: Sam Shih -Date: Tue, 28 Feb 2023 19:59:22 +0800 -Subject: [PATCH 21/21] cpufreq: mediatek: Add support for MT7988 - -This add cpufreq support for mediatek MT7988 SoC. - -The platform data of MT7988 is different from previous MediaTek SoCs, -so we add a new compatible and platform data for it. - -Signed-off-by: Sam Shih ---- - drivers/cpufreq/mediatek-cpufreq.c | 10 ++++++++++ - 1 file changed, 10 insertions(+) - ---- a/drivers/cpufreq/mediatek-cpufreq.c -+++ b/drivers/cpufreq/mediatek-cpufreq.c -@@ -702,6 +702,15 @@ static const struct mtk_cpufreq_platform - .ccifreq_supported = false, - }; - -+static const struct mtk_cpufreq_platform_data mt7988_platform_data = { -+ .min_volt_shift = 100000, -+ .max_volt_shift = 200000, -+ .proc_max_volt = 900000, -+ .sram_min_volt = 0, -+ .sram_max_volt = 1150000, -+ .ccifreq_supported = true, -+}; -+ - static const struct mtk_cpufreq_platform_data mt8183_platform_data = { - .min_volt_shift = 100000, - .max_volt_shift = 200000, -@@ -735,6 +744,7 @@ static const struct of_device_id mtk_cpu - { .compatible = "mediatek,mt2712", .data = &mt2701_platform_data }, - { .compatible = "mediatek,mt7622", .data = &mt7622_platform_data }, - { .compatible = "mediatek,mt7623", .data = &mt7622_platform_data }, -+ { .compatible = "mediatek,mt7988", .data = &mt7988_platform_data }, - { .compatible = "mediatek,mt8167", .data = &mt8516_platform_data }, - { .compatible = "mediatek,mt817x", .data = &mt2701_platform_data }, - { .compatible = "mediatek,mt8173", .data = &mt2701_platform_data }, diff --git a/target/linux/mediatek/patches-5.15/351-cpufreq-mediatek-correct-voltages-for-MT7622-and-MT7.patch b/target/linux/mediatek/patches-5.15/351-cpufreq-mediatek-correct-voltages-for-MT7622-and-MT7.patch deleted file mode 100644 index 6ab05b897..000000000 --- a/target/linux/mediatek/patches-5.15/351-cpufreq-mediatek-correct-voltages-for-MT7622-and-MT7.patch +++ /dev/null @@ -1,53 +0,0 @@ -From e7697814c142c99f470c3458d49e41b25a575f23 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Fri, 26 May 2023 10:31:40 +0100 -Subject: [PATCH] cpufreq: mediatek: correct voltages for MT7622 and MT7623 - -The MT6380 regulator typically used together with MT7622 does not -support the current maximum processor and SRAM voltage in the cpufreq -driver (1360000uV). -For MT7622 limit processor and SRAM supply voltages to 1350000uV to -avoid having the tracking algorithm request unsupported voltages from -the regulator. - -On MT7623 there is no separate SRAM supply and the maximum voltage used -is 1300000uV. Create dedicated platform data for MT7623 to cover that -case as well. - -Fixes: 0883426fd07e3 ("cpufreq: mediatek: Raise proc and sram max voltage for MT7622/7623") -Suggested-by: Jia-wei Chang -Signed-off-by: Daniel Golle ---- - drivers/cpufreq/mediatek-cpufreq.c | 13 ++++++++++--- - 1 file changed, 10 insertions(+), 3 deletions(-) - ---- a/drivers/cpufreq/mediatek-cpufreq.c -+++ b/drivers/cpufreq/mediatek-cpufreq.c -@@ -696,9 +696,16 @@ static const struct mtk_cpufreq_platform - static const struct mtk_cpufreq_platform_data mt7622_platform_data = { - .min_volt_shift = 100000, - .max_volt_shift = 200000, -- .proc_max_volt = 1360000, -+ .proc_max_volt = 1350000, - .sram_min_volt = 0, -- .sram_max_volt = 1360000, -+ .sram_max_volt = 1350000, -+ .ccifreq_supported = false, -+}; -+ -+static const struct mtk_cpufreq_platform_data mt7623_platform_data = { -+ .min_volt_shift = 100000, -+ .max_volt_shift = 200000, -+ .proc_max_volt = 1300000, - .ccifreq_supported = false, - }; - -@@ -743,7 +750,7 @@ static const struct of_device_id mtk_cpu - { .compatible = "mediatek,mt2701", .data = &mt2701_platform_data }, - { .compatible = "mediatek,mt2712", .data = &mt2701_platform_data }, - { .compatible = "mediatek,mt7622", .data = &mt7622_platform_data }, -- { .compatible = "mediatek,mt7623", .data = &mt7622_platform_data }, -+ { .compatible = "mediatek,mt7623", .data = &mt7623_platform_data }, - { .compatible = "mediatek,mt7988", .data = &mt7988_platform_data }, - { .compatible = "mediatek,mt8167", .data = &mt8516_platform_data }, - { .compatible = "mediatek,mt817x", .data = &mt2701_platform_data }, diff --git a/target/linux/mediatek/patches-5.15/400-crypto-add-eip97-inside-secure-support.patch b/target/linux/mediatek/patches-5.15/400-crypto-add-eip97-inside-secure-support.patch deleted file mode 100644 index 25ca9485e..000000000 --- a/target/linux/mediatek/patches-5.15/400-crypto-add-eip97-inside-secure-support.patch +++ /dev/null @@ -1,27 +0,0 @@ ---- a/drivers/crypto/inside-secure/safexcel.c -+++ b/drivers/crypto/inside-secure/safexcel.c -@@ -600,6 +600,14 @@ static int safexcel_hw_init(struct safex - val |= EIP197_MST_CTRL_TX_MAX_CMD(5); - writel(val, EIP197_HIA_AIC(priv) + EIP197_HIA_MST_CTRL); - } -+ /* -+ * Set maximum number of TX commands to 2^4 = 16 for EIP97 HW2.1/HW2.3 -+ */ -+ else { -+ val = 0; -+ val |= EIP97_MST_CTRL_TX_MAX_CMD(4); -+ writel(val, EIP197_HIA_AIC(priv) + EIP197_HIA_MST_CTRL); -+ } - - /* Configure wr/rd cache values */ - writel(EIP197_MST_CTRL_RD_CACHE(RD_CACHE_4BITS) | ---- a/drivers/crypto/inside-secure/safexcel.h -+++ b/drivers/crypto/inside-secure/safexcel.h -@@ -315,6 +315,7 @@ - #define EIP197_MST_CTRL_RD_CACHE(n) (((n) & 0xf) << 0) - #define EIP197_MST_CTRL_WD_CACHE(n) (((n) & 0xf) << 4) - #define EIP197_MST_CTRL_TX_MAX_CMD(n) (((n) & 0xf) << 20) -+#define EIP97_MST_CTRL_TX_MAX_CMD(n) (((n) & 0xf) << 4) - #define EIP197_MST_CTRL_BYTE_SWAP BIT(24) - #define EIP197_MST_CTRL_NO_BYTE_SWAP BIT(25) - #define EIP197_MST_CTRL_BYTE_SWAP_BITS GENMASK(25, 24) diff --git a/target/linux/mediatek/patches-5.15/401-crypto-fix-eip97-cache-incoherent.patch b/target/linux/mediatek/patches-5.15/401-crypto-fix-eip97-cache-incoherent.patch deleted file mode 100644 index 186c66f68..000000000 --- a/target/linux/mediatek/patches-5.15/401-crypto-fix-eip97-cache-incoherent.patch +++ /dev/null @@ -1,26 +0,0 @@ ---- a/drivers/crypto/inside-secure/safexcel.h -+++ b/drivers/crypto/inside-secure/safexcel.h -@@ -737,6 +737,9 @@ enum safexcel_eip_version { - /* Priority we use for advertising our algorithms */ - #define SAFEXCEL_CRA_PRIORITY 300 - -+/* System cache line size */ -+#define SYSTEM_CACHELINE_SIZE 64 -+ - /* SM3 digest result for zero length message */ - #define EIP197_SM3_ZEROM_HASH "\x1A\xB2\x1D\x83\x55\xCF\xA1\x7F" \ - "\x8E\x61\x19\x48\x31\xE8\x1A\x8F" \ ---- a/drivers/crypto/inside-secure/safexcel_hash.c -+++ b/drivers/crypto/inside-secure/safexcel_hash.c -@@ -55,9 +55,9 @@ struct safexcel_ahash_req { - u8 block_sz; /* block size, only set once */ - u8 digest_sz; /* output digest size, only set once */ - __le32 state[SHA3_512_BLOCK_SIZE / -- sizeof(__le32)] __aligned(sizeof(__le32)); -+ sizeof(__le32)] __aligned(SYSTEM_CACHELINE_SIZE); - -- u64 len; -+ u64 len __aligned(SYSTEM_CACHELINE_SIZE); - u64 processed; - - u8 cache[HASH_CACHE_SIZE] __aligned(sizeof(u32)); diff --git a/target/linux/mediatek/patches-5.15/405-mt7986-trng-add-rng-support.patch b/target/linux/mediatek/patches-5.15/405-mt7986-trng-add-rng-support.patch deleted file mode 100644 index 332f17bae..000000000 --- a/target/linux/mediatek/patches-5.15/405-mt7986-trng-add-rng-support.patch +++ /dev/null @@ -1,41 +0,0 @@ -From f6ba5e17bee38f8ffe118c47fbfef3cf90eb87ff Mon Sep 17 00:00:00 2001 -From: "Mingming.Su" -Date: Wed, 30 Jun 2021 16:59:32 +0800 -Subject: [PATCH] mt7986: trng: add rng support - -1. Add trng compatible name for MT7986 -2. Fix mtk_rng_wait_ready() function - -Signed-off-by: Mingming.Su ---- - drivers/char/hw_random/mtk-rng.c | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - ---- a/drivers/char/hw_random/mtk-rng.c -+++ b/drivers/char/hw_random/mtk-rng.c -@@ -22,7 +22,7 @@ - #define RNG_AUTOSUSPEND_TIMEOUT 100 - - #define USEC_POLL 2 --#define TIMEOUT_POLL 20 -+#define TIMEOUT_POLL 60 - - #define RNG_CTRL 0x00 - #define RNG_EN BIT(0) -@@ -77,7 +77,7 @@ static bool mtk_rng_wait_ready(struct hw - readl_poll_timeout_atomic(priv->base + RNG_CTRL, ready, - ready & RNG_READY, USEC_POLL, - TIMEOUT_POLL); -- return !!ready; -+ return !!(ready & RNG_READY); - } - - static int mtk_rng_read(struct hwrng *rng, void *buf, size_t max, bool wait) -@@ -179,6 +179,7 @@ static const struct dev_pm_ops mtk_rng_p - #endif /* CONFIG_PM */ - - static const struct of_device_id mtk_rng_match[] = { -+ { .compatible = "mediatek,mt7986-rng" }, - { .compatible = "mediatek,mt7623-rng" }, - {}, - }; diff --git a/target/linux/mediatek/patches-5.15/410-bt-mtk-serial-fix.patch b/target/linux/mediatek/patches-5.15/410-bt-mtk-serial-fix.patch deleted file mode 100644 index 4f703dbc0..000000000 --- a/target/linux/mediatek/patches-5.15/410-bt-mtk-serial-fix.patch +++ /dev/null @@ -1,33 +0,0 @@ ---- a/drivers/tty/serial/8250/8250.h -+++ b/drivers/tty/serial/8250/8250.h -@@ -85,6 +85,7 @@ struct serial8250_config { - #define UART_CAP_MINI BIT(17) /* Mini UART on BCM283X family lacks: - * STOP PARITY EPAR SPAR WLEN5 WLEN6 - */ -+#define UART_CAP_NMOD (1 << 18) /* UART doesn't do termios */ - - #define UART_BUG_QUOT BIT(0) /* UART has buggy quot LSB */ - #define UART_BUG_TXEN BIT(1) /* UART has buggy TX IIR status */ ---- a/drivers/tty/serial/8250/8250_port.c -+++ b/drivers/tty/serial/8250/8250_port.c -@@ -289,7 +289,7 @@ static const struct serial8250_config ua - .tx_loadsz = 16, - .fcr = UART_FCR_ENABLE_FIFO | - UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT, -- .flags = UART_CAP_FIFO, -+ .flags = UART_CAP_FIFO | UART_CAP_NMOD, - }, - [PORT_NPCM] = { - .name = "Nuvoton 16550", -@@ -2746,6 +2746,11 @@ serial8250_do_set_termios(struct uart_po - unsigned long flags; - unsigned int baud, quot, frac = 0; - -+ if (up->capabilities & UART_CAP_NMOD) { -+ termios->c_cflag = 0; -+ return; -+ } -+ - if (up->capabilities & UART_CAP_MINI) { - termios->c_cflag &= ~(CSTOPB | PARENB | PARODD | CMSPAR); - if ((termios->c_cflag & CSIZE) == CS5 || diff --git a/target/linux/mediatek/patches-5.15/420-mtd-spi-nor-add-support-for-Winbond-W25Q512JV.patch b/target/linux/mediatek/patches-5.15/420-mtd-spi-nor-add-support-for-Winbond-W25Q512JV.patch deleted file mode 100644 index cc9e9c55e..000000000 --- a/target/linux/mediatek/patches-5.15/420-mtd-spi-nor-add-support-for-Winbond-W25Q512JV.patch +++ /dev/null @@ -1,28 +0,0 @@ -From: David Bauer -To: linux-mtd@lists.infradead.org -Subject: [PATCH] mtd: spi-nor: add support for Winbond W25Q512JV -Date: Sat, 13 Feb 2021 16:10:47 +0100 - -The Winbond W25Q512JV is a 512mb SPI-NOR chip. It supports 4K -sectors as well as block protection and Dual-/Quad-read. - -Tested on: Ubiquiti UniFi 6 LR - -Signed-off-by: David Bauer ---- - drivers/mtd/spi-nor/winbond.c | 4 ++++ - 1 file changed, 4 insertions(+) - ---- a/drivers/mtd/spi-nor/winbond.c -+++ b/drivers/mtd/spi-nor/winbond.c -@@ -98,6 +98,10 @@ static const struct flash_info winbond_p - SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, - { "w25q256jw", INFO(0xef6019, 0, 64 * 1024, 512, - SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, -+ { "w25q512jv", INFO(0xef4020, 0, 64 * 1024, 1024, -+ SECT_4K | SPI_NOR_QUAD_READ | SPI_NOR_DUAL_READ | -+ SPI_NOR_HAS_TB | SPI_NOR_TB_SR_BIT6 | -+ SPI_NOR_HAS_LOCK | SPI_NOR_4BIT_BP) }, - { "w25m512jv", INFO(0xef7119, 0, 64 * 1024, 1024, - SECT_4K | SPI_NOR_QUAD_READ | SPI_NOR_DUAL_READ) }, - { "w25q512jvq", INFO(0xef4020, 0, 64 * 1024, 1024, diff --git a/target/linux/mediatek/patches-5.15/431-drivers-spi-mt65xx-Move-chip_config-to-driver-s-priv.patch b/target/linux/mediatek/patches-5.15/431-drivers-spi-mt65xx-Move-chip_config-to-driver-s-priv.patch deleted file mode 100644 index 3b67343a7..000000000 --- a/target/linux/mediatek/patches-5.15/431-drivers-spi-mt65xx-Move-chip_config-to-driver-s-priv.patch +++ /dev/null @@ -1,130 +0,0 @@ -From bfd3acc428085742d754a6d328d1a93ebf9451df Mon Sep 17 00:00:00 2001 -From: "SkyLake.Huang" -Date: Thu, 23 Jun 2022 18:29:51 +0800 -Subject: [PATCH 1/6] drivers: spi-mt65xx: Move chip_config to driver's private - data - -Signed-off-by: SkyLake.Huang ---- - drivers/spi/spi-mt65xx.c | 29 +++++++++--------------- - include/linux/platform_data/spi-mt65xx.h | 17 -------------- - 2 files changed, 11 insertions(+), 35 deletions(-) - delete mode 100644 include/linux/platform_data/spi-mt65xx.h - ---- a/drivers/spi/spi-mt65xx.c -+++ b/drivers/spi/spi-mt65xx.c -@@ -14,7 +14,6 @@ - #include - #include - #include --#include - #include - #include - #include -@@ -142,6 +141,8 @@ struct mtk_spi { - struct device *dev; - dma_addr_t tx_dma; - dma_addr_t rx_dma; -+ u32 sample_sel; -+ u32 get_tick_dly; - }; - - static const struct mtk_spi_compatible mtk_common_compat; -@@ -187,15 +188,6 @@ static const struct mtk_spi_compatible m - .no_need_unprepare = true, - }; - --/* -- * A piece of default chip info unless the platform -- * supplies it. -- */ --static const struct mtk_chip_config mtk_default_chip_info = { -- .sample_sel = 0, -- .tick_delay = 0, --}; -- - static const struct of_device_id mtk_spi_of_match[] = { - { .compatible = "mediatek,spi-ipm", - .data = (void *)&mtk_ipm_compat, -@@ -323,7 +315,6 @@ static int mtk_spi_hw_init(struct spi_ma - { - u16 cpha, cpol; - u32 reg_val; -- struct mtk_chip_config *chip_config = spi->controller_data; - struct mtk_spi *mdata = spi_master_get_devdata(master); - - cpha = spi->mode & SPI_CPHA ? 1 : 0; -@@ -373,7 +364,7 @@ static int mtk_spi_hw_init(struct spi_ma - else - reg_val &= ~SPI_CMD_CS_POL; - -- if (chip_config->sample_sel) -+ if (mdata->sample_sel) - reg_val |= SPI_CMD_SAMPLE_SEL; - else - reg_val &= ~SPI_CMD_SAMPLE_SEL; -@@ -400,20 +391,20 @@ static int mtk_spi_hw_init(struct spi_ma - if (mdata->dev_comp->ipm_design) { - reg_val = readl(mdata->base + SPI_CMD_REG); - reg_val &= ~SPI_CMD_IPM_GET_TICKDLY_MASK; -- reg_val |= ((chip_config->tick_delay & 0x7) -+ reg_val |= ((mdata->get_tick_dly & 0x7) - << SPI_CMD_IPM_GET_TICKDLY_OFFSET); - writel(reg_val, mdata->base + SPI_CMD_REG); - } else { - reg_val = readl(mdata->base + SPI_CFG1_REG); - reg_val &= ~SPI_CFG1_GET_TICK_DLY_MASK; -- reg_val |= ((chip_config->tick_delay & 0x7) -+ reg_val |= ((mdata->get_tick_dly & 0x7) - << SPI_CFG1_GET_TICK_DLY_OFFSET); - writel(reg_val, mdata->base + SPI_CFG1_REG); - } - } else { - reg_val = readl(mdata->base + SPI_CFG1_REG); - reg_val &= ~SPI_CFG1_GET_TICK_DLY_MASK_V1; -- reg_val |= ((chip_config->tick_delay & 0x3) -+ reg_val |= ((mdata->get_tick_dly & 0x3) - << SPI_CFG1_GET_TICK_DLY_OFFSET_V1); - writel(reg_val, mdata->base + SPI_CFG1_REG); - } -@@ -700,9 +691,6 @@ static int mtk_spi_setup(struct spi_devi - { - struct mtk_spi *mdata = spi_master_get_devdata(spi->master); - -- if (!spi->controller_data) -- spi->controller_data = (void *)&mtk_default_chip_info; -- - if (mdata->dev_comp->need_pad_sel && spi->cs_gpiod) - /* CS de-asserted, gpiolib will handle inversion */ - gpiod_direction_output(spi->cs_gpiod, 0); -@@ -1117,6 +1105,10 @@ static int mtk_spi_probe(struct platform - mdata = spi_master_get_devdata(master); - mdata->dev_comp = of_id->data; - -+ /* Set device configs to default first. Calibrate it later. */ -+ mdata->sample_sel = 0; -+ mdata->get_tick_dly = 2; -+ - if (mdata->dev_comp->enhance_timing) - master->mode_bits |= SPI_CS_HIGH; - ---- a/include/linux/platform_data/spi-mt65xx.h -+++ /dev/null -@@ -1,17 +0,0 @@ --/* SPDX-License-Identifier: GPL-2.0-only */ --/* -- * MTK SPI bus driver definitions -- * -- * Copyright (c) 2015 MediaTek Inc. -- * Author: Leilk Liu -- */ -- --#ifndef ____LINUX_PLATFORM_DATA_SPI_MTK_H --#define ____LINUX_PLATFORM_DATA_SPI_MTK_H -- --/* Board specific platform_data */ --struct mtk_chip_config { -- u32 sample_sel; -- u32 tick_delay; --}; --#endif diff --git a/target/linux/mediatek/patches-5.15/432-drivers-spi-Add-support-for-dynamic-calibration.patch b/target/linux/mediatek/patches-5.15/432-drivers-spi-Add-support-for-dynamic-calibration.patch deleted file mode 100644 index a335f8c54..000000000 --- a/target/linux/mediatek/patches-5.15/432-drivers-spi-Add-support-for-dynamic-calibration.patch +++ /dev/null @@ -1,236 +0,0 @@ -From 2ade0172154e50c8a2bfd8634c6eff943cffea29 Mon Sep 17 00:00:00 2001 -From: "SkyLake.Huang" -Date: Thu, 23 Jun 2022 18:35:52 +0800 -Subject: [PATCH 2/6] drivers: spi: Add support for dynamic calibration - -Signed-off-by: SkyLake.Huang ---- - drivers/spi/spi.c | 137 ++++++++++++++++++++++++++++++++++++++++ - include/linux/spi/spi.h | 42 ++++++++++++ - 2 files changed, 179 insertions(+) - ---- a/drivers/spi/spi.c -+++ b/drivers/spi/spi.c -@@ -1250,6 +1250,70 @@ static int spi_transfer_wait(struct spi_ - return 0; - } - -+int spi_do_calibration(struct spi_controller *ctlr, struct spi_device *spi, -+ int (*cal_read)(void *priv, u32 *addr, int addrlen, u8 *buf, int readlen), void *drv_priv) -+{ -+ int datalen = ctlr->cal_rule->datalen; -+ int addrlen = ctlr->cal_rule->addrlen; -+ u8 *buf; -+ int ret; -+ int i; -+ struct list_head *cal_head, *listptr; -+ struct spi_cal_target *target; -+ -+ /* Calculate calibration result */ -+ int hit_val, total_hit, origin; -+ bool hit; -+ -+ /* Make sure we can start calibration */ -+ if(!ctlr->cal_target || !ctlr->cal_rule || !ctlr->append_caldata) -+ return 0; -+ -+ buf = kzalloc(datalen * sizeof(u8), GFP_KERNEL); -+ if(!buf) -+ return -ENOMEM; -+ -+ ret = ctlr->append_caldata(ctlr); -+ if (ret) -+ goto cal_end; -+ -+ cal_head = ctlr->cal_target; -+ list_for_each(listptr, cal_head) { -+ target = list_entry(listptr, struct spi_cal_target, list); -+ -+ hit = false; -+ hit_val = 0; -+ total_hit = 0; -+ origin = *target->cal_item; -+ -+ for(i=target->cal_min; i<=target->cal_max; i+=target->step) { -+ *target->cal_item = i; -+ ret = (*cal_read)(drv_priv, ctlr->cal_rule->addr, addrlen, buf, datalen); -+ if(ret) -+ break; -+ dev_dbg(&spi->dev, "controller cal item value: 0x%x\n", i); -+ if(memcmp(ctlr->cal_rule->match_data, buf, datalen * sizeof(u8)) == 0) { -+ hit = true; -+ hit_val += i; -+ total_hit++; -+ dev_dbg(&spi->dev, "golden data matches data read!\n"); -+ } -+ } -+ if(hit) { -+ *target->cal_item = DIV_ROUND_CLOSEST(hit_val, total_hit); -+ dev_info(&spi->dev, "calibration result: 0x%x", *target->cal_item); -+ } else { -+ *target->cal_item = origin; -+ dev_warn(&spi->dev, "calibration failed, fallback to default: 0x%x", origin); -+ } -+ } -+ -+cal_end: -+ kfree(buf); -+ return ret? ret: 0; -+} -+EXPORT_SYMBOL_GPL(spi_do_calibration); -+ - static void _spi_transfer_delay_ns(u32 ns) - { - if (!ns) -@@ -2037,6 +2101,75 @@ void spi_flush_queue(struct spi_controll - /*-------------------------------------------------------------------------*/ - - #if defined(CONFIG_OF) -+static inline void alloc_cal_data(struct list_head **cal_target, -+ struct spi_cal_rule **cal_rule, bool enable) -+{ -+ if(enable) { -+ *cal_target = kmalloc(sizeof(struct list_head), GFP_KERNEL); -+ INIT_LIST_HEAD(*cal_target); -+ *cal_rule = kmalloc(sizeof(struct spi_cal_rule), GFP_KERNEL); -+ } else { -+ kfree(*cal_target); -+ kfree(*cal_rule); -+ } -+} -+ -+static int of_spi_parse_cal_dt(struct spi_controller *ctlr, struct spi_device *spi, -+ struct device_node *nc) -+{ -+ u32 value; -+ int rc; -+ const char *cal_mode; -+ -+ rc = of_property_read_bool(nc, "spi-cal-enable"); -+ if (rc) -+ alloc_cal_data(&ctlr->cal_target, &ctlr->cal_rule, true); -+ else -+ return 0; -+ -+ rc = of_property_read_string(nc, "spi-cal-mode", &cal_mode); -+ if(!rc) { -+ if(strcmp("read-data", cal_mode) == 0){ -+ ctlr->cal_rule->mode = SPI_CAL_READ_DATA; -+ } else if(strcmp("read-pp", cal_mode) == 0) { -+ ctlr->cal_rule->mode = SPI_CAL_READ_PP; -+ return 0; -+ } else if(strcmp("read-sfdp", cal_mode) == 0){ -+ ctlr->cal_rule->mode = SPI_CAL_READ_SFDP; -+ return 0; -+ } -+ } else -+ goto err; -+ -+ ctlr->cal_rule->datalen = 0; -+ rc = of_property_read_u32(nc, "spi-cal-datalen", &value); -+ if(!rc && value > 0) { -+ ctlr->cal_rule->datalen = value; -+ -+ ctlr->cal_rule->match_data = kzalloc(value * sizeof(u8), GFP_KERNEL); -+ rc = of_property_read_u8_array(nc, "spi-cal-data", -+ ctlr->cal_rule->match_data, value); -+ if(rc) -+ kfree(ctlr->cal_rule->match_data); -+ } -+ -+ rc = of_property_read_u32(nc, "spi-cal-addrlen", &value); -+ if(!rc && value > 0) { -+ ctlr->cal_rule->addrlen = value; -+ -+ ctlr->cal_rule->addr = kzalloc(value * sizeof(u32), GFP_KERNEL); -+ rc = of_property_read_u32_array(nc, "spi-cal-addr", -+ ctlr->cal_rule->addr, value); -+ if(rc) -+ kfree(ctlr->cal_rule->addr); -+ } -+ return 0; -+ -+err: -+ alloc_cal_data(&ctlr->cal_target, &ctlr->cal_rule, false); -+ return 0; -+} -+ - static int of_spi_parse_dt(struct spi_controller *ctlr, struct spi_device *spi, - struct device_node *nc) - { -@@ -2155,6 +2288,10 @@ of_register_spi_device(struct spi_contro - if (rc) - goto err_out; - -+ rc = of_spi_parse_cal_dt(ctlr, spi, nc); -+ if (rc) -+ goto err_out; -+ - /* Store a pointer to the node in the device structure */ - of_node_get(nc); - spi->dev.of_node = nc; ---- a/include/linux/spi/spi.h -+++ b/include/linux/spi/spi.h -@@ -290,6 +290,40 @@ struct spi_driver { - struct device_driver driver; - }; - -+enum { -+ SPI_CAL_READ_DATA = 0, -+ SPI_CAL_READ_PP = 1, /* only for SPI-NAND */ -+ SPI_CAL_READ_SFDP = 2, /* only for SPI-NOR */ -+}; -+ -+struct nand_addr { -+ unsigned int lun; -+ unsigned int plane; -+ unsigned int eraseblock; -+ unsigned int page; -+ unsigned int dataoffs; -+}; -+ -+/** -+ * Read calibration rule from device dts node. -+ * Once calibration result matches the rule, we regard is as success. -+ */ -+struct spi_cal_rule { -+ int datalen; -+ u8 *match_data; -+ int addrlen; -+ u32 *addr; -+ int mode; -+}; -+ -+struct spi_cal_target { -+ u32 *cal_item; -+ int cal_min; /* min of cal_item */ -+ int cal_max; /* max of cal_item */ -+ int step; /* Increase/decrease cal_item */ -+ struct list_head list; -+}; -+ - static inline struct spi_driver *to_spi_driver(struct device_driver *drv) - { - return drv ? container_of(drv, struct spi_driver, driver) : NULL; -@@ -665,6 +699,11 @@ struct spi_controller { - void *dummy_rx; - void *dummy_tx; - -+ /* For calibration */ -+ int (*append_caldata)(struct spi_controller *ctlr); -+ struct list_head *cal_target; -+ struct spi_cal_rule *cal_rule; -+ - int (*fw_translate_cs)(struct spi_controller *ctlr, unsigned cs); - - /* -@@ -1477,6 +1516,9 @@ spi_register_board_info(struct spi_board - { return 0; } - #endif - -+extern int spi_do_calibration(struct spi_controller *ctlr, -+ struct spi_device *spi, int (*cal_read)(void *, u32 *, int, u8 *, int), void *drv_priv); -+ - /* If you're hotplugging an adapter with devices (parport, usb, etc) - * use spi_new_device() to describe each device. You can also call - * spi_unregister_device() to start making that device vanish, but diff --git a/target/linux/mediatek/patches-5.15/433-drivers-spi-mem-Add-spi-calibration-hook.patch b/target/linux/mediatek/patches-5.15/433-drivers-spi-mem-Add-spi-calibration-hook.patch deleted file mode 100644 index aaacab013..000000000 --- a/target/linux/mediatek/patches-5.15/433-drivers-spi-mem-Add-spi-calibration-hook.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 06640a5da2973318c06e516da16a5b579622e7c5 Mon Sep 17 00:00:00 2001 -From: "SkyLake.Huang" -Date: Thu, 23 Jun 2022 18:37:55 +0800 -Subject: [PATCH 3/6] drivers: spi-mem: Add spi calibration hook - -Signed-off-by: SkyLake.Huang ---- - drivers/spi/spi-mem.c | 8 ++++++++ - include/linux/spi/spi-mem.h | 4 ++++ - 2 files changed, 12 insertions(+) - ---- a/drivers/spi/spi-mem.c -+++ b/drivers/spi/spi-mem.c -@@ -410,6 +410,14 @@ int spi_mem_exec_op(struct spi_mem *mem, - } - EXPORT_SYMBOL_GPL(spi_mem_exec_op); - -+int spi_mem_do_calibration(struct spi_mem *mem, -+ int (*cal_read)(void *priv, u32 *addr, int addrlen, u8 *buf, int readlen), -+ void *priv) -+{ -+ return spi_do_calibration(mem->spi->controller, mem->spi, cal_read, priv); -+} -+EXPORT_SYMBOL_GPL(spi_mem_do_calibration); -+ - /** - * spi_mem_get_name() - Return the SPI mem device name to be used by the - * upper layer if necessary ---- a/include/linux/spi/spi-mem.h -+++ b/include/linux/spi/spi-mem.h -@@ -366,6 +366,10 @@ bool spi_mem_supports_op(struct spi_mem - int spi_mem_exec_op(struct spi_mem *mem, - const struct spi_mem_op *op); - -+int spi_mem_do_calibration(struct spi_mem *mem, -+ int (*cal_read)(void *, u32 *, int, u8 *, int), -+ void *priv); -+ - const char *spi_mem_get_name(struct spi_mem *mem); - - struct spi_mem_dirmap_desc * diff --git a/target/linux/mediatek/patches-5.15/434-drivers-spi-mt65xx-Add-controller-s-calibration-para.patch b/target/linux/mediatek/patches-5.15/434-drivers-spi-mt65xx-Add-controller-s-calibration-para.patch deleted file mode 100644 index 0044c9cc2..000000000 --- a/target/linux/mediatek/patches-5.15/434-drivers-spi-mt65xx-Add-controller-s-calibration-para.patch +++ /dev/null @@ -1,43 +0,0 @@ -From d278c7a0bf730318a7ccf8d0a8b434c813e23fd0 Mon Sep 17 00:00:00 2001 -From: "SkyLake.Huang" -Date: Thu, 23 Jun 2022 18:39:03 +0800 -Subject: [PATCH 4/6] drivers: spi-mt65xx: Add controller's calibration - paramter - -Signed-off-by: SkyLake.Huang ---- - drivers/spi/spi-mt65xx.c | 16 ++++++++++++++++ - 1 file changed, 16 insertions(+) - ---- a/drivers/spi/spi-mt65xx.c -+++ b/drivers/spi/spi-mt65xx.c -@@ -802,6 +802,21 @@ static irqreturn_t mtk_spi_interrupt(int - return IRQ_HANDLED; - } - -+static int mtk_spi_append_caldata(struct spi_controller *ctlr) -+{ -+ struct spi_cal_target *cal_target = kmalloc(sizeof(*cal_target), GFP_KERNEL); -+ struct mtk_spi *mdata = spi_master_get_devdata(ctlr); -+ -+ cal_target->cal_item = &mdata->get_tick_dly; -+ cal_target->cal_min = 0; -+ cal_target->cal_max = 7; -+ cal_target->step = 1; -+ -+ list_add(&cal_target->list, ctlr->cal_target); -+ -+ return 0; -+} -+ - static int mtk_spi_mem_adjust_op_size(struct spi_mem *mem, - struct spi_mem_op *op) - { -@@ -1094,6 +1109,7 @@ static int mtk_spi_probe(struct platform - master->setup = mtk_spi_setup; - master->set_cs_timing = mtk_spi_set_hw_cs_timing; - master->use_gpio_descriptors = true; -+ master->append_caldata = mtk_spi_append_caldata; - - of_id = of_match_node(mtk_spi_of_match, pdev->dev.of_node); - if (!of_id) { diff --git a/target/linux/mediatek/patches-5.15/435-drivers-mtd-spinand-Add-calibration-support-for-spin.patch b/target/linux/mediatek/patches-5.15/435-drivers-mtd-spinand-Add-calibration-support-for-spin.patch deleted file mode 100644 index 5f1e2b9ce..000000000 --- a/target/linux/mediatek/patches-5.15/435-drivers-mtd-spinand-Add-calibration-support-for-spin.patch +++ /dev/null @@ -1,81 +0,0 @@ -From 7670ec4a14891a1a182b98a9c403ffbf6b49e4b1 Mon Sep 17 00:00:00 2001 -From: "SkyLake.Huang" -Date: Thu, 23 Jun 2022 18:39:56 +0800 -Subject: [PATCH 5/6] drivers: mtd: spinand: Add calibration support for - spinand - -Signed-off-by: SkyLake.Huang ---- - drivers/mtd/nand/spi/core.c | 54 +++++++++++++++++++++++++++++++++++++ - 1 file changed, 54 insertions(+) - ---- a/drivers/mtd/nand/spi/core.c -+++ b/drivers/mtd/nand/spi/core.c -@@ -966,6 +966,56 @@ static int spinand_manufacturer_match(st - return -ENOTSUPP; - } - -+int spinand_cal_read(void *priv, u32 *addr, int addrlen, u8 *buf, int readlen) { -+ struct spinand_device *spinand = (struct spinand_device *)priv; -+ struct device *dev = &spinand->spimem->spi->dev; -+ struct spi_mem_op op = SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, buf, readlen); -+ struct nand_pos pos; -+ struct nand_page_io_req req; -+ u8 status; -+ int ret; -+ -+ if(addrlen != sizeof(struct nand_addr)/sizeof(unsigned int)) { -+ dev_err(dev, "Must provide correct addr(length) for spinand calibration\n"); -+ return -EINVAL; -+ } -+ -+ ret = spinand_reset_op(spinand); -+ if (ret) -+ return ret; -+ -+ /* We should store our golden data in first target because -+ * we can't switch target at this moment. -+ */ -+ pos = (struct nand_pos){ -+ .target = 0, -+ .lun = *addr, -+ .plane = *(addr+1), -+ .eraseblock = *(addr+2), -+ .page = *(addr+3), -+ }; -+ -+ req = (struct nand_page_io_req){ -+ .pos = pos, -+ .dataoffs = *(addr+4), -+ .datalen = readlen, -+ .databuf.in = buf, -+ .mode = MTD_OPS_AUTO_OOB, -+ }; -+ -+ ret = spinand_load_page_op(spinand, &req); -+ if (ret) -+ return ret; -+ -+ ret = spinand_wait(spinand, &status); -+ if (ret < 0) -+ return ret; -+ -+ ret = spi_mem_exec_op(spinand->spimem, &op); -+ -+ return 0; -+} -+ - static int spinand_id_detect(struct spinand_device *spinand) - { - u8 *id = spinand->id.data; -@@ -1216,6 +1266,10 @@ static int spinand_init(struct spinand_d - if (!spinand->scratchbuf) - return -ENOMEM; - -+ ret = spi_mem_do_calibration(spinand->spimem, spinand_cal_read, spinand); -+ if (ret) -+ dev_err(dev, "Failed to calibrate SPI-NAND (err = %d)\n", ret); -+ - ret = spinand_detect(spinand); - if (ret) - goto err_free_bufs; diff --git a/target/linux/mediatek/patches-5.15/436-drivers-mtd-spi-nor-Add-calibration-support-for-spi-.patch b/target/linux/mediatek/patches-5.15/436-drivers-mtd-spi-nor-Add-calibration-support-for-spi-.patch deleted file mode 100644 index 279e6a9c2..000000000 --- a/target/linux/mediatek/patches-5.15/436-drivers-mtd-spi-nor-Add-calibration-support-for-spi-.patch +++ /dev/null @@ -1,57 +0,0 @@ -From f3fe3b15eca7908eaac57f9b8387a5dbc45ec5b2 Mon Sep 17 00:00:00 2001 -From: "SkyLake.Huang" -Date: Thu, 23 Jun 2022 18:40:59 +0800 -Subject: [PATCH 6/6] drivers: mtd: spi-nor: Add calibration support for - spi-nor - -Signed-off-by: SkyLake.Huang ---- - drivers/mtd/nand/spi/core.c | 5 ++++- - drivers/mtd/spi-nor/core.c | 15 +++++++++++++++ - 2 files changed, 19 insertions(+), 1 deletion(-) - ---- a/drivers/mtd/nand/spi/core.c -+++ b/drivers/mtd/nand/spi/core.c -@@ -1007,7 +1007,10 @@ int spinand_cal_read(void *priv, u32 *ad - if (ret) - return ret; - -- ret = spinand_wait(spinand, &status); -+ ret = spinand_wait(spinand, -+ SPINAND_READ_INITIAL_DELAY_US, -+ SPINAND_READ_POLL_DELAY_US, -+ &status); - if (ret < 0) - return ret; - ---- a/drivers/mtd/spi-nor/core.c -+++ b/drivers/mtd/spi-nor/core.c -@@ -3112,6 +3112,18 @@ static void spi_nor_debugfs_init(struct - info->id_len, info->id); - } - -+static int spi_nor_cal_read(void *priv, u32 *addr, int addrlen, u8 *buf, int readlen) -+{ -+ struct spi_nor *nor = (struct spi_nor *)priv; -+ -+ nor->reg_proto = SNOR_PROTO_1_1_1; -+ nor->read_proto = SNOR_PROTO_1_1_1; -+ nor->read_opcode = SPINOR_OP_READ; -+ nor->read_dummy = 0; -+ -+ return nor->controller_ops->read(nor, *addr, readlen, buf); -+} -+ - static const struct flash_info *spi_nor_get_flash_info(struct spi_nor *nor, - const char *name) - { -@@ -3185,6 +3197,9 @@ int spi_nor_scan(struct spi_nor *nor, co - if (!nor->bouncebuf) - return -ENOMEM; - -+ if(nor->spimem) -+ spi_mem_do_calibration(nor->spimem, spi_nor_cal_read, nor); -+ - info = spi_nor_get_flash_info(nor, name); - if (IS_ERR(info)) - return PTR_ERR(info); diff --git a/target/linux/mediatek/patches-5.15/500-gsw-rtl8367s-mt7622-support.patch b/target/linux/mediatek/patches-5.15/500-gsw-rtl8367s-mt7622-support.patch deleted file mode 100644 index b8964f4e7..000000000 --- a/target/linux/mediatek/patches-5.15/500-gsw-rtl8367s-mt7622-support.patch +++ /dev/null @@ -1,25 +0,0 @@ ---- a/drivers/net/phy/Kconfig -+++ b/drivers/net/phy/Kconfig -@@ -367,6 +367,12 @@ config ROCKCHIP_PHY - help - Currently supports the integrated Ethernet PHY. - -+config RTL8367S_GSW -+ tristate "rtl8367 Gigabit Switch support for mt7622" -+ depends on NET_VENDOR_MEDIATEK -+ help -+ This driver supports rtl8367s in mt7622 -+ - config SMSC_PHY - tristate "SMSC PHYs" - help ---- a/drivers/net/phy/Makefile -+++ b/drivers/net/phy/Makefile -@@ -95,6 +95,7 @@ obj-$(CONFIG_QSEMI_PHY) += qsemi.o - obj-$(CONFIG_REALTEK_PHY) += realtek.o - obj-$(CONFIG_RENESAS_PHY) += uPD60620.o - obj-$(CONFIG_ROCKCHIP_PHY) += rockchip.o -+obj-$(CONFIG_RTL8367S_GSW) += rtk/ - obj-$(CONFIG_SMSC_PHY) += smsc.o - obj-$(CONFIG_STE10XP) += ste10Xp.o - obj-$(CONFIG_TERANETICS_PHY) += teranetics.o diff --git a/target/linux/mediatek/patches-5.15/600-v5.16-arm64-dts-mediatek-Split-PCIe-node-for-MT2712-and-MT.patch b/target/linux/mediatek/patches-5.15/600-v5.16-arm64-dts-mediatek-Split-PCIe-node-for-MT2712-and-MT.patch deleted file mode 100644 index 4ca9f9c72..000000000 --- a/target/linux/mediatek/patches-5.15/600-v5.16-arm64-dts-mediatek-Split-PCIe-node-for-MT2712-and-MT.patch +++ /dev/null @@ -1,332 +0,0 @@ -From: Chuanjia Liu -Date: Mon, 23 Aug 2021 11:27:59 +0800 -Subject: [PATCH] arm64: dts: mediatek: Split PCIe node for MT2712 and MT7622 - -There are two independent PCIe controllers in MT2712 and MT7622 -platform. Each of them should contain an independent MSI domain. - -In old dts architecture, MSI domain will be inherited from the root -bridge, and all of the devices will share the same MSI domain. -Hence that, the PCIe devices will not work properly if the irq number -which required is more than 32. - -Split the PCIe node for MT2712 and MT7622 platform to comply with -the hardware design and fix MSI issue. - -Signed-off-by: Chuanjia Liu -Acked-by: Ryder Lee -Link: https://lore.kernel.org/r/20210823032800.1660-6-chuanjia.liu@mediatek.com -Signed-off-by: Matthias Brugger ---- - ---- a/arch/arm64/boot/dts/mediatek/mt2712e.dtsi -+++ b/arch/arm64/boot/dts/mediatek/mt2712e.dtsi -@@ -916,64 +916,67 @@ - }; - }; - -- pcie: pcie@11700000 { -+ pcie1: pcie@112ff000 { - compatible = "mediatek,mt2712-pcie"; - device_type = "pci"; -- reg = <0 0x11700000 0 0x1000>, -- <0 0x112ff000 0 0x1000>; -- reg-names = "port0", "port1"; -+ reg = <0 0x112ff000 0 0x1000>; -+ reg-names = "port1"; -+ linux,pci-domain = <1>; - #address-cells = <3>; - #size-cells = <2>; -- interrupts = , -- ; -- clocks = <&topckgen CLK_TOP_PE2_MAC_P0_SEL>, -- <&topckgen CLK_TOP_PE2_MAC_P1_SEL>, -- <&pericfg CLK_PERI_PCIE0>, -+ interrupts = ; -+ interrupt-names = "pcie_irq"; -+ clocks = <&topckgen CLK_TOP_PE2_MAC_P1_SEL>, - <&pericfg CLK_PERI_PCIE1>; -- clock-names = "sys_ck0", "sys_ck1", "ahb_ck0", "ahb_ck1"; -- phys = <&u3port0 PHY_TYPE_PCIE>, <&u3port1 PHY_TYPE_PCIE>; -- phy-names = "pcie-phy0", "pcie-phy1"; -+ clock-names = "sys_ck1", "ahb_ck1"; -+ phys = <&u3port1 PHY_TYPE_PCIE>; -+ phy-names = "pcie-phy1"; - bus-range = <0x00 0xff>; -- ranges = <0x82000000 0 0x20000000 0x0 0x20000000 0 0x10000000>; -+ ranges = <0x82000000 0 0x11400000 0x0 0x11400000 0 0x300000>; -+ status = "disabled"; - -- pcie0: pcie@0,0 { -- device_type = "pci"; -- status = "disabled"; -- reg = <0x0000 0 0 0 0>; -- #address-cells = <3>; -- #size-cells = <2>; -+ #interrupt-cells = <1>; -+ interrupt-map-mask = <0 0 0 7>; -+ interrupt-map = <0 0 0 1 &pcie_intc1 0>, -+ <0 0 0 2 &pcie_intc1 1>, -+ <0 0 0 3 &pcie_intc1 2>, -+ <0 0 0 4 &pcie_intc1 3>; -+ pcie_intc1: interrupt-controller { -+ interrupt-controller; -+ #address-cells = <0>; - #interrupt-cells = <1>; -- ranges; -- interrupt-map-mask = <0 0 0 7>; -- interrupt-map = <0 0 0 1 &pcie_intc0 0>, -- <0 0 0 2 &pcie_intc0 1>, -- <0 0 0 3 &pcie_intc0 2>, -- <0 0 0 4 &pcie_intc0 3>; -- pcie_intc0: interrupt-controller { -- interrupt-controller; -- #address-cells = <0>; -- #interrupt-cells = <1>; -- }; - }; -+ }; -+ -+ pcie0: pcie@11700000 { -+ compatible = "mediatek,mt2712-pcie"; -+ device_type = "pci"; -+ reg = <0 0x11700000 0 0x1000>; -+ reg-names = "port0"; -+ linux,pci-domain = <0>; -+ #address-cells = <3>; -+ #size-cells = <2>; -+ interrupts = ; -+ interrupt-names = "pcie_irq"; -+ clocks = <&topckgen CLK_TOP_PE2_MAC_P0_SEL>, -+ <&pericfg CLK_PERI_PCIE0>; -+ clock-names = "sys_ck0", "ahb_ck0"; -+ phys = <&u3port0 PHY_TYPE_PCIE>; -+ phy-names = "pcie-phy0"; -+ bus-range = <0x00 0xff>; -+ ranges = <0x82000000 0 0x20000000 0x0 0x20000000 0 0x10000000>; -+ status = "disabled"; - -- pcie1: pcie@1,0 { -- device_type = "pci"; -- status = "disabled"; -- reg = <0x0800 0 0 0 0>; -- #address-cells = <3>; -- #size-cells = <2>; -+ #interrupt-cells = <1>; -+ interrupt-map-mask = <0 0 0 7>; -+ interrupt-map = <0 0 0 1 &pcie_intc0 0>, -+ <0 0 0 2 &pcie_intc0 1>, -+ <0 0 0 3 &pcie_intc0 2>, -+ <0 0 0 4 &pcie_intc0 3>; -+ pcie_intc0: interrupt-controller { -+ interrupt-controller; -+ #address-cells = <0>; - #interrupt-cells = <1>; -- ranges; -- interrupt-map-mask = <0 0 0 7>; -- interrupt-map = <0 0 0 1 &pcie_intc1 0>, -- <0 0 0 2 &pcie_intc1 1>, -- <0 0 0 3 &pcie_intc1 2>, -- <0 0 0 4 &pcie_intc1 3>; -- pcie_intc1: interrupt-controller { -- interrupt-controller; -- #address-cells = <0>; -- #interrupt-cells = <1>; -- }; - }; - }; - ---- a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts -@@ -303,18 +303,16 @@ - }; - }; - --&pcie { -+&pcie0 { - pinctrl-names = "default"; -- pinctrl-0 = <&pcie0_pins>, <&pcie1_pins>; -+ pinctrl-0 = <&pcie0_pins>; - status = "okay"; -+}; - -- pcie@0,0 { -- status = "okay"; -- }; -- -- pcie@1,0 { -- status = "okay"; -- }; -+&pcie1 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pcie1_pins>; -+ status = "okay"; - }; - - &pio { ---- a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts -@@ -233,18 +233,16 @@ - }; - }; - --&pcie { -+&pcie0 { - pinctrl-names = "default"; -- pinctrl-0 = <&pcie0_pins>, <&pcie1_pins>; -+ pinctrl-0 = <&pcie0_pins>; - status = "okay"; -+}; - -- pcie@0,0 { -- status = "okay"; -- }; -- -- pcie@1,0 { -- status = "okay"; -- }; -+&pcie1 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pcie1_pins>; -+ status = "okay"; - }; - - &pio { ---- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi -+++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi -@@ -804,75 +804,83 @@ - #reset-cells = <1>; - }; - -- pcie: pcie@1a140000 { -+ pciecfg: pciecfg@1a140000 { -+ compatible = "mediatek,generic-pciecfg", "syscon"; -+ reg = <0 0x1a140000 0 0x1000>; -+ }; -+ -+ pcie0: pcie@1a143000 { - compatible = "mediatek,mt7622-pcie"; - device_type = "pci"; -- reg = <0 0x1a140000 0 0x1000>, -- <0 0x1a143000 0 0x1000>, -- <0 0x1a145000 0 0x1000>; -- reg-names = "subsys", "port0", "port1"; -+ reg = <0 0x1a143000 0 0x1000>; -+ reg-names = "port0"; -+ linux,pci-domain = <0>; - #address-cells = <3>; - #size-cells = <2>; -- interrupts = , -- ; -+ interrupts = ; -+ interrupt-names = "pcie_irq"; - clocks = <&pciesys CLK_PCIE_P0_MAC_EN>, -- <&pciesys CLK_PCIE_P1_MAC_EN>, -- <&pciesys CLK_PCIE_P0_AHB_EN>, - <&pciesys CLK_PCIE_P0_AHB_EN>, - <&pciesys CLK_PCIE_P0_AUX_EN>, -- <&pciesys CLK_PCIE_P1_AUX_EN>, - <&pciesys CLK_PCIE_P0_AXI_EN>, -- <&pciesys CLK_PCIE_P1_AXI_EN>, - <&pciesys CLK_PCIE_P0_OBFF_EN>, -- <&pciesys CLK_PCIE_P1_OBFF_EN>, -- <&pciesys CLK_PCIE_P0_PIPE_EN>, -- <&pciesys CLK_PCIE_P1_PIPE_EN>; -- clock-names = "sys_ck0", "sys_ck1", "ahb_ck0", "ahb_ck1", -- "aux_ck0", "aux_ck1", "axi_ck0", "axi_ck1", -- "obff_ck0", "obff_ck1", "pipe_ck0", "pipe_ck1"; -+ <&pciesys CLK_PCIE_P0_PIPE_EN>; -+ clock-names = "sys_ck0", "ahb_ck0", "aux_ck0", -+ "axi_ck0", "obff_ck0", "pipe_ck0"; -+ - power-domains = <&scpsys MT7622_POWER_DOMAIN_HIF0>; - bus-range = <0x00 0xff>; -- ranges = <0x82000000 0 0x20000000 0x0 0x20000000 0 0x10000000>; -+ ranges = <0x82000000 0 0x20000000 0x0 0x20000000 0 0x8000000>; - status = "disabled"; - -- pcie0: pcie@0,0 { -- reg = <0x0000 0 0 0 0>; -- #address-cells = <3>; -- #size-cells = <2>; -+ #interrupt-cells = <1>; -+ interrupt-map-mask = <0 0 0 7>; -+ interrupt-map = <0 0 0 1 &pcie_intc0 0>, -+ <0 0 0 2 &pcie_intc0 1>, -+ <0 0 0 3 &pcie_intc0 2>, -+ <0 0 0 4 &pcie_intc0 3>; -+ pcie_intc0: interrupt-controller { -+ interrupt-controller; -+ #address-cells = <0>; - #interrupt-cells = <1>; -- ranges; -- status = "disabled"; -- -- interrupt-map-mask = <0 0 0 7>; -- interrupt-map = <0 0 0 1 &pcie_intc0 0>, -- <0 0 0 2 &pcie_intc0 1>, -- <0 0 0 3 &pcie_intc0 2>, -- <0 0 0 4 &pcie_intc0 3>; -- pcie_intc0: interrupt-controller { -- interrupt-controller; -- #address-cells = <0>; -- #interrupt-cells = <1>; -- }; - }; -+ }; - -- pcie1: pcie@1,0 { -- reg = <0x0800 0 0 0 0>; -- #address-cells = <3>; -- #size-cells = <2>; -- #interrupt-cells = <1>; -- ranges; -- status = "disabled"; -+ pcie1: pcie@1a145000 { -+ compatible = "mediatek,mt7622-pcie"; -+ device_type = "pci"; -+ reg = <0 0x1a145000 0 0x1000>; -+ reg-names = "port1"; -+ linux,pci-domain = <1>; -+ #address-cells = <3>; -+ #size-cells = <2>; -+ interrupts = ; -+ interrupt-names = "pcie_irq"; -+ clocks = <&pciesys CLK_PCIE_P1_MAC_EN>, -+ /* designer has connect RC1 with p0_ahb clock */ -+ <&pciesys CLK_PCIE_P0_AHB_EN>, -+ <&pciesys CLK_PCIE_P1_AUX_EN>, -+ <&pciesys CLK_PCIE_P1_AXI_EN>, -+ <&pciesys CLK_PCIE_P1_OBFF_EN>, -+ <&pciesys CLK_PCIE_P1_PIPE_EN>; -+ clock-names = "sys_ck1", "ahb_ck1", "aux_ck1", -+ "axi_ck1", "obff_ck1", "pipe_ck1"; -+ -+ power-domains = <&scpsys MT7622_POWER_DOMAIN_HIF0>; -+ bus-range = <0x00 0xff>; -+ ranges = <0x82000000 0 0x28000000 0x0 0x28000000 0 0x8000000>; -+ status = "disabled"; - -- interrupt-map-mask = <0 0 0 7>; -- interrupt-map = <0 0 0 1 &pcie_intc1 0>, -- <0 0 0 2 &pcie_intc1 1>, -- <0 0 0 3 &pcie_intc1 2>, -- <0 0 0 4 &pcie_intc1 3>; -- pcie_intc1: interrupt-controller { -- interrupt-controller; -- #address-cells = <0>; -- #interrupt-cells = <1>; -- }; -+ #interrupt-cells = <1>; -+ interrupt-map-mask = <0 0 0 7>; -+ interrupt-map = <0 0 0 1 &pcie_intc1 0>, -+ <0 0 0 2 &pcie_intc1 1>, -+ <0 0 0 3 &pcie_intc1 2>, -+ <0 0 0 4 &pcie_intc1 3>; -+ pcie_intc1: interrupt-controller { -+ interrupt-controller; -+ #address-cells = <0>; -+ #interrupt-cells = <1>; - }; - }; - diff --git a/target/linux/mediatek/patches-5.15/601-PCI-mediatek-Assert-PERST-for-100ms-for-power-and-cl.patch b/target/linux/mediatek/patches-5.15/601-PCI-mediatek-Assert-PERST-for-100ms-for-power-and-cl.patch deleted file mode 100644 index b7311e042..000000000 --- a/target/linux/mediatek/patches-5.15/601-PCI-mediatek-Assert-PERST-for-100ms-for-power-and-cl.patch +++ /dev/null @@ -1,34 +0,0 @@ -From: qizhong cheng -Date: Mon, 27 Dec 2021 21:31:10 +0800 -Subject: [PATCH] PCI: mediatek: Assert PERST# for 100ms for power and clock to - stabilize -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Described in PCIe CEM specification sections 2.2 (PERST# Signal) and -2.2.1 (Initial Power-Up (G3 to S0)). The deassertion of PERST# should -be delayed 100ms (TPVPERL) for the power and clock to become stable. - -Link: https://lore.kernel.org/r/20211227133110.14500-1-qizhong.cheng@mediatek.com -Signed-off-by: qizhong cheng -Signed-off-by: Lorenzo Pieralisi -Acked-by: Pali Rohár ---- - ---- a/drivers/pci/controller/pcie-mediatek.c -+++ b/drivers/pci/controller/pcie-mediatek.c -@@ -708,6 +708,13 @@ static int mtk_pcie_startup_port_v2(stru - */ - writel(PCIE_LINKDOWN_RST_EN, port->base + PCIE_RST_CTRL); - -+ /* -+ * Described in PCIe CEM specification sections 2.2 (PERST# Signal) and -+ * 2.2.1 (Initial Power-Up (G3 to S0)). The deassertion of PERST# should -+ * be delayed 100ms (TPVPERL) for the power and clock to become stable. -+ */ -+ msleep(100); -+ - /* De-assert PHY, PE, PIPE, MAC and configuration reset */ - val = readl(port->base + PCIE_RST_CTRL); - val |= PCIE_PHY_RSTB | PCIE_PERSTB | PCIE_PIPE_SRSTB | diff --git a/target/linux/mediatek/patches-5.15/602-arm64-dts-mediatek-add-mt7622-pcie-slot-node.patch b/target/linux/mediatek/patches-5.15/602-arm64-dts-mediatek-add-mt7622-pcie-slot-node.patch deleted file mode 100644 index d58082aa6..000000000 --- a/target/linux/mediatek/patches-5.15/602-arm64-dts-mediatek-add-mt7622-pcie-slot-node.patch +++ /dev/null @@ -1,28 +0,0 @@ ---- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi -+++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi -@@ -844,6 +844,12 @@ - #address-cells = <0>; - #interrupt-cells = <1>; - }; -+ -+ slot0: pcie@0,0 { -+ reg = <0x0000 0 0 0 0>; -+ #address-cells = <3>; -+ #size-cells = <2>; -+ }; - }; - - pcie1: pcie@1a145000 { -@@ -882,6 +888,12 @@ - #address-cells = <0>; - #interrupt-cells = <1>; - }; -+ -+ slot1: pcie@1,0 { -+ reg = <0x0800 0 0 0 0>; -+ #address-cells = <3>; -+ #size-cells = <2>; -+ }; - }; - - sata: sata@1a200000 { diff --git a/target/linux/mediatek/patches-5.15/603-v5.16-ARM-dts-mediatek-Update-mt7629-PCIe-node.patch b/target/linux/mediatek/patches-5.15/603-v5.16-ARM-dts-mediatek-Update-mt7629-PCIe-node.patch deleted file mode 100644 index 252ef080f..000000000 --- a/target/linux/mediatek/patches-5.15/603-v5.16-ARM-dts-mediatek-Update-mt7629-PCIe-node.patch +++ /dev/null @@ -1,203 +0,0 @@ -From patchwork Thu May 28 06:16:48 2020 -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 7bit -X-Patchwork-Submitter: Chuanjia Liu -X-Patchwork-Id: 11574797 -Return-Path: - -Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org - [172.30.200.123]) - by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 30A5E1392 - for ; - Thu, 28 May 2020 06:29:05 +0000 (UTC) -Received: from bombadil.infradead.org (bombadil.infradead.org - [198.137.202.133]) - (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) - (No client certificate requested) - by mail.kernel.org (Postfix) with ESMTPS id 08B6320721 - for ; - Thu, 28 May 2020 06:29:05 +0000 (UTC) -Authentication-Results: mail.kernel.org; - dkim=pass (2048-bit key) header.d=lists.infradead.org - header.i=@lists.infradead.org header.b="auhxDafY"; - dkim=fail reason="signature verification failed" (1024-bit key) - header.d=mediatek.com header.i=@mediatek.com header.b="Kj09Arxb" -DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 08B6320721 -Authentication-Results: mail.kernel.org; - dmarc=fail (p=none dis=none) header.from=mediatek.com -Authentication-Results: mail.kernel.org; - spf=none - smtp.mailfrom=linux-mediatek-bounces+patchwork-linux-mediatek=patchwork.kernel.org@lists.infradead.org -DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; - d=lists.infradead.org; s=bombadil.20170209; h=Sender: - Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: - List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: - Message-ID:Date:Subject:To:From:Reply-To:Content-ID:Content-Description: - Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: - List-Owner; bh=+QPxF1vlOH7StIZYuXJa3V40x8QVDxCLF9AFXHblB9M=; b=auhxDafYBeaUZO - aYp2KVO8Aie0v4tYtRwBon7hF+x55JwD78SAxQR2RsSvrlOo9cMYYby+ToUWflVUWQ60FapAl+w+l - nkEjIOrLBErHwxNOcsD8T5kjyCBMqlz4OMAQYUDNJ3fSugRlGhOtxkjCGd9ebB8N2Rvu6/U8P1A9n - P15mEQoc+RLonR1+9mBgwTEXErjsraxkimTD4Txsp4IvMs3UdsMkP+r3OT5S/p+Uj6O9ES0h7xIon - aL79KaVqRLHrfZxnrVwuGiecAiTp8qLy9clHuJU32NA6ZcXH1OnWipKApgp8Ck7ys80WPKaMrat9B - XuskJ63w13DZAbCVvuGQ==; -Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) - by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) - id 1jeC2J-00014n-M9; Thu, 28 May 2020 06:29:03 +0000 -Received: from mailgw02.mediatek.com ([216.200.240.185]) - by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) - id 1jeC2H-00013t-Li; Thu, 28 May 2020 06:29:03 +0000 -X-UUID: a4877c1586e64afeb2d6172e10605d2b-20200527 -DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; - d=mediatek.com; - s=dk; - h=Content-Transfer-Encoding:Content-Type:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:CC:To:From; - bh=CIwcBFK1x0LbOjDt1BG6/knHFxDHRiqj8ov/jWEZDBY=; - b=Kj09ArxbnLVTc9bpaVPT3jQrIVjhL87sSYyVF9dFypS976k78Ce9gZd0f4K3zAZbYZHYoQtuyOQ9TOeufQfgD+Cr+j5VR7pTdO2E1iXHFs/eQAz5gAjvjlK01z1JiunrLnn9dvIr6c1gEkjQHny0VpuZ1duxx79jwYusg/Nw6Wc=; -X-UUID: a4877c1586e64afeb2d6172e10605d2b-20200527 -Received: from mtkcas66.mediatek.inc [(172.29.193.44)] by - mailgw02.mediatek.com - (envelope-from ) - (musrelay.mediatek.com ESMTP with TLS) - with ESMTP id 899663677; Wed, 27 May 2020 22:29:21 -0800 -Received: from MTKMBS07N2.mediatek.inc (172.21.101.141) by - MTKMBS62DR.mediatek.inc (172.29.94.18) with Microsoft SMTP Server (TLS) id - 15.0.1497.2; Wed, 27 May 2020 23:18:50 -0700 -Received: from mtkcas07.mediatek.inc (172.21.101.84) by - mtkmbs07n2.mediatek.inc (172.21.101.141) with Microsoft SMTP Server (TLS) id - 15.0.1497.2; Thu, 28 May 2020 14:18:54 +0800 -Received: from localhost.localdomain (10.17.3.153) by mtkcas07.mediatek.inc - (172.21.101.73) with Microsoft SMTP Server id 15.0.1497.2 via Frontend - Transport; Thu, 28 May 2020 14:18:52 +0800 -From: -To: , , -Subject: [PATCH v2 4/4] ARM: dts: mediatek: Update mt7629 PCIe node -Date: Thu, 28 May 2020 14:16:48 +0800 -Message-ID: <20200528061648.32078-5-chuanjia.liu@mediatek.com> -X-Mailer: git-send-email 2.18.0 -In-Reply-To: <20200528061648.32078-1-chuanjia.liu@mediatek.com> -References: <20200528061648.32078-1-chuanjia.liu@mediatek.com> -MIME-Version: 1.0 -X-MTK: N -X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 -X-CRM114-CacheID: sfid-20200527_232901_719172_E5A99C62 -X-CRM114-Status: GOOD ( 11.61 ) -X-Spam-Score: -0.2 (/) -X-Spam-Report: SpamAssassin version 3.4.4 on bombadil.infradead.org summary: - Content analysis details: (-0.2 points) - pts rule name description - ---- ---------------------- - -------------------------------------------------- - -0.0 SPF_PASS SPF: sender matches SPF record - 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record - 0.0 MIME_BASE64_TEXT RAW: Message text disguised using base64 - encoding - -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from - author's domain - 0.1 DKIM_SIGNED Message has a DKIM or DK signature, - not necessarily - valid - -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature - -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from - envelope-from domain - 0.0 UNPARSEABLE_RELAY Informational: message has unparseable relay - lines -X-BeenThere: linux-mediatek@lists.infradead.org -X-Mailman-Version: 2.1.29 -Precedence: list -List-Id: -List-Unsubscribe: , - -List-Archive: -List-Post: -List-Help: -List-Subscribe: , - -Cc: devicetree@vger.kernel.org, lorenzo.pieralisi@arm.com, - srv_heupstream@mediatek.com, "chuanjia.liu" , - linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org, - jianjun.wang@mediatek.com, linux-mediatek@lists.infradead.org, - yong.wu@mediatek.com, bhelgaas@google.com, - linux-arm-kernel@lists.infradead.org, amurray@thegoodpenguin.co.uk -Sender: "Linux-mediatek" -Errors-To: - linux-mediatek-bounces+patchwork-linux-mediatek=patchwork.kernel.org@lists.infradead.org - -From: "chuanjia.liu" - -Remove unused property and add pciecfg node. - -Signed-off-by: chuanjia.liu ---- - arch/arm/boot/dts/mt7629-rfb.dts | 3 ++- - arch/arm/boot/dts/mt7629.dtsi | 23 +++++++++++++---------- - 2 files changed, 15 insertions(+), 11 deletions(-) - ---- a/arch/arm/boot/dts/mt7629-rfb.dts -+++ b/arch/arm/boot/dts/mt7629-rfb.dts -@@ -149,9 +149,10 @@ - }; - }; - --&pcie { -+&pcie1 { - pinctrl-names = "default"; - pinctrl-0 = <&pcie_pins>; -+ status = "okay"; - }; - - &pciephy1 { ---- a/arch/arm/boot/dts/mt7629.dtsi -+++ b/arch/arm/boot/dts/mt7629.dtsi -@@ -382,16 +382,21 @@ - #reset-cells = <1>; - }; - -- pcie: pcie@1a140000 { -+ pciecfg: pciecfg@1a140000 { -+ compatible = "mediatek,mt7629-pciecfg", "syscon"; -+ reg = <0x1a140000 0x1000>; -+ }; -+ -+ pcie1: pcie@1a145000 { - compatible = "mediatek,mt7629-pcie"; - device_type = "pci"; -- reg = <0x1a140000 0x1000>, -- <0x1a145000 0x1000>; -- reg-names = "subsys","port1"; -+ reg = <0x1a145000 0x1000>; -+ reg-names = "port1"; -+ mediatek,pcie-cfg = <&pciecfg>; - #address-cells = <3>; - #size-cells = <2>; -- interrupts = , -- ; -+ interrupts = ; -+ interrupt-names = "pcie_irq"; - clocks = <&pciesys CLK_PCIE_P1_MAC_EN>, - <&pciesys CLK_PCIE_P0_AHB_EN>, - <&pciesys CLK_PCIE_P1_AUX_EN>, -@@ -412,21 +417,19 @@ - power-domains = <&scpsys MT7622_POWER_DOMAIN_HIF0>; - bus-range = <0x00 0xff>; - ranges = <0x82000000 0 0x20000000 0x20000000 0 0x10000000>; -+ status = "disabled"; - -- pcie1: pcie@1,0 { -- device_type = "pci"; -+ slot1: pcie@1,0 { - reg = <0x0800 0 0 0 0>; - #address-cells = <3>; - #size-cells = <2>; - #interrupt-cells = <1>; - ranges; -- num-lanes = <1>; - interrupt-map-mask = <0 0 0 7>; - interrupt-map = <0 0 0 1 &pcie_intc1 0>, - <0 0 0 2 &pcie_intc1 1>, - <0 0 0 3 &pcie_intc1 2>, - <0 0 0 4 &pcie_intc1 3>; -- - pcie_intc1: interrupt-controller { - interrupt-controller; - #address-cells = <0>; diff --git a/target/linux/mediatek/patches-5.15/610-pcie-mediatek-fix-clearing-interrupt-status.patch b/target/linux/mediatek/patches-5.15/610-pcie-mediatek-fix-clearing-interrupt-status.patch deleted file mode 100644 index 2bebfddf5..000000000 --- a/target/linux/mediatek/patches-5.15/610-pcie-mediatek-fix-clearing-interrupt-status.patch +++ /dev/null @@ -1,23 +0,0 @@ -From: Felix Fietkau -Date: Fri, 4 Sep 2020 18:33:27 +0200 -Subject: [PATCH] pcie-mediatek: fix clearing interrupt status - -Clearing the status needs to happen after running the handler, otherwise -we will get an extra spurious interrupt after the cause has been cleared - -Signed-off-by: Felix Fietkau ---- - ---- a/drivers/pci/controller/pcie-mediatek.c -+++ b/drivers/pci/controller/pcie-mediatek.c -@@ -614,9 +614,9 @@ static void mtk_pcie_intr_handler(struct - if (status & INTX_MASK) { - for_each_set_bit_from(bit, &status, PCI_NUM_INTX + INTX_SHIFT) { - /* Clear the INTx */ -- writel(1 << bit, port->base + PCIE_INT_STATUS); - generic_handle_domain_irq(port->irq_domain, - bit - INTX_SHIFT); -+ writel(1 << bit, port->base + PCIE_INT_STATUS); - } - } - diff --git a/target/linux/mediatek/patches-5.15/702-v5.17-net-mdio-add-helpers-to-extract-clause-45-regad-and-.patch b/target/linux/mediatek/patches-5.15/702-v5.17-net-mdio-add-helpers-to-extract-clause-45-regad-and-.patch deleted file mode 100644 index da33aaa72..000000000 --- a/target/linux/mediatek/patches-5.15/702-v5.17-net-mdio-add-helpers-to-extract-clause-45-regad-and-.patch +++ /dev/null @@ -1,53 +0,0 @@ -From c6af53f038aa32cec12e8a305ba07c7ef168f1b0 Mon Sep 17 00:00:00 2001 -From: "Russell King (Oracle)" -Date: Tue, 4 Jan 2022 12:07:00 +0000 -Subject: [PATCH 2/3] net: mdio: add helpers to extract clause 45 regad and - devad fields - -Add a couple of helpers and definitions to extract the clause 45 regad -and devad fields from the regnum passed into MDIO drivers. - -Tested-by: Daniel Golle -Reviewed-by: Andrew Lunn -Signed-off-by: Russell King (Oracle) -Signed-off-by: Daniel Golle -Signed-off-by: David S. Miller ---- - include/linux/mdio.h | 12 ++++++++++++ - 1 file changed, 12 insertions(+) - ---- a/include/linux/mdio.h -+++ b/include/linux/mdio.h -@@ -7,6 +7,7 @@ - #define __LINUX_MDIO_H__ - - #include -+#include - #include - - /* Or MII_ADDR_C45 into regnum for read/write on mii_bus to enable the 21 bit -@@ -14,6 +15,7 @@ - */ - #define MII_ADDR_C45 (1<<30) - #define MII_DEVADDR_C45_SHIFT 16 -+#define MII_DEVADDR_C45_MASK GENMASK(20, 16) - #define MII_REGADDR_C45_MASK GENMASK(15, 0) - - struct gpio_desc; -@@ -355,6 +357,16 @@ static inline u32 mdiobus_c45_addr(int d - return MII_ADDR_C45 | devad << MII_DEVADDR_C45_SHIFT | regnum; - } - -+static inline u16 mdiobus_c45_regad(u32 regnum) -+{ -+ return FIELD_GET(MII_REGADDR_C45_MASK, regnum); -+} -+ -+static inline u16 mdiobus_c45_devad(u32 regnum) -+{ -+ return FIELD_GET(MII_DEVADDR_C45_MASK, regnum); -+} -+ - static inline int __mdiobus_c45_read(struct mii_bus *bus, int prtad, int devad, - u16 regnum) - { diff --git a/target/linux/mediatek/patches-5.15/703-v5.17-net-ethernet-mtk_eth_soc-implement-Clause-45-MDIO-ac.patch b/target/linux/mediatek/patches-5.15/703-v5.17-net-ethernet-mtk_eth_soc-implement-Clause-45-MDIO-ac.patch deleted file mode 100644 index efda5fda4..000000000 --- a/target/linux/mediatek/patches-5.15/703-v5.17-net-ethernet-mtk_eth_soc-implement-Clause-45-MDIO-ac.patch +++ /dev/null @@ -1,128 +0,0 @@ -From e2e7f6e29c99a1c6afc0e0aa4b9ea80302d28720 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Tue, 4 Jan 2022 12:07:46 +0000 -Subject: [PATCH 3/3] net: ethernet: mtk_eth_soc: implement Clause 45 MDIO - access - -Implement read and write access to IEEE 802.3 Clause 45 Ethernet -phy registers while making use of new mdiobus_c45_regad and -mdiobus_c45_devad helpers. - -Tested on the Ubiquiti UniFi 6 LR access point featuring -MediaTek MT7622BV WiSoC with Aquantia AQR112C. - -Signed-off-by: Daniel Golle -Signed-off-by: David S. Miller ---- - drivers/net/ethernet/mediatek/mtk_eth_soc.c | 70 +++++++++++++++++---- - drivers/net/ethernet/mediatek/mtk_eth_soc.h | 3 + - 2 files changed, 60 insertions(+), 13 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -323,13 +323,35 @@ static int _mtk_mdio_write(struct mtk_et - if (ret < 0) - return ret; - -- mtk_w32(eth, PHY_IAC_ACCESS | -- PHY_IAC_START_C22 | -- PHY_IAC_CMD_WRITE | -- PHY_IAC_REG(phy_reg) | -- PHY_IAC_ADDR(phy_addr) | -- PHY_IAC_DATA(write_data), -- MTK_PHY_IAC); -+ if (phy_reg & MII_ADDR_C45) { -+ mtk_w32(eth, PHY_IAC_ACCESS | -+ PHY_IAC_START_C45 | -+ PHY_IAC_CMD_C45_ADDR | -+ PHY_IAC_REG(mdiobus_c45_devad(phy_reg)) | -+ PHY_IAC_ADDR(phy_addr) | -+ PHY_IAC_DATA(mdiobus_c45_regad(phy_reg)), -+ MTK_PHY_IAC); -+ -+ ret = mtk_mdio_busy_wait(eth); -+ if (ret < 0) -+ return ret; -+ -+ mtk_w32(eth, PHY_IAC_ACCESS | -+ PHY_IAC_START_C45 | -+ PHY_IAC_CMD_WRITE | -+ PHY_IAC_REG(mdiobus_c45_devad(phy_reg)) | -+ PHY_IAC_ADDR(phy_addr) | -+ PHY_IAC_DATA(write_data), -+ MTK_PHY_IAC); -+ } else { -+ mtk_w32(eth, PHY_IAC_ACCESS | -+ PHY_IAC_START_C22 | -+ PHY_IAC_CMD_WRITE | -+ PHY_IAC_REG(phy_reg) | -+ PHY_IAC_ADDR(phy_addr) | -+ PHY_IAC_DATA(write_data), -+ MTK_PHY_IAC); -+ } - - ret = mtk_mdio_busy_wait(eth); - if (ret < 0) -@@ -346,12 +368,33 @@ static int _mtk_mdio_read(struct mtk_eth - if (ret < 0) - return ret; - -- mtk_w32(eth, PHY_IAC_ACCESS | -- PHY_IAC_START_C22 | -- PHY_IAC_CMD_C22_READ | -- PHY_IAC_REG(phy_reg) | -- PHY_IAC_ADDR(phy_addr), -- MTK_PHY_IAC); -+ if (phy_reg & MII_ADDR_C45) { -+ mtk_w32(eth, PHY_IAC_ACCESS | -+ PHY_IAC_START_C45 | -+ PHY_IAC_CMD_C45_ADDR | -+ PHY_IAC_REG(mdiobus_c45_devad(phy_reg)) | -+ PHY_IAC_ADDR(phy_addr) | -+ PHY_IAC_DATA(mdiobus_c45_regad(phy_reg)), -+ MTK_PHY_IAC); -+ -+ ret = mtk_mdio_busy_wait(eth); -+ if (ret < 0) -+ return ret; -+ -+ mtk_w32(eth, PHY_IAC_ACCESS | -+ PHY_IAC_START_C45 | -+ PHY_IAC_CMD_C45_READ | -+ PHY_IAC_REG(mdiobus_c45_devad(phy_reg)) | -+ PHY_IAC_ADDR(phy_addr), -+ MTK_PHY_IAC); -+ } else { -+ mtk_w32(eth, PHY_IAC_ACCESS | -+ PHY_IAC_START_C22 | -+ PHY_IAC_CMD_C22_READ | -+ PHY_IAC_REG(phy_reg) | -+ PHY_IAC_ADDR(phy_addr), -+ MTK_PHY_IAC); -+ } - - ret = mtk_mdio_busy_wait(eth); - if (ret < 0) -@@ -897,6 +940,7 @@ static int mtk_mdio_init(struct mtk_eth - eth->mii_bus->name = "mdio"; - eth->mii_bus->read = mtk_mdio_read; - eth->mii_bus->write = mtk_mdio_write; -+ eth->mii_bus->probe_capabilities = MDIOBUS_C22_C45; - eth->mii_bus->priv = eth; - eth->mii_bus->parent = eth->dev; - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -402,9 +402,12 @@ - #define PHY_IAC_ADDR_MASK GENMASK(24, 20) - #define PHY_IAC_ADDR(x) FIELD_PREP(PHY_IAC_ADDR_MASK, (x)) - #define PHY_IAC_CMD_MASK GENMASK(19, 18) -+#define PHY_IAC_CMD_C45_ADDR FIELD_PREP(PHY_IAC_CMD_MASK, 0) - #define PHY_IAC_CMD_WRITE FIELD_PREP(PHY_IAC_CMD_MASK, 1) - #define PHY_IAC_CMD_C22_READ FIELD_PREP(PHY_IAC_CMD_MASK, 2) -+#define PHY_IAC_CMD_C45_READ FIELD_PREP(PHY_IAC_CMD_MASK, 3) - #define PHY_IAC_START_MASK GENMASK(17, 16) -+#define PHY_IAC_START_C45 FIELD_PREP(PHY_IAC_START_MASK, 0) - #define PHY_IAC_START_C22 FIELD_PREP(PHY_IAC_START_MASK, 1) - #define PHY_IAC_DATA_MASK GENMASK(15, 0) - #define PHY_IAC_DATA(x) FIELD_PREP(PHY_IAC_DATA_MASK, (x)) diff --git a/target/linux/mediatek/patches-5.15/710-pci-pcie-mediatek-add-support-for-coherent-DMA.patch b/target/linux/mediatek/patches-5.15/710-pci-pcie-mediatek-add-support-for-coherent-DMA.patch deleted file mode 100644 index 917a458d3..000000000 --- a/target/linux/mediatek/patches-5.15/710-pci-pcie-mediatek-add-support-for-coherent-DMA.patch +++ /dev/null @@ -1,91 +0,0 @@ -From: Felix Fietkau -Date: Fri, 4 Sep 2020 18:42:42 +0200 -Subject: [PATCH] pci: pcie-mediatek: add support for coherent DMA - -It improves performance by eliminating the need for a cache flush for DMA on -attached devices - -Signed-off-by: Felix Fietkau ---- - ---- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi -+++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi -@@ -832,6 +832,9 @@ - bus-range = <0x00 0xff>; - ranges = <0x82000000 0 0x20000000 0x0 0x20000000 0 0x8000000>; - status = "disabled"; -+ dma-coherent; -+ mediatek,hifsys = <&hifsys>; -+ mediatek,cci-control = <&cci_control2>; - - #interrupt-cells = <1>; - interrupt-map-mask = <0 0 0 7>; -@@ -876,6 +879,9 @@ - bus-range = <0x00 0xff>; - ranges = <0x82000000 0 0x28000000 0x0 0x28000000 0 0x8000000>; - status = "disabled"; -+ dma-coherent; -+ mediatek,hifsys = <&hifsys>; -+ mediatek,cci-control = <&cci_control2>; - - #interrupt-cells = <1>; - interrupt-map-mask = <0 0 0 7>; -@@ -937,7 +943,7 @@ - }; - - hifsys: clock-controller@1af00000 { -- compatible = "mediatek,mt7622-hifsys"; -+ compatible = "mediatek,mt7622-hifsys", "syscon"; - reg = <0 0x1af00000 0 0x70>; - #clock-cells = <1>; - }; ---- a/drivers/pci/controller/pcie-mediatek.c -+++ b/drivers/pci/controller/pcie-mediatek.c -@@ -20,6 +20,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -139,6 +140,11 @@ - #define PCIE_LINK_STATUS_V2 0x804 - #define PCIE_PORT_LINKUP_V2 BIT(10) - -+/* DMA channel mapping */ -+#define HIFSYS_DMA_AG_MAP 0x008 -+#define HIFSYS_DMA_AG_MAP_PCIE0 BIT(0) -+#define HIFSYS_DMA_AG_MAP_PCIE1 BIT(1) -+ - struct mtk_pcie_port; - - /** -@@ -1060,6 +1066,27 @@ static int mtk_pcie_setup(struct mtk_pci - struct mtk_pcie_port *port, *tmp; - int err, slot; - -+ if (of_dma_is_coherent(node)) { -+ struct regmap *con; -+ u32 mask; -+ -+ con = syscon_regmap_lookup_by_phandle(node, -+ "mediatek,cci-control"); -+ /* enable CPU/bus coherency */ -+ if (!IS_ERR(con)) -+ regmap_write(con, 0, 3); -+ -+ con = syscon_regmap_lookup_by_phandle(node, -+ "mediatek,hifsys"); -+ if (IS_ERR(con)) { -+ dev_err(dev, "missing hifsys node\n"); -+ return PTR_ERR(con); -+ } -+ -+ mask = HIFSYS_DMA_AG_MAP_PCIE0 | HIFSYS_DMA_AG_MAP_PCIE1; -+ regmap_update_bits(con, HIFSYS_DMA_AG_MAP, mask, mask); -+ } -+ - slot = of_get_pci_domain_nr(dev->of_node); - if (slot < 0) { - for_each_available_child_of_node(node, child) { diff --git a/target/linux/mediatek/patches-5.15/721-dts-mt7622-mediatek-fix-300mhz.patch b/target/linux/mediatek/patches-5.15/721-dts-mt7622-mediatek-fix-300mhz.patch deleted file mode 100644 index f9a5fdbd0..000000000 --- a/target/linux/mediatek/patches-5.15/721-dts-mt7622-mediatek-fix-300mhz.patch +++ /dev/null @@ -1,27 +0,0 @@ -From: Jip de Beer -Date: Sun, 9 Jan 2022 13:14:04 +0100 -Subject: [PATCH] mediatek mt7622: fix 300mhz typo in dts - -The lowest frequency should be 300MHz, since that is the label -assigned to the OPP in the mt7622.dtsi device tree, while there is one -missing zero in the actual value. - -To be clear, the lowest frequency should be 300MHz instead of 30MHz. - -As mentioned @dangowrt on the OpenWrt forum there is no benefit in -leaving 30MHz as the lowest frequency. - -Signed-off-by: Jip de Beer -Signed-off-by: Fritz D. Ansel ---- ---- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi -+++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi -@@ -24,7 +24,7 @@ - compatible = "operating-points-v2"; - opp-shared; - opp-300000000 { -- opp-hz = /bits/ 64 <30000000>; -+ opp-hz = /bits/ 64 <300000000>; - opp-microvolt = <950000>; - }; - diff --git a/target/linux/mediatek/patches-5.15/722-remove-300Hz-to-prevent-freeze.patch b/target/linux/mediatek/patches-5.15/722-remove-300Hz-to-prevent-freeze.patch deleted file mode 100644 index 52069496c..000000000 --- a/target/linux/mediatek/patches-5.15/722-remove-300Hz-to-prevent-freeze.patch +++ /dev/null @@ -1,25 +0,0 @@ ---- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi -+++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi -@@ -23,11 +23,17 @@ - cpu_opp_table: opp-table { - compatible = "operating-points-v2"; - opp-shared; -- opp-300000000 { -- opp-hz = /bits/ 64 <300000000>; -- opp-microvolt = <950000>; -- }; -- -+ /* Due to the bug described at the link below, remove the 300 MHz clock to avoid a low -+ * voltage condition that can cause a hang when rebooting the RT3200/E8450. -+ * -+ * https://forum.openwrt.org/t/belkin-rt3200-linksys-e8450-wifi-ax-discussion/94302/1490 -+ * -+ * opp-300000000 { -+ * opp-hz = /bits/ 64 <300000000>; -+ * opp-microvolt = <950000>; -+ * }; -+ * -+ */ - opp-437500000 { - opp-hz = /bits/ 64 <437500000>; - opp-microvolt = <1000000>; diff --git a/target/linux/mediatek/patches-5.15/730-v6.5-net-phy-add-driver-for-MediaTek-SoC-built-in-GE-PHYs.patch b/target/linux/mediatek/patches-5.15/730-v6.5-net-phy-add-driver-for-MediaTek-SoC-built-in-GE-PHYs.patch deleted file mode 100644 index 7b27bd2f6..000000000 --- a/target/linux/mediatek/patches-5.15/730-v6.5-net-phy-add-driver-for-MediaTek-SoC-built-in-GE-PHYs.patch +++ /dev/null @@ -1,1204 +0,0 @@ -From 98c485eaf509bc0e2a85f9b58d17cd501f274c4e Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Sun, 11 Jun 2023 00:48:10 +0100 -Subject: [PATCH] net: phy: add driver for MediaTek SoC built-in GE PHYs - -Some of MediaTek's Filogic SoCs come with built-in gigabit Ethernet -PHYs which require calibration data from the SoC's efuse. -Despite the similar design the driver doesn't share any code with the -existing mediatek-ge.c. -Add support for such PHYs by introducing a new driver with basic -support for MediaTek SoCs MT7981 and MT7988 built-in 1GE PHYs. - -Signed-off-by: Daniel Golle -Reviewed-by: Andrew Lunn -Signed-off-by: David S. Miller ---- - MAINTAINERS | 9 + - drivers/net/phy/Kconfig | 12 + - drivers/net/phy/Makefile | 1 + - drivers/net/phy/mediatek-ge-soc.c | 1116 +++++++++++++++++++++++++++++ - drivers/net/phy/mediatek-ge.c | 3 +- - 5 files changed, 1140 insertions(+), 1 deletion(-) - create mode 100644 drivers/net/phy/mediatek-ge-soc.c - ---- a/MAINTAINERS -+++ b/MAINTAINERS -@@ -11798,6 +11798,15 @@ S: Maintained - F: drivers/net/pcs/pcs-mtk-lynxi.c - F: include/linux/pcs/pcs-mtk-lynxi.h - -+MEDIATEK ETHERNET PHY DRIVERS -+M: Daniel Golle -+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 -+ - MEDIATEK I2C CONTROLLER DRIVER - M: Qii Wang - L: linux-i2c@vger.kernel.org ---- a/drivers/net/phy/Kconfig -+++ b/drivers/net/phy/Kconfig -@@ -293,6 +293,18 @@ config MEDIATEK_GE_PHY - help - Supports the MediaTek Gigabit Ethernet PHYs. - -+config MEDIATEK_GE_SOC_PHY -+ tristate "MediaTek SoC Ethernet PHYs" -+ depends on (ARM64 && ARCH_MEDIATEK) || COMPILE_TEST -+ select 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. -+ - config MICREL_PHY - tristate "Micrel PHYs" - help ---- a/drivers/net/phy/Makefile -+++ b/drivers/net/phy/Makefile -@@ -81,6 +81,7 @@ obj-$(CONFIG_MARVELL_PHY) += marvell.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-$(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-ge-soc.c -@@ -0,0 +1,1116 @@ -+// SPDX-License-Identifier: GPL-2.0+ -+#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_SHIFT (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 -+ -+#define MTK_PHY_RG_BG_RASEL 0x115 -+#define MTK_PHY_RG_BG_RASEL_MASK GENMASK(2, 0) -+ -+/* 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 { -+ GPHY_PORT0, -+ GPHY_PORT1, -+ GPHY_PORT2, -+ GPHY_PORT3, -+}; -+ -+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 -+}; -+ -+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) >> -+ MTK_PHY_AD_CAL_COMP_OUT_SHIFT; -+ 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) -+{ -+ 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 }; -+ 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, (buf[0] + bias[0]) << 10); -+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TXVLD_DA_RG, -+ 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); -+ 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]); -+ -+ 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); -+ 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]); -+ 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); -+ 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]); -+ -+ 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); -+ 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]); -+ 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); -+ 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]); -+ -+ 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); -+ 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]); -+ 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); -+ 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]); -+ -+ 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 = -2; -+ -+ 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); -+ /* 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); -+ -+ /* TrFreeze = 0 */ -+ __phy_write(phydev, 0x11, 0x0); -+ __phy_write(phydev, 0x12, 0x0); -+ __phy_write(phydev, 0x10, 0x9686); -+ -+ /* SSTrKp1000Slv = 5 */ -+ __phy_write(phydev, 0x11, 0xbaef); -+ __phy_write(phydev, 0x12, 0x2e); -+ __phy_write(phydev, 0x10, 0x968c); -+ -+ /* 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 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); -+ /* SlvDSPreadyTime = 24, MasDSPreadyTime = 24 */ -+ __phy_write(phydev, 0x11, 0xc71); -+ __phy_write(phydev, 0x12, 0xc); -+ __phy_write(phydev, 0x10, 0x8fae); -+ -+ /* 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); -+ -+ /* FfeUpdGainForce = 4 */ -+ __phy_write(phydev, 0x11, 0x240); -+ __phy_write(phydev, 0x12, 0x0); -+ __phy_write(phydev, 0x10, 0x9680); -+ -+ phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0); -+} -+ -+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); -+ -+ /* Disable TX power saving */ -+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RXADC_CTRL_RG7, -+ MTK_PHY_DA_AD_BUF_BIAS_LP_MASK, 0x3 << 8); -+ -+ phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5); -+ -+ /* SlvDSPreadyTime = 24, MasDSPreadyTime = 12 */ -+ __phy_write(phydev, 0x11, 0x671); -+ __phy_write(phydev, 0x12, 0xc); -+ __phy_write(phydev, 0x10, 0x8fae); -+ -+ /* ResetSyncOffset = 5 */ -+ __phy_write(phydev, 0x11, 0x500); -+ __phy_write(phydev, 0x12, 0x0); -+ __phy_write(phydev, 0x10, 0x8fc0); -+ -+ /* VgaDecRate is 1 at default on mt7988 */ -+ -+ phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0); -+ -+ phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_2A30); -+ /* TxClkOffset = 2 */ -+ __phy_modify(phydev, MTK_PHY_ANARG_RG, MTK_PHY_TCLKOFFSET_MASK, -+ FIELD_PREP(MTK_PHY_TCLKOFFSET_MASK, 0x2)); -+ phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0); -+} -+ -+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)); -+ -+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG239, -+ MTK_PHY_LPI_SEND_LOC_TIMER_MASK | -+ MTK_PHY_LPI_TXPCS_LOC_RCV, -+ FIELD_PREP(MTK_PHY_LPI_SEND_LOC_TIMER_MASK, 0x117)); -+ -+ 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 = 3 */ -+ __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 = 1 */ -+ __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) -+{ -+ int ret = 0; -+ u32 *buf; -+ size_t len; -+ struct nvmem_cell *cell; -+ -+ 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 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 = mt798x_phy_calibration, -+ .suspend = genphy_suspend, -+ .resume = genphy_resume, -+ .read_page = mtk_socphy_read_page, -+ .write_page = mtk_socphy_write_page, -+ }, -+ { -+ 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 = mt798x_phy_calibration, -+ .suspend = genphy_suspend, -+ .resume = genphy_resume, -+ .read_page = mtk_socphy_read_page, -+ .write_page = mtk_socphy_write_page, -+ }, -+}; -+ -+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 -+++ b/drivers/net/phy/mediatek-ge.c -@@ -136,7 +136,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_VENDOR(0x03a29400) }, -+ { PHY_ID_MATCH_EXACT(0x03a29441) }, -+ { PHY_ID_MATCH_EXACT(0x03a29412) }, - { } - }; - diff --git a/target/linux/mediatek/patches-5.15/731-net-phy-mediatek-ge-soc-initialize-MT7988-PHY-LEDs-d.patch b/target/linux/mediatek/patches-5.15/731-net-phy-mediatek-ge-soc-initialize-MT7988-PHY-LEDs-d.patch deleted file mode 100644 index 83d0f26bf..000000000 --- a/target/linux/mediatek/patches-5.15/731-net-phy-mediatek-ge-soc-initialize-MT7988-PHY-LEDs-d.patch +++ /dev/null @@ -1,213 +0,0 @@ -From 5d2d78860f98eb5c03bc404eb024606878901ac8 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Tue, 13 Jun 2023 03:27:14 +0100 -Subject: [PATCH] net: phy: mediatek-ge-soc: initialize MT7988 PHY LEDs default - state - -Initialize LEDs and set sane default values. -Read boottrap register and apply LED polarities accordingly to get -uniform behavior from all LEDs on MT7988. -Requires syscon phandle 'mediatek,pio' present in parenting MDIO bus -which should point to the syscon holding the boottrap register. - -Signed-off-by: Daniel Golle ---- - drivers/net/phy/mediatek-ge-soc.c | 144 ++++++++++++++++++++++++++++-- - 1 file changed, 136 insertions(+), 8 deletions(-) - ---- a/drivers/net/phy/mediatek-ge-soc.c -+++ b/drivers/net/phy/mediatek-ge-soc.c -@@ -1,11 +1,13 @@ - // SPDX-License-Identifier: GPL-2.0+ - #include -+#include - #include - #include - #include - #include - #include - #include -+#include - - #define MTK_GPHY_ID_MT7981 0x03a29461 - #define MTK_GPHY_ID_MT7988 0x03a29481 -@@ -208,9 +210,40 @@ - #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_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_FORCE_ON BIT(6) -+#define MTK_PHY_LED_POLARITY BIT(14) -+#define MTK_PHY_LED_ENABLE BIT(15) -+ -+#define MTK_PHY_LED0_BLINK_CTRL 0x25 -+#define MTK_PHY_LED1_BLINK_CTRL 0x27 -+#define MTK_PHY_LED_1000TX BIT(0) -+#define MTK_PHY_LED_1000RX BIT(1) -+#define MTK_PHY_LED_100TX BIT(2) -+#define MTK_PHY_LED_100RX BIT(3) -+#define MTK_PHY_LED_10TX BIT(4) -+#define MTK_PHY_LED_10RX BIT(5) -+#define MTK_PHY_LED_COLLISION BIT(6) -+#define MTK_PHY_LED_RX_CRC_ERR BIT(7) -+#define MTK_PHY_LED_RX_IDLE_ERR BIT(8) -+#define MTK_PHY_LED_FORCE_BLINK BIT(9) -+ - #define MTK_PHY_RG_BG_RASEL 0x115 - #define MTK_PHY_RG_BG_RASEL_MASK GENMASK(2, 0) - -+/* Register in boottrap syscon defining the initial state 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)) -@@ -238,13 +271,6 @@ enum { - PAIR_D, - }; - --enum { -- GPHY_PORT0, -- GPHY_PORT1, -- GPHY_PORT2, -- GPHY_PORT3, --}; -- - enum calibration_mode { - EFUSE_K, - SW_K -@@ -263,6 +289,10 @@ enum CAL_MODE { - SW_M - }; - -+struct mtk_socphy_shared { -+ u32 boottrap; -+}; -+ - static int mtk_socphy_read_page(struct phy_device *phydev) - { - return __phy_read(phydev, MTK_EXT_PAGE_ACCESS); -@@ -1073,6 +1103,104 @@ static int mt798x_phy_config_init(struct - return mt798x_phy_calibration(phydev); - } - -+static int mt798x_phy_setup_led(struct phy_device *phydev, bool inverted) -+{ -+ struct pinctrl *pinctrl; -+ const u16 led_on_ctrl_defaults = MTK_PHY_LED_ENABLE | -+ MTK_PHY_LED_ON_LINK1000 | -+ MTK_PHY_LED_ON_LINK100 | -+ MTK_PHY_LED_ON_LINK10; -+ const u16 led_blink_defaults = MTK_PHY_LED_1000TX | -+ MTK_PHY_LED_1000RX | -+ MTK_PHY_LED_100TX | -+ MTK_PHY_LED_100RX | -+ MTK_PHY_LED_10TX | -+ MTK_PHY_LED_10RX; -+ -+ phy_write_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_LED0_ON_CTRL, -+ led_on_ctrl_defaults ^ -+ (inverted ? MTK_PHY_LED_POLARITY : 0)); -+ -+ phy_write_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_LED1_ON_CTRL, -+ led_on_ctrl_defaults); -+ -+ phy_write_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_LED0_BLINK_CTRL, -+ led_blink_defaults); -+ -+ phy_write_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_LED1_BLINK_CTRL, -+ led_blink_defaults); -+ -+ 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\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 *priv = 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 practise 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; -+ -+ priv->boottrap = FIELD_GET(RG_GPIO_MISC_TPBANK0_BOOTMODE, reg); -+ -+ return 0; -+} -+ -+static bool mt7988_phy_get_boottrap_polarity(struct phy_device *phydev) -+{ -+ struct mtk_socphy_shared *priv = phydev->shared->priv; -+ -+ if (priv->boottrap & BIT(phydev->mdio.addr)) -+ return false; -+ -+ return true; -+} -+ -+static int mt7988_phy_probe(struct phy_device *phydev) -+{ -+ int err; -+ -+ 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; -+ } -+ -+ mt798x_phy_setup_led(phydev, mt7988_phy_get_boottrap_polarity(phydev)); -+ -+ return mt798x_phy_calibration(phydev); -+} -+ - static struct phy_driver mtk_socphy_driver[] = { - { - PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7981), -@@ -1092,7 +1220,7 @@ static struct phy_driver mtk_socphy_driv - .config_init = mt798x_phy_config_init, - .config_intr = genphy_no_config_intr, - .handle_interrupt = genphy_handle_interrupt_no_ack, -- .probe = mt798x_phy_calibration, -+ .probe = mt7988_phy_probe, - .suspend = genphy_suspend, - .resume = genphy_resume, - .read_page = mtk_socphy_read_page, diff --git a/target/linux/mediatek/patches-5.15/732-net-phy-mxl-gpy-don-t-use-SGMII-AN-if-using-phylink.patch b/target/linux/mediatek/patches-5.15/732-net-phy-mxl-gpy-don-t-use-SGMII-AN-if-using-phylink.patch deleted file mode 100644 index 598d9d0d2..000000000 --- a/target/linux/mediatek/patches-5.15/732-net-phy-mxl-gpy-don-t-use-SGMII-AN-if-using-phylink.patch +++ /dev/null @@ -1,63 +0,0 @@ -From a969b663c866129ed9eb217785a6574fbe826f1d Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Thu, 6 Apr 2023 23:36:50 +0100 -Subject: [PATCH] net: phy: mxl-gpy: don't use SGMII AN if using phylink - -MAC drivers using phylink expect SGMII in-band-status to be switched off -when attached to a PHY. Make sure this is the case also for mxl-gpy which -keeps SGMII in-band-status in case of SGMII interface mode is used. - -Signed-off-by: Daniel Golle ---- - drivers/net/phy/mxl-gpy.c | 19 ++++++++++++++++--- - 1 file changed, 16 insertions(+), 3 deletions(-) - ---- a/drivers/net/phy/mxl-gpy.c -+++ b/drivers/net/phy/mxl-gpy.c -@@ -191,8 +191,11 @@ static bool gpy_2500basex_chk(struct phy - - phydev->speed = SPEED_2500; - phydev->interface = PHY_INTERFACE_MODE_2500BASEX; -- phy_modify_mmd(phydev, MDIO_MMD_VEND1, VSPEC1_SGMII_CTRL, -- VSPEC1_SGMII_CTRL_ANEN, 0); -+ -+ if (!phydev->phylink) -+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, VSPEC1_SGMII_CTRL, -+ VSPEC1_SGMII_CTRL_ANEN, 0); -+ - return true; - } - -@@ -216,6 +219,14 @@ static int gpy_config_aneg(struct phy_de - u32 adv; - int ret; - -+ /* Disable SGMII auto-negotiation if using phylink */ -+ if (phydev->phylink) { -+ ret = phy_modify_mmd(phydev, MDIO_MMD_VEND1, VSPEC1_SGMII_CTRL, -+ VSPEC1_SGMII_CTRL_ANEN, 0); -+ if (ret < 0) -+ return ret; -+ } -+ - if (phydev->autoneg == AUTONEG_DISABLE) { - /* Configure half duplex with genphy_setup_forced, - * because genphy_c45_pma_setup_forced does not support. -@@ -306,6 +317,8 @@ static void gpy_update_interface(struct - switch (phydev->speed) { - case SPEED_2500: - phydev->interface = PHY_INTERFACE_MODE_2500BASEX; -+ if (phydev->phylink) -+ break; - ret = phy_modify_mmd(phydev, MDIO_MMD_VEND1, VSPEC1_SGMII_CTRL, - VSPEC1_SGMII_CTRL_ANEN, 0); - if (ret < 0) -@@ -317,7 +330,7 @@ static void gpy_update_interface(struct - case SPEED_100: - case SPEED_10: - phydev->interface = PHY_INTERFACE_MODE_SGMII; -- if (gpy_sgmii_aneg_en(phydev)) -+ if (phydev->phylink || gpy_sgmii_aneg_en(phydev)) - break; - /* Enable and restart SGMII ANEG for 10/100/1000Mbps link speed - * if ANEG is disabled (in 2500-BaseX mode). diff --git a/target/linux/mediatek/patches-5.15/733-net-phy-add-driver-for-MediaTek-2.5G-PHY.patch b/target/linux/mediatek/patches-5.15/733-net-phy-add-driver-for-MediaTek-2.5G-PHY.patch deleted file mode 100644 index 7151eb35c..000000000 --- a/target/linux/mediatek/patches-5.15/733-net-phy-add-driver-for-MediaTek-2.5G-PHY.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 128dc09b0af36772062142ce9e85b19c84ac789a Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Tue, 28 Feb 2023 17:53:37 +0000 -Subject: [PATCH] net: phy: add driver for MediaTek 2.5G PHY - -Signed-off-by: Daniel Golle ---- - drivers/net/phy/Kconfig | 7 ++ - drivers/net/phy/Makefile | 1 + - drivers/net/phy/mediatek-2p5ge.c | 220 +++++++++++++++++++++++++++++++ - 3 files changed, 226 insertions(+) - create mode 100644 drivers/net/phy/mediatek-2p5ge.c - ---- a/drivers/net/phy/Kconfig -+++ b/drivers/net/phy/Kconfig -@@ -305,6 +305,13 @@ config MEDIATEK_GE_SOC_PHY - present in the SoCs efuse and will dynamically calibrate VCM - (common-mode voltage) during startup. - -+config MEDIATEK_2P5G_PHY -+ tristate "MediaTek 2.5G Ethernet PHY" -+ depends on (ARCH_MEDIATEK && ARM64) || COMPILE_TEST -+ default NET_MEDIATEK_SOC -+ help -+ Supports the MediaTek 2.5G Ethernet PHY. -+ - config MICREL_PHY - tristate "Micrel PHYs" - help ---- a/drivers/net/phy/Makefile -+++ b/drivers/net/phy/Makefile -@@ -80,6 +80,7 @@ obj-$(CONFIG_MARVELL_10G_PHY) += marvell - obj-$(CONFIG_MARVELL_PHY) += marvell.o - obj-$(CONFIG_MARVELL_88X2222_PHY) += marvell-88x2222.o - obj-$(CONFIG_MAXLINEAR_GPHY) += mxl-gpy.o -+obj-$(CONFIG_MEDIATEK_2P5G_PHY) += mediatek-2p5ge.o - obj-$(CONFIG_MEDIATEK_GE_PHY) += mediatek-ge.o - obj-$(CONFIG_MEDIATEK_GE_SOC_PHY) += mediatek-ge-soc.o - obj-$(CONFIG_MESON_GXL_PHY) += meson-gxl.o diff --git a/target/linux/mediatek/patches-5.15/800-v5.17-nvmem-mtk-efuse-support-minimum-one-byte-access-stri.patch b/target/linux/mediatek/patches-5.15/800-v5.17-nvmem-mtk-efuse-support-minimum-one-byte-access-stri.patch deleted file mode 100644 index 785bfe53f..000000000 --- a/target/linux/mediatek/patches-5.15/800-v5.17-nvmem-mtk-efuse-support-minimum-one-byte-access-stri.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 98e2c4efae214fb7086cac9117616eb6ea11475d Mon Sep 17 00:00:00 2001 -From: Chunfeng Yun -Date: Thu, 9 Dec 2021 17:42:34 +0000 -Subject: [PATCH] nvmem: mtk-efuse: support minimum one byte access stride and - granularity - -In order to support nvmem bits property, should support minimum 1 byte -read stride and minimum 1 byte read granularity at the same time. - -Signed-off-by: Chunfeng Yun -Signed-off-by: Srinivas Kandagatla -Link: https://lore.kernel.org/r/20211209174235.14049-4-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman ---- - drivers/nvmem/mtk-efuse.c | 13 +++++++------ - 1 file changed, 7 insertions(+), 6 deletions(-) - ---- a/drivers/nvmem/mtk-efuse.c -+++ b/drivers/nvmem/mtk-efuse.c -@@ -19,11 +19,12 @@ static int mtk_reg_read(void *context, - unsigned int reg, void *_val, size_t bytes) - { - struct mtk_efuse_priv *priv = context; -- u32 *val = _val; -- int i = 0, words = bytes / 4; -+ void __iomem *addr = priv->base + reg; -+ u8 *val = _val; -+ int i; - -- while (words--) -- *val++ = readl(priv->base + reg + (i++ * 4)); -+ for (i = 0; i < bytes; i++, val++) -+ *val = readb(addr + i); - - return 0; - } -@@ -45,8 +46,8 @@ static int mtk_efuse_probe(struct platfo - if (IS_ERR(priv->base)) - return PTR_ERR(priv->base); - -- econfig.stride = 4; -- econfig.word_size = 4; -+ econfig.stride = 1; -+ econfig.word_size = 1; - econfig.reg_read = mtk_reg_read; - econfig.size = resource_size(res); - econfig.priv = priv; diff --git a/target/linux/mediatek/patches-5.15/801-phy-phy-mtk-tphy-Add-PCIe-2-lane-efuse-support.patch b/target/linux/mediatek/patches-5.15/801-phy-phy-mtk-tphy-Add-PCIe-2-lane-efuse-support.patch deleted file mode 100644 index 691a7c039..000000000 --- a/target/linux/mediatek/patches-5.15/801-phy-phy-mtk-tphy-Add-PCIe-2-lane-efuse-support.patch +++ /dev/null @@ -1,225 +0,0 @@ -From 41ffe32e7ec23f592e21c508b5108899ad393059 Mon Sep 17 00:00:00 2001 -From: Zhanyong Wang -Date: Tue, 25 Jan 2022 16:50:47 +0800 -Subject: [PATCH 4/5] phy: phy-mtk-tphy: Add PCIe 2 lane efuse support - -Add PCIe 2 lane efuse support in tphy driver. - -Signed-off-by: Jie Yang -Signed-off-by: Zhanyong Wang ---- - drivers/phy/mediatek/phy-mtk-tphy.c | 140 ++++++++++++++++++++++++++++ - 1 file changed, 140 insertions(+) - ---- a/drivers/phy/mediatek/phy-mtk-tphy.c -+++ b/drivers/phy/mediatek/phy-mtk-tphy.c -@@ -44,6 +44,15 @@ - #define SSUSB_SIFSLV_V2_U3PHYD 0x200 - #define SSUSB_SIFSLV_V2_U3PHYA 0x400 - -+/* version V4 sub-banks offset base address */ -+/* pcie phy banks */ -+#define SSUSB_SIFSLV_V4_SPLLC 0x000 -+#define SSUSB_SIFSLV_V4_CHIP 0x100 -+#define SSUSB_SIFSLV_V4_U3PHYD 0x900 -+#define SSUSB_SIFSLV_V4_U3PHYA 0xb00 -+ -+#define SSUSB_LN1_OFFSET 0x10000 -+ - #define U3P_MISC_REG1 0x04 - #define MR1_EFUSE_AUTO_LOAD_DIS BIT(6) - -@@ -320,6 +329,7 @@ enum mtk_phy_version { - MTK_PHY_V1 = 1, - MTK_PHY_V2, - MTK_PHY_V3, -+ MTK_PHY_V4, - }; - - struct mtk_phy_pdata { -@@ -369,6 +379,9 @@ struct mtk_phy_instance { - u32 efuse_intr; - u32 efuse_tx_imp; - u32 efuse_rx_imp; -+ u32 efuse_intr_ln1; -+ u32 efuse_tx_imp_ln1; -+ u32 efuse_rx_imp_ln1; - int eye_src; - int eye_vrt; - int eye_term; -@@ -946,6 +959,36 @@ static void phy_v2_banks_init(struct mtk - } - } - -+static void phy_v4_banks_init(struct mtk_tphy *tphy, -+ struct mtk_phy_instance *instance) -+{ -+ struct u2phy_banks *u2_banks = &instance->u2_banks; -+ struct u3phy_banks *u3_banks = &instance->u3_banks; -+ -+ switch (instance->type) { -+ case PHY_TYPE_USB2: -+ u2_banks->misc = instance->port_base + SSUSB_SIFSLV_V2_MISC; -+ u2_banks->fmreg = instance->port_base + SSUSB_SIFSLV_V2_U2FREQ; -+ u2_banks->com = instance->port_base + SSUSB_SIFSLV_V2_U2PHY_COM; -+ break; -+ case PHY_TYPE_USB3: -+ u3_banks->spllc = instance->port_base + SSUSB_SIFSLV_V2_SPLLC; -+ u3_banks->chip = instance->port_base + SSUSB_SIFSLV_V2_CHIP; -+ u3_banks->phyd = instance->port_base + SSUSB_SIFSLV_V2_U3PHYD; -+ u3_banks->phya = instance->port_base + SSUSB_SIFSLV_V2_U3PHYA; -+ break; -+ case PHY_TYPE_PCIE: -+ u3_banks->spllc = instance->port_base + SSUSB_SIFSLV_V4_SPLLC; -+ u3_banks->chip = instance->port_base + SSUSB_SIFSLV_V4_CHIP; -+ u3_banks->phyd = instance->port_base + SSUSB_SIFSLV_V4_U3PHYD; -+ u3_banks->phya = instance->port_base + SSUSB_SIFSLV_V4_U3PHYA; -+ break; -+ default: -+ dev_err(tphy->dev, "incompatible PHY type\n"); -+ return; -+ } -+} -+ - static void phy_parse_property(struct mtk_tphy *tphy, - struct mtk_phy_instance *instance) - { -@@ -1144,6 +1187,40 @@ static int phy_efuse_get(struct mtk_tphy - - dev_dbg(dev, "u3 efuse - intr %x, rx_imp %x, tx_imp %x\n", - instance->efuse_intr, instance->efuse_rx_imp,instance->efuse_tx_imp); -+ -+ if (tphy->pdata->version != MTK_PHY_V4) -+ break; -+ -+ ret = nvmem_cell_read_variable_le_u32(dev, "intr_ln1", &instance->efuse_intr_ln1); -+ if (ret) { -+ dev_err(dev, "fail to get u3 lane1 intr efuse, %d\n", ret); -+ break; -+ } -+ -+ ret = nvmem_cell_read_variable_le_u32(dev, "rx_imp_ln1", &instance->efuse_rx_imp_ln1); -+ if (ret) { -+ dev_err(dev, "fail to get u3 lane1 rx_imp efuse, %d\n", ret); -+ break; -+ } -+ -+ ret = nvmem_cell_read_variable_le_u32(dev, "tx_imp_ln1", &instance->efuse_tx_imp_ln1); -+ if (ret) { -+ dev_err(dev, "fail to get u3 lane1 tx_imp efuse, %d\n", ret); -+ break; -+ } -+ -+ /* no efuse, ignore it */ -+ if (!instance->efuse_intr_ln1 && -+ !instance->efuse_rx_imp_ln1 && -+ !instance->efuse_tx_imp_ln1) { -+ dev_warn(dev, "no u3 lane1 efuse, but dts enable it\n"); -+ instance->efuse_sw_en = 0; -+ break; -+ } -+ -+ dev_info(dev, "u3 lane1 efuse - intr %x, rx_imp %x, tx_imp %x\n", -+ instance->efuse_intr_ln1, instance->efuse_rx_imp_ln1, -+ instance->efuse_tx_imp_ln1); - break; - default: - dev_err(dev, "no sw efuse for type %d\n", instance->type); -@@ -1175,6 +1252,31 @@ static void phy_efuse_set(struct mtk_phy - writel(tmp, u2_banks->com + U3P_USBPHYACR1); - break; - case PHY_TYPE_USB3: -+ tmp = readl(u3_banks->phyd + U3P_U3_PHYD_RSV); -+ tmp |= P3D_RG_EFUSE_AUTO_LOAD_DIS; -+ writel(tmp, u3_banks->phyd + U3P_U3_PHYD_RSV); -+ -+ tmp = readl(u3_banks->phyd + U3P_U3_PHYD_IMPCAL0); -+ tmp &= ~P3D_RG_TX_IMPEL; -+ tmp |= P3D_RG_TX_IMPEL_VAL(instance->efuse_tx_imp); -+ tmp |= P3D_RG_FORCE_TX_IMPEL; -+ writel(tmp, u3_banks->phyd + U3P_U3_PHYD_IMPCAL0); -+ -+ tmp = readl(u3_banks->phyd + U3P_U3_PHYD_IMPCAL1); -+ tmp &= ~P3D_RG_RX_IMPEL; -+ tmp |= P3D_RG_RX_IMPEL_VAL(instance->efuse_rx_imp); -+ tmp |= P3D_RG_FORCE_RX_IMPEL; -+ writel(tmp, u3_banks->phyd + U3P_U3_PHYD_IMPCAL1); -+ -+ tmp = readl(u3_banks->phya + U3P_U3_PHYA_REG0); -+ tmp &= ~P3A_RG_IEXT_INTR; -+ tmp |= P3A_RG_IEXT_INTR_VAL(instance->efuse_intr); -+ writel(tmp, u3_banks->phya + U3P_U3_PHYA_REG0); -+ pr_err("%s set efuse, tx_imp %x, rx_imp %x intr %x\n", -+ __func__, instance->efuse_tx_imp, -+ instance->efuse_rx_imp, instance->efuse_intr); -+ -+ break; - case PHY_TYPE_PCIE: - tmp = readl(u3_banks->phyd + U3P_U3_PHYD_RSV); - tmp |= P3D_RG_EFUSE_AUTO_LOAD_DIS; -@@ -1196,6 +1298,34 @@ static void phy_efuse_set(struct mtk_phy - tmp &= ~P3A_RG_IEXT_INTR; - tmp |= P3A_RG_IEXT_INTR_VAL(instance->efuse_intr); - writel(tmp, u3_banks->phya + U3P_U3_PHYA_REG0); -+ if (!instance->efuse_intr_ln1 && -+ !instance->efuse_rx_imp_ln1 && -+ !instance->efuse_tx_imp_ln1) -+ break; -+ -+ tmp = readl(u3_banks->phyd + SSUSB_LN1_OFFSET + U3P_U3_PHYD_RSV); -+ tmp |= P3D_RG_EFUSE_AUTO_LOAD_DIS; -+ writel(tmp, u3_banks->phyd + SSUSB_LN1_OFFSET + U3P_U3_PHYD_RSV); -+ -+ tmp = readl(u3_banks->phyd + SSUSB_LN1_OFFSET + U3P_U3_PHYD_IMPCAL0); -+ tmp &= ~P3D_RG_TX_IMPEL; -+ tmp |= P3D_RG_TX_IMPEL_VAL(instance->efuse_tx_imp_ln1); -+ tmp |= P3D_RG_FORCE_TX_IMPEL; -+ writel(tmp, u3_banks->phyd + SSUSB_LN1_OFFSET + U3P_U3_PHYD_IMPCAL0); -+ -+ tmp = readl(u3_banks->phyd + SSUSB_LN1_OFFSET + U3P_U3_PHYD_IMPCAL1); -+ tmp &= ~P3D_RG_RX_IMPEL; -+ tmp |= P3D_RG_RX_IMPEL_VAL(instance->efuse_rx_imp_ln1); -+ tmp |= P3D_RG_FORCE_RX_IMPEL; -+ writel(tmp, u3_banks->phyd + SSUSB_LN1_OFFSET + U3P_U3_PHYD_IMPCAL1); -+ -+ tmp = readl(u3_banks->phya + SSUSB_LN1_OFFSET + U3P_U3_PHYA_REG0); -+ tmp &= ~P3A_RG_IEXT_INTR; -+ tmp |= P3A_RG_IEXT_INTR_VAL(instance->efuse_intr_ln1); -+ writel(tmp, u3_banks->phya + SSUSB_LN1_OFFSET + U3P_U3_PHYA_REG0); -+ dev_info(dev, "%s set LN1 efuse, tx_imp %x, rx_imp %x intr %x\n", -+ __func__, instance->efuse_tx_imp_ln1, -+ instance->efuse_rx_imp_ln1, instance->efuse_intr_ln1); - break; - default: - dev_warn(dev, "no sw efuse for type %d\n", instance->type); -@@ -1335,6 +1465,9 @@ static struct phy *mtk_phy_xlate(struct - case MTK_PHY_V3: - phy_v2_banks_init(tphy, instance); - break; -+ case MTK_PHY_V4: -+ phy_v4_banks_init(tphy, instance); -+ break; - default: - dev_err(dev, "phy version is not supported\n"); - return ERR_PTR(-EINVAL); -@@ -1375,6 +1508,12 @@ static const struct mtk_phy_pdata tphy_v - .version = MTK_PHY_V3, - }; - -+static const struct mtk_phy_pdata tphy_v4_pdata = { -+ .avoid_rx_sen_degradation = false, -+ .sw_efuse_supported = true, -+ .version = MTK_PHY_V4, -+}; -+ - static const struct mtk_phy_pdata mt8173_pdata = { - .avoid_rx_sen_degradation = true, - .version = MTK_PHY_V1, -@@ -1394,6 +1533,7 @@ static const struct of_device_id mtk_tph - { .compatible = "mediatek,generic-tphy-v1", .data = &tphy_v1_pdata }, - { .compatible = "mediatek,generic-tphy-v2", .data = &tphy_v2_pdata }, - { .compatible = "mediatek,generic-tphy-v3", .data = &tphy_v3_pdata }, -+ { .compatible = "mediatek,generic-tphy-v4", .data = &tphy_v4_pdata }, - { }, - }; - MODULE_DEVICE_TABLE(of, mtk_tphy_id_table); diff --git a/target/linux/mediatek/patches-5.15/802-phy-phy-mtk-tphy-add-auto-load-valid-check-mechanism.patch b/target/linux/mediatek/patches-5.15/802-phy-phy-mtk-tphy-add-auto-load-valid-check-mechanism.patch deleted file mode 100644 index 3b8285bf4..000000000 --- a/target/linux/mediatek/patches-5.15/802-phy-phy-mtk-tphy-add-auto-load-valid-check-mechanism.patch +++ /dev/null @@ -1,149 +0,0 @@ -From 1d5819e90f2ef6dead11809744372a9863227a92 Mon Sep 17 00:00:00 2001 -From: Zhanyong Wang -Date: Tue, 25 Jan 2022 19:03:34 +0800 -Subject: [PATCH 5/5] phy: phy-mtk-tphy: add auto-load-valid check mechanism - support - -add auto-load-valid check mechanism support - -Signed-off-by: Zhanyong Wang ---- - drivers/phy/mediatek/phy-mtk-tphy.c | 67 +++++++++++++++++++++++++++-- - 1 file changed, 64 insertions(+), 3 deletions(-) - ---- a/drivers/phy/mediatek/phy-mtk-tphy.c -+++ b/drivers/phy/mediatek/phy-mtk-tphy.c -@@ -376,9 +376,13 @@ struct mtk_phy_instance { - u32 type_sw_reg; - u32 type_sw_index; - u32 efuse_sw_en; -+ bool efuse_alv_en; -+ u32 efuse_autoloadvalid; - u32 efuse_intr; - u32 efuse_tx_imp; - u32 efuse_rx_imp; -+ bool efuse_alv_ln1_en; -+ u32 efuse_ln1_autoloadvalid; - u32 efuse_intr_ln1; - u32 efuse_tx_imp_ln1; - u32 efuse_rx_imp_ln1; -@@ -1126,6 +1130,7 @@ static int phy_efuse_get(struct mtk_tphy - { - struct device *dev = &instance->phy->dev; - int ret = 0; -+ bool alv = false; - - /* tphy v1 doesn't support sw efuse, skip it */ - if (!tphy->pdata->sw_efuse_supported) { -@@ -1140,6 +1145,20 @@ static int phy_efuse_get(struct mtk_tphy - - switch (instance->type) { - case PHY_TYPE_USB2: -+ alv = of_property_read_bool(dev->of_node, "auto_load_valid"); -+ if (alv) { -+ instance->efuse_alv_en = alv; -+ ret = nvmem_cell_read_variable_le_u32(dev, "auto_load_valid", -+ &instance->efuse_autoloadvalid); -+ if (ret) { -+ dev_err(dev, "fail to get u2 alv efuse, %d\n", ret); -+ break; -+ } -+ dev_info(dev, -+ "u2 auto load valid efuse: ENABLE with value: %u\n", -+ instance->efuse_autoloadvalid); -+ } -+ - ret = nvmem_cell_read_variable_le_u32(dev, "intr", &instance->efuse_intr); - if (ret) { - dev_err(dev, "fail to get u2 intr efuse, %d\n", ret); -@@ -1158,6 +1177,20 @@ static int phy_efuse_get(struct mtk_tphy - - case PHY_TYPE_USB3: - case PHY_TYPE_PCIE: -+ alv = of_property_read_bool(dev->of_node, "auto_load_valid"); -+ if (alv) { -+ instance->efuse_alv_en = alv; -+ ret = nvmem_cell_read_variable_le_u32(dev, "auto_load_valid", -+ &instance->efuse_autoloadvalid); -+ if (ret) { -+ dev_err(dev, "fail to get u3(pcei) alv efuse, %d\n", ret); -+ break; -+ } -+ dev_info(dev, -+ "u3 auto load valid efuse: ENABLE with value: %u\n", -+ instance->efuse_autoloadvalid); -+ } -+ - ret = nvmem_cell_read_variable_le_u32(dev, "intr", &instance->efuse_intr); - if (ret) { - dev_err(dev, "fail to get u3 intr efuse, %d\n", ret); -@@ -1191,6 +1224,20 @@ static int phy_efuse_get(struct mtk_tphy - if (tphy->pdata->version != MTK_PHY_V4) - break; - -+ alv = of_property_read_bool(dev->of_node, "auto_load_valid_ln1"); -+ if (alv) { -+ instance->efuse_alv_ln1_en = alv; -+ ret = nvmem_cell_read_variable_le_u32(dev, "auto_load_valid_ln1", -+ &instance->efuse_ln1_autoloadvalid); -+ if (ret) { -+ dev_err(dev, "fail to get pcie auto_load_valid efuse, %d\n", ret); -+ break; -+ } -+ dev_info(dev, -+ "pcie auto load valid efuse: ENABLE with value: %u\n", -+ instance->efuse_ln1_autoloadvalid); -+ } -+ - ret = nvmem_cell_read_variable_le_u32(dev, "intr_ln1", &instance->efuse_intr_ln1); - if (ret) { - dev_err(dev, "fail to get u3 lane1 intr efuse, %d\n", ret); -@@ -1242,6 +1289,10 @@ static void phy_efuse_set(struct mtk_phy - - switch (instance->type) { - case PHY_TYPE_USB2: -+ if (instance->efuse_alv_en && -+ instance->efuse_autoloadvalid == 1) -+ break; -+ - tmp = readl(u2_banks->misc + U3P_MISC_REG1); - tmp |= MR1_EFUSE_AUTO_LOAD_DIS; - writel(tmp, u2_banks->misc + U3P_MISC_REG1); -@@ -1252,6 +1303,10 @@ static void phy_efuse_set(struct mtk_phy - writel(tmp, u2_banks->com + U3P_USBPHYACR1); - break; - case PHY_TYPE_USB3: -+ if (instance->efuse_alv_en && -+ instance->efuse_autoloadvalid == 1) -+ break; -+ - tmp = readl(u3_banks->phyd + U3P_U3_PHYD_RSV); - tmp |= P3D_RG_EFUSE_AUTO_LOAD_DIS; - writel(tmp, u3_banks->phyd + U3P_U3_PHYD_RSV); -@@ -1278,6 +1333,10 @@ static void phy_efuse_set(struct mtk_phy - - break; - case PHY_TYPE_PCIE: -+ if (instance->efuse_alv_en && -+ instance->efuse_autoloadvalid == 1) -+ break; -+ - tmp = readl(u3_banks->phyd + U3P_U3_PHYD_RSV); - tmp |= P3D_RG_EFUSE_AUTO_LOAD_DIS; - writel(tmp, u3_banks->phyd + U3P_U3_PHYD_RSV); -@@ -1298,9 +1357,12 @@ static void phy_efuse_set(struct mtk_phy - tmp &= ~P3A_RG_IEXT_INTR; - tmp |= P3A_RG_IEXT_INTR_VAL(instance->efuse_intr); - writel(tmp, u3_banks->phya + U3P_U3_PHYA_REG0); -- if (!instance->efuse_intr_ln1 && -- !instance->efuse_rx_imp_ln1 && -- !instance->efuse_tx_imp_ln1) -+ -+ if ((!instance->efuse_intr_ln1 && -+ !instance->efuse_rx_imp_ln1 && -+ !instance->efuse_tx_imp_ln1) || -+ (instance->efuse_alv_ln1_en && -+ instance->efuse_ln1_autoloadvalid == 1)) - break; - - tmp = readl(u3_banks->phyd + SSUSB_LN1_OFFSET + U3P_U3_PHYD_RSV); diff --git a/target/linux/mediatek/patches-5.15/804-pwm-add-mt7986-support.patch b/target/linux/mediatek/patches-5.15/804-pwm-add-mt7986-support.patch deleted file mode 100644 index 7a10dac05..000000000 --- a/target/linux/mediatek/patches-5.15/804-pwm-add-mt7986-support.patch +++ /dev/null @@ -1,23 +0,0 @@ ---- a/drivers/pwm/pwm-mediatek.c -+++ b/drivers/pwm/pwm-mediatek.c -@@ -302,6 +302,12 @@ static const struct pwm_mediatek_of_data - .has_ck_26m_sel = true, - }; - -+static const struct pwm_mediatek_of_data mt7986_pwm_data = { -+ .num_pwms = 2, -+ .pwm45_fixup = false, -+ .has_ck_26m_sel = true, -+}; -+ - static const struct pwm_mediatek_of_data mt8516_pwm_data = { - .num_pwms = 5, - .pwm45_fixup = false, -@@ -314,6 +320,7 @@ static const struct of_device_id pwm_med - { .compatible = "mediatek,mt7623-pwm", .data = &mt7623_pwm_data }, - { .compatible = "mediatek,mt7628-pwm", .data = &mt7628_pwm_data }, - { .compatible = "mediatek,mt7629-pwm", .data = &mt7629_pwm_data }, -+ { .compatible = "mediatek,mt7986-pwm", .data = &mt7986_pwm_data }, - { .compatible = "mediatek,mt8183-pwm", .data = &mt8183_pwm_data }, - { .compatible = "mediatek,mt8516-pwm", .data = &mt8516_pwm_data }, - { }, diff --git a/target/linux/mediatek/patches-5.15/805-v6.2-thermal-drivers-mtk-use-function-pointer-for-raw_to_.patch b/target/linux/mediatek/patches-5.15/805-v6.2-thermal-drivers-mtk-use-function-pointer-for-raw_to_.patch deleted file mode 100644 index c58ae9640..000000000 --- a/target/linux/mediatek/patches-5.15/805-v6.2-thermal-drivers-mtk-use-function-pointer-for-raw_to_.patch +++ /dev/null @@ -1,56 +0,0 @@ -From 69c17529e8418da3eec703dde31e1b01e5b0f7e8 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Wed, 18 Jan 2023 02:48:41 +0000 -Subject: [PATCH 1/2] thermal/drivers/mtk: use function pointer for - raw_to_mcelsius - -Instead of having if-else logic selecting either raw_to_mcelsius_v1 or -raw_to_mcelsius_v2 in mtk_thermal_bank_temperature introduce a function -pointer raw_to_mcelsius to struct mtk_thermal which is initialized in the -probe function. - -Signed-off-by: Daniel Golle ---- - drivers/thermal/mtk_thermal.c | 17 ++++++++++------- - 1 file changed, 10 insertions(+), 7 deletions(-) - ---- a/drivers/thermal/mtk_thermal.c -+++ b/drivers/thermal/mtk_thermal.c -@@ -292,6 +292,8 @@ struct mtk_thermal { - - const struct mtk_thermal_data *conf; - struct mtk_thermal_bank banks[MAX_NUM_ZONES]; -+ -+ int (*raw_to_mcelsius)(struct mtk_thermal *mt, int sensno, s32 raw); - }; - - /* MT8183 thermal sensor data */ -@@ -656,13 +658,9 @@ static int mtk_thermal_bank_temperature( - for (i = 0; i < conf->bank_data[bank->id].num_sensors; i++) { - raw = readl(mt->thermal_base + conf->msr[i]); - -- if (mt->conf->version == MTK_THERMAL_V1) { -- temp = raw_to_mcelsius_v1( -- mt, conf->bank_data[bank->id].sensors[i], raw); -- } else { -- temp = raw_to_mcelsius_v2( -- mt, conf->bank_data[bank->id].sensors[i], raw); -- } -+ temp = mt->raw_to_mcelsius( -+ mt, conf->bank_data[bank->id].sensors[i], raw); -+ - - /* - * The first read of a sensor often contains very high bogus -@@ -1075,6 +1073,11 @@ static int mtk_thermal_probe(struct plat - mtk_thermal_release_periodic_ts(mt, auxadc_base); - } - -+ if (mt->conf->version == MTK_THERMAL_V1) -+ mt->raw_to_mcelsius = raw_to_mcelsius_v1; -+ else -+ mt->raw_to_mcelsius = raw_to_mcelsius_v2; -+ - for (ctrl_id = 0; ctrl_id < mt->conf->num_controller ; ctrl_id++) - for (i = 0; i < mt->conf->num_banks; i++) - mtk_thermal_init_bank(mt, i, apmixed_phys_base, diff --git a/target/linux/mediatek/patches-5.15/806-v6.2-thermal-mediatek-add-support-for-MT7986-and-MT7981.patch b/target/linux/mediatek/patches-5.15/806-v6.2-thermal-mediatek-add-support-for-MT7986-and-MT7981.patch deleted file mode 100644 index 65311d571..000000000 --- a/target/linux/mediatek/patches-5.15/806-v6.2-thermal-mediatek-add-support-for-MT7986-and-MT7981.patch +++ /dev/null @@ -1,240 +0,0 @@ -From aa957c759b1182aee00cc35178667f849f941b42 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Wed, 30 Nov 2022 13:19:39 +0000 -Subject: [PATCH 2/2] thermal: mediatek: add support for MT7986 and MT7981 - -Add support for V3 generation thermal found in MT7986 and MT7981 SoCs. -Brings code to assign values from efuse as well as new function to -convert raw temperature to millidegree celsius, as found in MediaTek's -SDK sources (but cleaned up and de-duplicated) - -[1]: https://git01.mediatek.com/plugins/gitiles/openwrt/feeds/mtk-openwrt-feeds/+/baf36c7eef477aae1f8f2653b6c29e2caf48475b -Signed-off-by: Daniel Golle ---- - drivers/thermal/mtk_thermal.c | 137 ++++++++++++++++++++++++++++++++-- - 1 file changed, 132 insertions(+), 5 deletions(-) - ---- a/drivers/thermal/mtk_thermal.c -+++ b/drivers/thermal/mtk_thermal.c -@@ -150,6 +150,20 @@ - #define CALIB_BUF1_VALID_V2(x) (((x) >> 4) & 0x1) - #define CALIB_BUF1_O_SLOPE_SIGN_V2(x) (((x) >> 3) & 0x1) - -+/* -+ * Layout of the fuses providing the calibration data -+ * These macros can be used for MT7981 and MT7986. -+ */ -+#define CALIB_BUF0_ADC_GE_V3(x) (((x) >> 0) & 0x3ff) -+#define CALIB_BUF0_DEGC_CALI_V3(x) (((x) >> 20) & 0x3f) -+#define CALIB_BUF0_O_SLOPE_V3(x) (((x) >> 26) & 0x3f) -+#define CALIB_BUF1_VTS_TS1_V3(x) (((x) >> 0) & 0x1ff) -+#define CALIB_BUF1_VTS_TS2_V3(x) (((x) >> 21) & 0x1ff) -+#define CALIB_BUF1_VTS_TSABB_V3(x) (((x) >> 9) & 0x1ff) -+#define CALIB_BUF1_VALID_V3(x) (((x) >> 18) & 0x1) -+#define CALIB_BUF1_O_SLOPE_SIGN_V3(x) (((x) >> 19) & 0x1) -+#define CALIB_BUF1_ID_V3(x) (((x) >> 20) & 0x1) -+ - enum { - VTS1, - VTS2, -@@ -163,6 +177,7 @@ enum { - enum mtk_thermal_version { - MTK_THERMAL_V1 = 1, - MTK_THERMAL_V2, -+ MTK_THERMAL_V3, - }; - - /* MT2701 thermal sensors */ -@@ -245,6 +260,27 @@ enum mtk_thermal_version { - /* The calibration coefficient of sensor */ - #define MT8183_CALIBRATION 153 - -+/* AUXADC channel 11 is used for the temperature sensors */ -+#define MT7986_TEMP_AUXADC_CHANNEL 11 -+ -+/* The total number of temperature sensors in the MT7986 */ -+#define MT7986_NUM_SENSORS 1 -+ -+/* The number of banks in the MT7986 */ -+#define MT7986_NUM_ZONES 1 -+ -+/* The number of sensing points per bank */ -+#define MT7986_NUM_SENSORS_PER_ZONE 1 -+ -+/* MT7986 thermal sensors */ -+#define MT7986_TS1 0 -+ -+/* The number of controller in the MT7986 */ -+#define MT7986_NUM_CONTROLLER 1 -+ -+/* The calibration coefficient of sensor */ -+#define MT7986_CALIBRATION 165 -+ - struct mtk_thermal; - - struct thermal_bank_cfg { -@@ -388,6 +424,14 @@ static const int mt7622_mux_values[MT762 - static const int mt7622_vts_index[MT7622_NUM_SENSORS] = { VTS1 }; - static const int mt7622_tc_offset[MT7622_NUM_CONTROLLER] = { 0x0, }; - -+/* MT7986 thermal sensor data */ -+static const int mt7986_bank_data[MT7986_NUM_SENSORS] = { MT7986_TS1, }; -+static const int mt7986_msr[MT7986_NUM_SENSORS_PER_ZONE] = { TEMP_MSR0, }; -+static const int mt7986_adcpnp[MT7986_NUM_SENSORS_PER_ZONE] = { TEMP_ADCPNP0, }; -+static const int mt7986_mux_values[MT7986_NUM_SENSORS] = { 0, }; -+static const int mt7986_vts_index[MT7986_NUM_SENSORS] = { VTS1 }; -+static const int mt7986_tc_offset[MT7986_NUM_CONTROLLER] = { 0x0, }; -+ - /* - * The MT8173 thermal controller has four banks. Each bank can read up to - * four temperature sensors simultaneously. The MT8173 has a total of 5 -@@ -551,6 +595,30 @@ static const struct mtk_thermal_data mt8 - .version = MTK_THERMAL_V1, - }; - -+/* -+ * MT7986 uses AUXADC Channel 11 for raw data access. -+ */ -+static const struct mtk_thermal_data mt7986_thermal_data = { -+ .auxadc_channel = MT7986_TEMP_AUXADC_CHANNEL, -+ .num_banks = MT7986_NUM_ZONES, -+ .num_sensors = MT7986_NUM_SENSORS, -+ .vts_index = mt7986_vts_index, -+ .cali_val = MT7986_CALIBRATION, -+ .num_controller = MT7986_NUM_CONTROLLER, -+ .controller_offset = mt7986_tc_offset, -+ .need_switch_bank = true, -+ .bank_data = { -+ { -+ .num_sensors = 1, -+ .sensors = mt7986_bank_data, -+ }, -+ }, -+ .msr = mt7986_msr, -+ .adcpnp = mt7986_adcpnp, -+ .sensor_mux_values = mt7986_mux_values, -+ .version = MTK_THERMAL_V3, -+}; -+ - /** - * raw_to_mcelsius - convert a raw ADC value to mcelsius - * @mt: The thermal controller -@@ -605,6 +673,22 @@ static int raw_to_mcelsius_v2(struct mtk - return (format_2 - tmp) * 100; - } - -+static int raw_to_mcelsius_v3(struct mtk_thermal *mt, int sensno, s32 raw) -+{ -+ s32 tmp; -+ -+ if (raw == 0) -+ return 0; -+ -+ raw &= 0xfff; -+ tmp = 100000 * 15 / 16 * 10000; -+ tmp /= 4096 - 512 + mt->adc_ge; -+ tmp /= 1490; -+ tmp *= raw - mt->vts[sensno] - 2900; -+ -+ return mt->degc_cali * 500 - tmp; -+} -+ - /** - * mtk_thermal_get_bank - get bank - * @bank: The bank -@@ -885,6 +969,25 @@ static int mtk_thermal_extract_efuse_v2( - return 0; - } - -+static int mtk_thermal_extract_efuse_v3(struct mtk_thermal *mt, u32 *buf) -+{ -+ if (!CALIB_BUF1_VALID_V3(buf[1])) -+ return -EINVAL; -+ -+ mt->adc_ge = CALIB_BUF0_ADC_GE_V3(buf[0]); -+ mt->degc_cali = CALIB_BUF0_DEGC_CALI_V3(buf[0]); -+ mt->o_slope = CALIB_BUF0_O_SLOPE_V3(buf[0]); -+ mt->vts[VTS1] = CALIB_BUF1_VTS_TS1_V3(buf[1]); -+ mt->vts[VTS2] = CALIB_BUF1_VTS_TS2_V3(buf[1]); -+ mt->vts[VTSABB] = CALIB_BUF1_VTS_TSABB_V3(buf[1]); -+ mt->o_slope_sign = CALIB_BUF1_O_SLOPE_SIGN_V3(buf[1]); -+ -+ if (CALIB_BUF1_ID_V3(buf[1]) == 0) -+ mt->o_slope = 0; -+ -+ return 0; -+} -+ - static int mtk_thermal_get_calibration_data(struct device *dev, - struct mtk_thermal *mt) - { -@@ -895,6 +998,7 @@ static int mtk_thermal_get_calibration_d - - /* Start with default values */ - mt->adc_ge = 512; -+ mt->adc_oe = 512; - for (i = 0; i < mt->conf->num_sensors; i++) - mt->vts[i] = 260; - mt->degc_cali = 40; -@@ -920,10 +1024,20 @@ static int mtk_thermal_get_calibration_d - goto out; - } - -- if (mt->conf->version == MTK_THERMAL_V1) -+ switch (mt->conf->version) { -+ case MTK_THERMAL_V1: - ret = mtk_thermal_extract_efuse_v1(mt, buf); -- else -+ break; -+ case MTK_THERMAL_V2: - ret = mtk_thermal_extract_efuse_v2(mt, buf); -+ break; -+ case MTK_THERMAL_V3: -+ ret = mtk_thermal_extract_efuse_v3(mt, buf); -+ break; -+ default: -+ ret = -EINVAL; -+ break; -+ } - - if (ret) { - dev_info(dev, "Device not calibrated, using default calibration values\n"); -@@ -954,6 +1068,10 @@ static const struct of_device_id mtk_the - .data = (void *)&mt7622_thermal_data, - }, - { -+ .compatible = "mediatek,mt7986-thermal", -+ .data = (void *)&mt7986_thermal_data, -+ }, -+ { - .compatible = "mediatek,mt8183-thermal", - .data = (void *)&mt8183_thermal_data, - }, { -@@ -1068,15 +1186,24 @@ static int mtk_thermal_probe(struct plat - goto err_disable_clk_auxadc; - } - -- if (mt->conf->version == MTK_THERMAL_V2) { -+ if (mt->conf->version != MTK_THERMAL_V1) { - mtk_thermal_turn_on_buffer(apmixed_base); - mtk_thermal_release_periodic_ts(mt, auxadc_base); - } - -- if (mt->conf->version == MTK_THERMAL_V1) -+ switch (mt->conf->version) { -+ case MTK_THERMAL_V1: - mt->raw_to_mcelsius = raw_to_mcelsius_v1; -- else -+ break; -+ case MTK_THERMAL_V2: - mt->raw_to_mcelsius = raw_to_mcelsius_v2; -+ break; -+ case MTK_THERMAL_V3: -+ mt->raw_to_mcelsius = raw_to_mcelsius_v3; -+ break; -+ default: -+ break; -+ } - - for (ctrl_id = 0; ctrl_id < mt->conf->num_controller ; ctrl_id++) - for (i = 0; i < mt->conf->num_banks; i++) diff --git a/target/linux/mediatek/patches-5.15/811-pwm-mediatek-Add-support-for-MT7981.patch b/target/linux/mediatek/patches-5.15/811-pwm-mediatek-Add-support-for-MT7981.patch deleted file mode 100644 index 8f27462cb..000000000 --- a/target/linux/mediatek/patches-5.15/811-pwm-mediatek-Add-support-for-MT7981.patch +++ /dev/null @@ -1,122 +0,0 @@ -From 73d20ebc21c562fbe79d02fa0fa38e095e716fa9 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Wed, 19 Apr 2023 20:25:51 +0100 -Subject: [PATCH] pwm: mediatek: Add support for MT7981 - -The PWM unit on MT7981 uses different register offsets than previous -MediaTek PWM units. Add support for these new offsets and add support -for PWM on MT7981 which has 3 PWM channels, one of them is typically -used for a temperature controlled fan. - -Signed-off-by: Daniel Golle ---- - drivers/pwm/pwm-mediatek.c | 41 ++++++++++++++++++++++++++++++-------- - 1 file changed, 33 insertions(+), 8 deletions(-) - ---- a/drivers/pwm/pwm-mediatek.c -+++ b/drivers/pwm/pwm-mediatek.c -@@ -38,6 +38,7 @@ struct pwm_mediatek_of_data { - unsigned int num_pwms; - bool pwm45_fixup; - bool has_ck_26m_sel; -+ const unsigned int *reg_offset; - }; - - /** -@@ -59,10 +60,14 @@ struct pwm_mediatek_chip { - const struct pwm_mediatek_of_data *soc; - }; - --static const unsigned int pwm_mediatek_reg_offset[] = { -+static const unsigned int mtk_pwm_reg_offset_v1[] = { - 0x0010, 0x0050, 0x0090, 0x00d0, 0x0110, 0x0150, 0x0190, 0x0220 - }; - -+static const unsigned int mtk_pwm_reg_offset_v2[] = { -+ 0x0080, 0x00c0, 0x0100, 0x0140, 0x0180, 0x01c0, 0x0200, 0x0240 -+}; -+ - static inline struct pwm_mediatek_chip * - to_pwm_mediatek_chip(struct pwm_chip *chip) - { -@@ -111,7 +116,7 @@ static inline void pwm_mediatek_writel(s - unsigned int num, unsigned int offset, - u32 value) - { -- writel(value, chip->regs + pwm_mediatek_reg_offset[num] + offset); -+ writel(value, chip->regs + chip->soc->reg_offset[num] + offset); - } - - static int pwm_mediatek_config(struct pwm_chip *chip, struct pwm_device *pwm, -@@ -270,48 +275,63 @@ static const struct pwm_mediatek_of_data - .num_pwms = 8, - .pwm45_fixup = false, - .has_ck_26m_sel = false, -+ .reg_offset = mtk_pwm_reg_offset_v1, - }; - - static const struct pwm_mediatek_of_data mt7622_pwm_data = { - .num_pwms = 6, - .pwm45_fixup = false, - .has_ck_26m_sel = true, -+ .reg_offset = mtk_pwm_reg_offset_v1, - }; - - static const struct pwm_mediatek_of_data mt7623_pwm_data = { - .num_pwms = 5, - .pwm45_fixup = true, - .has_ck_26m_sel = false, -+ .reg_offset = mtk_pwm_reg_offset_v1, - }; - - static const struct pwm_mediatek_of_data mt7628_pwm_data = { - .num_pwms = 4, - .pwm45_fixup = true, - .has_ck_26m_sel = false, -+ .reg_offset = mtk_pwm_reg_offset_v1, - }; - - static const struct pwm_mediatek_of_data mt7629_pwm_data = { - .num_pwms = 1, - .pwm45_fixup = false, - .has_ck_26m_sel = false, -+ .reg_offset = mtk_pwm_reg_offset_v1, - }; - - static const struct pwm_mediatek_of_data mt8183_pwm_data = { - .num_pwms = 4, - .pwm45_fixup = false, - .has_ck_26m_sel = true, -+ .reg_offset = mtk_pwm_reg_offset_v1, -+}; -+ -+static const struct pwm_mediatek_of_data mt7981_pwm_data = { -+ .num_pwms = 3, -+ .pwm45_fixup = false, -+ .has_ck_26m_sel = true, -+ .reg_offset = mtk_pwm_reg_offset_v2, - }; - - static const struct pwm_mediatek_of_data mt7986_pwm_data = { - .num_pwms = 2, - .pwm45_fixup = false, - .has_ck_26m_sel = true, -+ .reg_offset = mtk_pwm_reg_offset_v1, - }; - - static const struct pwm_mediatek_of_data mt8516_pwm_data = { - .num_pwms = 5, - .pwm45_fixup = false, - .has_ck_26m_sel = true, -+ .reg_offset = mtk_pwm_reg_offset_v1, - }; - - static const struct of_device_id pwm_mediatek_of_match[] = { -@@ -320,6 +340,7 @@ static const struct of_device_id pwm_med - { .compatible = "mediatek,mt7623-pwm", .data = &mt7623_pwm_data }, - { .compatible = "mediatek,mt7628-pwm", .data = &mt7628_pwm_data }, - { .compatible = "mediatek,mt7629-pwm", .data = &mt7629_pwm_data }, -+ { .compatible = "mediatek,mt7981-pwm", .data = &mt7981_pwm_data }, - { .compatible = "mediatek,mt7986-pwm", .data = &mt7986_pwm_data }, - { .compatible = "mediatek,mt8183-pwm", .data = &mt8183_pwm_data }, - { .compatible = "mediatek,mt8516-pwm", .data = &mt8516_pwm_data }, diff --git a/target/linux/mediatek/patches-5.15/820-v5.16-dt-bindings-pinctrl-mt8195-add-rsel-define.patch b/target/linux/mediatek/patches-5.15/820-v5.16-dt-bindings-pinctrl-mt8195-add-rsel-define.patch deleted file mode 100644 index f2be73714..000000000 --- a/target/linux/mediatek/patches-5.15/820-v5.16-dt-bindings-pinctrl-mt8195-add-rsel-define.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 26564c44357e19d03c124550bbd0b5851e6638c2 Mon Sep 17 00:00:00 2001 -From: Zhiyong Tao -Date: Fri, 24 Sep 2021 16:06:28 +0800 -Subject: [PATCH] dt-bindings: pinctrl: mt8195: add rsel define - -This patch adds rsel define for mt8195. - -Signed-off-by: Zhiyong Tao -Acked-by: Rob Herring -Link: https://lore.kernel.org/r/20210924080632.28410-2-zhiyong.tao@mediatek.com -Signed-off-by: Linus Walleij ---- - include/dt-bindings/pinctrl/mt65xx.h | 9 +++++++++ - 1 file changed, 9 insertions(+) - ---- a/include/dt-bindings/pinctrl/mt65xx.h -+++ b/include/dt-bindings/pinctrl/mt65xx.h -@@ -16,6 +16,15 @@ - #define MTK_PUPD_SET_R1R0_10 102 - #define MTK_PUPD_SET_R1R0_11 103 - -+#define MTK_PULL_SET_RSEL_000 200 -+#define MTK_PULL_SET_RSEL_001 201 -+#define MTK_PULL_SET_RSEL_010 202 -+#define MTK_PULL_SET_RSEL_011 203 -+#define MTK_PULL_SET_RSEL_100 204 -+#define MTK_PULL_SET_RSEL_101 205 -+#define MTK_PULL_SET_RSEL_110 206 -+#define MTK_PULL_SET_RSEL_111 207 -+ - #define MTK_DRIVE_2mA 2 - #define MTK_DRIVE_4mA 4 - #define MTK_DRIVE_6mA 6 diff --git a/target/linux/mediatek/patches-5.15/821-v5.16-pinctrl-mediatek-moore-check-if-pin_desc-is-valid-be.patch b/target/linux/mediatek/patches-5.15/821-v5.16-pinctrl-mediatek-moore-check-if-pin_desc-is-valid-be.patch deleted file mode 100644 index aa9f879e3..000000000 --- a/target/linux/mediatek/patches-5.15/821-v5.16-pinctrl-mediatek-moore-check-if-pin_desc-is-valid-be.patch +++ /dev/null @@ -1,93 +0,0 @@ -From d8b94c9ff96c2024a527086d850eb0b314337ff9 Mon Sep 17 00:00:00 2001 -From: Sam Shih -Date: Tue, 14 Sep 2021 16:51:32 +0800 -Subject: [PATCH] pinctrl: mediatek: moore: check if pin_desc is valid before - use - -Certain SoC are missing the middle part gpios in consecutive pins, -it's better to check if mtk_pin_desc is a valid pin for the extensibility - -Signed-off-by: Sam Shih -Acked-by: Sean Wang -Link: https://lore.kernel.org/r/20210914085137.31761-5-sam.shih@mediatek.com -Signed-off-by: Linus Walleij ---- - drivers/pinctrl/mediatek/pinctrl-moore.c | 18 ++++++++++++++++++ - 1 file changed, 18 insertions(+) - ---- a/drivers/pinctrl/mediatek/pinctrl-moore.c -+++ b/drivers/pinctrl/mediatek/pinctrl-moore.c -@@ -60,6 +60,8 @@ static int mtk_pinmux_set_mux(struct pin - int pin = grp->pins[i]; - - desc = (const struct mtk_pin_desc *)&hw->soc->pins[pin]; -+ if (!desc->name) -+ return -ENOTSUPP; - - mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_MODE, - pin_modes[i]); -@@ -76,6 +78,8 @@ static int mtk_pinmux_gpio_request_enabl - const struct mtk_pin_desc *desc; - - desc = (const struct mtk_pin_desc *)&hw->soc->pins[pin]; -+ if (!desc->name) -+ return -ENOTSUPP; - - return mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_MODE, - hw->soc->gpio_m); -@@ -89,6 +93,8 @@ static int mtk_pinmux_gpio_set_direction - const struct mtk_pin_desc *desc; - - desc = (const struct mtk_pin_desc *)&hw->soc->pins[pin]; -+ if (!desc->name) -+ return -ENOTSUPP; - - /* hardware would take 0 as input direction */ - return mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR, !input); -@@ -103,6 +109,8 @@ static int mtk_pinconf_get(struct pinctr - const struct mtk_pin_desc *desc; - - desc = (const struct mtk_pin_desc *)&hw->soc->pins[pin]; -+ if (!desc->name) -+ return -ENOTSUPP; - - switch (param) { - case PIN_CONFIG_BIAS_DISABLE: -@@ -218,6 +226,8 @@ static int mtk_pinconf_set(struct pinctr - int cfg, err = 0; - - desc = (const struct mtk_pin_desc *)&hw->soc->pins[pin]; -+ if (!desc->name) -+ return -ENOTSUPP; - - for (cfg = 0; cfg < num_configs; cfg++) { - param = pinconf_to_config_param(configs[cfg]); -@@ -435,6 +445,8 @@ static int mtk_gpio_get(struct gpio_chip - int value, err; - - desc = (const struct mtk_pin_desc *)&hw->soc->pins[gpio]; -+ if (!desc->name) -+ return -ENOTSUPP; - - err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DI, &value); - if (err) -@@ -449,6 +461,10 @@ static void mtk_gpio_set(struct gpio_chi - const struct mtk_pin_desc *desc; - - desc = (const struct mtk_pin_desc *)&hw->soc->pins[gpio]; -+ if (!desc->name) { -+ dev_err(hw->dev, "Failed to set gpio %d\n", gpio); -+ return; -+ } - - mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DO, !!value); - } -@@ -490,6 +506,8 @@ static int mtk_gpio_set_config(struct gp - u32 debounce; - - desc = (const struct mtk_pin_desc *)&hw->soc->pins[offset]; -+ if (!desc->name) -+ return -ENOTSUPP; - - if (!hw->eint || - pinconf_to_config_param(config) != PIN_CONFIG_INPUT_DEBOUNCE || diff --git a/target/linux/mediatek/patches-5.15/822-v5.16-pinctrl-mediatek-support-rsel-feature.patch b/target/linux/mediatek/patches-5.15/822-v5.16-pinctrl-mediatek-support-rsel-feature.patch deleted file mode 100644 index d30e09ef9..000000000 --- a/target/linux/mediatek/patches-5.15/822-v5.16-pinctrl-mediatek-support-rsel-feature.patch +++ /dev/null @@ -1,457 +0,0 @@ -From fb34a9ae383ae26326d4889fd2513e49f1019b88 Mon Sep 17 00:00:00 2001 -From: Zhiyong Tao -Date: Fri, 24 Sep 2021 16:06:31 +0800 -Subject: [PATCH] pinctrl: mediatek: support rsel feature - -This patch supports rsel(resistance selection) feature for I2C pins. -It provides more resistance selection solution in different ICs. -It provides rsel define and si unit solution by identifying -"mediatek,rsel_resistance_in_si_unit" property in pio dtsi node. - -Signed-off-by: Zhiyong Tao -Reviewed-by: Chen-Yu Tsai -Link: https://lore.kernel.org/r/20210924080632.28410-5-zhiyong.tao@mediatek.com -Signed-off-by: Linus Walleij ---- - .../pinctrl/mediatek/pinctrl-mtk-common-v2.c | 231 +++++++++++++++--- - .../pinctrl/mediatek/pinctrl-mtk-common-v2.h | 46 ++++ - drivers/pinctrl/mediatek/pinctrl-paris.c | 60 +++-- - 3 files changed, 289 insertions(+), 48 deletions(-) - ---- a/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c -+++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c -@@ -665,6 +665,181 @@ out: - return err; - } - -+static int mtk_hw_pin_rsel_lookup(struct mtk_pinctrl *hw, -+ const struct mtk_pin_desc *desc, -+ u32 pullup, u32 arg, u32 *rsel_val) -+{ -+ const struct mtk_pin_rsel *rsel; -+ int check; -+ bool found = false; -+ -+ rsel = hw->soc->pin_rsel; -+ -+ for (check = 0; check <= hw->soc->npin_rsel - 1; check++) { -+ if (desc->number >= rsel[check].s_pin && -+ desc->number <= rsel[check].e_pin) { -+ if (pullup) { -+ if (rsel[check].up_rsel == arg) { -+ found = true; -+ *rsel_val = rsel[check].rsel_index; -+ break; -+ } -+ } else { -+ if (rsel[check].down_rsel == arg) { -+ found = true; -+ *rsel_val = rsel[check].rsel_index; -+ break; -+ } -+ } -+ } -+ } -+ -+ if (!found) { -+ dev_err(hw->dev, "Not support rsel value %d Ohm for pin = %d (%s)\n", -+ arg, desc->number, desc->name); -+ return -ENOTSUPP; -+ } -+ -+ return 0; -+} -+ -+static int mtk_pinconf_bias_set_rsel(struct mtk_pinctrl *hw, -+ const struct mtk_pin_desc *desc, -+ u32 pullup, u32 arg) -+{ -+ int err, rsel_val; -+ -+ if (hw->rsel_si_unit) { -+ /* find pin rsel_index from pin_rsel array*/ -+ err = mtk_hw_pin_rsel_lookup(hw, desc, pullup, arg, &rsel_val); -+ if (err) -+ goto out; -+ } else { -+ if (arg < MTK_PULL_SET_RSEL_000 || -+ arg > MTK_PULL_SET_RSEL_111) { -+ err = -EINVAL; -+ goto out; -+ } -+ -+ rsel_val = arg - MTK_PULL_SET_RSEL_000; -+ } -+ -+ err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_RSEL, rsel_val); -+ if (err) -+ goto out; -+ -+ err = mtk_pinconf_bias_set_pu_pd(hw, desc, pullup, MTK_ENABLE); -+ -+out: -+ return err; -+} -+ -+int mtk_pinconf_bias_set_combo(struct mtk_pinctrl *hw, -+ const struct mtk_pin_desc *desc, -+ u32 pullup, u32 arg) -+{ -+ int err = -ENOTSUPP; -+ u32 try_all_type; -+ -+ if (hw->soc->pull_type) -+ try_all_type = hw->soc->pull_type[desc->number]; -+ else -+ try_all_type = MTK_PULL_TYPE_MASK; -+ -+ if (try_all_type & MTK_PULL_RSEL_TYPE) { -+ err = mtk_pinconf_bias_set_rsel(hw, desc, pullup, arg); -+ if (!err) -+ return err; -+ } -+ -+ if (try_all_type & MTK_PULL_PU_PD_TYPE) { -+ err = mtk_pinconf_bias_set_pu_pd(hw, desc, pullup, arg); -+ if (!err) -+ return err; -+ } -+ -+ if (try_all_type & MTK_PULL_PULLSEL_TYPE) { -+ err = mtk_pinconf_bias_set_pullsel_pullen(hw, desc, -+ pullup, arg); -+ if (!err) -+ return err; -+ } -+ -+ if (try_all_type & MTK_PULL_PUPD_R1R0_TYPE) -+ err = mtk_pinconf_bias_set_pupd_r1_r0(hw, desc, pullup, arg); -+ -+ if (err) -+ dev_err(hw->dev, "Invalid pull argument\n"); -+ -+ return err; -+} -+EXPORT_SYMBOL_GPL(mtk_pinconf_bias_set_combo); -+ -+static int mtk_rsel_get_si_unit(struct mtk_pinctrl *hw, -+ const struct mtk_pin_desc *desc, -+ u32 pullup, u32 rsel_val, u32 *si_unit) -+{ -+ const struct mtk_pin_rsel *rsel; -+ int check; -+ -+ rsel = hw->soc->pin_rsel; -+ -+ for (check = 0; check <= hw->soc->npin_rsel - 1; check++) { -+ if (desc->number >= rsel[check].s_pin && -+ desc->number <= rsel[check].e_pin) { -+ if (rsel_val == rsel[check].rsel_index) { -+ if (pullup) -+ *si_unit = rsel[check].up_rsel; -+ else -+ *si_unit = rsel[check].down_rsel; -+ break; -+ } -+ } -+ } -+ -+ return 0; -+} -+ -+static int mtk_pinconf_bias_get_rsel(struct mtk_pinctrl *hw, -+ const struct mtk_pin_desc *desc, -+ u32 *pullup, u32 *enable) -+{ -+ int pu, pd, rsel, err; -+ -+ err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_RSEL, &rsel); -+ if (err) -+ goto out; -+ -+ err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_PU, &pu); -+ if (err) -+ goto out; -+ -+ err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_PD, &pd); -+ -+ if (pu == 0 && pd == 0) { -+ *pullup = 0; -+ *enable = MTK_DISABLE; -+ } else if (pu == 1 && pd == 0) { -+ *pullup = 1; -+ if (hw->rsel_si_unit) -+ mtk_rsel_get_si_unit(hw, desc, *pullup, rsel, enable); -+ else -+ *enable = rsel + MTK_PULL_SET_RSEL_000; -+ } else if (pu == 0 && pd == 1) { -+ *pullup = 0; -+ if (hw->rsel_si_unit) -+ mtk_rsel_get_si_unit(hw, desc, *pullup, rsel, enable); -+ else -+ *enable = rsel + MTK_PULL_SET_RSEL_000; -+ } else { -+ err = -EINVAL; -+ goto out; -+ } -+ -+out: -+ return err; -+} -+ - static int mtk_pinconf_bias_get_pu_pd(struct mtk_pinctrl *hw, - const struct mtk_pin_desc *desc, - u32 *pullup, u32 *enable) -@@ -746,44 +921,40 @@ out: - return err; - } - --int mtk_pinconf_bias_set_combo(struct mtk_pinctrl *hw, -- const struct mtk_pin_desc *desc, -- u32 pullup, u32 arg) --{ -- int err; -- -- err = mtk_pinconf_bias_set_pu_pd(hw, desc, pullup, arg); -- if (!err) -- goto out; -- -- err = mtk_pinconf_bias_set_pullsel_pullen(hw, desc, pullup, arg); -- if (!err) -- goto out; -- -- err = mtk_pinconf_bias_set_pupd_r1_r0(hw, desc, pullup, arg); -- --out: -- return err; --} --EXPORT_SYMBOL_GPL(mtk_pinconf_bias_set_combo); -- - int mtk_pinconf_bias_get_combo(struct mtk_pinctrl *hw, - const struct mtk_pin_desc *desc, - u32 *pullup, u32 *enable) - { -- int err; -+ int err = -ENOTSUPP; -+ u32 try_all_type; - -- err = mtk_pinconf_bias_get_pu_pd(hw, desc, pullup, enable); -- if (!err) -- goto out; -+ if (hw->soc->pull_type) -+ try_all_type = hw->soc->pull_type[desc->number]; -+ else -+ try_all_type = MTK_PULL_TYPE_MASK; - -- err = mtk_pinconf_bias_get_pullsel_pullen(hw, desc, pullup, enable); -- if (!err) -- goto out; -+ if (try_all_type & MTK_PULL_RSEL_TYPE) { -+ err = mtk_pinconf_bias_get_rsel(hw, desc, pullup, enable); -+ if (!err) -+ return err; -+ } -+ -+ if (try_all_type & MTK_PULL_PU_PD_TYPE) { -+ err = mtk_pinconf_bias_get_pu_pd(hw, desc, pullup, enable); -+ if (!err) -+ return err; -+ } -+ -+ if (try_all_type & MTK_PULL_PULLSEL_TYPE) { -+ err = mtk_pinconf_bias_get_pullsel_pullen(hw, desc, -+ pullup, enable); -+ if (!err) -+ return err; -+ } - -- err = mtk_pinconf_bias_get_pupd_r1_r0(hw, desc, pullup, enable); -+ if (try_all_type & MTK_PULL_PUPD_R1R0_TYPE) -+ err = mtk_pinconf_bias_get_pupd_r1_r0(hw, desc, pullup, enable); - --out: - return err; - } - EXPORT_SYMBOL_GPL(mtk_pinconf_bias_get_combo); ---- a/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.h -+++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.h -@@ -17,6 +17,22 @@ - #define MTK_ENABLE 1 - #define MTK_PULLDOWN 0 - #define MTK_PULLUP 1 -+#define MTK_PULL_PU_PD_TYPE BIT(0) -+#define MTK_PULL_PULLSEL_TYPE BIT(1) -+#define MTK_PULL_PUPD_R1R0_TYPE BIT(2) -+/* MTK_PULL_RSEL_TYPE can select resistance and can be -+ * turned on/off itself. But it can't be selected pull up/down -+ */ -+#define MTK_PULL_RSEL_TYPE BIT(3) -+/* MTK_PULL_PU_PD_RSEL_TYPE is a type which is controlled by -+ * MTK_PULL_PU_PD_TYPE and MTK_PULL_RSEL_TYPE. -+ */ -+#define MTK_PULL_PU_PD_RSEL_TYPE (MTK_PULL_PU_PD_TYPE \ -+ | MTK_PULL_RSEL_TYPE) -+#define MTK_PULL_TYPE_MASK (MTK_PULL_PU_PD_TYPE |\ -+ MTK_PULL_PULLSEL_TYPE |\ -+ MTK_PULL_PUPD_R1R0_TYPE |\ -+ MTK_PULL_RSEL_TYPE) - - #define EINT_NA U16_MAX - #define NO_EINT_SUPPORT EINT_NA -@@ -42,6 +58,14 @@ - PIN_FIELD_CALC(_s_pin, _e_pin, 0, _s_addr, _x_addrs, _s_bit, \ - _x_bits, 32, 1) - -+#define PIN_RSEL(_s_pin, _e_pin, _rsel_index, _up_resl, _down_rsel) { \ -+ .s_pin = _s_pin, \ -+ .e_pin = _e_pin, \ -+ .rsel_index = _rsel_index, \ -+ .up_rsel = _up_resl, \ -+ .down_rsel = _down_rsel, \ -+ } -+ - /* List these attributes which could be modified for the pin */ - enum { - PINCTRL_PIN_REG_MODE, -@@ -67,6 +91,7 @@ enum { - PINCTRL_PIN_REG_DRV_E0, - PINCTRL_PIN_REG_DRV_E1, - PINCTRL_PIN_REG_DRV_ADV, -+ PINCTRL_PIN_REG_RSEL, - PINCTRL_PIN_REG_MAX, - }; - -@@ -129,6 +154,22 @@ struct mtk_pin_field_calc { - u8 fixed; - }; - -+/** -+ * struct mtk_pin_rsel - the structure that provides bias resistance selection. -+ * @s_pin: the start pin within the rsel range -+ * @e_pin: the end pin within the rsel range -+ * @rsel_index: the rsel bias resistance index -+ * @up_rsel: the pullup rsel bias resistance value -+ * @down_rsel: the pulldown rsel bias resistance value -+ */ -+struct mtk_pin_rsel { -+ u16 s_pin; -+ u16 e_pin; -+ u16 rsel_index; -+ u32 up_rsel; -+ u32 down_rsel; -+}; -+ - /* struct mtk_pin_reg_calc - the structure that holds all ranges used to - * determine which register the pin would make use of - * for certain pin attribute. -@@ -206,6 +247,9 @@ struct mtk_pin_soc { - bool ies_present; - const char * const *base_names; - unsigned int nbase_names; -+ const unsigned int *pull_type; -+ const struct mtk_pin_rsel *pin_rsel; -+ unsigned int npin_rsel; - - /* Specific pinconfig operations */ - int (*bias_disable_set)(struct mtk_pinctrl *hw, -@@ -254,6 +298,8 @@ struct mtk_pinctrl { - const char **grp_names; - /* lock pin's register resource to avoid multiple threads issue*/ - spinlock_t lock; -+ /* identify rsel setting by si unit or rsel define in dts node */ -+ bool rsel_si_unit; - }; - - void mtk_rmw(struct mtk_pinctrl *pctl, u8 i, u32 reg, u32 mask, u32 set); ---- a/drivers/pinctrl/mediatek/pinctrl-paris.c -+++ b/drivers/pinctrl/mediatek/pinctrl-paris.c -@@ -538,8 +538,9 @@ static int mtk_hw_get_value_wrap(struct - ssize_t mtk_pctrl_show_one_pin(struct mtk_pinctrl *hw, - unsigned int gpio, char *buf, unsigned int buf_len) - { -- int pinmux, pullup = 0, pullen = 0, len = 0, r1 = -1, r0 = -1; -+ int pinmux, pullup = 0, pullen = 0, len = 0, r1 = -1, r0 = -1, rsel = -1; - const struct mtk_pin_desc *desc; -+ u32 try_all_type; - - if (gpio >= hw->soc->npins) - return -EINVAL; -@@ -553,24 +554,39 @@ ssize_t mtk_pctrl_show_one_pin(struct mt - pinmux -= hw->soc->nfuncs; - - mtk_pinconf_bias_get_combo(hw, desc, &pullup, &pullen); -- if (pullen == MTK_PUPD_SET_R1R0_00) { -- pullen = 0; -- r1 = 0; -- r0 = 0; -- } else if (pullen == MTK_PUPD_SET_R1R0_01) { -- pullen = 1; -- r1 = 0; -- r0 = 1; -- } else if (pullen == MTK_PUPD_SET_R1R0_10) { -- pullen = 1; -- r1 = 1; -- r0 = 0; -- } else if (pullen == MTK_PUPD_SET_R1R0_11) { -+ -+ if (hw->soc->pull_type) -+ try_all_type = hw->soc->pull_type[desc->number]; -+ -+ if (hw->rsel_si_unit && (try_all_type & MTK_PULL_RSEL_TYPE)) { -+ rsel = pullen; - pullen = 1; -- r1 = 1; -- r0 = 1; -- } else if (pullen != MTK_DISABLE && pullen != MTK_ENABLE) { -- pullen = 0; -+ } else { -+ /* Case for: R1R0 */ -+ if (pullen == MTK_PUPD_SET_R1R0_00) { -+ pullen = 0; -+ r1 = 0; -+ r0 = 0; -+ } else if (pullen == MTK_PUPD_SET_R1R0_01) { -+ pullen = 1; -+ r1 = 0; -+ r0 = 1; -+ } else if (pullen == MTK_PUPD_SET_R1R0_10) { -+ pullen = 1; -+ r1 = 1; -+ r0 = 0; -+ } else if (pullen == MTK_PUPD_SET_R1R0_11) { -+ pullen = 1; -+ r1 = 1; -+ r0 = 1; -+ } -+ -+ /* Case for: RSEL */ -+ if (pullen >= MTK_PULL_SET_RSEL_000 && -+ pullen <= MTK_PULL_SET_RSEL_111) { -+ rsel = pullen - MTK_PULL_SET_RSEL_000; -+ pullen = 1; -+ } - } - len += scnprintf(buf + len, buf_len - len, - "%03d: %1d%1d%1d%1d%02d%1d%1d%1d%1d", -@@ -588,6 +604,8 @@ ssize_t mtk_pctrl_show_one_pin(struct mt - if (r1 != -1) { - len += scnprintf(buf + len, buf_len - len, " (%1d %1d)\n", - r1, r0); -+ } else if (rsel != -1) { -+ len += scnprintf(buf + len, buf_len - len, " (%1d)\n", rsel); - } else { - len += scnprintf(buf + len, buf_len - len, "\n"); - } -@@ -930,6 +948,12 @@ int mtk_paris_pinctrl_probe(struct platf - - hw->nbase = hw->soc->nbase_names; - -+ if (of_find_property(hw->dev->of_node, -+ "mediatek,rsel_resistance_in_si_unit", NULL)) -+ hw->rsel_si_unit = true; -+ else -+ hw->rsel_si_unit = false; -+ - spin_lock_init(&hw->lock); - - err = mtk_pctrl_build_state(pdev); diff --git a/target/linux/mediatek/patches-5.15/823-v5.17-pinctrl-mediatek-add-a-check-for-error-in-mtk_pincon.patch b/target/linux/mediatek/patches-5.15/823-v5.17-pinctrl-mediatek-add-a-check-for-error-in-mtk_pincon.patch deleted file mode 100644 index 6752b4093..000000000 --- a/target/linux/mediatek/patches-5.15/823-v5.17-pinctrl-mediatek-add-a-check-for-error-in-mtk_pincon.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 9f9d17c228c89e38ed612500126daf626270be9a Mon Sep 17 00:00:00 2001 -From: Dan Carpenter -Date: Sat, 27 Nov 2021 17:08:36 +0300 -Subject: [PATCH] pinctrl: mediatek: add a check for error in - mtk_pinconf_bias_get_rsel() - -All the other mtk_hw_get_value() calls have a check for "if (err)" so -we can add one here as well. This silences a Smatch warning: - - drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c:819 mtk_pinconf_bias_get_rsel() - error: uninitialized symbol 'pd'. - -Fixes: fb34a9ae383a ("pinctrl: mediatek: support rsel feature") -Signed-off-by: Dan Carpenter -Link: https://lore.kernel.org/r/20211127140836.GB24002@kili -Signed-off-by: Linus Walleij ---- - drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c | 2 ++ - 1 file changed, 2 insertions(+) - ---- a/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c -+++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c -@@ -815,6 +815,8 @@ static int mtk_pinconf_bias_get_rsel(str - goto out; - - err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_PD, &pd); -+ if (err) -+ goto out; - - if (pu == 0 && pd == 0) { - *pullup = 0; diff --git a/target/linux/mediatek/patches-5.15/824-v6.1-pinctrl-mediatek-Fix-EINT-pins-input-debounce-time-c.patch b/target/linux/mediatek/patches-5.15/824-v6.1-pinctrl-mediatek-Fix-EINT-pins-input-debounce-time-c.patch deleted file mode 100644 index 47a29fbdb..000000000 --- a/target/linux/mediatek/patches-5.15/824-v6.1-pinctrl-mediatek-Fix-EINT-pins-input-debounce-time-c.patch +++ /dev/null @@ -1,297 +0,0 @@ -From e1ff91f9d2303cd4e706cc908bfca21cd17b9927 Mon Sep 17 00:00:00 2001 -From: AngeloGioacchino Del Regno -Date: Fri, 11 Nov 2022 10:41:06 +0100 -Subject: [PATCH] pinctrl: mediatek: Fix EINT pins input debounce time - configuration - -The External Interrupt Controller (EINTC) on all of the supported -MediaTek SoCs does support input debouncing, but not all of them -index the debounce time values (DBNC_SETTING registers) the same way. - -Before this change, in some cases, as an example, requesting a debounce -time of 16 milliseconds would mistakenly set the relative DBNC_SETTING -register to 0x2, resulting in a way shorter debounce time of 500uS. - -To fix the aforementioned issue, define three different debounce_time -arrays, reflecting the correct register index for each value and for -each register index variant, and make sure that each SoC pinctrl -driver uses the right one. - -Signed-off-by: AngeloGioacchino Del Regno -Link: https://lore.kernel.org/r/20221111094106.18486-1-angelogioacchino.delregno@collabora.com -Signed-off-by: Linus Walleij ---- - drivers/pinctrl/mediatek/mtk-eint.c | 31 +++++++++++++++++++---- - drivers/pinctrl/mediatek/mtk-eint.h | 6 +++++ - drivers/pinctrl/mediatek/pinctrl-mt2701.c | 1 + - drivers/pinctrl/mediatek/pinctrl-mt2712.c | 1 + - drivers/pinctrl/mediatek/pinctrl-mt6765.c | 1 + - drivers/pinctrl/mediatek/pinctrl-mt6779.c | 1 + - drivers/pinctrl/mediatek/pinctrl-mt7622.c | 1 + - drivers/pinctrl/mediatek/pinctrl-mt7623.c | 1 + - drivers/pinctrl/mediatek/pinctrl-mt7629.c | 1 + - drivers/pinctrl/mediatek/pinctrl-mt8127.c | 1 + - drivers/pinctrl/mediatek/pinctrl-mt8135.c | 1 + - drivers/pinctrl/mediatek/pinctrl-mt8167.c | 1 + - drivers/pinctrl/mediatek/pinctrl-mt8173.c | 1 + - drivers/pinctrl/mediatek/pinctrl-mt8183.c | 1 + - drivers/pinctrl/mediatek/pinctrl-mt8192.c | 1 + - drivers/pinctrl/mediatek/pinctrl-mt8195.c | 1 + - drivers/pinctrl/mediatek/pinctrl-mt8365.c | 1 + - drivers/pinctrl/mediatek/pinctrl-mt8516.c | 1 + - 22 files changed, 53 insertions(+), 5 deletions(-) - ---- a/drivers/pinctrl/mediatek/mtk-eint.c -+++ b/drivers/pinctrl/mediatek/mtk-eint.c -@@ -24,6 +24,7 @@ - #define MTK_EINT_EDGE_SENSITIVE 0 - #define MTK_EINT_LEVEL_SENSITIVE 1 - #define MTK_EINT_DBNC_SET_DBNC_BITS 4 -+#define MTK_EINT_DBNC_MAX 16 - #define MTK_EINT_DBNC_RST_BIT (0x1 << 1) - #define MTK_EINT_DBNC_SET_EN (0x1 << 0) - -@@ -48,6 +49,18 @@ static const struct mtk_eint_regs mtk_ge - .dbnc_clr = 0x700, - }; - -+const unsigned int debounce_time_mt2701[] = { -+ 500, 1000, 16000, 32000, 64000, 128000, 256000, 0 -+}; -+ -+const unsigned int debounce_time_mt6765[] = { -+ 125, 250, 500, 1000, 16000, 32000, 64000, 128000, 256000, 512000, 0 -+}; -+ -+const unsigned int debounce_time_mt6795[] = { -+ 500, 1000, 16000, 32000, 64000, 128000, 256000, 512000, 0 -+}; -+ - static void __iomem *mtk_eint_get_offset(struct mtk_eint *eint, - unsigned int eint_num, - unsigned int offset) -@@ -407,10 +420,11 @@ int mtk_eint_set_debounce(struct mtk_ein - int virq, eint_offset; - unsigned int set_offset, bit, clr_bit, clr_offset, rst, i, unmask, - dbnc; -- static const unsigned int debounce_time[] = {500, 1000, 16000, 32000, -- 64000, 128000, 256000}; - struct irq_data *d; - -+ if (!eint->hw->db_time) -+ return -EOPNOTSUPP; -+ - virq = irq_find_mapping(eint->domain, eint_num); - eint_offset = (eint_num % 4) * 8; - d = irq_get_irq_data(virq); -@@ -421,9 +435,9 @@ int mtk_eint_set_debounce(struct mtk_ein - if (!mtk_eint_can_en_debounce(eint, eint_num)) - return -EINVAL; - -- dbnc = ARRAY_SIZE(debounce_time); -- for (i = 0; i < ARRAY_SIZE(debounce_time); i++) { -- if (debounce <= debounce_time[i]) { -+ dbnc = eint->num_db_time; -+ for (i = 0; i < eint->num_db_time; i++) { -+ if (debounce <= eint->hw->db_time[i]) { - dbnc = i; - break; - } -@@ -497,6 +511,13 @@ int mtk_eint_do_init(struct mtk_eint *ei - if (!eint->domain) - return -ENOMEM; - -+ if (eint->hw->db_time) { -+ for (i = 0; i < MTK_EINT_DBNC_MAX; i++) -+ if (eint->hw->db_time[i] == 0) -+ break; -+ eint->num_db_time = i; -+ } -+ - mtk_eint_hw_init(eint); - for (i = 0; i < eint->hw->ap_num; i++) { - int virq = irq_create_mapping(eint->domain, i); ---- a/drivers/pinctrl/mediatek/mtk-eint.h -+++ b/drivers/pinctrl/mediatek/mtk-eint.h -@@ -37,8 +37,13 @@ struct mtk_eint_hw { - u8 ports; - unsigned int ap_num; - unsigned int db_cnt; -+ const unsigned int *db_time; - }; - -+extern const unsigned int debounce_time_mt2701[]; -+extern const unsigned int debounce_time_mt6765[]; -+extern const unsigned int debounce_time_mt6795[]; -+ - struct mtk_eint; - - struct mtk_eint_xt { -@@ -62,6 +67,7 @@ struct mtk_eint { - /* Used to fit into various EINT device */ - const struct mtk_eint_hw *hw; - const struct mtk_eint_regs *regs; -+ u16 num_db_time; - - /* Used to fit into various pinctrl device */ - void *pctl; ---- a/drivers/pinctrl/mediatek/pinctrl-mt2701.c -+++ b/drivers/pinctrl/mediatek/pinctrl-mt2701.c -@@ -531,6 +531,7 @@ static const struct mtk_pinctrl_devdata - .ports = 6, - .ap_num = 169, - .db_cnt = 16, -+ .db_time = debounce_time_mt2701, - }, - }; - ---- a/drivers/pinctrl/mediatek/pinctrl-mt2712.c -+++ b/drivers/pinctrl/mediatek/pinctrl-mt2712.c -@@ -584,6 +584,7 @@ static const struct mtk_pinctrl_devdata - .ports = 8, - .ap_num = 229, - .db_cnt = 40, -+ .db_time = debounce_time_mt2701, - }, - }; - ---- a/drivers/pinctrl/mediatek/pinctrl-mt6765.c -+++ b/drivers/pinctrl/mediatek/pinctrl-mt6765.c -@@ -1062,6 +1062,7 @@ static const struct mtk_eint_hw mt6765_e - .ports = 6, - .ap_num = 160, - .db_cnt = 13, -+ .db_time = debounce_time_mt6765, - }; - - static const struct mtk_pin_soc mt6765_data = { ---- a/drivers/pinctrl/mediatek/pinctrl-mt6779.c -+++ b/drivers/pinctrl/mediatek/pinctrl-mt6779.c -@@ -737,6 +737,7 @@ static const struct mtk_eint_hw mt6779_e - .ports = 6, - .ap_num = 195, - .db_cnt = 13, -+ .db_time = debounce_time_mt2701, - }; - - static const struct mtk_pin_soc mt6779_data = { ---- a/drivers/pinctrl/mediatek/pinctrl-mt7622.c -+++ b/drivers/pinctrl/mediatek/pinctrl-mt7622.c -@@ -846,6 +846,7 @@ static const struct mtk_eint_hw mt7622_e - .ports = 7, - .ap_num = ARRAY_SIZE(mt7622_pins), - .db_cnt = 20, -+ .db_time = debounce_time_mt6765, - }; - - static const struct mtk_pin_soc mt7622_data = { ---- a/drivers/pinctrl/mediatek/pinctrl-mt7623.c -+++ b/drivers/pinctrl/mediatek/pinctrl-mt7623.c -@@ -1369,6 +1369,7 @@ static const struct mtk_eint_hw mt7623_e - .ports = 6, - .ap_num = 169, - .db_cnt = 20, -+ .db_time = debounce_time_mt2701, - }; - - static struct mtk_pin_soc mt7623_data = { ---- a/drivers/pinctrl/mediatek/pinctrl-mt7629.c -+++ b/drivers/pinctrl/mediatek/pinctrl-mt7629.c -@@ -402,6 +402,7 @@ static const struct mtk_eint_hw mt7629_e - .ports = 7, - .ap_num = ARRAY_SIZE(mt7629_pins), - .db_cnt = 16, -+ .db_time = debounce_time_mt2701, - }; - - static struct mtk_pin_soc mt7629_data = { ---- a/drivers/pinctrl/mediatek/pinctrl-mt8127.c -+++ b/drivers/pinctrl/mediatek/pinctrl-mt8127.c -@@ -300,6 +300,7 @@ static const struct mtk_pinctrl_devdata - .ports = 6, - .ap_num = 143, - .db_cnt = 16, -+ .db_time = debounce_time_mt2701, - }, - }; - ---- a/drivers/pinctrl/mediatek/pinctrl-mt8135.c -+++ b/drivers/pinctrl/mediatek/pinctrl-mt8135.c -@@ -313,6 +313,7 @@ static const struct mtk_pinctrl_devdata - .ports = 6, - .ap_num = 192, - .db_cnt = 16, -+ .db_time = debounce_time_mt2701, - }, - }; - ---- a/drivers/pinctrl/mediatek/pinctrl-mt8167.c -+++ b/drivers/pinctrl/mediatek/pinctrl-mt8167.c -@@ -332,6 +332,7 @@ static const struct mtk_pinctrl_devdata - .ports = 6, - .ap_num = 169, - .db_cnt = 64, -+ .db_time = debounce_time_mt6795, - }, - }; - ---- a/drivers/pinctrl/mediatek/pinctrl-mt8173.c -+++ b/drivers/pinctrl/mediatek/pinctrl-mt8173.c -@@ -340,6 +340,7 @@ static const struct mtk_pinctrl_devdata - .ports = 6, - .ap_num = 224, - .db_cnt = 16, -+ .db_time = debounce_time_mt2701, - }, - }; - ---- a/drivers/pinctrl/mediatek/pinctrl-mt8183.c -+++ b/drivers/pinctrl/mediatek/pinctrl-mt8183.c -@@ -545,6 +545,7 @@ static const struct mtk_eint_hw mt8183_e - .ports = 6, - .ap_num = 212, - .db_cnt = 13, -+ .db_time = debounce_time_mt6765, - }; - - static const struct mtk_pin_soc mt8183_data = { ---- a/drivers/pinctrl/mediatek/pinctrl-mt8192.c -+++ b/drivers/pinctrl/mediatek/pinctrl-mt8192.c -@@ -1339,6 +1339,7 @@ static const struct mtk_eint_hw mt8192_e - .ports = 7, - .ap_num = 224, - .db_cnt = 32, -+ .db_time = debounce_time_mt6765, - }; - - static const struct mtk_pin_reg_calc mt8192_reg_cals[PINCTRL_PIN_REG_MAX] = { ---- a/drivers/pinctrl/mediatek/pinctrl-mt8195.c -+++ b/drivers/pinctrl/mediatek/pinctrl-mt8195.c -@@ -805,6 +805,7 @@ static const struct mtk_eint_hw mt8195_e - .ports = 7, - .ap_num = 225, - .db_cnt = 32, -+ .db_time = debounce_time_mt6765, - }; - - static const struct mtk_pin_soc mt8195_data = { ---- a/drivers/pinctrl/mediatek/pinctrl-mt8365.c -+++ b/drivers/pinctrl/mediatek/pinctrl-mt8365.c -@@ -466,6 +466,7 @@ static const struct mtk_pinctrl_devdata - .ports = 5, - .ap_num = 160, - .db_cnt = 160, -+ .db_time = debounce_time_mt6765, - }, - }; - ---- a/drivers/pinctrl/mediatek/pinctrl-mt8516.c -+++ b/drivers/pinctrl/mediatek/pinctrl-mt8516.c -@@ -332,6 +332,7 @@ static const struct mtk_pinctrl_devdata - .ports = 6, - .ap_num = 169, - .db_cnt = 64, -+ .db_time = debounce_time_mt6795, - }, - }; - diff --git a/target/linux/mediatek/patches-5.15/825-v6.1-pinctrl-mediatek-Export-debounce-time-tables.patch b/target/linux/mediatek/patches-5.15/825-v6.1-pinctrl-mediatek-Export-debounce-time-tables.patch deleted file mode 100644 index 92f4e842e..000000000 --- a/target/linux/mediatek/patches-5.15/825-v6.1-pinctrl-mediatek-Export-debounce-time-tables.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 2e35b25dd8e666b8619355fc3defb1b246a5dc02 Mon Sep 17 00:00:00 2001 -From: Linus Walleij -Date: Tue, 15 Nov 2022 09:11:07 +0100 -Subject: [PATCH] pinctrl: mediatek: Export debounce time tables - -The kernel test robot complains that in certain combinations -when building the Mediatek drivers as modules we lack some -debounce table symbols, so export them. - -Reported-by: kernel test robot -Fixes: e1ff91f9d230 ("pinctrl: mediatek: Fix EINT pins input debounce time configuration") -Cc: AngeloGioacchino Del Regno -Signed-off-by: Linus Walleij ---- - drivers/pinctrl/mediatek/mtk-eint.c | 3 +++ - 1 file changed, 3 insertions(+) - ---- a/drivers/pinctrl/mediatek/mtk-eint.c -+++ b/drivers/pinctrl/mediatek/mtk-eint.c -@@ -52,14 +52,17 @@ static const struct mtk_eint_regs mtk_ge - const unsigned int debounce_time_mt2701[] = { - 500, 1000, 16000, 32000, 64000, 128000, 256000, 0 - }; -+EXPORT_SYMBOL_GPL(debounce_time_mt2701); - - const unsigned int debounce_time_mt6765[] = { - 125, 250, 500, 1000, 16000, 32000, 64000, 128000, 256000, 512000, 0 - }; -+EXPORT_SYMBOL_GPL(debounce_time_mt6765); - - const unsigned int debounce_time_mt6795[] = { - 500, 1000, 16000, 32000, 64000, 128000, 256000, 512000, 0 - }; -+EXPORT_SYMBOL_GPL(debounce_time_mt6795); - - static void __iomem *mtk_eint_get_offset(struct mtk_eint *eint, - unsigned int eint_num, diff --git a/target/linux/mediatek/patches-5.15/826-v6.2-pinctrl-mediatek-extend-pinctrl-moore-to-support-new.patch b/target/linux/mediatek/patches-5.15/826-v6.2-pinctrl-mediatek-extend-pinctrl-moore-to-support-new.patch deleted file mode 100644 index f130fdbc5..000000000 --- a/target/linux/mediatek/patches-5.15/826-v6.2-pinctrl-mediatek-extend-pinctrl-moore-to-support-new.patch +++ /dev/null @@ -1,129 +0,0 @@ -From fae82621ac33e2a4a96220c56e90d1ec6237d394 Mon Sep 17 00:00:00 2001 -From: Sam Shih -Date: Sun, 6 Nov 2022 09:01:12 +0100 -Subject: [PATCH] pinctrl: mediatek: extend pinctrl-moore to support new bias - functions - -Commit fb34a9ae383a ("pinctrl: mediatek: support rsel feature") -introduced SoC specify 'pull_type' attribute to mtk_pinconf_bias_set_combo -and mtk_pinconf_bias_get_combo, and make the functions able to support -almost all Mediatek SoCs that use pinctrl-mtk-common-v2.c. - -This patch enables pinctrl_moore to support these functions. - -Signed-off-by: Sam Shih -Signed-off-by: Frank Wunderlich -Reviewed-by: AngeloGioacchino Del Regno -Link: https://lore.kernel.org/r/20221106080114.7426-6-linux@fw-web.de -Signed-off-by: Linus Walleij ---- - drivers/pinctrl/mediatek/pinctrl-moore.c | 49 ++++++++++++++++++++---- - 1 file changed, 42 insertions(+), 7 deletions(-) - ---- a/drivers/pinctrl/mediatek/pinctrl-moore.c -+++ b/drivers/pinctrl/mediatek/pinctrl-moore.c -@@ -8,6 +8,7 @@ - * - */ - -+#include - #include - #include "pinctrl-moore.h" - -@@ -105,7 +106,7 @@ static int mtk_pinconf_get(struct pinctr - { - struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev); - u32 param = pinconf_to_config_param(*config); -- int val, val2, err, reg, ret = 1; -+ int val, val2, err, pullup, reg, ret = 1; - const struct mtk_pin_desc *desc; - - desc = (const struct mtk_pin_desc *)&hw->soc->pins[pin]; -@@ -114,7 +115,13 @@ static int mtk_pinconf_get(struct pinctr - - switch (param) { - case PIN_CONFIG_BIAS_DISABLE: -- if (hw->soc->bias_disable_get) { -+ if (hw->soc->bias_get_combo) { -+ err = hw->soc->bias_get_combo(hw, desc, &pullup, &ret); -+ if (err) -+ return err; -+ if (ret != MTK_PUPD_SET_R1R0_00 && ret != MTK_DISABLE) -+ return -EINVAL; -+ } else if (hw->soc->bias_disable_get) { - err = hw->soc->bias_disable_get(hw, desc, &ret); - if (err) - return err; -@@ -123,7 +130,15 @@ static int mtk_pinconf_get(struct pinctr - } - break; - case PIN_CONFIG_BIAS_PULL_UP: -- if (hw->soc->bias_get) { -+ if (hw->soc->bias_get_combo) { -+ err = hw->soc->bias_get_combo(hw, desc, &pullup, &ret); -+ if (err) -+ return err; -+ if (ret == MTK_PUPD_SET_R1R0_00 || ret == MTK_DISABLE) -+ return -EINVAL; -+ if (!pullup) -+ return -EINVAL; -+ } else if (hw->soc->bias_get) { - err = hw->soc->bias_get(hw, desc, 1, &ret); - if (err) - return err; -@@ -132,7 +147,15 @@ static int mtk_pinconf_get(struct pinctr - } - break; - case PIN_CONFIG_BIAS_PULL_DOWN: -- if (hw->soc->bias_get) { -+ if (hw->soc->bias_get_combo) { -+ err = hw->soc->bias_get_combo(hw, desc, &pullup, &ret); -+ if (err) -+ return err; -+ if (ret == MTK_PUPD_SET_R1R0_00 || ret == MTK_DISABLE) -+ return -EINVAL; -+ if (pullup) -+ return -EINVAL; -+ } else if (hw->soc->bias_get) { - err = hw->soc->bias_get(hw, desc, 0, &ret); - if (err) - return err; -@@ -235,7 +258,11 @@ static int mtk_pinconf_set(struct pinctr - - switch (param) { - case PIN_CONFIG_BIAS_DISABLE: -- if (hw->soc->bias_disable_set) { -+ if (hw->soc->bias_set_combo) { -+ err = hw->soc->bias_set_combo(hw, desc, 0, MTK_DISABLE); -+ if (err) -+ return err; -+ } else if (hw->soc->bias_disable_set) { - err = hw->soc->bias_disable_set(hw, desc); - if (err) - return err; -@@ -244,7 +271,11 @@ static int mtk_pinconf_set(struct pinctr - } - break; - case PIN_CONFIG_BIAS_PULL_UP: -- if (hw->soc->bias_set) { -+ if (hw->soc->bias_set_combo) { -+ err = hw->soc->bias_set_combo(hw, desc, 1, arg); -+ if (err) -+ return err; -+ } else if (hw->soc->bias_set) { - err = hw->soc->bias_set(hw, desc, 1); - if (err) - return err; -@@ -253,7 +284,11 @@ static int mtk_pinconf_set(struct pinctr - } - break; - case PIN_CONFIG_BIAS_PULL_DOWN: -- if (hw->soc->bias_set) { -+ if (hw->soc->bias_set_combo) { -+ err = hw->soc->bias_set_combo(hw, desc, 0, arg); -+ if (err) -+ return err; -+ } else if (hw->soc->bias_set) { - err = hw->soc->bias_set(hw, desc, 0); - if (err) - return err; diff --git a/target/linux/mediatek/patches-5.15/830-v5.18-regulator-Add-bindings-for-Richtek-RT5190A-PMIC.patch b/target/linux/mediatek/patches-5.15/830-v5.18-regulator-Add-bindings-for-Richtek-RT5190A-PMIC.patch deleted file mode 100644 index 30891d348..000000000 --- a/target/linux/mediatek/patches-5.15/830-v5.18-regulator-Add-bindings-for-Richtek-RT5190A-PMIC.patch +++ /dev/null @@ -1,180 +0,0 @@ -From b77e70f6b8f2cc62fba847f3008a430a09ef275d Mon Sep 17 00:00:00 2001 -From: ChiYuan Huang -Date: Wed, 9 Mar 2022 16:01:42 +0800 -Subject: [PATCH 1/2] regulator: Add bindings for Richtek RT5190A PMIC - -Add bindings for Richtek RT5190A PMIC. - -Signed-off-by: ChiYuan Huang -Reviewed-by: Krzysztof Kozlowski -Link: https://lore.kernel.org/r/1646812903-32496-2-git-send-email-u0084500@gmail.com -Signed-off-by: Mark Brown ---- - .../regulator/richtek,rt5190a-regulator.yaml | 141 ++++++++++++++++++ - .../regulator/richtek,rt5190a-regulator.h | 15 ++ - 2 files changed, 156 insertions(+) - create mode 100644 Documentation/devicetree/bindings/regulator/richtek,rt5190a-regulator.yaml - create mode 100644 include/dt-bindings/regulator/richtek,rt5190a-regulator.h - ---- /dev/null -+++ b/Documentation/devicetree/bindings/regulator/richtek,rt5190a-regulator.yaml -@@ -0,0 +1,141 @@ -+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause -+%YAML 1.2 -+--- -+$id: http://devicetree.org/schemas/regulator/richtek,rt5190a-regulator.yaml# -+$schema: http://devicetree.org/meta-schemas/core.yaml# -+ -+title: Richtek RT5190A PMIC Regulator -+ -+maintainers: -+ - ChiYuan Huang -+ -+description: | -+ The RT5190A integrates 1 channel buck controller, 3 channels high efficiency -+ synchronous buck converters, 1 LDO, I2C control interface and peripherial -+ logical control. -+ -+ It also supports mute AC OFF depop sound and quick setting storage while -+ input power is removed. -+ -+properties: -+ compatible: -+ enum: -+ - richtek,rt5190a -+ -+ reg: -+ maxItems: 1 -+ -+ interrupts: -+ maxItems: 1 -+ -+ vin2-supply: -+ description: phandle to buck2 input voltage. -+ -+ vin3-supply: -+ description: phandle to buck3 input voltage. -+ -+ vin4-supply: -+ description: phandle to buck4 input voltage. -+ -+ vinldo-supply: -+ description: phandle to ldo input voltage -+ -+ richtek,mute-enable: -+ description: | -+ The mute function uses 'mutein', 'muteout', and 'vdet' pins as the control -+ signal. When enabled, The normal behavior is to bypass the 'mutein' signal -+ 'muteout'. But if the power source removal is detected from 'vdet', -+ whatever the 'mutein' signal is, it will pull down the 'muteout' to force -+ speakers mute. this function is commonly used to prevent the speaker pop -+ noise during AC power turned off in the modern TV system design. -+ type: boolean -+ -+ regulators: -+ type: object -+ -+ patternProperties: -+ "^buck[1-4]$|^ldo$": -+ type: object -+ $ref: regulator.yaml# -+ description: | -+ regulator description for buck1 and buck4. -+ -+ properties: -+ regulator-allowed-modes: -+ description: | -+ buck operating mode, only buck1/4 support mode operating. -+ 0: auto mode -+ 1: force pwm mode -+ items: -+ enum: [0, 1] -+ -+ richtek,latchup-enable: -+ type: boolean -+ description: | -+ If specified, undervolt protection mode changes from the default -+ hiccup to latchup. -+ -+ unevaluatedProperties: false -+ -+ additionalProperties: false -+ -+required: -+ - compatible -+ - reg -+ - regulators -+ -+additionalProperties: false -+ -+examples: -+ - | -+ #include -+ #include -+ -+ i2c { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ pmic@64 { -+ compatible = "richtek,rt5190a"; -+ reg = <0x64>; -+ interrupts-extended = <&gpio26 0 IRQ_TYPE_LEVEL_LOW>; -+ vin2-supply = <&rt5190_buck1>; -+ vin3-supply = <&rt5190_buck1>; -+ vin4-supply = <&rt5190_buck1>; -+ -+ regulators { -+ rt5190_buck1: buck1 { -+ regulator-name = "rt5190a-buck1"; -+ regulator-min-microvolt = <5090000>; -+ regulator-max-microvolt = <5090000>; -+ regulator-allowed-modes = ; -+ regulator-boot-on; -+ }; -+ buck2 { -+ regulator-name = "rt5190a-buck2"; -+ regulator-min-microvolt = <600000>; -+ regulator-max-microvolt = <1400000>; -+ regulator-boot-on; -+ }; -+ buck3 { -+ regulator-name = "rt5190a-buck3"; -+ regulator-min-microvolt = <600000>; -+ regulator-max-microvolt = <1400000>; -+ regulator-boot-on; -+ }; -+ buck4 { -+ regulator-name = "rt5190a-buck4"; -+ regulator-min-microvolt = <850000>; -+ regulator-max-microvolt = <850000>; -+ regulator-allowed-modes = ; -+ regulator-boot-on; -+ }; -+ ldo { -+ regulator-name = "rt5190a-ldo"; -+ regulator-min-microvolt = <1200000>; -+ regulator-max-microvolt = <1200000>; -+ regulator-boot-on; -+ }; -+ }; -+ }; -+ }; ---- /dev/null -+++ b/include/dt-bindings/regulator/richtek,rt5190a-regulator.h -@@ -0,0 +1,15 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+ -+#ifndef __DT_BINDINGS_RICHTEK_RT5190A_REGULATOR_H__ -+#define __DT_BINDINGS_RICHTEK_RT5190A_REGULATOR_H__ -+ -+/* -+ * BUCK/LDO mode constants which may be used in devicetree properties -+ * (eg. regulator-allowed-modes). -+ * See the manufacturer's datasheet for more information on these modes. -+ */ -+ -+#define RT5190A_OPMODE_AUTO 0 -+#define RT5190A_OPMODE_FPWM 1 -+ -+#endif diff --git a/target/linux/mediatek/patches-5.15/831-v5.18-regulator-rt5190a-Add-support-for-Richtek-RT5190A-PM.patch b/target/linux/mediatek/patches-5.15/831-v5.18-regulator-rt5190a-Add-support-for-Richtek-RT5190A-PM.patch deleted file mode 100644 index 0e0f099e5..000000000 --- a/target/linux/mediatek/patches-5.15/831-v5.18-regulator-rt5190a-Add-support-for-Richtek-RT5190A-PM.patch +++ /dev/null @@ -1,562 +0,0 @@ -From 760423dfad53877b468490758fe7ea968ded9402 Mon Sep 17 00:00:00 2001 -From: ChiYuan Huang -Date: Wed, 9 Mar 2022 16:01:43 +0800 -Subject: [PATCH 2/2] regulator: rt5190a: Add support for Richtek RT5190A PMIC - -Add support for Richtek RT5190A PMIC. - -Signed-off-by: ChiYuan Huang -Link: https://lore.kernel.org/r/1646812903-32496-3-git-send-email-u0084500@gmail.com -Signed-off-by: Mark Brown ---- - drivers/regulator/Kconfig | 10 + - drivers/regulator/Makefile | 1 + - drivers/regulator/rt5190a-regulator.c | 513 ++++++++++++++++++++++++++ - 3 files changed, 524 insertions(+) - create mode 100644 drivers/regulator/rt5190a-regulator.c - ---- a/drivers/regulator/Kconfig -+++ b/drivers/regulator/Kconfig -@@ -1037,6 +1037,16 @@ config REGULATOR_RT5033 - RT5033 PMIC. The device supports multiple regulators like - current source, LDO and Buck. - -+config REGULATOR_RT5190A -+ tristate "Richtek RT5190A PMIC" -+ depends on I2C -+ select REGMAP_I2C -+ help -+ This adds support for voltage regulator in Richtek RT5190A PMIC. -+ It integratas 1 channel buck controller, 3 channels high efficiency -+ buck converters, 1 LDO, mute AC OFF depop function, with the general -+ I2C control interface. -+ - config REGULATOR_RT6160 - tristate "Richtek RT6160 BuckBoost voltage regulator" - depends on I2C ---- a/drivers/regulator/Makefile -+++ b/drivers/regulator/Makefile -@@ -125,6 +125,7 @@ obj-$(CONFIG_REGULATOR_ROHM) += rohm-reg - obj-$(CONFIG_REGULATOR_RT4801) += rt4801-regulator.o - obj-$(CONFIG_REGULATOR_RT4831) += rt4831-regulator.o - obj-$(CONFIG_REGULATOR_RT5033) += rt5033-regulator.o -+obj-$(CONFIG_REGULATOR_RT5190A) += rt5190a-regulator.o - obj-$(CONFIG_REGULATOR_RT6160) += rt6160-regulator.o - obj-$(CONFIG_REGULATOR_RT6245) += rt6245-regulator.o - obj-$(CONFIG_REGULATOR_RTMV20) += rtmv20-regulator.o ---- /dev/null -+++ b/drivers/regulator/rt5190a-regulator.c -@@ -0,0 +1,513 @@ -+// SPDX-License-Identifier: GPL-2.0+ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define RT5190A_REG_MANUFACTURE 0x00 -+#define RT5190A_REG_BUCK2VSEL 0x04 -+#define RT5190A_REG_BUCK3VSEL 0x05 -+#define RT5190A_REG_DCDCCNTL 0x06 -+#define RT5190A_REG_ENABLE 0x07 -+#define RT5190A_REG_DISCHARGE 0x09 -+#define RT5190A_REG_PROTMODE 0x0A -+#define RT5190A_REG_MUTECNTL 0x0B -+#define RT5190A_REG_PGSTAT 0x0F -+#define RT5190A_REG_OVINT 0x10 -+#define RT5190A_REG_HOTDIEMASK 0x17 -+ -+#define RT5190A_VSEL_MASK GENMASK(6, 0) -+#define RT5190A_RID_BITMASK(rid) BIT(rid + 1) -+#define RT5190A_BUCK1_DISCHG_MASK GENMASK(1, 0) -+#define RT5190A_BUCK1_DISCHG_ONVAL 0x01 -+#define RT5190A_OVERVOLT_MASK GENMASK(7, 0) -+#define RT5190A_UNDERVOLT_MASK GENMASK(15, 8) -+#define RT5190A_CH234OT_MASK BIT(29) -+#define RT5190A_CHIPOT_MASK BIT(28) -+ -+#define RT5190A_BUCK23_MINUV 600000 -+#define RT5190A_BUCK23_MAXUV 1400000 -+#define RT5190A_BUCK23_STEPUV 10000 -+#define RT5190A_BUCK23_STEPNUM ((1400000 - 600000) / 10000 + 1) -+ -+enum { -+ RT5190A_IDX_BUCK1 = 0, -+ RT5190A_IDX_BUCK2, -+ RT5190A_IDX_BUCK3, -+ RT5190A_IDX_BUCK4, -+ RT5190A_IDX_LDO, -+ RT5190A_MAX_IDX -+}; -+ -+struct rt5190a_priv { -+ struct device *dev; -+ struct regmap *regmap; -+ struct regulator_desc rdesc[RT5190A_MAX_IDX]; -+ struct regulator_dev *rdev[RT5190A_MAX_IDX]; -+}; -+ -+static int rt5190a_get_error_flags(struct regulator_dev *rdev, -+ unsigned int *flags) -+{ -+ struct regmap *regmap = rdev_get_regmap(rdev); -+ int rid = rdev_get_id(rdev); -+ unsigned int pgood_stat; -+ int ret; -+ -+ ret = regmap_read(regmap, RT5190A_REG_PGSTAT, &pgood_stat); -+ if (ret) -+ return ret; -+ -+ if (!(pgood_stat & RT5190A_RID_BITMASK(rid))) -+ *flags = REGULATOR_ERROR_FAIL; -+ else -+ *flags = 0; -+ -+ return 0; -+} -+ -+static int rt5190a_fixed_buck_set_mode(struct regulator_dev *rdev, -+ unsigned int mode) -+{ -+ struct regmap *regmap = rdev_get_regmap(rdev); -+ int rid = rdev_get_id(rdev); -+ unsigned int mask = RT5190A_RID_BITMASK(rid), val; -+ -+ switch (mode) { -+ case REGULATOR_MODE_FAST: -+ val = mask; -+ break; -+ case REGULATOR_MODE_NORMAL: -+ val = 0; -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ return regmap_update_bits(regmap, RT5190A_REG_DCDCCNTL, mask, val); -+} -+ -+static unsigned int rt5190a_fixed_buck_get_mode(struct regulator_dev *rdev) -+{ -+ struct regmap *regmap = rdev_get_regmap(rdev); -+ int rid = rdev_get_id(rdev); -+ unsigned int val; -+ int ret; -+ -+ ret = regmap_read(regmap, RT5190A_REG_DCDCCNTL, &val); -+ if (ret) { -+ dev_err(&rdev->dev, "Failed to get mode [%d]\n", ret); -+ return ret; -+ } -+ -+ if (val & RT5190A_RID_BITMASK(rid)) -+ return REGULATOR_MODE_FAST; -+ -+ return REGULATOR_MODE_NORMAL; -+} -+ -+static const struct regulator_ops rt5190a_ranged_buck_ops = { -+ .enable = regulator_enable_regmap, -+ .disable = regulator_disable_regmap, -+ .is_enabled = regulator_is_enabled_regmap, -+ .set_voltage_sel = regulator_set_voltage_sel_regmap, -+ .get_voltage_sel = regulator_get_voltage_sel_regmap, -+ .list_voltage = regulator_list_voltage_linear, -+ .set_active_discharge = regulator_set_active_discharge_regmap, -+ .get_error_flags = rt5190a_get_error_flags, -+}; -+ -+static const struct regulator_ops rt5190a_fixed_buck_ops = { -+ .enable = regulator_enable_regmap, -+ .disable = regulator_disable_regmap, -+ .is_enabled = regulator_is_enabled_regmap, -+ .set_active_discharge = regulator_set_active_discharge_regmap, -+ .set_mode = rt5190a_fixed_buck_set_mode, -+ .get_mode = rt5190a_fixed_buck_get_mode, -+ .get_error_flags = rt5190a_get_error_flags, -+}; -+ -+static const struct regulator_ops rt5190a_fixed_ldo_ops = { -+ .enable = regulator_enable_regmap, -+ .disable = regulator_disable_regmap, -+ .is_enabled = regulator_is_enabled_regmap, -+ .set_active_discharge = regulator_set_active_discharge_regmap, -+ .get_error_flags = rt5190a_get_error_flags, -+}; -+ -+static irqreturn_t rt5190a_irq_handler(int irq, void *data) -+{ -+ struct rt5190a_priv *priv = data; -+ __le32 raws; -+ unsigned int events, fields; -+ static const struct { -+ unsigned int bitmask; -+ unsigned int report; -+ } event_tbl[] = { -+ { RT5190A_OVERVOLT_MASK, REGULATOR_ERROR_REGULATION_OUT }, -+ { RT5190A_UNDERVOLT_MASK, REGULATOR_ERROR_UNDER_VOLTAGE } -+ }; -+ int i, j, ret; -+ -+ ret = regmap_raw_read(priv->regmap, RT5190A_REG_OVINT, &raws, -+ sizeof(raws)); -+ if (ret) { -+ dev_err(priv->dev, "Failed to read events\n"); -+ return IRQ_NONE; -+ } -+ -+ events = le32_to_cpu(raws); -+ -+ ret = regmap_raw_write(priv->regmap, RT5190A_REG_OVINT, &raws, -+ sizeof(raws)); -+ if (ret) -+ dev_err(priv->dev, "Failed to write-clear events\n"); -+ -+ /* Handle OV,UV events */ -+ for (i = 0; i < ARRAY_SIZE(event_tbl); i++) { -+ fields = events & event_tbl[i].bitmask; -+ fields >>= ffs(event_tbl[i].bitmask) - 1; -+ -+ for (j = 0; j < RT5190A_MAX_IDX; j++) { -+ if (!(fields & RT5190A_RID_BITMASK(j))) -+ continue; -+ -+ regulator_notifier_call_chain(priv->rdev[j], -+ event_tbl[i].report, -+ NULL); -+ } -+ } -+ -+ /* Handle CH234 OT event */ -+ if (events & RT5190A_CH234OT_MASK) { -+ for (j = RT5190A_IDX_BUCK2; j < RT5190A_IDX_LDO; j++) { -+ regulator_notifier_call_chain(priv->rdev[j], -+ REGULATOR_ERROR_OVER_TEMP, -+ NULL); -+ } -+ } -+ -+ /* Warning if CHIP OT occur */ -+ if (events & RT5190A_CHIPOT_MASK) -+ dev_warn(priv->dev, "CHIP overheat\n"); -+ -+ return IRQ_HANDLED; -+} -+ -+static unsigned int rt5190a_of_map_mode(unsigned int mode) -+{ -+ switch (mode) { -+ case RT5190A_OPMODE_AUTO: -+ return REGULATOR_MODE_NORMAL; -+ case RT5190A_OPMODE_FPWM: -+ return REGULATOR_MODE_FAST; -+ default: -+ return REGULATOR_MODE_INVALID; -+ } -+} -+ -+static int rt5190a_of_parse_cb(struct rt5190a_priv *priv, int rid, -+ struct of_regulator_match *match) -+{ -+ struct regulator_desc *desc = priv->rdesc + rid; -+ struct regulator_init_data *init_data = match->init_data; -+ struct device_node *np = match->of_node; -+ bool latchup_enable; -+ unsigned int mask = RT5190A_RID_BITMASK(rid), val; -+ -+ switch (rid) { -+ case RT5190A_IDX_BUCK1: -+ case RT5190A_IDX_BUCK4: -+ case RT5190A_IDX_LDO: -+ init_data->constraints.apply_uV = 0; -+ -+ if (init_data->constraints.min_uV == -+ init_data->constraints.max_uV) -+ desc->fixed_uV = init_data->constraints.min_uV; -+ else { -+ dev_err(priv->dev, -+ "Variable voltage for fixed regulator\n"); -+ return -EINVAL; -+ } -+ break; -+ default: -+ break; -+ } -+ -+ latchup_enable = of_property_read_bool(np, "richtek,latchup-enable"); -+ -+ /* latchup: 0, default hiccup: 1 */ -+ val = !latchup_enable ? mask : 0; -+ -+ return regmap_update_bits(priv->regmap, RT5190A_REG_PROTMODE, mask, val); -+} -+ -+static void rt5190a_fillin_regulator_desc(struct regulator_desc *desc, int rid) -+{ -+ static const char * const regu_name[] = { "buck1", "buck2", -+ "buck3", "buck4", -+ "ldo" }; -+ static const char * const supply[] = { NULL, "vin2", "vin3", "vin4", -+ "vinldo" }; -+ -+ desc->name = regu_name[rid]; -+ desc->supply_name = supply[rid]; -+ desc->owner = THIS_MODULE; -+ desc->type = REGULATOR_VOLTAGE; -+ desc->id = rid; -+ desc->enable_reg = RT5190A_REG_ENABLE; -+ desc->enable_mask = RT5190A_RID_BITMASK(rid); -+ desc->active_discharge_reg = RT5190A_REG_DISCHARGE; -+ desc->active_discharge_mask = RT5190A_RID_BITMASK(rid); -+ desc->active_discharge_on = RT5190A_RID_BITMASK(rid); -+ -+ switch (rid) { -+ case RT5190A_IDX_BUCK1: -+ desc->active_discharge_mask = RT5190A_BUCK1_DISCHG_MASK; -+ desc->active_discharge_on = RT5190A_BUCK1_DISCHG_ONVAL; -+ desc->n_voltages = 1; -+ desc->ops = &rt5190a_fixed_buck_ops; -+ desc->of_map_mode = rt5190a_of_map_mode; -+ break; -+ case RT5190A_IDX_BUCK2: -+ desc->vsel_reg = RT5190A_REG_BUCK2VSEL; -+ desc->vsel_mask = RT5190A_VSEL_MASK; -+ desc->min_uV = RT5190A_BUCK23_MINUV; -+ desc->uV_step = RT5190A_BUCK23_STEPUV; -+ desc->n_voltages = RT5190A_BUCK23_STEPNUM; -+ desc->ops = &rt5190a_ranged_buck_ops; -+ break; -+ case RT5190A_IDX_BUCK3: -+ desc->vsel_reg = RT5190A_REG_BUCK3VSEL; -+ desc->vsel_mask = RT5190A_VSEL_MASK; -+ desc->min_uV = RT5190A_BUCK23_MINUV; -+ desc->uV_step = RT5190A_BUCK23_STEPUV; -+ desc->n_voltages = RT5190A_BUCK23_STEPNUM; -+ desc->ops = &rt5190a_ranged_buck_ops; -+ break; -+ case RT5190A_IDX_BUCK4: -+ desc->n_voltages = 1; -+ desc->ops = &rt5190a_fixed_buck_ops; -+ desc->of_map_mode = rt5190a_of_map_mode; -+ break; -+ case RT5190A_IDX_LDO: -+ desc->n_voltages = 1; -+ desc->ops = &rt5190a_fixed_ldo_ops; -+ break; -+ } -+} -+ -+static struct of_regulator_match rt5190a_regulator_match[] = { -+ { .name = "buck1", }, -+ { .name = "buck2", }, -+ { .name = "buck3", }, -+ { .name = "buck4", }, -+ { .name = "ldo", } -+}; -+ -+static int rt5190a_parse_regulator_dt_data(struct rt5190a_priv *priv) -+{ -+ struct device_node *regulator_np; -+ struct regulator_desc *reg_desc; -+ struct of_regulator_match *match; -+ int i, ret; -+ -+ for (i = 0; i < RT5190A_MAX_IDX; i++) { -+ reg_desc = priv->rdesc + i; -+ match = rt5190a_regulator_match + i; -+ -+ rt5190a_fillin_regulator_desc(reg_desc, i); -+ -+ match->desc = reg_desc; -+ } -+ -+ regulator_np = of_get_child_by_name(priv->dev->of_node, "regulators"); -+ if (!regulator_np) { -+ dev_err(priv->dev, "Could not find 'regulators' node\n"); -+ return -ENODEV; -+ } -+ -+ ret = of_regulator_match(priv->dev, regulator_np, -+ rt5190a_regulator_match, -+ ARRAY_SIZE(rt5190a_regulator_match)); -+ -+ of_node_put(regulator_np); -+ -+ if (ret < 0) { -+ dev_err(priv->dev, -+ "Error parsing regulator init data: %d\n", ret); -+ return ret; -+ } -+ -+ for (i = 0; i < RT5190A_MAX_IDX; i++) { -+ match = rt5190a_regulator_match + i; -+ -+ ret = rt5190a_of_parse_cb(priv, i, match); -+ if (ret) { -+ dev_err(priv->dev, "Failed in [%d] of_parse_cb\n", i); -+ return ret; -+ } -+ } -+ -+ return 0; -+} -+ -+static const struct reg_sequence rt5190a_init_patch[] = { -+ { 0x09, 0x3d, }, -+ { 0x0a, 0x3e, }, -+ { 0x0b, 0x01, }, -+ { 0x10, 0xff, }, -+ { 0x11, 0xff, }, -+ { 0x12, 0xff, }, -+ { 0x13, 0xff, }, -+ { 0x14, 0, }, -+ { 0x15, 0, }, -+ { 0x16, 0x3e, }, -+ { 0x17, 0, } -+}; -+ -+static int rt5190a_device_initialize(struct rt5190a_priv *priv) -+{ -+ bool mute_enable; -+ int ret; -+ -+ ret = regmap_register_patch(priv->regmap, rt5190a_init_patch, -+ ARRAY_SIZE(rt5190a_init_patch)); -+ if (ret) { -+ dev_err(priv->dev, "Failed to do register patch\n"); -+ return ret; -+ } -+ -+ mute_enable = device_property_read_bool(priv->dev, -+ "richtek,mute-enable"); -+ -+ if (mute_enable) { -+ ret = regmap_write(priv->regmap, RT5190A_REG_MUTECNTL, 0x00); -+ if (ret) { -+ dev_err(priv->dev, "Failed to enable mute function\n"); -+ return ret; -+ } -+ } -+ -+ return 0; -+} -+ -+static int rt5190a_device_check(struct rt5190a_priv *priv) -+{ -+ u16 devid; -+ int ret; -+ -+ ret = regmap_raw_read(priv->regmap, RT5190A_REG_MANUFACTURE, &devid, -+ sizeof(devid)); -+ if (ret) -+ return ret; -+ -+ if (devid) { -+ dev_err(priv->dev, "Incorrect device id 0x%04x\n", devid); -+ return -ENODEV; -+ } -+ -+ return 0; -+} -+ -+static const struct regmap_config rt5190a_regmap_config = { -+ .reg_bits = 8, -+ .val_bits = 8, -+ .max_register = RT5190A_REG_HOTDIEMASK, -+}; -+ -+static int rt5190a_probe(struct i2c_client *i2c) -+{ -+ struct rt5190a_priv *priv; -+ struct regulator_config cfg = {}; -+ int i, ret; -+ -+ priv = devm_kzalloc(&i2c->dev, sizeof(*priv), GFP_KERNEL); -+ if (!priv) -+ return -ENOMEM; -+ -+ priv->dev = &i2c->dev; -+ -+ priv->regmap = devm_regmap_init_i2c(i2c, &rt5190a_regmap_config); -+ if (IS_ERR(priv->regmap)) { -+ dev_err(&i2c->dev, "Failed to allocate regmap\n"); -+ return PTR_ERR(priv->regmap); -+ } -+ -+ ret = rt5190a_device_check(priv); -+ if (ret) { -+ dev_err(&i2c->dev, "Failed to check device %d\n", ret); -+ return ret; -+ } -+ -+ ret = rt5190a_device_initialize(priv); -+ if (ret) { -+ dev_err(&i2c->dev, "Failed to initialize the device\n"); -+ return ret; -+ } -+ -+ ret = rt5190a_parse_regulator_dt_data(priv); -+ if (ret) { -+ dev_err(&i2c->dev, "Failed to parse regulator dt\n"); -+ return ret; -+ } -+ -+ cfg.dev = &i2c->dev; -+ cfg.regmap = priv->regmap; -+ -+ for (i = 0; i < RT5190A_MAX_IDX; i++) { -+ struct regulator_desc *desc = priv->rdesc + i; -+ struct of_regulator_match *match = rt5190a_regulator_match + i; -+ -+ cfg.init_data = match->init_data; -+ cfg.of_node = match->of_node; -+ -+ priv->rdev[i] = devm_regulator_register(&i2c->dev, desc, &cfg); -+ if (IS_ERR(priv->rdev[i])) { -+ dev_err(&i2c->dev, "Failed to register regulator %s\n", -+ desc->name); -+ return PTR_ERR(priv->rdev[i]); -+ } -+ } -+ -+ if (i2c->irq) { -+ ret = devm_request_threaded_irq(&i2c->dev, i2c->irq, NULL, -+ rt5190a_irq_handler, -+ IRQF_ONESHOT, -+ dev_name(&i2c->dev), priv); -+ if (ret) { -+ dev_err(&i2c->dev, "Failed to register interrupt\n"); -+ return ret; -+ } -+ } -+ -+ return 0; -+} -+ -+static const struct of_device_id __maybe_unused rt5190a_device_table[] = { -+ { .compatible = "richtek,rt5190a", }, -+ {} -+}; -+MODULE_DEVICE_TABLE(of, rt5190a_device_table); -+ -+static struct i2c_driver rt5190a_driver = { -+ .driver = { -+ .name = "rt5190a", -+ .of_match_table = rt5190a_device_table, -+ }, -+ .probe_new = rt5190a_probe, -+}; -+module_i2c_driver(rt5190a_driver); -+ -+MODULE_AUTHOR("ChiYuan Huang "); -+MODULE_DESCRIPTION("Richtek RT5190A Regulator Driver"); -+MODULE_LICENSE("GPL v2"); diff --git a/target/linux/mediatek/patches-5.15/840-v5.16-i2c-mediatek-Reset-the-handshake-signal-between-i2c-.patch b/target/linux/mediatek/patches-5.15/840-v5.16-i2c-mediatek-Reset-the-handshake-signal-between-i2c-.patch deleted file mode 100644 index 8b0119640..000000000 --- a/target/linux/mediatek/patches-5.15/840-v5.16-i2c-mediatek-Reset-the-handshake-signal-between-i2c-.patch +++ /dev/null @@ -1,74 +0,0 @@ -From 95e4dfbf33dc0a0843ba20db811f7ea271235e1e Mon Sep 17 00:00:00 2001 -From: Kewei Xu -Date: Sun, 10 Oct 2021 15:05:12 +0800 -Subject: [PATCH 01/16] i2c: mediatek: Reset the handshake signal between i2c - and dma - -Due to changes in the hardware design of the handshaking signal -between i2c and dma, it is necessary to reset the handshaking -signal before each transfer to ensure that the multi-msgs can -be transferred correctly. - -Signed-off-by: Kewei Xu -Reviewed-by: Qii Wang -Signed-off-by: Wolfram Sang ---- - drivers/i2c/busses/i2c-mt65xx.c | 26 ++++++++++++++++++++++++++ - 1 file changed, 26 insertions(+) - ---- a/drivers/i2c/busses/i2c-mt65xx.c -+++ b/drivers/i2c/busses/i2c-mt65xx.c -@@ -15,6 +15,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -49,6 +50,8 @@ - #define I2C_RD_TRANAC_VALUE 0x0001 - #define I2C_SCL_MIS_COMP_VALUE 0x0000 - #define I2C_CHN_CLR_FLAG 0x0000 -+#define I2C_RELIABILITY 0x0010 -+#define I2C_DMAACK_ENABLE 0x0008 - - #define I2C_DMA_CON_TX 0x0000 - #define I2C_DMA_CON_RX 0x0001 -@@ -851,6 +854,7 @@ static int mtk_i2c_do_transfer(struct mt - u16 restart_flag = 0; - u16 dma_sync = 0; - u32 reg_4g_mode; -+ u32 reg_dma_reset; - u8 *dma_rd_buf = NULL; - u8 *dma_wr_buf = NULL; - dma_addr_t rpaddr = 0; -@@ -864,6 +868,28 @@ static int mtk_i2c_do_transfer(struct mt - - reinit_completion(&i2c->msg_complete); - -+ if (i2c->dev_comp->apdma_sync && -+ i2c->op != I2C_MASTER_WRRD && num > 1) { -+ mtk_i2c_writew(i2c, 0x00, OFFSET_DEBUGCTRL); -+ writel(I2C_DMA_HANDSHAKE_RST | I2C_DMA_WARM_RST, -+ i2c->pdmabase + OFFSET_RST); -+ -+ ret = readw_poll_timeout(i2c->pdmabase + OFFSET_RST, -+ reg_dma_reset, -+ !(reg_dma_reset & I2C_DMA_WARM_RST), -+ 0, 100); -+ if (ret) { -+ dev_err(i2c->dev, "DMA warm reset timeout\n"); -+ return -ETIMEDOUT; -+ } -+ -+ writel(I2C_DMA_CLR_FLAG, i2c->pdmabase + OFFSET_RST); -+ mtk_i2c_writew(i2c, I2C_HANDSHAKE_RST, OFFSET_SOFTRESET); -+ mtk_i2c_writew(i2c, I2C_CHN_CLR_FLAG, OFFSET_SOFTRESET); -+ mtk_i2c_writew(i2c, I2C_RELIABILITY | I2C_DMAACK_ENABLE, -+ OFFSET_DEBUGCTRL); -+ } -+ - control_reg = mtk_i2c_readw(i2c, OFFSET_CONTROL) & - ~(I2C_CONTROL_DIR_CHANGE | I2C_CONTROL_RS); - if ((i2c->speed_hz > I2C_MAX_FAST_MODE_PLUS_FREQ) || (left_num >= 1)) diff --git a/target/linux/mediatek/patches-5.15/841-v5.16-i2c-mediatek-Dump-i2c-dma-register-when-a-timeout-oc.patch b/target/linux/mediatek/patches-5.15/841-v5.16-i2c-mediatek-Dump-i2c-dma-register-when-a-timeout-oc.patch deleted file mode 100644 index a2d2521c7..000000000 --- a/target/linux/mediatek/patches-5.15/841-v5.16-i2c-mediatek-Dump-i2c-dma-register-when-a-timeout-oc.patch +++ /dev/null @@ -1,102 +0,0 @@ -From 5b8e29e566e086ef9b5b9ea0d054370a295e1d05 Mon Sep 17 00:00:00 2001 -From: Kewei Xu -Date: Sun, 10 Oct 2021 15:05:13 +0800 -Subject: [PATCH 02/16] i2c: mediatek: Dump i2c/dma register when a timeout - occurs - -When a timeout error occurs in i2c transter, it is usually related -to the i2c/dma IP hardware configuration. Therefore, the purpose of -this patch is to dump the key register values of i2c/dma when a -timeout occurs in i2c for debugging. - -Signed-off-by: Kewei Xu -Reviewed-by: Qii Wang -Signed-off-by: Wolfram Sang ---- - drivers/i2c/busses/i2c-mt65xx.c | 54 +++++++++++++++++++++++++++++++++ - 1 file changed, 54 insertions(+) - ---- a/drivers/i2c/busses/i2c-mt65xx.c -+++ b/drivers/i2c/busses/i2c-mt65xx.c -@@ -130,6 +130,7 @@ enum I2C_REGS_OFFSET { - OFFSET_HS, - OFFSET_SOFTRESET, - OFFSET_DCM_EN, -+ OFFSET_MULTI_DMA, - OFFSET_PATH_DIR, - OFFSET_DEBUGSTAT, - OFFSET_DEBUGCTRL, -@@ -197,6 +198,7 @@ static const u16 mt_i2c_regs_v2[] = { - [OFFSET_TRANSFER_LEN_AUX] = 0x44, - [OFFSET_CLOCK_DIV] = 0x48, - [OFFSET_SOFTRESET] = 0x50, -+ [OFFSET_MULTI_DMA] = 0x8c, - [OFFSET_SCL_MIS_COMP_POINT] = 0x90, - [OFFSET_DEBUGSTAT] = 0xe4, - [OFFSET_DEBUGCTRL] = 0xe8, -@@ -845,6 +847,57 @@ static int mtk_i2c_set_speed(struct mtk_ - return 0; - } - -+static void i2c_dump_register(struct mtk_i2c *i2c) -+{ -+ dev_dbg(i2c->dev, "SLAVE_ADDR: 0x%x, INTR_MASK: 0x%x\n", -+ mtk_i2c_readw(i2c, OFFSET_SLAVE_ADDR), -+ mtk_i2c_readw(i2c, OFFSET_INTR_MASK)); -+ dev_dbg(i2c->dev, "INTR_STAT: 0x%x, CONTROL: 0x%x\n", -+ mtk_i2c_readw(i2c, OFFSET_INTR_STAT), -+ mtk_i2c_readw(i2c, OFFSET_CONTROL)); -+ dev_dbg(i2c->dev, "TRANSFER_LEN: 0x%x, TRANSAC_LEN: 0x%x\n", -+ mtk_i2c_readw(i2c, OFFSET_TRANSFER_LEN), -+ mtk_i2c_readw(i2c, OFFSET_TRANSAC_LEN)); -+ dev_dbg(i2c->dev, "DELAY_LEN: 0x%x, HTIMING: 0x%x\n", -+ mtk_i2c_readw(i2c, OFFSET_DELAY_LEN), -+ mtk_i2c_readw(i2c, OFFSET_TIMING)); -+ dev_dbg(i2c->dev, "START: 0x%x, EXT_CONF: 0x%x\n", -+ mtk_i2c_readw(i2c, OFFSET_START), -+ mtk_i2c_readw(i2c, OFFSET_EXT_CONF)); -+ dev_dbg(i2c->dev, "HS: 0x%x, IO_CONFIG: 0x%x\n", -+ mtk_i2c_readw(i2c, OFFSET_HS), -+ mtk_i2c_readw(i2c, OFFSET_IO_CONFIG)); -+ dev_dbg(i2c->dev, "DCM_EN: 0x%x, TRANSFER_LEN_AUX: 0x%x\n", -+ mtk_i2c_readw(i2c, OFFSET_DCM_EN), -+ mtk_i2c_readw(i2c, OFFSET_TRANSFER_LEN_AUX)); -+ dev_dbg(i2c->dev, "CLOCK_DIV: 0x%x, FIFO_STAT: 0x%x\n", -+ mtk_i2c_readw(i2c, OFFSET_CLOCK_DIV), -+ mtk_i2c_readw(i2c, OFFSET_FIFO_STAT)); -+ dev_dbg(i2c->dev, "DEBUGCTRL : 0x%x, DEBUGSTAT: 0x%x\n", -+ mtk_i2c_readw(i2c, OFFSET_DEBUGCTRL), -+ mtk_i2c_readw(i2c, OFFSET_DEBUGSTAT)); -+ if (i2c->dev_comp->regs == mt_i2c_regs_v2) { -+ dev_dbg(i2c->dev, "LTIMING: 0x%x, MULTI_DMA: 0x%x\n", -+ mtk_i2c_readw(i2c, OFFSET_LTIMING), -+ mtk_i2c_readw(i2c, OFFSET_MULTI_DMA)); -+ } -+ dev_dbg(i2c->dev, "\nDMA_INT_FLAG: 0x%x, DMA_INT_EN: 0x%x\n", -+ readl(i2c->pdmabase + OFFSET_INT_FLAG), -+ readl(i2c->pdmabase + OFFSET_INT_EN)); -+ dev_dbg(i2c->dev, "DMA_EN: 0x%x, DMA_CON: 0x%x\n", -+ readl(i2c->pdmabase + OFFSET_EN), -+ readl(i2c->pdmabase + OFFSET_CON)); -+ dev_dbg(i2c->dev, "DMA_TX_MEM_ADDR: 0x%x, DMA_RX_MEM_ADDR: 0x%x\n", -+ readl(i2c->pdmabase + OFFSET_TX_MEM_ADDR), -+ readl(i2c->pdmabase + OFFSET_RX_MEM_ADDR)); -+ dev_dbg(i2c->dev, "DMA_TX_LEN: 0x%x, DMA_RX_LEN: 0x%x\n", -+ readl(i2c->pdmabase + OFFSET_TX_LEN), -+ readl(i2c->pdmabase + OFFSET_RX_LEN)); -+ dev_dbg(i2c->dev, "DMA_TX_4G_MODE: 0x%x, DMA_RX_4G_MODE: 0x%x", -+ readl(i2c->pdmabase + OFFSET_TX_4G_MODE), -+ readl(i2c->pdmabase + OFFSET_RX_4G_MODE)); -+} -+ - static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs, - int num, int left_num) - { -@@ -1075,6 +1128,7 @@ static int mtk_i2c_do_transfer(struct mt - - if (ret == 0) { - dev_dbg(i2c->dev, "addr: %x, transfer timeout\n", msgs->addr); -+ i2c_dump_register(i2c); - mtk_i2c_init_hw(i2c); - return -ETIMEDOUT; - } diff --git a/target/linux/mediatek/patches-5.15/842-v5.18-i2c-mediatek-Add-i2c-compatible-for-Mediatek-MT8186.patch b/target/linux/mediatek/patches-5.15/842-v5.18-i2c-mediatek-Add-i2c-compatible-for-Mediatek-MT8186.patch deleted file mode 100644 index 184fe94ff..000000000 --- a/target/linux/mediatek/patches-5.15/842-v5.18-i2c-mediatek-Add-i2c-compatible-for-Mediatek-MT8186.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 83630e3c6147bf7bb18a18f3d5a99462464f450b Mon Sep 17 00:00:00 2001 -From: Kewei Xu -Date: Tue, 25 Jan 2022 19:04:13 +0800 -Subject: [PATCH 03/16] i2c: mediatek: Add i2c compatible for Mediatek MT8186 - -Add i2c compatible for MT8186. Compare to MT8192 i2c controller, -MT8186 doesn't need handshake signal witch apdma. - -Signed-off-by: Kewei Xu -Reviewed-by: Qii Wang -Signed-off-by: Wolfram Sang ---- - drivers/i2c/busses/i2c-mt65xx.c | 14 ++++++++++++++ - 1 file changed, 14 insertions(+) - ---- a/drivers/i2c/busses/i2c-mt65xx.c -+++ b/drivers/i2c/busses/i2c-mt65xx.c -@@ -397,6 +397,19 @@ static const struct mtk_i2c_compatible m - .max_dma_support = 33, - }; - -+static const struct mtk_i2c_compatible mt8186_compat = { -+ .regs = mt_i2c_regs_v2, -+ .pmic_i2c = 0, -+ .dcm = 0, -+ .auto_restart = 1, -+ .aux_len_reg = 1, -+ .timing_adjust = 1, -+ .dma_sync = 0, -+ .ltiming_adjust = 1, -+ .apdma_sync = 0, -+ .max_dma_support = 36, -+}; -+ - static const struct mtk_i2c_compatible mt8192_compat = { - .quirks = &mt8183_i2c_quirks, - .regs = mt_i2c_regs_v2, -@@ -418,6 +431,7 @@ static const struct of_device_id mtk_i2c - { .compatible = "mediatek,mt7622-i2c", .data = &mt7622_compat }, - { .compatible = "mediatek,mt8173-i2c", .data = &mt8173_compat }, - { .compatible = "mediatek,mt8183-i2c", .data = &mt8183_compat }, -+ { .compatible = "mediatek,mt8186-i2c", .data = &mt8186_compat }, - { .compatible = "mediatek,mt8192-i2c", .data = &mt8192_compat }, - {} - }; diff --git a/target/linux/mediatek/patches-5.15/843-v5.18-i2c-mediatek-modify-bus-speed-calculation-formula.patch b/target/linux/mediatek/patches-5.15/843-v5.18-i2c-mediatek-modify-bus-speed-calculation-formula.patch deleted file mode 100644 index 0ace4a670..000000000 --- a/target/linux/mediatek/patches-5.15/843-v5.18-i2c-mediatek-modify-bus-speed-calculation-formula.patch +++ /dev/null @@ -1,132 +0,0 @@ -From f606aab3f1a49d723d66e14e545f6ca45005bda6 Mon Sep 17 00:00:00 2001 -From: Kewei Xu -Date: Thu, 17 Feb 2022 20:22:43 +0800 -Subject: [PATCH 04/16] i2c: mediatek: modify bus speed calculation formula - -When clock-div is 0 or greater than 1, the bus speed -calculated by the old speed calculation formula will be -larger than the target speed. So we update the formula. - -Signed-off-by: Kewei Xu -Reviewed-by: AngeloGioacchino Del Regno -Reviewed-by: Qii Wang -Signed-off-by: Wolfram Sang ---- - drivers/i2c/busses/i2c-mt65xx.c | 51 ++++++++++++++++++++++++++------- - 1 file changed, 41 insertions(+), 10 deletions(-) - ---- a/drivers/i2c/busses/i2c-mt65xx.c -+++ b/drivers/i2c/busses/i2c-mt65xx.c -@@ -67,11 +67,12 @@ - - #define MAX_SAMPLE_CNT_DIV 8 - #define MAX_STEP_CNT_DIV 64 --#define MAX_CLOCK_DIV 256 -+#define MAX_CLOCK_DIV_8BITS 256 -+#define MAX_CLOCK_DIV_5BITS 32 - #define MAX_HS_STEP_CNT_DIV 8 --#define I2C_STANDARD_MODE_BUFFER (1000 / 2) --#define I2C_FAST_MODE_BUFFER (300 / 2) --#define I2C_FAST_MODE_PLUS_BUFFER (20 / 2) -+#define I2C_STANDARD_MODE_BUFFER (1000 / 3) -+#define I2C_FAST_MODE_BUFFER (300 / 3) -+#define I2C_FAST_MODE_PLUS_BUFFER (20 / 3) - - #define I2C_CONTROL_RS (0x1 << 1) - #define I2C_CONTROL_DMA_EN (0x1 << 2) -@@ -604,6 +605,31 @@ static int mtk_i2c_max_step_cnt(unsigned - return MAX_STEP_CNT_DIV; - } - -+static int mtk_i2c_get_clk_div_restri(struct mtk_i2c *i2c, -+ unsigned int sample_cnt) -+{ -+ int clk_div_restri = 0; -+ -+ if (i2c->dev_comp->ltiming_adjust == 0) -+ return 0; -+ -+ if (sample_cnt == 1) { -+ if (i2c->ac_timing.inter_clk_div == 0) -+ clk_div_restri = 0; -+ else -+ clk_div_restri = 1; -+ } else { -+ if (i2c->ac_timing.inter_clk_div == 0) -+ clk_div_restri = -1; -+ else if (i2c->ac_timing.inter_clk_div == 1) -+ clk_div_restri = 0; -+ else -+ clk_div_restri = 1; -+ } -+ -+ return clk_div_restri; -+} -+ - /* - * Check and Calculate i2c ac-timing - * -@@ -732,6 +758,7 @@ static int mtk_i2c_calculate_speed(struc - unsigned int best_mul; - unsigned int cnt_mul; - int ret = -EINVAL; -+ int clk_div_restri = 0; - - if (target_speed > I2C_MAX_HIGH_SPEED_MODE_FREQ) - target_speed = I2C_MAX_HIGH_SPEED_MODE_FREQ; -@@ -749,7 +776,8 @@ static int mtk_i2c_calculate_speed(struc - * optimizing for sample_cnt * step_cnt being minimal - */ - for (sample_cnt = 1; sample_cnt <= MAX_SAMPLE_CNT_DIV; sample_cnt++) { -- step_cnt = DIV_ROUND_UP(opt_div, sample_cnt); -+ clk_div_restri = mtk_i2c_get_clk_div_restri(i2c, sample_cnt); -+ step_cnt = DIV_ROUND_UP(opt_div + clk_div_restri, sample_cnt); - cnt_mul = step_cnt * sample_cnt; - if (step_cnt > max_step_cnt) - continue; -@@ -763,7 +791,7 @@ static int mtk_i2c_calculate_speed(struc - best_mul = cnt_mul; - base_sample_cnt = sample_cnt; - base_step_cnt = step_cnt; -- if (best_mul == opt_div) -+ if (best_mul == (opt_div + clk_div_restri)) - break; - } - } -@@ -774,7 +802,8 @@ static int mtk_i2c_calculate_speed(struc - sample_cnt = base_sample_cnt; - step_cnt = base_step_cnt; - -- if ((clk_src / (2 * sample_cnt * step_cnt)) > target_speed) { -+ if ((clk_src / (2 * (sample_cnt * step_cnt - clk_div_restri))) > -+ target_speed) { - /* In this case, hardware can't support such - * low i2c_bus_freq - */ -@@ -803,13 +832,16 @@ static int mtk_i2c_set_speed(struct mtk_ - target_speed = i2c->speed_hz; - parent_clk /= i2c->clk_src_div; - -- if (i2c->dev_comp->timing_adjust) -- max_clk_div = MAX_CLOCK_DIV; -+ if (i2c->dev_comp->timing_adjust && i2c->dev_comp->ltiming_adjust) -+ max_clk_div = MAX_CLOCK_DIV_5BITS; -+ else if (i2c->dev_comp->timing_adjust) -+ max_clk_div = MAX_CLOCK_DIV_8BITS; - else - max_clk_div = 1; - - for (clk_div = 1; clk_div <= max_clk_div; clk_div++) { - clk_src = parent_clk / clk_div; -+ i2c->ac_timing.inter_clk_div = clk_div - 1; - - if (target_speed > I2C_MAX_FAST_MODE_PLUS_FREQ) { - /* Set master code speed register */ -@@ -856,7 +888,6 @@ static int mtk_i2c_set_speed(struct mtk_ - break; - } - -- i2c->ac_timing.inter_clk_div = clk_div - 1; - - return 0; - } diff --git a/target/linux/mediatek/patches-5.15/844-v5.18-i2c-mediatek-remove-redundant-null-check.patch b/target/linux/mediatek/patches-5.15/844-v5.18-i2c-mediatek-remove-redundant-null-check.patch deleted file mode 100644 index 8f3c965a8..000000000 --- a/target/linux/mediatek/patches-5.15/844-v5.18-i2c-mediatek-remove-redundant-null-check.patch +++ /dev/null @@ -1,41 +0,0 @@ -From eb4a2ae019815946f574cd9f8209e12bdcd8fd34 Mon Sep 17 00:00:00 2001 -From: Xu Wang -Date: Wed, 30 Sep 2020 08:42:33 +0000 -Subject: [PATCH 05/16] i2c: mediatek: remove redundant null check - -Because clk_disable_unprepare already checked NULL clock parameter, -so the additional checks are unnecessary, just remove it - -Signed-off-by: Xu Wang -Reviewed-by: Qii Wang -Signed-off-by: Wolfram Sang ---- - drivers/i2c/busses/i2c-mt65xx.c | 9 +++------ - 1 file changed, 3 insertions(+), 6 deletions(-) - ---- a/drivers/i2c/busses/i2c-mt65xx.c -+++ b/drivers/i2c/busses/i2c-mt65xx.c -@@ -476,8 +476,7 @@ static int mtk_i2c_clock_enable(struct m - return 0; - - err_arb: -- if (i2c->have_pmic) -- clk_disable_unprepare(i2c->clk_pmic); -+ clk_disable_unprepare(i2c->clk_pmic); - err_pmic: - clk_disable_unprepare(i2c->clk_main); - err_main: -@@ -488,11 +487,9 @@ err_main: - - static void mtk_i2c_clock_disable(struct mtk_i2c *i2c) - { -- if (i2c->clk_arb) -- clk_disable_unprepare(i2c->clk_arb); -+ clk_disable_unprepare(i2c->clk_arb); - -- if (i2c->have_pmic) -- clk_disable_unprepare(i2c->clk_pmic); -+ clk_disable_unprepare(i2c->clk_pmic); - - clk_disable_unprepare(i2c->clk_main); - clk_disable_unprepare(i2c->clk_dma); diff --git a/target/linux/mediatek/patches-5.15/845-v5.18-i2c-mt65xx-Simplify-with-clk-bulk.patch b/target/linux/mediatek/patches-5.15/845-v5.18-i2c-mt65xx-Simplify-with-clk-bulk.patch deleted file mode 100644 index 71d083f31..000000000 --- a/target/linux/mediatek/patches-5.15/845-v5.18-i2c-mt65xx-Simplify-with-clk-bulk.patch +++ /dev/null @@ -1,234 +0,0 @@ -From cc6faa5e0772296d815fd298c231277d47308a6a Mon Sep 17 00:00:00 2001 -From: AngeloGioacchino Del Regno -Date: Thu, 3 Mar 2022 10:15:47 +0100 -Subject: [PATCH 06/16] i2c: mt65xx: Simplify with clk-bulk - -Since depending on the SoC or specific bus functionality some clocks -may be optional, we cannot get the benefit of using devm_clk_bulk_get() -but, by migrating to clk-bulk, we are able to remove the custom functions -mtk_i2c_clock_enable() and mtk_i2c_clock_disable(), increasing common -APIs usage, hence (lightly) decreasing kernel footprint. - -Signed-off-by: AngeloGioacchino Del Regno -Reviewed-by: Qii Wang -Signed-off-by: Wolfram Sang ---- - drivers/i2c/busses/i2c-mt65xx.c | 124 +++++++++++++------------------- - 1 file changed, 51 insertions(+), 73 deletions(-) - ---- a/drivers/i2c/busses/i2c-mt65xx.c -+++ b/drivers/i2c/busses/i2c-mt65xx.c -@@ -86,6 +86,27 @@ - - #define I2C_DRV_NAME "i2c-mt65xx" - -+/** -+ * enum i2c_mt65xx_clks - Clocks enumeration for MT65XX I2C -+ * -+ * @I2C_MT65XX_CLK_MAIN: main clock for i2c bus -+ * @I2C_MT65XX_CLK_DMA: DMA clock for i2c via DMA -+ * @I2C_MT65XX_CLK_PMIC: PMIC clock for i2c from PMIC -+ * @I2C_MT65XX_CLK_ARB: Arbitrator clock for i2c -+ * @I2C_MT65XX_CLK_MAX: Number of supported clocks -+ */ -+enum i2c_mt65xx_clks { -+ I2C_MT65XX_CLK_MAIN = 0, -+ I2C_MT65XX_CLK_DMA, -+ I2C_MT65XX_CLK_PMIC, -+ I2C_MT65XX_CLK_ARB, -+ I2C_MT65XX_CLK_MAX -+}; -+ -+static const char * const i2c_mt65xx_clk_ids[I2C_MT65XX_CLK_MAX] = { -+ "main", "dma", "pmic", "arb" -+}; -+ - enum DMA_REGS_OFFSET { - OFFSET_INT_FLAG = 0x0, - OFFSET_INT_EN = 0x04, -@@ -244,10 +265,7 @@ struct mtk_i2c { - /* set in i2c probe */ - void __iomem *base; /* i2c base addr */ - void __iomem *pdmabase; /* dma base address*/ -- struct clk *clk_main; /* main clock for i2c bus */ -- struct clk *clk_dma; /* DMA clock for i2c via DMA */ -- struct clk *clk_pmic; /* PMIC clock for i2c from PMIC */ -- struct clk *clk_arb; /* Arbitrator clock for i2c */ -+ struct clk_bulk_data clocks[I2C_MT65XX_CLK_MAX]; /* clocks for i2c */ - bool have_pmic; /* can use i2c pins from PMIC */ - bool use_push_pull; /* IO config push-pull mode */ - -@@ -449,52 +467,6 @@ static void mtk_i2c_writew(struct mtk_i2 - writew(val, i2c->base + i2c->dev_comp->regs[reg]); - } - --static int mtk_i2c_clock_enable(struct mtk_i2c *i2c) --{ -- int ret; -- -- ret = clk_prepare_enable(i2c->clk_dma); -- if (ret) -- return ret; -- -- ret = clk_prepare_enable(i2c->clk_main); -- if (ret) -- goto err_main; -- -- if (i2c->have_pmic) { -- ret = clk_prepare_enable(i2c->clk_pmic); -- if (ret) -- goto err_pmic; -- } -- -- if (i2c->clk_arb) { -- ret = clk_prepare_enable(i2c->clk_arb); -- if (ret) -- goto err_arb; -- } -- -- return 0; -- --err_arb: -- clk_disable_unprepare(i2c->clk_pmic); --err_pmic: -- clk_disable_unprepare(i2c->clk_main); --err_main: -- clk_disable_unprepare(i2c->clk_dma); -- -- return ret; --} -- --static void mtk_i2c_clock_disable(struct mtk_i2c *i2c) --{ -- clk_disable_unprepare(i2c->clk_arb); -- -- clk_disable_unprepare(i2c->clk_pmic); -- -- clk_disable_unprepare(i2c->clk_main); -- clk_disable_unprepare(i2c->clk_dma); --} -- - static void mtk_i2c_init_hw(struct mtk_i2c *i2c) - { - u16 control_reg; -@@ -1191,7 +1163,7 @@ static int mtk_i2c_transfer(struct i2c_a - int left_num = num; - struct mtk_i2c *i2c = i2c_get_adapdata(adap); - -- ret = mtk_i2c_clock_enable(i2c); -+ ret = clk_bulk_prepare_enable(I2C_MT65XX_CLK_MAX, i2c->clocks); - if (ret) - return ret; - -@@ -1245,7 +1217,7 @@ static int mtk_i2c_transfer(struct i2c_a - ret = num; - - err_exit: -- mtk_i2c_clock_disable(i2c); -+ clk_bulk_disable_unprepare(I2C_MT65XX_CLK_MAX, i2c->clocks); - return ret; - } - -@@ -1323,9 +1295,8 @@ static int mtk_i2c_probe(struct platform - { - int ret = 0; - struct mtk_i2c *i2c; -- struct clk *clk; - struct resource *res; -- int irq; -+ int i, irq, speed_clk; - - i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL); - if (!i2c) -@@ -1371,35 +1342,42 @@ static int mtk_i2c_probe(struct platform - if (i2c->have_pmic && !i2c->dev_comp->pmic_i2c) - return -EINVAL; - -- i2c->clk_main = devm_clk_get(&pdev->dev, "main"); -- if (IS_ERR(i2c->clk_main)) { -+ /* Fill in clk-bulk IDs */ -+ for (i = 0; i < I2C_MT65XX_CLK_MAX; i++) -+ i2c->clocks[i].id = i2c_mt65xx_clk_ids[i]; -+ -+ /* Get clocks one by one, some may be optional */ -+ i2c->clocks[I2C_MT65XX_CLK_MAIN].clk = devm_clk_get(&pdev->dev, "main"); -+ if (IS_ERR(i2c->clocks[I2C_MT65XX_CLK_MAIN].clk)) { - dev_err(&pdev->dev, "cannot get main clock\n"); -- return PTR_ERR(i2c->clk_main); -+ return PTR_ERR(i2c->clocks[I2C_MT65XX_CLK_MAIN].clk); - } - -- i2c->clk_dma = devm_clk_get(&pdev->dev, "dma"); -- if (IS_ERR(i2c->clk_dma)) { -+ i2c->clocks[I2C_MT65XX_CLK_DMA].clk = devm_clk_get(&pdev->dev, "dma"); -+ if (IS_ERR(i2c->clocks[I2C_MT65XX_CLK_DMA].clk)) { - dev_err(&pdev->dev, "cannot get dma clock\n"); -- return PTR_ERR(i2c->clk_dma); -+ return PTR_ERR(i2c->clocks[I2C_MT65XX_CLK_DMA].clk); - } - -- i2c->clk_arb = devm_clk_get(&pdev->dev, "arb"); -- if (IS_ERR(i2c->clk_arb)) -- i2c->clk_arb = NULL; -+ i2c->clocks[I2C_MT65XX_CLK_ARB].clk = devm_clk_get_optional(&pdev->dev, "arb"); -+ if (IS_ERR(i2c->clocks[I2C_MT65XX_CLK_ARB].clk)) -+ return PTR_ERR(i2c->clocks[I2C_MT65XX_CLK_ARB].clk); - -- clk = i2c->clk_main; - if (i2c->have_pmic) { -- i2c->clk_pmic = devm_clk_get(&pdev->dev, "pmic"); -- if (IS_ERR(i2c->clk_pmic)) { -+ i2c->clocks[I2C_MT65XX_CLK_PMIC].clk = devm_clk_get(&pdev->dev, "pmic"); -+ if (IS_ERR(i2c->clocks[I2C_MT65XX_CLK_PMIC].clk)) { - dev_err(&pdev->dev, "cannot get pmic clock\n"); -- return PTR_ERR(i2c->clk_pmic); -+ return PTR_ERR(i2c->clocks[I2C_MT65XX_CLK_PMIC].clk); - } -- clk = i2c->clk_pmic; -+ speed_clk = I2C_MT65XX_CLK_PMIC; -+ } else { -+ i2c->clocks[I2C_MT65XX_CLK_PMIC].clk = NULL; -+ speed_clk = I2C_MT65XX_CLK_MAIN; - } - - strlcpy(i2c->adap.name, I2C_DRV_NAME, sizeof(i2c->adap.name)); - -- ret = mtk_i2c_set_speed(i2c, clk_get_rate(clk)); -+ ret = mtk_i2c_set_speed(i2c, clk_get_rate(i2c->clocks[speed_clk].clk)); - if (ret) { - dev_err(&pdev->dev, "Failed to set the speed.\n"); - return -EINVAL; -@@ -1414,13 +1392,13 @@ static int mtk_i2c_probe(struct platform - } - } - -- ret = mtk_i2c_clock_enable(i2c); -+ ret = clk_bulk_prepare_enable(I2C_MT65XX_CLK_MAX, i2c->clocks); - if (ret) { - dev_err(&pdev->dev, "clock enable failed!\n"); - return ret; - } - mtk_i2c_init_hw(i2c); -- mtk_i2c_clock_disable(i2c); -+ clk_bulk_disable_unprepare(I2C_MT65XX_CLK_MAX, i2c->clocks); - - ret = devm_request_irq(&pdev->dev, irq, mtk_i2c_irq, - IRQF_NO_SUSPEND | IRQF_TRIGGER_NONE, -@@ -1465,7 +1443,7 @@ static int mtk_i2c_resume_noirq(struct d - int ret; - struct mtk_i2c *i2c = dev_get_drvdata(dev); - -- ret = mtk_i2c_clock_enable(i2c); -+ ret = clk_bulk_prepare_enable(I2C_MT65XX_CLK_MAX, i2c->clocks); - if (ret) { - dev_err(dev, "clock enable failed!\n"); - return ret; -@@ -1473,7 +1451,7 @@ static int mtk_i2c_resume_noirq(struct d - - mtk_i2c_init_hw(i2c); - -- mtk_i2c_clock_disable(i2c); -+ clk_bulk_disable_unprepare(I2C_MT65XX_CLK_MAX, i2c->clocks); - - i2c_mark_adapter_resumed(&i2c->adap); - diff --git a/target/linux/mediatek/patches-5.15/846-v5.18-i2c-mediatek-Add-i2c-compatible-for-Mediatek-MT8168.patch b/target/linux/mediatek/patches-5.15/846-v5.18-i2c-mediatek-Add-i2c-compatible-for-Mediatek-MT8168.patch deleted file mode 100644 index fe5be94fc..000000000 --- a/target/linux/mediatek/patches-5.15/846-v5.18-i2c-mediatek-Add-i2c-compatible-for-Mediatek-MT8168.patch +++ /dev/null @@ -1,46 +0,0 @@ -From de054c03f90b3ea22bc346fbf78ac716df192b2d Mon Sep 17 00:00:00 2001 -From: Kewei Xu -Date: Mon, 7 Mar 2022 11:36:49 +0800 -Subject: [PATCH 07/16] i2c: mediatek: Add i2c compatible for Mediatek MT8168 - -Add i2c compatible for MT8168. Compare to MT2712 i2c controller, -MT8168 need to synchronize signal with dma. - -Signed-off-by: Kewei Xu -Reviewed-by: AngeloGioacchino Del Regno -Reviewed-by: Qii Wang -Signed-off-by: Wolfram Sang ---- - drivers/i2c/busses/i2c-mt65xx.c | 14 ++++++++++++++ - 1 file changed, 14 insertions(+) - ---- a/drivers/i2c/busses/i2c-mt65xx.c -+++ b/drivers/i2c/busses/i2c-mt65xx.c -@@ -389,6 +389,19 @@ static const struct mtk_i2c_compatible m - .max_dma_support = 32, - }; - -+static const struct mtk_i2c_compatible mt8168_compat = { -+ .regs = mt_i2c_regs_v1, -+ .pmic_i2c = 0, -+ .dcm = 1, -+ .auto_restart = 1, -+ .aux_len_reg = 1, -+ .timing_adjust = 1, -+ .dma_sync = 1, -+ .ltiming_adjust = 0, -+ .apdma_sync = 0, -+ .max_dma_support = 33, -+}; -+ - static const struct mtk_i2c_compatible mt8173_compat = { - .regs = mt_i2c_regs_v1, - .pmic_i2c = 0, -@@ -448,6 +461,7 @@ static const struct of_device_id mtk_i2c - { .compatible = "mediatek,mt6577-i2c", .data = &mt6577_compat }, - { .compatible = "mediatek,mt6589-i2c", .data = &mt6589_compat }, - { .compatible = "mediatek,mt7622-i2c", .data = &mt7622_compat }, -+ { .compatible = "mediatek,mt8168-i2c", .data = &mt8168_compat }, - { .compatible = "mediatek,mt8173-i2c", .data = &mt8173_compat }, - { .compatible = "mediatek,mt8183-i2c", .data = &mt8183_compat }, - { .compatible = "mediatek,mt8186-i2c", .data = &mt8186_compat }, diff --git a/target/linux/mediatek/patches-5.15/847-v5.19-i2c-mediatek-Optimize-master_xfer-and-avoid-circular.patch b/target/linux/mediatek/patches-5.15/847-v5.19-i2c-mediatek-Optimize-master_xfer-and-avoid-circular.patch deleted file mode 100644 index 5c4ce4076..000000000 --- a/target/linux/mediatek/patches-5.15/847-v5.19-i2c-mediatek-Optimize-master_xfer-and-avoid-circular.patch +++ /dev/null @@ -1,101 +0,0 @@ -From 2831f9a53ec3a16012d2d23590e3ebad6084b763 Mon Sep 17 00:00:00 2001 -From: AngeloGioacchino Del Regno -Date: Mon, 11 Apr 2022 15:21:07 +0200 -Subject: [PATCH 08/16] i2c: mediatek: Optimize master_xfer() and avoid - circular locking -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Especially (but not only) during probe, it may happen that multiple -devices are communicating via i2c (or multiple i2c busses) and -sometimes while others are probing asynchronously. -For example, a Cr50 TPM may be filling entropy (or userspace may be -reading random data) while the rt5682 (i2c) codec driver reads/sets -some registers, like while getting/setting a clock's rate, which -happens both during probe and during system operation. - -In this driver, the mtk_i2c_transfer() function (which is the i2c -.master_xfer() callback) was granularly managing the clocks by -performing a clk_bulk_prepare_enable() to start them and its inverse. -This is not only creating possible circular locking dependencies in -the some cases (like former explanation), but it's also suboptimal, -as clk_core prepare/unprepare operations are using mutex locking, -which creates a bit of unwanted overhead (for example, i2c trackpads -will call master_xfer() every few milliseconds!). - -With this commit, we avoid both the circular locking and additional -overhead by changing how we handle the clocks in this driver: -- Prepare the clocks during probe (and PM resume) -- Enable/disable clocks in mtk_i2c_transfer() -- Unprepare the clocks only for driver removal (and PM suspend) - -For the sake of providing a full explanation: during probe, the -clocks are not only prepared but also enabled, as this is needed -for some hardware initialization but, after that, we are disabling -but not unpreparing them, leaving an expected state for the -aforementioned clock handling strategy. - -Signed-off-by: AngeloGioacchino Del Regno -Tested-by: Nícolas F. R. A. Prado -Reviewed-by: Qii Wang -Signed-off-by: Wolfram Sang ---- - drivers/i2c/busses/i2c-mt65xx.c | 11 +++++++---- - 1 file changed, 7 insertions(+), 4 deletions(-) - ---- a/drivers/i2c/busses/i2c-mt65xx.c -+++ b/drivers/i2c/busses/i2c-mt65xx.c -@@ -1177,7 +1177,7 @@ static int mtk_i2c_transfer(struct i2c_a - int left_num = num; - struct mtk_i2c *i2c = i2c_get_adapdata(adap); - -- ret = clk_bulk_prepare_enable(I2C_MT65XX_CLK_MAX, i2c->clocks); -+ ret = clk_bulk_enable(I2C_MT65XX_CLK_MAX, i2c->clocks); - if (ret) - return ret; - -@@ -1231,7 +1231,7 @@ static int mtk_i2c_transfer(struct i2c_a - ret = num; - - err_exit: -- clk_bulk_disable_unprepare(I2C_MT65XX_CLK_MAX, i2c->clocks); -+ clk_bulk_disable(I2C_MT65XX_CLK_MAX, i2c->clocks); - return ret; - } - -@@ -1412,7 +1412,7 @@ static int mtk_i2c_probe(struct platform - return ret; - } - mtk_i2c_init_hw(i2c); -- clk_bulk_disable_unprepare(I2C_MT65XX_CLK_MAX, i2c->clocks); -+ clk_bulk_disable(I2C_MT65XX_CLK_MAX, i2c->clocks); - - ret = devm_request_irq(&pdev->dev, irq, mtk_i2c_irq, - IRQF_NO_SUSPEND | IRQF_TRIGGER_NONE, -@@ -1439,6 +1439,8 @@ static int mtk_i2c_remove(struct platfor - - i2c_del_adapter(&i2c->adap); - -+ clk_bulk_unprepare(I2C_MT65XX_CLK_MAX, i2c->clocks); -+ - return 0; - } - -@@ -1448,6 +1450,7 @@ static int mtk_i2c_suspend_noirq(struct - struct mtk_i2c *i2c = dev_get_drvdata(dev); - - i2c_mark_adapter_suspended(&i2c->adap); -+ clk_bulk_unprepare(I2C_MT65XX_CLK_MAX, i2c->clocks); - - return 0; - } -@@ -1465,7 +1468,7 @@ static int mtk_i2c_resume_noirq(struct d - - mtk_i2c_init_hw(i2c); - -- clk_bulk_disable_unprepare(I2C_MT65XX_CLK_MAX, i2c->clocks); -+ clk_bulk_disable(I2C_MT65XX_CLK_MAX, i2c->clocks); - - i2c_mark_adapter_resumed(&i2c->adap); - diff --git a/target/linux/mediatek/patches-5.15/848-v5.19-i2c-mediatek-Fix-an-error-handling-path-in-mtk_i2c_p.patch b/target/linux/mediatek/patches-5.15/848-v5.19-i2c-mediatek-Fix-an-error-handling-path-in-mtk_i2c_p.patch deleted file mode 100644 index 354f12e21..000000000 --- a/target/linux/mediatek/patches-5.15/848-v5.19-i2c-mediatek-Fix-an-error-handling-path-in-mtk_i2c_p.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 6f3a5814c7aaea4176e0ac8b1ec6dc0a65aa2808 Mon Sep 17 00:00:00 2001 -From: Christophe JAILLET -Date: Sun, 22 May 2022 14:22:07 +0200 -Subject: [PATCH 09/16] i2c: mediatek: Fix an error handling path in - mtk_i2c_probe() - -The clsk are prepared, enabled, then disabled. So if an error occurs after -the disable step, they are still prepared. - -Add an error handling path to unprepare the clks in such a case, as already -done in the .remove function. - -Fixes: 8b4fc246c3ff ("i2c: mediatek: Optimize master_xfer() and avoid circular locking") -Signed-off-by: Christophe JAILLET -Reviewed-by: AngeloGioacchino Del Regno -Reviewed-by: Qii Wang -Signed-off-by: Wolfram Sang ---- - drivers/i2c/busses/i2c-mt65xx.c | 9 +++++++-- - 1 file changed, 7 insertions(+), 2 deletions(-) - ---- a/drivers/i2c/busses/i2c-mt65xx.c -+++ b/drivers/i2c/busses/i2c-mt65xx.c -@@ -1420,17 +1420,22 @@ static int mtk_i2c_probe(struct platform - if (ret < 0) { - dev_err(&pdev->dev, - "Request I2C IRQ %d fail\n", irq); -- return ret; -+ goto err_bulk_unprepare; - } - - i2c_set_adapdata(&i2c->adap, i2c); - ret = i2c_add_adapter(&i2c->adap); - if (ret) -- return ret; -+ goto err_bulk_unprepare; - - platform_set_drvdata(pdev, i2c); - - return 0; -+ -+err_bulk_unprepare: -+ clk_bulk_unprepare(I2C_MT65XX_CLK_MAX, i2c->clocks); -+ -+ return ret; - } - - static int mtk_i2c_remove(struct platform_device *pdev) diff --git a/target/linux/mediatek/patches-5.15/849-v6.0-i2c-mediatek-add-i2c-compatible-for-MT8188.patch b/target/linux/mediatek/patches-5.15/849-v6.0-i2c-mediatek-add-i2c-compatible-for-MT8188.patch deleted file mode 100644 index 744aa96ed..000000000 --- a/target/linux/mediatek/patches-5.15/849-v6.0-i2c-mediatek-add-i2c-compatible-for-MT8188.patch +++ /dev/null @@ -1,82 +0,0 @@ -From 94c7f8af2c0a399c8aa66f2522b60c5784b5be6c Mon Sep 17 00:00:00 2001 -From: Kewei Xu -Date: Sat, 6 Aug 2022 18:02:49 +0800 -Subject: [PATCH 10/16] i2c: mediatek: add i2c compatible for MT8188 - -Add i2c compatible for MT8188 and added mt_i2c_regs_v3[], since -MT8188 i2c OFFSET_SLAVE_ADDR register changed from 0x04 to 0x94. - -Signed-off-by: Kewei Xu -Reviewed-by: AngeloGioacchino Del Regno -Reviewed-by: Qii Wang -Signed-off-by: Wolfram Sang ---- - drivers/i2c/busses/i2c-mt65xx.c | 43 +++++++++++++++++++++++++++++++++ - 1 file changed, 43 insertions(+) - ---- a/drivers/i2c/busses/i2c-mt65xx.c -+++ b/drivers/i2c/busses/i2c-mt65xx.c -@@ -229,6 +229,35 @@ static const u16 mt_i2c_regs_v2[] = { - [OFFSET_DCM_EN] = 0xf88, - }; - -+static const u16 mt_i2c_regs_v3[] = { -+ [OFFSET_DATA_PORT] = 0x0, -+ [OFFSET_INTR_MASK] = 0x8, -+ [OFFSET_INTR_STAT] = 0xc, -+ [OFFSET_CONTROL] = 0x10, -+ [OFFSET_TRANSFER_LEN] = 0x14, -+ [OFFSET_TRANSAC_LEN] = 0x18, -+ [OFFSET_DELAY_LEN] = 0x1c, -+ [OFFSET_TIMING] = 0x20, -+ [OFFSET_START] = 0x24, -+ [OFFSET_EXT_CONF] = 0x28, -+ [OFFSET_LTIMING] = 0x2c, -+ [OFFSET_HS] = 0x30, -+ [OFFSET_IO_CONFIG] = 0x34, -+ [OFFSET_FIFO_ADDR_CLR] = 0x38, -+ [OFFSET_SDA_TIMING] = 0x3c, -+ [OFFSET_TRANSFER_LEN_AUX] = 0x44, -+ [OFFSET_CLOCK_DIV] = 0x48, -+ [OFFSET_SOFTRESET] = 0x50, -+ [OFFSET_MULTI_DMA] = 0x8c, -+ [OFFSET_SCL_MIS_COMP_POINT] = 0x90, -+ [OFFSET_SLAVE_ADDR] = 0x94, -+ [OFFSET_DEBUGSTAT] = 0xe4, -+ [OFFSET_DEBUGCTRL] = 0xe8, -+ [OFFSET_FIFO_STAT] = 0xf4, -+ [OFFSET_FIFO_THRESH] = 0xf8, -+ [OFFSET_DCM_EN] = 0xf88, -+}; -+ - struct mtk_i2c_compatible { - const struct i2c_adapter_quirks *quirks; - const u16 *regs; -@@ -442,6 +471,19 @@ static const struct mtk_i2c_compatible m - .max_dma_support = 36, - }; - -+static const struct mtk_i2c_compatible mt8188_compat = { -+ .regs = mt_i2c_regs_v3, -+ .pmic_i2c = 0, -+ .dcm = 0, -+ .auto_restart = 1, -+ .aux_len_reg = 1, -+ .timing_adjust = 1, -+ .dma_sync = 0, -+ .ltiming_adjust = 1, -+ .apdma_sync = 1, -+ .max_dma_support = 36, -+}; -+ - static const struct mtk_i2c_compatible mt8192_compat = { - .quirks = &mt8183_i2c_quirks, - .regs = mt_i2c_regs_v2, -@@ -465,6 +507,7 @@ static const struct of_device_id mtk_i2c - { .compatible = "mediatek,mt8173-i2c", .data = &mt8173_compat }, - { .compatible = "mediatek,mt8183-i2c", .data = &mt8183_compat }, - { .compatible = "mediatek,mt8186-i2c", .data = &mt8186_compat }, -+ { .compatible = "mediatek,mt8188-i2c", .data = &mt8188_compat }, - { .compatible = "mediatek,mt8192-i2c", .data = &mt8192_compat }, - {} - }; diff --git a/target/linux/mediatek/patches-5.15/850-v6.0-i2c-move-drivers-from-strlcpy-to-strscpy.patch b/target/linux/mediatek/patches-5.15/850-v6.0-i2c-move-drivers-from-strlcpy-to-strscpy.patch deleted file mode 100644 index 2741aa5bd..000000000 --- a/target/linux/mediatek/patches-5.15/850-v6.0-i2c-move-drivers-from-strlcpy-to-strscpy.patch +++ /dev/null @@ -1,579 +0,0 @@ -From 2f4ca256a98cc19787b7c861109dd1150a21b0bf Mon Sep 17 00:00:00 2001 -From: Wolfram Sang -Date: Thu, 11 Aug 2022 09:10:30 +0200 -Subject: [PATCH 11/16] i2c: move drivers from strlcpy to strscpy - -Follow the advice of the below link and prefer 'strscpy'. Conversion is -easy because no driver used the return value and has been done with a -simple sed invocation. - -Link: https://lore.kernel.org/r/CAHk-=wgfRnXz0W3D37d01q3JFkr_i_uTL=V6A6G1oUZcprmknw@mail.gmail.com/ -Signed-off-by: Wolfram Sang -Signed-off-by: Wolfram Sang ---- - drivers/i2c/busses/i2c-altera.c | 2 +- - drivers/i2c/busses/i2c-aspeed.c | 2 +- - drivers/i2c/busses/i2c-au1550.c | 2 +- - drivers/i2c/busses/i2c-axxia.c | 2 +- - drivers/i2c/busses/i2c-bcm-kona.c | 2 +- - drivers/i2c/busses/i2c-cbus-gpio.c | 2 +- - drivers/i2c/busses/i2c-cht-wc.c | 2 +- - drivers/i2c/busses/i2c-cros-ec-tunnel.c | 2 +- - drivers/i2c/busses/i2c-davinci.c | 2 +- - drivers/i2c/busses/i2c-digicolor.c | 2 +- - drivers/i2c/busses/i2c-eg20t.c | 2 +- - drivers/i2c/busses/i2c-emev2.c | 2 +- - drivers/i2c/busses/i2c-exynos5.c | 2 +- - drivers/i2c/busses/i2c-gpio.c | 2 +- - drivers/i2c/busses/i2c-highlander.c | 2 +- - drivers/i2c/busses/i2c-hix5hd2.c | 2 +- - drivers/i2c/busses/i2c-i801.c | 4 ++-- - drivers/i2c/busses/i2c-ibm_iic.c | 2 +- - drivers/i2c/busses/i2c-icy.c | 2 +- - drivers/i2c/busses/i2c-imx-lpi2c.c | 2 +- - drivers/i2c/busses/i2c-lpc2k.c | 2 +- - drivers/i2c/busses/i2c-meson.c | 2 +- - drivers/i2c/busses/i2c-mt65xx.c | 2 +- - drivers/i2c/busses/i2c-mt7621.c | 2 +- - drivers/i2c/busses/i2c-mv64xxx.c | 2 +- - drivers/i2c/busses/i2c-mxs.c | 2 +- - drivers/i2c/busses/i2c-nvidia-gpu.c | 2 +- - drivers/i2c/busses/i2c-omap.c | 2 +- - drivers/i2c/busses/i2c-opal.c | 4 ++-- - drivers/i2c/busses/i2c-parport.c | 2 +- - drivers/i2c/busses/i2c-pxa.c | 2 +- - drivers/i2c/busses/i2c-qcom-geni.c | 2 +- - drivers/i2c/busses/i2c-qup.c | 2 +- - drivers/i2c/busses/i2c-rcar.c | 2 +- - drivers/i2c/busses/i2c-riic.c | 2 +- - drivers/i2c/busses/i2c-rk3x.c | 2 +- - drivers/i2c/busses/i2c-s3c2410.c | 2 +- - drivers/i2c/busses/i2c-sh_mobile.c | 2 +- - drivers/i2c/busses/i2c-simtec.c | 2 +- - drivers/i2c/busses/i2c-taos-evm.c | 2 +- - drivers/i2c/busses/i2c-tegra-bpmp.c | 2 +- - drivers/i2c/busses/i2c-tegra.c | 2 +- - drivers/i2c/busses/i2c-uniphier-f.c | 2 +- - drivers/i2c/busses/i2c-uniphier.c | 2 +- - drivers/i2c/busses/i2c-versatile.c | 2 +- - drivers/i2c/busses/i2c-wmt.c | 2 +- - 46 files changed, 48 insertions(+), 48 deletions(-) - ---- a/drivers/i2c/busses/i2c-altera.c -+++ b/drivers/i2c/busses/i2c-altera.c -@@ -447,7 +447,7 @@ static int altr_i2c_probe(struct platfor - mutex_unlock(&idev->isr_mutex); - - i2c_set_adapdata(&idev->adapter, idev); -- strlcpy(idev->adapter.name, pdev->name, sizeof(idev->adapter.name)); -+ strscpy(idev->adapter.name, pdev->name, sizeof(idev->adapter.name)); - idev->adapter.owner = THIS_MODULE; - idev->adapter.algo = &altr_i2c_algo; - idev->adapter.dev.parent = &pdev->dev; ---- a/drivers/i2c/busses/i2c-aspeed.c -+++ b/drivers/i2c/busses/i2c-aspeed.c -@@ -1044,7 +1044,7 @@ static int aspeed_i2c_probe_bus(struct p - bus->adap.algo = &aspeed_i2c_algo; - bus->adap.dev.parent = &pdev->dev; - bus->adap.dev.of_node = pdev->dev.of_node; -- strlcpy(bus->adap.name, pdev->name, sizeof(bus->adap.name)); -+ strscpy(bus->adap.name, pdev->name, sizeof(bus->adap.name)); - i2c_set_adapdata(&bus->adap, bus); - - bus->dev = &pdev->dev; ---- a/drivers/i2c/busses/i2c-au1550.c -+++ b/drivers/i2c/busses/i2c-au1550.c -@@ -321,7 +321,7 @@ i2c_au1550_probe(struct platform_device - priv->adap.algo = &au1550_algo; - priv->adap.algo_data = priv; - priv->adap.dev.parent = &pdev->dev; -- strlcpy(priv->adap.name, "Au1xxx PSC I2C", sizeof(priv->adap.name)); -+ strscpy(priv->adap.name, "Au1xxx PSC I2C", sizeof(priv->adap.name)); - - /* Now, set up the PSC for SMBus PIO mode. */ - i2c_au1550_setup(priv); ---- a/drivers/i2c/busses/i2c-axxia.c -+++ b/drivers/i2c/busses/i2c-axxia.c -@@ -783,7 +783,7 @@ static int axxia_i2c_probe(struct platfo - } - - i2c_set_adapdata(&idev->adapter, idev); -- strlcpy(idev->adapter.name, pdev->name, sizeof(idev->adapter.name)); -+ strscpy(idev->adapter.name, pdev->name, sizeof(idev->adapter.name)); - idev->adapter.owner = THIS_MODULE; - idev->adapter.algo = &axxia_i2c_algo; - idev->adapter.bus_recovery_info = &axxia_i2c_recovery_info; ---- a/drivers/i2c/busses/i2c-bcm-kona.c -+++ b/drivers/i2c/busses/i2c-bcm-kona.c -@@ -849,7 +849,7 @@ static int bcm_kona_i2c_probe(struct pla - adap = &dev->adapter; - i2c_set_adapdata(adap, dev); - adap->owner = THIS_MODULE; -- strlcpy(adap->name, "Broadcom I2C adapter", sizeof(adap->name)); -+ strscpy(adap->name, "Broadcom I2C adapter", sizeof(adap->name)); - adap->algo = &bcm_algo; - adap->dev.parent = &pdev->dev; - adap->dev.of_node = pdev->dev.of_node; ---- a/drivers/i2c/busses/i2c-cbus-gpio.c -+++ b/drivers/i2c/busses/i2c-cbus-gpio.c -@@ -245,7 +245,7 @@ static int cbus_i2c_probe(struct platfor - adapter->nr = pdev->id; - adapter->timeout = HZ; - adapter->algo = &cbus_i2c_algo; -- strlcpy(adapter->name, "CBUS I2C adapter", sizeof(adapter->name)); -+ strscpy(adapter->name, "CBUS I2C adapter", sizeof(adapter->name)); - - spin_lock_init(&chost->lock); - chost->dev = &pdev->dev; ---- a/drivers/i2c/busses/i2c-cht-wc.c -+++ b/drivers/i2c/busses/i2c-cht-wc.c -@@ -334,7 +334,7 @@ static int cht_wc_i2c_adap_i2c_probe(str - adap->adapter.class = I2C_CLASS_HWMON; - adap->adapter.algo = &cht_wc_i2c_adap_algo; - adap->adapter.lock_ops = &cht_wc_i2c_adap_lock_ops; -- strlcpy(adap->adapter.name, "PMIC I2C Adapter", -+ strscpy(adap->adapter.name, "PMIC I2C Adapter", - sizeof(adap->adapter.name)); - adap->adapter.dev.parent = &pdev->dev; - ---- a/drivers/i2c/busses/i2c-cros-ec-tunnel.c -+++ b/drivers/i2c/busses/i2c-cros-ec-tunnel.c -@@ -267,7 +267,7 @@ static int ec_i2c_probe(struct platform_ - bus->dev = dev; - - bus->adap.owner = THIS_MODULE; -- strlcpy(bus->adap.name, "cros-ec-i2c-tunnel", sizeof(bus->adap.name)); -+ strscpy(bus->adap.name, "cros-ec-i2c-tunnel", sizeof(bus->adap.name)); - bus->adap.algo = &ec_i2c_algorithm; - bus->adap.algo_data = bus; - bus->adap.dev.parent = &pdev->dev; ---- a/drivers/i2c/busses/i2c-davinci.c -+++ b/drivers/i2c/busses/i2c-davinci.c -@@ -847,7 +847,7 @@ static int davinci_i2c_probe(struct plat - i2c_set_adapdata(adap, dev); - adap->owner = THIS_MODULE; - adap->class = I2C_CLASS_DEPRECATED; -- strlcpy(adap->name, "DaVinci I2C adapter", sizeof(adap->name)); -+ strscpy(adap->name, "DaVinci I2C adapter", sizeof(adap->name)); - adap->algo = &i2c_davinci_algo; - adap->dev.parent = &pdev->dev; - adap->timeout = DAVINCI_I2C_TIMEOUT; ---- a/drivers/i2c/busses/i2c-digicolor.c -+++ b/drivers/i2c/busses/i2c-digicolor.c -@@ -322,7 +322,7 @@ static int dc_i2c_probe(struct platform_ - if (ret < 0) - return ret; - -- strlcpy(i2c->adap.name, "Conexant Digicolor I2C adapter", -+ strscpy(i2c->adap.name, "Conexant Digicolor I2C adapter", - sizeof(i2c->adap.name)); - i2c->adap.owner = THIS_MODULE; - i2c->adap.algo = &dc_i2c_algorithm; ---- a/drivers/i2c/busses/i2c-eg20t.c -+++ b/drivers/i2c/busses/i2c-eg20t.c -@@ -773,7 +773,7 @@ static int pch_i2c_probe(struct pci_dev - - pch_adap->owner = THIS_MODULE; - pch_adap->class = I2C_CLASS_HWMON; -- strlcpy(pch_adap->name, KBUILD_MODNAME, sizeof(pch_adap->name)); -+ strscpy(pch_adap->name, KBUILD_MODNAME, sizeof(pch_adap->name)); - pch_adap->algo = &pch_algorithm; - pch_adap->algo_data = &adap_info->pch_data[i]; - ---- a/drivers/i2c/busses/i2c-emev2.c -+++ b/drivers/i2c/busses/i2c-emev2.c -@@ -371,7 +371,7 @@ static int em_i2c_probe(struct platform_ - if (IS_ERR(priv->base)) - return PTR_ERR(priv->base); - -- strlcpy(priv->adap.name, "EMEV2 I2C", sizeof(priv->adap.name)); -+ strscpy(priv->adap.name, "EMEV2 I2C", sizeof(priv->adap.name)); - - priv->sclk = devm_clk_get(&pdev->dev, "sclk"); - if (IS_ERR(priv->sclk)) ---- a/drivers/i2c/busses/i2c-exynos5.c -+++ b/drivers/i2c/busses/i2c-exynos5.c -@@ -751,7 +751,7 @@ static int exynos5_i2c_probe(struct plat - if (of_property_read_u32(np, "clock-frequency", &i2c->op_clock)) - i2c->op_clock = I2C_MAX_STANDARD_MODE_FREQ; - -- strlcpy(i2c->adap.name, "exynos5-i2c", sizeof(i2c->adap.name)); -+ strscpy(i2c->adap.name, "exynos5-i2c", sizeof(i2c->adap.name)); - i2c->adap.owner = THIS_MODULE; - i2c->adap.algo = &exynos5_i2c_algorithm; - i2c->adap.retries = 3; ---- a/drivers/i2c/busses/i2c-gpio.c -+++ b/drivers/i2c/busses/i2c-gpio.c -@@ -436,7 +436,7 @@ static int i2c_gpio_probe(struct platfor - - adap->owner = THIS_MODULE; - if (np) -- strlcpy(adap->name, dev_name(dev), sizeof(adap->name)); -+ strscpy(adap->name, dev_name(dev), sizeof(adap->name)); - else - snprintf(adap->name, sizeof(adap->name), "i2c-gpio%d", pdev->id); - ---- a/drivers/i2c/busses/i2c-highlander.c -+++ b/drivers/i2c/busses/i2c-highlander.c -@@ -402,7 +402,7 @@ static int highlander_i2c_probe(struct p - i2c_set_adapdata(adap, dev); - adap->owner = THIS_MODULE; - adap->class = I2C_CLASS_HWMON; -- strlcpy(adap->name, "HL FPGA I2C adapter", sizeof(adap->name)); -+ strscpy(adap->name, "HL FPGA I2C adapter", sizeof(adap->name)); - adap->algo = &highlander_i2c_algo; - adap->dev.parent = &pdev->dev; - adap->nr = pdev->id; ---- a/drivers/i2c/busses/i2c-hix5hd2.c -+++ b/drivers/i2c/busses/i2c-hix5hd2.c -@@ -423,7 +423,7 @@ static int hix5hd2_i2c_probe(struct plat - } - clk_prepare_enable(priv->clk); - -- strlcpy(priv->adap.name, "hix5hd2-i2c", sizeof(priv->adap.name)); -+ strscpy(priv->adap.name, "hix5hd2-i2c", sizeof(priv->adap.name)); - priv->dev = &pdev->dev; - priv->adap.owner = THIS_MODULE; - priv->adap.algo = &hix5hd2_i2c_algorithm; ---- a/drivers/i2c/busses/i2c-i801.c -+++ b/drivers/i2c/busses/i2c-i801.c -@@ -1103,7 +1103,7 @@ static void dmi_check_onboard_device(u8 - - memset(&info, 0, sizeof(struct i2c_board_info)); - info.addr = dmi_devices[i].i2c_addr; -- strlcpy(info.type, dmi_devices[i].i2c_type, I2C_NAME_SIZE); -+ strscpy(info.type, dmi_devices[i].i2c_type, I2C_NAME_SIZE); - i2c_new_client_device(adap, &info); - break; - } -@@ -1259,7 +1259,7 @@ static void register_dell_lis3lv02d_i2c_ - - memset(&info, 0, sizeof(struct i2c_board_info)); - info.addr = dell_lis3lv02d_devices[i].i2c_addr; -- strlcpy(info.type, "lis3lv02d", I2C_NAME_SIZE); -+ strscpy(info.type, "lis3lv02d", I2C_NAME_SIZE); - i2c_new_client_device(&priv->adapter, &info); - } - ---- a/drivers/i2c/busses/i2c-ibm_iic.c -+++ b/drivers/i2c/busses/i2c-ibm_iic.c -@@ -736,7 +736,7 @@ static int iic_probe(struct platform_dev - adap = &dev->adap; - adap->dev.parent = &ofdev->dev; - adap->dev.of_node = of_node_get(np); -- strlcpy(adap->name, "IBM IIC", sizeof(adap->name)); -+ strscpy(adap->name, "IBM IIC", sizeof(adap->name)); - i2c_set_adapdata(adap, dev); - adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD; - adap->algo = &iic_algo; ---- a/drivers/i2c/busses/i2c-icy.c -+++ b/drivers/i2c/busses/i2c-icy.c -@@ -141,7 +141,7 @@ static int icy_probe(struct zorro_dev *z - i2c->adapter.owner = THIS_MODULE; - /* i2c->adapter.algo assigned by i2c_pcf_add_bus() */ - i2c->adapter.algo_data = algo_data; -- strlcpy(i2c->adapter.name, "ICY I2C Zorro adapter", -+ strscpy(i2c->adapter.name, "ICY I2C Zorro adapter", - sizeof(i2c->adapter.name)); - - if (!devm_request_mem_region(&z->dev, ---- a/drivers/i2c/busses/i2c-imx-lpi2c.c -+++ b/drivers/i2c/busses/i2c-imx-lpi2c.c -@@ -564,7 +564,7 @@ static int lpi2c_imx_probe(struct platfo - lpi2c_imx->adapter.algo = &lpi2c_imx_algo; - lpi2c_imx->adapter.dev.parent = &pdev->dev; - lpi2c_imx->adapter.dev.of_node = pdev->dev.of_node; -- strlcpy(lpi2c_imx->adapter.name, pdev->name, -+ strscpy(lpi2c_imx->adapter.name, pdev->name, - sizeof(lpi2c_imx->adapter.name)); - - lpi2c_imx->clk = devm_clk_get(&pdev->dev, NULL); ---- a/drivers/i2c/busses/i2c-lpc2k.c -+++ b/drivers/i2c/busses/i2c-lpc2k.c -@@ -417,7 +417,7 @@ static int i2c_lpc2k_probe(struct platfo - - i2c_set_adapdata(&i2c->adap, i2c); - i2c->adap.owner = THIS_MODULE; -- strlcpy(i2c->adap.name, "LPC2K I2C adapter", sizeof(i2c->adap.name)); -+ strscpy(i2c->adap.name, "LPC2K I2C adapter", sizeof(i2c->adap.name)); - i2c->adap.algo = &i2c_lpc2k_algorithm; - i2c->adap.dev.parent = &pdev->dev; - i2c->adap.dev.of_node = pdev->dev.of_node; ---- a/drivers/i2c/busses/i2c-meson.c -+++ b/drivers/i2c/busses/i2c-meson.c -@@ -451,7 +451,7 @@ static int meson_i2c_probe(struct platfo - return ret; - } - -- strlcpy(i2c->adap.name, "Meson I2C adapter", -+ strscpy(i2c->adap.name, "Meson I2C adapter", - sizeof(i2c->adap.name)); - i2c->adap.owner = THIS_MODULE; - i2c->adap.algo = &meson_i2c_algorithm; ---- a/drivers/i2c/busses/i2c-mt65xx.c -+++ b/drivers/i2c/busses/i2c-mt65xx.c -@@ -1432,7 +1432,7 @@ static int mtk_i2c_probe(struct platform - speed_clk = I2C_MT65XX_CLK_MAIN; - } - -- strlcpy(i2c->adap.name, I2C_DRV_NAME, sizeof(i2c->adap.name)); -+ strscpy(i2c->adap.name, I2C_DRV_NAME, sizeof(i2c->adap.name)); - - ret = mtk_i2c_set_speed(i2c, clk_get_rate(i2c->clocks[speed_clk].clk)); - if (ret) { ---- a/drivers/i2c/busses/i2c-mt7621.c -+++ b/drivers/i2c/busses/i2c-mt7621.c -@@ -315,7 +315,7 @@ static int mtk_i2c_probe(struct platform - adap->dev.parent = &pdev->dev; - i2c_set_adapdata(adap, i2c); - adap->dev.of_node = pdev->dev.of_node; -- strlcpy(adap->name, dev_name(&pdev->dev), sizeof(adap->name)); -+ strscpy(adap->name, dev_name(&pdev->dev), sizeof(adap->name)); - - platform_set_drvdata(pdev, i2c); - ---- a/drivers/i2c/busses/i2c-mv64xxx.c -+++ b/drivers/i2c/busses/i2c-mv64xxx.c -@@ -1000,7 +1000,7 @@ mv64xxx_i2c_probe(struct platform_device - if (IS_ERR(drv_data->reg_base)) - return PTR_ERR(drv_data->reg_base); - -- strlcpy(drv_data->adapter.name, MV64XXX_I2C_CTLR_NAME " adapter", -+ strscpy(drv_data->adapter.name, MV64XXX_I2C_CTLR_NAME " adapter", - sizeof(drv_data->adapter.name)); - - init_waitqueue_head(&drv_data->waitq); ---- a/drivers/i2c/busses/i2c-mxs.c -+++ b/drivers/i2c/busses/i2c-mxs.c -@@ -838,7 +838,7 @@ static int mxs_i2c_probe(struct platform - return err; - - adap = &i2c->adapter; -- strlcpy(adap->name, "MXS I2C adapter", sizeof(adap->name)); -+ strscpy(adap->name, "MXS I2C adapter", sizeof(adap->name)); - adap->owner = THIS_MODULE; - adap->algo = &mxs_i2c_algo; - adap->quirks = &mxs_i2c_quirks; ---- a/drivers/i2c/busses/i2c-nvidia-gpu.c -+++ b/drivers/i2c/busses/i2c-nvidia-gpu.c -@@ -319,7 +319,7 @@ static int gpu_i2c_probe(struct pci_dev - - i2c_set_adapdata(&i2cd->adapter, i2cd); - i2cd->adapter.owner = THIS_MODULE; -- strlcpy(i2cd->adapter.name, "NVIDIA GPU I2C adapter", -+ strscpy(i2cd->adapter.name, "NVIDIA GPU I2C adapter", - sizeof(i2cd->adapter.name)); - i2cd->adapter.algo = &gpu_i2c_algorithm; - i2cd->adapter.quirks = &gpu_i2c_quirks; ---- a/drivers/i2c/busses/i2c-omap.c -+++ b/drivers/i2c/busses/i2c-omap.c -@@ -1488,7 +1488,7 @@ omap_i2c_probe(struct platform_device *p - i2c_set_adapdata(adap, omap); - adap->owner = THIS_MODULE; - adap->class = I2C_CLASS_DEPRECATED; -- strlcpy(adap->name, "OMAP I2C adapter", sizeof(adap->name)); -+ strscpy(adap->name, "OMAP I2C adapter", sizeof(adap->name)); - adap->algo = &omap_i2c_algo; - adap->quirks = &omap_i2c_quirks; - adap->dev.parent = &pdev->dev; ---- a/drivers/i2c/busses/i2c-opal.c -+++ b/drivers/i2c/busses/i2c-opal.c -@@ -220,9 +220,9 @@ static int i2c_opal_probe(struct platfor - adapter->dev.of_node = of_node_get(pdev->dev.of_node); - pname = of_get_property(pdev->dev.of_node, "ibm,port-name", NULL); - if (pname) -- strlcpy(adapter->name, pname, sizeof(adapter->name)); -+ strscpy(adapter->name, pname, sizeof(adapter->name)); - else -- strlcpy(adapter->name, "opal", sizeof(adapter->name)); -+ strscpy(adapter->name, "opal", sizeof(adapter->name)); - - platform_set_drvdata(pdev, adapter); - rc = i2c_add_adapter(adapter); ---- a/drivers/i2c/busses/i2c-parport.c -+++ b/drivers/i2c/busses/i2c-parport.c -@@ -308,7 +308,7 @@ static void i2c_parport_attach(struct pa - /* Fill the rest of the structure */ - adapter->adapter.owner = THIS_MODULE; - adapter->adapter.class = I2C_CLASS_HWMON; -- strlcpy(adapter->adapter.name, "Parallel port adapter", -+ strscpy(adapter->adapter.name, "Parallel port adapter", - sizeof(adapter->adapter.name)); - adapter->algo_data = parport_algo_data; - /* Slow down if we can't sense SCL */ ---- a/drivers/i2c/busses/i2c-pxa.c -+++ b/drivers/i2c/busses/i2c-pxa.c -@@ -1463,7 +1463,7 @@ static int i2c_pxa_probe(struct platform - spin_lock_init(&i2c->lock); - init_waitqueue_head(&i2c->wait); - -- strlcpy(i2c->adap.name, "pxa_i2c-i2c", sizeof(i2c->adap.name)); -+ strscpy(i2c->adap.name, "pxa_i2c-i2c", sizeof(i2c->adap.name)); - - i2c->clk = devm_clk_get(&dev->dev, NULL); - if (IS_ERR(i2c->clk)) { ---- a/drivers/i2c/busses/i2c-qcom-geni.c -+++ b/drivers/i2c/busses/i2c-qcom-geni.c -@@ -577,7 +577,7 @@ static int geni_i2c_probe(struct platfor - i2c_set_adapdata(&gi2c->adap, gi2c); - gi2c->adap.dev.parent = dev; - gi2c->adap.dev.of_node = dev->of_node; -- strlcpy(gi2c->adap.name, "Geni-I2C", sizeof(gi2c->adap.name)); -+ strscpy(gi2c->adap.name, "Geni-I2C", sizeof(gi2c->adap.name)); - - ret = geni_icc_get(&gi2c->se, "qup-memory"); - if (ret) ---- a/drivers/i2c/busses/i2c-qup.c -+++ b/drivers/i2c/busses/i2c-qup.c -@@ -1885,7 +1885,7 @@ nodma: - qup->adap.dev.of_node = pdev->dev.of_node; - qup->is_last = true; - -- strlcpy(qup->adap.name, "QUP I2C adapter", sizeof(qup->adap.name)); -+ strscpy(qup->adap.name, "QUP I2C adapter", sizeof(qup->adap.name)); - - pm_runtime_set_autosuspend_delay(qup->dev, MSEC_PER_SEC); - pm_runtime_use_autosuspend(qup->dev); ---- a/drivers/i2c/busses/i2c-rcar.c -+++ b/drivers/i2c/busses/i2c-rcar.c -@@ -1059,7 +1059,7 @@ static int rcar_i2c_probe(struct platfor - adap->bus_recovery_info = &rcar_i2c_bri; - adap->quirks = &rcar_i2c_quirks; - i2c_set_adapdata(adap, priv); -- strlcpy(adap->name, pdev->name, sizeof(adap->name)); -+ strscpy(adap->name, pdev->name, sizeof(adap->name)); - - /* Init DMA */ - sg_init_table(&priv->sg, 1); ---- a/drivers/i2c/busses/i2c-riic.c -+++ b/drivers/i2c/busses/i2c-riic.c -@@ -447,7 +447,7 @@ static int riic_i2c_probe(struct platfor - - adap = &riic->adapter; - i2c_set_adapdata(adap, riic); -- strlcpy(adap->name, "Renesas RIIC adapter", sizeof(adap->name)); -+ strscpy(adap->name, "Renesas RIIC adapter", sizeof(adap->name)); - adap->owner = THIS_MODULE; - adap->algo = &riic_algo; - adap->dev.parent = &pdev->dev; ---- a/drivers/i2c/busses/i2c-rk3x.c -+++ b/drivers/i2c/busses/i2c-rk3x.c -@@ -1247,7 +1247,7 @@ static int rk3x_i2c_probe(struct platfor - /* use common interface to get I2C timing properties */ - i2c_parse_fw_timings(&pdev->dev, &i2c->t, true); - -- strlcpy(i2c->adap.name, "rk3x-i2c", sizeof(i2c->adap.name)); -+ strscpy(i2c->adap.name, "rk3x-i2c", sizeof(i2c->adap.name)); - i2c->adap.owner = THIS_MODULE; - i2c->adap.algo = &rk3x_i2c_algorithm; - i2c->adap.retries = 3; ---- a/drivers/i2c/busses/i2c-s3c2410.c -+++ b/drivers/i2c/busses/i2c-s3c2410.c -@@ -1078,7 +1078,7 @@ static int s3c24xx_i2c_probe(struct plat - else - s3c24xx_i2c_parse_dt(pdev->dev.of_node, i2c); - -- strlcpy(i2c->adap.name, "s3c2410-i2c", sizeof(i2c->adap.name)); -+ strscpy(i2c->adap.name, "s3c2410-i2c", sizeof(i2c->adap.name)); - i2c->adap.owner = THIS_MODULE; - i2c->adap.algo = &s3c24xx_i2c_algorithm; - i2c->adap.retries = 2; ---- a/drivers/i2c/busses/i2c-sh_mobile.c -+++ b/drivers/i2c/busses/i2c-sh_mobile.c -@@ -930,7 +930,7 @@ static int sh_mobile_i2c_probe(struct pl - adap->nr = dev->id; - adap->dev.of_node = dev->dev.of_node; - -- strlcpy(adap->name, dev->name, sizeof(adap->name)); -+ strscpy(adap->name, dev->name, sizeof(adap->name)); - - spin_lock_init(&pd->lock); - init_waitqueue_head(&pd->wait); ---- a/drivers/i2c/busses/i2c-simtec.c -+++ b/drivers/i2c/busses/i2c-simtec.c -@@ -99,7 +99,7 @@ static int simtec_i2c_probe(struct platf - pd->adap.algo_data = &pd->bit; - pd->adap.dev.parent = &dev->dev; - -- strlcpy(pd->adap.name, "Simtec I2C", sizeof(pd->adap.name)); -+ strscpy(pd->adap.name, "Simtec I2C", sizeof(pd->adap.name)); - - pd->bit.data = pd; - pd->bit.setsda = simtec_i2c_setsda; ---- a/drivers/i2c/busses/i2c-taos-evm.c -+++ b/drivers/i2c/busses/i2c-taos-evm.c -@@ -239,7 +239,7 @@ static int taos_connect(struct serio *se - dev_err(&serio->dev, "TAOS EVM identification failed\n"); - goto exit_close; - } -- strlcpy(adapter->name, name, sizeof(adapter->name)); -+ strscpy(adapter->name, name, sizeof(adapter->name)); - - /* Turn echo off for better performance */ - taos->state = TAOS_STATE_EOFF; ---- a/drivers/i2c/busses/i2c-tegra-bpmp.c -+++ b/drivers/i2c/busses/i2c-tegra-bpmp.c -@@ -305,7 +305,7 @@ static int tegra_bpmp_i2c_probe(struct p - - i2c_set_adapdata(&i2c->adapter, i2c); - i2c->adapter.owner = THIS_MODULE; -- strlcpy(i2c->adapter.name, "Tegra BPMP I2C adapter", -+ strscpy(i2c->adapter.name, "Tegra BPMP I2C adapter", - sizeof(i2c->adapter.name)); - i2c->adapter.algo = &tegra_bpmp_i2c_algo; - i2c->adapter.dev.parent = &pdev->dev; ---- a/drivers/i2c/busses/i2c-tegra.c -+++ b/drivers/i2c/busses/i2c-tegra.c -@@ -1799,7 +1799,7 @@ static int tegra_i2c_probe(struct platfo - if (i2c_dev->hw->supports_bus_clear) - i2c_dev->adapter.bus_recovery_info = &tegra_i2c_recovery_info; - -- strlcpy(i2c_dev->adapter.name, dev_name(i2c_dev->dev), -+ strscpy(i2c_dev->adapter.name, dev_name(i2c_dev->dev), - sizeof(i2c_dev->adapter.name)); - - err = i2c_add_numbered_adapter(&i2c_dev->adapter); ---- a/drivers/i2c/busses/i2c-uniphier-f.c -+++ b/drivers/i2c/busses/i2c-uniphier-f.c -@@ -564,7 +564,7 @@ static int uniphier_fi2c_probe(struct pl - priv->adap.algo = &uniphier_fi2c_algo; - priv->adap.dev.parent = dev; - priv->adap.dev.of_node = dev->of_node; -- strlcpy(priv->adap.name, "UniPhier FI2C", sizeof(priv->adap.name)); -+ strscpy(priv->adap.name, "UniPhier FI2C", sizeof(priv->adap.name)); - priv->adap.bus_recovery_info = &uniphier_fi2c_bus_recovery_info; - i2c_set_adapdata(&priv->adap, priv); - platform_set_drvdata(pdev, priv); ---- a/drivers/i2c/busses/i2c-uniphier.c -+++ b/drivers/i2c/busses/i2c-uniphier.c -@@ -358,7 +358,7 @@ static int uniphier_i2c_probe(struct pla - priv->adap.algo = &uniphier_i2c_algo; - priv->adap.dev.parent = dev; - priv->adap.dev.of_node = dev->of_node; -- strlcpy(priv->adap.name, "UniPhier I2C", sizeof(priv->adap.name)); -+ strscpy(priv->adap.name, "UniPhier I2C", sizeof(priv->adap.name)); - priv->adap.bus_recovery_info = &uniphier_i2c_bus_recovery_info; - i2c_set_adapdata(&priv->adap, priv); - platform_set_drvdata(pdev, priv); ---- a/drivers/i2c/busses/i2c-versatile.c -+++ b/drivers/i2c/busses/i2c-versatile.c -@@ -79,7 +79,7 @@ static int i2c_versatile_probe(struct pl - writel(SCL | SDA, i2c->base + I2C_CONTROLS); - - i2c->adap.owner = THIS_MODULE; -- strlcpy(i2c->adap.name, "Versatile I2C adapter", sizeof(i2c->adap.name)); -+ strscpy(i2c->adap.name, "Versatile I2C adapter", sizeof(i2c->adap.name)); - i2c->adap.algo_data = &i2c->algo; - i2c->adap.dev.parent = &dev->dev; - i2c->adap.dev.of_node = dev->dev.of_node; ---- a/drivers/i2c/busses/i2c-wmt.c -+++ b/drivers/i2c/busses/i2c-wmt.c -@@ -413,7 +413,7 @@ static int wmt_i2c_probe(struct platform - - adap = &i2c_dev->adapter; - i2c_set_adapdata(adap, i2c_dev); -- strlcpy(adap->name, "WMT I2C adapter", sizeof(adap->name)); -+ strscpy(adap->name, "WMT I2C adapter", sizeof(adap->name)); - adap->owner = THIS_MODULE; - adap->algo = &wmt_i2c_algo; - adap->dev.parent = &pdev->dev; diff --git a/target/linux/mediatek/patches-5.15/851-v6.2-i2c-mediatek-add-mt7986-support.patch b/target/linux/mediatek/patches-5.15/851-v6.2-i2c-mediatek-add-mt7986-support.patch deleted file mode 100644 index 4c398c59f..000000000 --- a/target/linux/mediatek/patches-5.15/851-v6.2-i2c-mediatek-add-mt7986-support.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 11f9a0f4e51887ad7b4a2898a368fcd0c2984e89 Mon Sep 17 00:00:00 2001 -From: Frank Wunderlich -Date: Sun, 9 Oct 2022 12:16:31 +0200 -Subject: [PATCH 12/16] i2c: mediatek: add mt7986 support - -Add i2c support for MT7986 SoC. - -Signed-off-by: Frank Wunderlich -Reviewed-by: AngeloGioacchino Del Regno -Signed-off-by: Wolfram Sang ---- - drivers/i2c/busses/i2c-mt65xx.c | 14 ++++++++++++++ - 1 file changed, 14 insertions(+) - ---- a/drivers/i2c/busses/i2c-mt65xx.c -+++ b/drivers/i2c/busses/i2c-mt65xx.c -@@ -431,6 +431,19 @@ static const struct mtk_i2c_compatible m - .max_dma_support = 33, - }; - -+static const struct mtk_i2c_compatible mt7986_compat = { -+ .quirks = &mt7622_i2c_quirks, -+ .regs = mt_i2c_regs_v1, -+ .pmic_i2c = 0, -+ .dcm = 1, -+ .auto_restart = 1, -+ .aux_len_reg = 1, -+ .timing_adjust = 0, -+ .dma_sync = 1, -+ .ltiming_adjust = 0, -+ .max_dma_support = 32, -+}; -+ - static const struct mtk_i2c_compatible mt8173_compat = { - .regs = mt_i2c_regs_v1, - .pmic_i2c = 0, -@@ -503,6 +516,7 @@ static const struct of_device_id mtk_i2c - { .compatible = "mediatek,mt6577-i2c", .data = &mt6577_compat }, - { .compatible = "mediatek,mt6589-i2c", .data = &mt6589_compat }, - { .compatible = "mediatek,mt7622-i2c", .data = &mt7622_compat }, -+ { .compatible = "mediatek,mt7986-i2c", .data = &mt7986_compat }, - { .compatible = "mediatek,mt8168-i2c", .data = &mt8168_compat }, - { .compatible = "mediatek,mt8173-i2c", .data = &mt8173_compat }, - { .compatible = "mediatek,mt8183-i2c", .data = &mt8183_compat }, diff --git a/target/linux/mediatek/patches-5.15/852-v6.3-i2c-mt65xx-Use-devm_platform_get_and_ioremap_resourc.patch b/target/linux/mediatek/patches-5.15/852-v6.3-i2c-mt65xx-Use-devm_platform_get_and_ioremap_resourc.patch deleted file mode 100644 index 18c66cdac..000000000 --- a/target/linux/mediatek/patches-5.15/852-v6.3-i2c-mt65xx-Use-devm_platform_get_and_ioremap_resourc.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 98204ccafd45a8a6109ff2d60e2c179b95d92578 Mon Sep 17 00:00:00 2001 -From: ye xingchen -Date: Thu, 19 Jan 2023 17:19:58 +0800 -Subject: [PATCH 13/16] i2c: mt65xx: Use - devm_platform_get_and_ioremap_resource() - -Convert platform_get_resource(), devm_ioremap_resource() to a single -call to devm_platform_get_and_ioremap_resource(), as this is exactly -what this function does. - -Signed-off-by: ye xingchen -Reviewed-by: AngeloGioacchino Del Regno -Signed-off-by: Wolfram Sang ---- - drivers/i2c/busses/i2c-mt65xx.c | 7 ++----- - 1 file changed, 2 insertions(+), 5 deletions(-) - ---- a/drivers/i2c/busses/i2c-mt65xx.c -+++ b/drivers/i2c/busses/i2c-mt65xx.c -@@ -1366,20 +1366,17 @@ static int mtk_i2c_probe(struct platform - { - int ret = 0; - struct mtk_i2c *i2c; -- struct resource *res; - int i, irq, speed_clk; - - i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL); - if (!i2c) - return -ENOMEM; - -- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -- i2c->base = devm_ioremap_resource(&pdev->dev, res); -+ i2c->base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL); - if (IS_ERR(i2c->base)) - return PTR_ERR(i2c->base); - -- res = platform_get_resource(pdev, IORESOURCE_MEM, 1); -- i2c->pdmabase = devm_ioremap_resource(&pdev->dev, res); -+ i2c->pdmabase = devm_platform_get_and_ioremap_resource(pdev, 1, NULL); - if (IS_ERR(i2c->pdmabase)) - return PTR_ERR(i2c->pdmabase); - diff --git a/target/linux/mediatek/patches-5.15/853-v6.3-i2c-mt65xx-drop-of_match_ptr-for-ID-table.patch b/target/linux/mediatek/patches-5.15/853-v6.3-i2c-mt65xx-drop-of_match_ptr-for-ID-table.patch deleted file mode 100644 index d000d5352..000000000 --- a/target/linux/mediatek/patches-5.15/853-v6.3-i2c-mt65xx-drop-of_match_ptr-for-ID-table.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 8106fa2e0ae6082833fe1df97829c46c0183eaea Mon Sep 17 00:00:00 2001 -From: Krzysztof Kozlowski -Date: Sat, 11 Mar 2023 12:16:54 +0100 -Subject: [PATCH 14/16] i2c: mt65xx: drop of_match_ptr for ID table -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The driver can match only via the DT table so the table should be always -used and the of_match_ptr does not have any sense (this also allows ACPI -matching via PRP0001, even though it might not be relevant here). - - drivers/i2c/busses/i2c-mt65xx.c:514:34: error: ‘mtk_i2c_of_match’ defined but not used [-Werror=unused-const-variable=] - -Signed-off-by: Krzysztof Kozlowski -Reviewed-by: Guenter Roeck -Reviewed-by: AngeloGioacchino Del Regno -Signed-off-by: Wolfram Sang ---- - drivers/i2c/busses/i2c-mt65xx.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/i2c/busses/i2c-mt65xx.c -+++ b/drivers/i2c/busses/i2c-mt65xx.c -@@ -1546,7 +1546,7 @@ static struct platform_driver mtk_i2c_dr - .driver = { - .name = I2C_DRV_NAME, - .pm = &mtk_i2c_pm, -- .of_match_table = of_match_ptr(mtk_i2c_of_match), -+ .of_match_table = mtk_i2c_of_match, - }, - }; - diff --git a/target/linux/mediatek/patches-5.15/854-v6.4-i2c-mediatek-add-support-for-MT7981-SoC.patch b/target/linux/mediatek/patches-5.15/854-v6.4-i2c-mediatek-add-support-for-MT7981-SoC.patch deleted file mode 100644 index e0973741e..000000000 --- a/target/linux/mediatek/patches-5.15/854-v6.4-i2c-mediatek-add-support-for-MT7981-SoC.patch +++ /dev/null @@ -1,47 +0,0 @@ -From f69f3d662ba3bf999c36d9ac1e684540c4487bc3 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Mon, 10 Apr 2023 17:19:38 +0100 -Subject: [PATCH 15/16] i2c: mediatek: add support for MT7981 SoC - -Add support for the I2C units found in the MediaTek MT7981 and MT7988 -SoCs. Just like other recent MediaTek I2C units that also uses v3 -register offsets (which differ from v2 only by OFFSET_SLAVE_ADDR being -0x94 instead of 0x4). - -Signed-off-by: Daniel Golle -Reviewed-by: AngeloGioacchino Del Regno -Reviewed-by: Alexandre Mergnat -Signed-off-by: Wolfram Sang ---- - drivers/i2c/busses/i2c-mt65xx.c | 13 +++++++++++++ - 1 file changed, 13 insertions(+) - ---- a/drivers/i2c/busses/i2c-mt65xx.c -+++ b/drivers/i2c/busses/i2c-mt65xx.c -@@ -431,6 +431,18 @@ static const struct mtk_i2c_compatible m - .max_dma_support = 33, - }; - -+static const struct mtk_i2c_compatible mt7981_compat = { -+ .regs = mt_i2c_regs_v3, -+ .pmic_i2c = 0, -+ .dcm = 0, -+ .auto_restart = 1, -+ .aux_len_reg = 1, -+ .timing_adjust = 1, -+ .dma_sync = 1, -+ .ltiming_adjust = 1, -+ .max_dma_support = 33 -+}; -+ - static const struct mtk_i2c_compatible mt7986_compat = { - .quirks = &mt7622_i2c_quirks, - .regs = mt_i2c_regs_v1, -@@ -516,6 +528,7 @@ static const struct of_device_id mtk_i2c - { .compatible = "mediatek,mt6577-i2c", .data = &mt6577_compat }, - { .compatible = "mediatek,mt6589-i2c", .data = &mt6589_compat }, - { .compatible = "mediatek,mt7622-i2c", .data = &mt7622_compat }, -+ { .compatible = "mediatek,mt7981-i2c", .data = &mt7981_compat }, - { .compatible = "mediatek,mt7986-i2c", .data = &mt7986_compat }, - { .compatible = "mediatek,mt8168-i2c", .data = &mt8168_compat }, - { .compatible = "mediatek,mt8173-i2c", .data = &mt8173_compat }, diff --git a/target/linux/mediatek/patches-5.15/900-dts-mt7622-bpi-r64-aliases-for-dtoverlay.patch b/target/linux/mediatek/patches-5.15/900-dts-mt7622-bpi-r64-aliases-for-dtoverlay.patch deleted file mode 100644 index b9aca93d3..000000000 --- a/target/linux/mediatek/patches-5.15/900-dts-mt7622-bpi-r64-aliases-for-dtoverlay.patch +++ /dev/null @@ -1,65 +0,0 @@ ---- a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts -@@ -319,7 +319,7 @@ - /* Attention: GPIO 90 is used to switch between PCIe@1,0 and - * SATA functions. i.e. output-high: PCIe, output-low: SATA - */ -- asm_sel { -+ asmsel: asm_sel { - gpio-hog; - gpios = <90 GPIO_ACTIVE_HIGH>; - output-high; ---- /dev/null -+++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64-sata.dtso -@@ -0,0 +1,31 @@ -+/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */ -+ -+#include -+ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "bananapi,bpi-r64", "mediatek,mt7622"; -+ -+ fragment@0 { -+ target = <&asmsel>; -+ __overlay__ { -+ gpios = <90 GPIO_ACTIVE_LOW>; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&sata>; -+ __overlay__ { -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@2 { -+ target = <&sata_phy>; -+ __overlay__ { -+ status = "okay"; -+ }; -+ }; -+}; ---- /dev/null -+++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64-pcie1.dtso -@@ -0,0 +1,17 @@ -+/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */ -+ -+#include -+ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "bananapi,bpi-r64", "mediatek,mt7622"; -+ -+ fragment@0 { -+ target = <&asmsel>; -+ __overlay__ { -+ gpios = <90 GPIO_ACTIVE_HIGH>; -+ }; -+ }; -+}; diff --git a/target/linux/mediatek/patches-5.15/901-arm-add-cmdline-override.patch b/target/linux/mediatek/patches-5.15/901-arm-add-cmdline-override.patch deleted file mode 100644 index c51f7576d..000000000 --- a/target/linux/mediatek/patches-5.15/901-arm-add-cmdline-override.patch +++ /dev/null @@ -1,54 +0,0 @@ ---- a/arch/arm/Kconfig -+++ b/arch/arm/Kconfig -@@ -1730,6 +1730,14 @@ config ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEN - - endchoice - -+config CMDLINE_OVERRIDE -+ bool "Use alternative cmdline from device tree" -+ help -+ Some bootloaders may have uneditable bootargs. While CMDLINE_FORCE can -+ be used, this is not a good option for kernels that are shared across -+ devices. This setting enables using "chosen/cmdline-override" as the -+ cmdline if it exists in the device tree. -+ - config CMDLINE - string "Default kernel command string" - default "" ---- a/drivers/of/fdt.c -+++ b/drivers/of/fdt.c -@@ -1162,6 +1162,17 @@ int __init early_init_dt_scan_chosen(uns - if (p != NULL && l > 0) - strlcat(data, p, min_t(int, strlen(data) + (int)l, COMMAND_LINE_SIZE)); - -+ /* CONFIG_CMDLINE_OVERRIDE is used to fallback to a different -+ * device tree option of chosen/bootargs-override. This is -+ * helpful on boards where u-boot sets bootargs, and is unable -+ * to be modified. -+ */ -+#ifdef CONFIG_CMDLINE_OVERRIDE -+ p = of_get_flat_dt_prop(node, "bootargs-override", &l); -+ if (p != NULL && l > 0) -+ strlcpy(data, p, min((int)l, COMMAND_LINE_SIZE)); -+#endif -+ - /* - * CONFIG_CMDLINE is meant to be a default in case nothing else - * managed to set the command line, unless CONFIG_CMDLINE_FORCE ---- a/arch/arm64/Kconfig -+++ b/arch/arm64/Kconfig -@@ -2060,6 +2060,14 @@ config CMDLINE_FORCE - - endchoice - -+config CMDLINE_OVERRIDE -+ bool "Use alternative cmdline from device tree" -+ help -+ Some bootloaders may have uneditable bootargs. While CMDLINE_FORCE can -+ be used, this is not a good option for kernels that are shared across -+ devices. This setting enables using "chosen/cmdline-override" as the -+ cmdline if it exists in the device tree. -+ - config EFI_STUB - bool - diff --git a/target/linux/mediatek/patches-5.15/910-dts-mt7622-bpi-r64-wifi-eeprom.patch b/target/linux/mediatek/patches-5.15/910-dts-mt7622-bpi-r64-wifi-eeprom.patch deleted file mode 100644 index 268fb7994..000000000 --- a/target/linux/mediatek/patches-5.15/910-dts-mt7622-bpi-r64-wifi-eeprom.patch +++ /dev/null @@ -1,31 +0,0 @@ ---- a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts -@@ -646,5 +646,28 @@ - }; - - &wmac { -+ mediatek,eeprom-data = <0x22760500 0x0 0x0 0x0 -+ 0x0 0x0 0x0 0x0 -+ 0x0 0x0 0x0 0x0 -+ 0x0 0x44000020 0x0 0x10002000 -+ 0x4400 0x4000000 0x0 0x0 -+ 0x200000b3 0x40b6c3c3 0x26000000 0x41c42600 -+ 0x41c4 0x26000000 0xc0c52600 0x0 -+ 0x0 0x0 0x0 0x0 -+ 0x0 0x0 0x0 0x0 -+ 0x0 0x0 0x0 0x0 -+ 0x0 0x0 0x0 0x0 -+ 0x0 0x0 0x0 0xc6c6 -+ 0xc3c3c2c1 0xc300c3 0x818181 0x83c1c182 -+ 0x83838382 0x0 0x0 0x0 -+ 0x0 0x0 0x0 0x0 -+ 0x84002e00 0x90000087 0x8a000000 0x0 -+ 0x0 0x0 0x0 0x0 -+ 0x0 0x0 0x0 0x0 -+ 0xb000009 0x0 0x0 0x0 -+ 0x0 0x0 0x0 0x0 -+ 0x0 0x0 0x0 0x0 -+ 0x0 0x0 0x0 0x7707>; -+ - status = "okay"; - }; diff --git a/target/linux/mediatek/patches-5.15/920-v5.16-watchdog-mtk-add-disable_wdt_extrst-support.patch b/target/linux/mediatek/patches-5.15/920-v5.16-watchdog-mtk-add-disable_wdt_extrst-support.patch deleted file mode 100644 index d9379721f..000000000 --- a/target/linux/mediatek/patches-5.15/920-v5.16-watchdog-mtk-add-disable_wdt_extrst-support.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 59b0f51335644ee603260faaa4298c0115fb7187 Mon Sep 17 00:00:00 2001 -From: Fengquan Chen -Date: Tue, 14 Sep 2021 20:34:54 +0800 -Subject: [PATCH] watchdog: mtk: add disable_wdt_extrst support - -In some cases, we may need watchdog just to trigger an -internal soc reset without sending any output signal. - -Provide a disable_wdt_extrst parameter for configuration. -We can disable or enable it just by configuring dts. - -Signed-off-by: Fengquan Chen -Reviewed-by: Guenter Roeck -Link: https://lore.kernel.org/r/20210914123454.32603-3-Fengquan.Chen@mediatek.com -Signed-off-by: Guenter Roeck -Signed-off-by: Wim Van Sebroeck ---- - drivers/watchdog/mtk_wdt.c | 7 +++++++ - 1 file changed, 7 insertions(+) - ---- a/drivers/watchdog/mtk_wdt.c -+++ b/drivers/watchdog/mtk_wdt.c -@@ -65,6 +65,7 @@ struct mtk_wdt_dev { - void __iomem *wdt_base; - spinlock_t lock; /* protects WDT_SWSYSRST reg */ - struct reset_controller_dev rcdev; -+ bool disable_wdt_extrst; - }; - - struct mtk_wdt_data { -@@ -256,6 +257,8 @@ static int mtk_wdt_start(struct watchdog - reg |= (WDT_MODE_IRQ_EN | WDT_MODE_DUAL_EN); - else - reg &= ~(WDT_MODE_IRQ_EN | WDT_MODE_DUAL_EN); -+ if (mtk_wdt->disable_wdt_extrst) -+ reg &= ~WDT_MODE_EXRST_EN; - reg |= (WDT_MODE_EN | WDT_MODE_KEY); - iowrite32(reg, wdt_base + WDT_MODE); - -@@ -381,6 +384,10 @@ static int mtk_wdt_probe(struct platform - if (err) - return err; - } -+ -+ mtk_wdt->disable_wdt_extrst = -+ of_property_read_bool(dev->of_node, "mediatek,disable-extrst"); -+ - return 0; - } - diff --git a/target/linux/mediatek/patches-5.15/921-v5.19-watchdog-mtk_wdt-mt7986-Add-toprgu-reset-controller.patch b/target/linux/mediatek/patches-5.15/921-v5.19-watchdog-mtk_wdt-mt7986-Add-toprgu-reset-controller.patch deleted file mode 100644 index 96fb215f7..000000000 --- a/target/linux/mediatek/patches-5.15/921-v5.19-watchdog-mtk_wdt-mt7986-Add-toprgu-reset-controller.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 711a5b25bac95dcd1111521ed71693330e74a926 Mon Sep 17 00:00:00 2001 -From: Sam Shih -Date: Wed, 5 Jan 2022 18:04:56 +0800 -Subject: [PATCH] watchdog: mtk_wdt: mt7986: Add toprgu reset controller - support - -Besides watchdog, the mt7986 toprgu module also provides software reset -functionality for various peripheral subsystems -(eg, ethernet, pcie, and connectivity) - -Signed-off-by: Sam Shih -Reviewed-by: Matthias Brugger -Reviewed-by: Guenter Roeck -Link: https://lore.kernel.org/r/20220105100456.7126-3-sam.shih@mediatek.com -Signed-off-by: Guenter Roeck -Signed-off-by: Wim Van Sebroeck ---- - drivers/watchdog/mtk_wdt.c | 6 ++++++ - 1 file changed, 6 insertions(+) - ---- a/drivers/watchdog/mtk_wdt.c -+++ b/drivers/watchdog/mtk_wdt.c -@@ -10,6 +10,7 @@ - */ - - #include -+#include - #include - #include - #include -@@ -76,6 +77,10 @@ static const struct mtk_wdt_data mt2712_ - .toprgu_sw_rst_num = MT2712_TOPRGU_SW_RST_NUM, - }; - -+static const struct mtk_wdt_data mt7986_data = { -+ .toprgu_sw_rst_num = MT7986_TOPRGU_SW_RST_NUM, -+}; -+ - static const struct mtk_wdt_data mt8183_data = { - .toprgu_sw_rst_num = MT8183_TOPRGU_SW_RST_NUM, - }; -@@ -418,6 +423,7 @@ static int mtk_wdt_resume(struct device - static const struct of_device_id mtk_wdt_dt_ids[] = { - { .compatible = "mediatek,mt2712-wdt", .data = &mt2712_data }, - { .compatible = "mediatek,mt6589-wdt" }, -+ { .compatible = "mediatek,mt7986-wdt", .data = &mt7986_data }, - { .compatible = "mediatek,mt8183-wdt", .data = &mt8183_data }, - { .compatible = "mediatek,mt8192-wdt", .data = &mt8192_data }, - { .compatible = "mediatek,mt8195-wdt", .data = &mt8195_data }, diff --git a/target/linux/mediatek/patches-5.15/922-v6.1-PCI-mediatek-gen3-change-driver-name-to-mtk-pcie-gen.patch b/target/linux/mediatek/patches-5.15/922-v6.1-PCI-mediatek-gen3-change-driver-name-to-mtk-pcie-gen.patch deleted file mode 100644 index 44aed2207..000000000 --- a/target/linux/mediatek/patches-5.15/922-v6.1-PCI-mediatek-gen3-change-driver-name-to-mtk-pcie-gen.patch +++ /dev/null @@ -1,20 +0,0 @@ -From: Felix Fietkau -Date: Wed, 4 May 2022 12:03:42 +0200 -Subject: [PATCH] PCI: mediatek-gen3: change driver name to mtk-pcie-gen3 - -This allows it to coexist with the other mtk pcie driver in the same kernel - -Signed-off-by: Felix Fietkau ---- - ---- a/drivers/pci/controller/pcie-mediatek-gen3.c -+++ b/drivers/pci/controller/pcie-mediatek-gen3.c -@@ -1025,7 +1025,7 @@ static struct platform_driver mtk_pcie_d - .probe = mtk_pcie_probe, - .remove = mtk_pcie_remove, - .driver = { -- .name = "mtk-pcie", -+ .name = "mtk-pcie-gen3", - .of_match_table = mtk_pcie_of_match, - .pm = &mtk_pcie_pm_ops, - }, diff --git a/target/linux/mediatek/patches-5.15/930-spi-mt65xx-enable-sel-clk.patch b/target/linux/mediatek/patches-5.15/930-spi-mt65xx-enable-sel-clk.patch deleted file mode 100644 index 09ee4bdaa..000000000 --- a/target/linux/mediatek/patches-5.15/930-spi-mt65xx-enable-sel-clk.patch +++ /dev/null @@ -1,29 +0,0 @@ ---- a/drivers/spi/spi-mt65xx.c -+++ b/drivers/spi/spi-mt65xx.c -@@ -1233,10 +1233,16 @@ static int mtk_spi_probe(struct platform - goto err_disable_spi_hclk; - } - -+ ret = clk_prepare_enable(mdata->sel_clk); -+ if (ret < 0) { -+ dev_err(&pdev->dev, "failed to enable sel_clk (%d)\n", ret); -+ goto err_disable_spi_clk; -+ } -+ - ret = clk_set_parent(mdata->sel_clk, mdata->parent_clk); - if (ret < 0) { - dev_err(&pdev->dev, "failed to clk_set_parent (%d)\n", ret); -- goto err_disable_spi_clk; -+ goto err_disable_spi_sel_clk; - } - - mdata->spi_clk_hz = clk_get_rate(mdata->spi_clk); -@@ -1287,6 +1293,8 @@ static int mtk_spi_probe(struct platform - - err_disable_runtime_pm: - pm_runtime_disable(&pdev->dev); -+err_disable_spi_sel_clk: -+ clk_disable_unprepare(mdata->sel_clk); - err_disable_spi_clk: - clk_disable_unprepare(mdata->spi_clk); - err_disable_spi_hclk: diff --git a/target/linux/mediatek/patches-5.15/940-net-ethernet-mtk_wed-rename-mtk_wed_get_memory_regio.patch b/target/linux/mediatek/patches-5.15/940-net-ethernet-mtk_wed-rename-mtk_wed_get_memory_regio.patch deleted file mode 100644 index 2fe565f3b..000000000 --- a/target/linux/mediatek/patches-5.15/940-net-ethernet-mtk_wed-rename-mtk_wed_get_memory_regio.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 3cf212c4ce6cd72c09bc47f35f539ba0afd4d106 Mon Sep 17 00:00:00 2001 -Message-Id: <3cf212c4ce6cd72c09bc47f35f539ba0afd4d106.1678716918.git.lorenzo@kernel.org> -From: Lorenzo Bianconi -Date: Sun, 12 Mar 2023 16:40:31 +0100 -Subject: [PATCH net-next 1/2] net: ethernet: mtk_wed: rename - mtk_wed_get_memory_region in mtk_wed_get_reserved_memory_region - -This is a preliminary patch to move wed ilm/dlm and cpuboot properties in -dedicated dts nodes. - -Signed-off-by: Lorenzo Bianconi ---- - drivers/net/ethernet/mediatek/mtk_wed_mcu.c | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_wed_mcu.c -+++ b/drivers/net/ethernet/mediatek/mtk_wed_mcu.c -@@ -215,8 +215,8 @@ int mtk_wed_mcu_msg_update(struct mtk_we - } - - static int --mtk_wed_get_memory_region(struct mtk_wed_wo *wo, -- struct mtk_wed_wo_memory_region *region) -+mtk_wed_get_reserved_memory_region(struct mtk_wed_wo *wo, -+ struct mtk_wed_wo_memory_region *region) - { - struct reserved_mem *rmem; - struct device_node *np; -@@ -311,13 +311,13 @@ mtk_wed_mcu_load_firmware(struct mtk_wed - - /* load firmware region metadata */ - for (i = 0; i < ARRAY_SIZE(mem_region); i++) { -- ret = mtk_wed_get_memory_region(wo, &mem_region[i]); -+ ret = mtk_wed_get_reserved_memory_region(wo, &mem_region[i]); - if (ret) - return ret; - } - - wo->boot.name = "wo-boot"; -- ret = mtk_wed_get_memory_region(wo, &wo->boot); -+ ret = mtk_wed_get_reserved_memory_region(wo, &wo->boot); - if (ret) - return ret; - diff --git a/target/linux/mediatek/patches-5.15/941-arm64-dts-mt7986-move-cpuboot-in-a-dedicated-node.patch b/target/linux/mediatek/patches-5.15/941-arm64-dts-mt7986-move-cpuboot-in-a-dedicated-node.patch deleted file mode 100644 index 0a58ae953..000000000 --- a/target/linux/mediatek/patches-5.15/941-arm64-dts-mt7986-move-cpuboot-in-a-dedicated-node.patch +++ /dev/null @@ -1,66 +0,0 @@ -From 247e566e3459481f1fa98733534bfed767e18b42 Mon Sep 17 00:00:00 2001 -Message-Id: <247e566e3459481f1fa98733534bfed767e18b42.1678620342.git.lorenzo@kernel.org> -From: Lorenzo Bianconi -Date: Sat, 11 Mar 2023 16:32:41 +0100 -Subject: [PATCH net-next] arm64: dts: mt7986: move cpuboot in a dedicated node - -Signed-off-by: Lorenzo Bianconi ---- - arch/arm64/boot/dts/mediatek/mt7986a.dtsi | 21 +++++++++++---------- - 1 file changed, 11 insertions(+), 10 deletions(-) - ---- a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi -+++ b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi -@@ -121,12 +121,6 @@ - reg = <0 0x151f8000 0 0x2000>; - no-map; - }; -- -- wo_boot: wo-boot@15194000 { -- reg = <0 0x15194000 0 0x1000>; -- no-map; -- }; -- - }; - - timer { -@@ -518,10 +512,11 @@ - interrupt-parent = <&gic>; - interrupts = ; - memory-region = <&wo_emi0>, <&wo_ilm0>, <&wo_dlm0>, -- <&wo_data>, <&wo_boot>; -+ <&wo_data>; - memory-region-names = "wo-emi", "wo-ilm", "wo-dlm", -- "wo-data", "wo-boot"; -+ "wo-data"; - mediatek,wo-ccif = <&wo_ccif0>; -+ mediatek,wo-cpuboot = <&wo_cpuboot>; - }; - - wed1: wed@15011000 { -@@ -531,10 +526,11 @@ - interrupt-parent = <&gic>; - interrupts = ; - memory-region = <&wo_emi1>, <&wo_ilm1>, <&wo_dlm1>, -- <&wo_data>, <&wo_boot>; -+ <&wo_data>; - memory-region-names = "wo-emi", "wo-ilm", "wo-dlm", -- "wo-data", "wo-boot"; -+ "wo-data"; - mediatek,wo-ccif = <&wo_ccif1>; -+ mediatek,wo-cpuboot = <&wo_cpuboot>; - }; - - wo_ccif0: syscon@151a5000 { -@@ -551,6 +547,11 @@ - interrupts = ; - }; - -+ wo_cpuboot: syscon@15194000 { -+ compatible = "mediatek,mt7986-wo-cpuboot", "syscon"; -+ reg = <0 0x15194000 0 0x1000>; -+ }; -+ - eth: ethernet@15100000 { - compatible = "mediatek,mt7986-eth"; - reg = <0 0x15100000 0 0x80000>; diff --git a/target/linux/mediatek/patches-5.15/942-net-ethernet-mtk_wed-move-cpuboot-in-a-dedicated-dts.patch b/target/linux/mediatek/patches-5.15/942-net-ethernet-mtk_wed-move-cpuboot-in-a-dedicated-dts.patch deleted file mode 100644 index 9de4ffa43..000000000 --- a/target/linux/mediatek/patches-5.15/942-net-ethernet-mtk_wed-move-cpuboot-in-a-dedicated-dts.patch +++ /dev/null @@ -1,89 +0,0 @@ -From f292d1bf83ec160bef2532b58aa08f5b71041923 Mon Sep 17 00:00:00 2001 -Message-Id: -In-Reply-To: <3cf212c4ce6cd72c09bc47f35f539ba0afd4d106.1678716918.git.lorenzo@kernel.org> -References: <3cf212c4ce6cd72c09bc47f35f539ba0afd4d106.1678716918.git.lorenzo@kernel.org> -From: Lorenzo Bianconi -Date: Sat, 11 Mar 2023 18:13:04 +0100 -Subject: [PATCH net-next 2/2] net: ethernet: mtk_wed: move cpuboot in a - dedicated dts node - -Since the cpuboot memory region is not part of the RAM SoC, move cpuboot -in a deidicated syscon node. -This patch helps to keep backward-compatibility with older version of -uboot codebase where we have a limit of 8 reserved-memory dts child -nodes. -Keep backward-compatibility with older dts version where cpuboot was -defined as reserved-memory child node. - -Signed-off-by: Lorenzo Bianconi ---- - drivers/net/ethernet/mediatek/mtk_wed_mcu.c | 34 +++++++++++++++++---- - drivers/net/ethernet/mediatek/mtk_wed_wo.h | 3 +- - 2 files changed, 30 insertions(+), 7 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_wed_mcu.c -+++ b/drivers/net/ethernet/mediatek/mtk_wed_mcu.c -@@ -18,12 +18,23 @@ - - static u32 wo_r32(struct mtk_wed_wo *wo, u32 reg) - { -- return readl(wo->boot.addr + reg); -+ u32 val; -+ -+ if (!wo->boot_regmap) -+ return readl(wo->boot.addr + reg); -+ -+ if (regmap_read(wo->boot_regmap, reg, &val)) -+ val = ~0; -+ -+ return val; - } - - static void wo_w32(struct mtk_wed_wo *wo, u32 reg, u32 val) - { -- writel(val, wo->boot.addr + reg); -+ if (wo->boot_regmap) -+ regmap_write(wo->boot_regmap, reg, val); -+ else -+ writel(val, wo->boot.addr + reg); - } - - static struct sk_buff * -@@ -316,10 +327,21 @@ mtk_wed_mcu_load_firmware(struct mtk_wed - return ret; - } - -- wo->boot.name = "wo-boot"; -- ret = mtk_wed_get_reserved_memory_region(wo, &wo->boot); -- if (ret) -- return ret; -+ wo->boot_regmap = syscon_regmap_lookup_by_phandle(wo->hw->node, -+ "mediatek,wo-cpuboot"); -+ if (IS_ERR(wo->boot_regmap)) { -+ if (wo->boot_regmap != ERR_PTR(-ENODEV)) -+ return PTR_ERR(wo->boot_regmap); -+ -+ /* For backward compatibility, we need to check if cpu_boot -+ * is defined through reserved memory property. -+ */ -+ wo->boot_regmap = NULL; -+ wo->boot.name = "wo-boot"; -+ ret = mtk_wed_get_reserved_memory_region(wo, &wo->boot); -+ if (ret) -+ return ret; -+ } - - /* set dummy cr */ - wed_w32(wo->hw->wed_dev, MTK_WED_SCR0 + 4 * MTK_WED_DUMMY_CR_FWDL, ---- a/drivers/net/ethernet/mediatek/mtk_wed_wo.h -+++ b/drivers/net/ethernet/mediatek/mtk_wed_wo.h -@@ -228,7 +228,8 @@ struct mtk_wed_wo_queue { - - struct mtk_wed_wo { - struct mtk_wed_hw *hw; -- struct mtk_wed_wo_memory_region boot; -+ struct mtk_wed_wo_memory_region boot; /* backward compatibility */ -+ struct regmap *boot_regmap; - - struct mtk_wed_wo_queue q_tx; - struct mtk_wed_wo_queue q_rx; diff --git a/target/linux/mediatek/patches-5.15/943-net-ethernet-mtk_wed-move-ilm-a-dedicated-dts-node.patch b/target/linux/mediatek/patches-5.15/943-net-ethernet-mtk_wed-move-ilm-a-dedicated-dts-node.patch deleted file mode 100644 index 7b6c5d1e2..000000000 --- a/target/linux/mediatek/patches-5.15/943-net-ethernet-mtk_wed-move-ilm-a-dedicated-dts-node.patch +++ /dev/null @@ -1,91 +0,0 @@ -From f3565e6c2276411275e707a5442d3f69cc111273 Mon Sep 17 00:00:00 2001 -Message-Id: -From: Lorenzo Bianconi -Date: Sun, 12 Mar 2023 18:51:47 +0100 -Subject: [PATCH net-next 1/3] net: ethernet: mtk_wed: move ilm a dedicated dts - node - -Since the ilm memory region is not part of the RAM SoC, move ilm in a -deidicated syscon node. -This patch helps to keep backward-compatibility with older version of -uboot codebase where we have a limit of 8 reserved-memory dts child -nodes. -Keep backward-compatibility with older dts version where ilm was defined -as reserved-memory child node. - -Signed-off-by: Lorenzo Bianconi ---- - drivers/net/ethernet/mediatek/mtk_wed_mcu.c | 55 ++++++++++++++++++--- - 1 file changed, 49 insertions(+), 6 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_wed_mcu.c -+++ b/drivers/net/ethernet/mediatek/mtk_wed_mcu.c -@@ -300,6 +300,52 @@ next: - } - - static int -+mtk_wed_mcu_load_memory_regions(struct mtk_wed_wo *wo, -+ struct mtk_wed_wo_memory_region *region) -+{ -+ struct device_node *np; -+ int ret; -+ -+ /* firmware EMI memory region */ -+ ret = mtk_wed_get_reserved_memory_region(wo, -+ ®ion[MTK_WED_WO_REGION_EMI]); -+ if (ret) -+ return ret; -+ -+ /* firmware DATA memory region */ -+ ret = mtk_wed_get_reserved_memory_region(wo, -+ ®ion[MTK_WED_WO_REGION_DATA]); -+ if (ret) -+ return ret; -+ -+ np = of_parse_phandle(wo->hw->node, "mediatek,wo-ilm", 0); -+ if (np) { -+ struct mtk_wed_wo_memory_region *ilm_region; -+ struct resource res; -+ -+ ret = of_address_to_resource(np, 0, &res); -+ of_node_put(np); -+ -+ if (ret < 0) -+ return ret; -+ -+ ilm_region = ®ion[MTK_WED_WO_REGION_ILM]; -+ ilm_region->phy_addr = res.start; -+ ilm_region->size = resource_size(&res); -+ ilm_region->addr = devm_ioremap(wo->hw->dev, res.start, -+ resource_size(&res)); -+ -+ return IS_ERR(ilm_region->addr) ? PTR_ERR(ilm_region->addr) : 0; -+ } -+ -+ /* For backward compatibility, we need to check if ILM -+ * node is defined through reserved memory property. -+ */ -+ return mtk_wed_get_reserved_memory_region(wo, -+ ®ion[MTK_WED_WO_REGION_ILM]); -+} -+ -+static int - mtk_wed_mcu_load_firmware(struct mtk_wed_wo *wo) - { - static struct mtk_wed_wo_memory_region mem_region[] = { -@@ -320,12 +366,9 @@ mtk_wed_mcu_load_firmware(struct mtk_wed - u32 val, boot_cr; - int ret, i; - -- /* load firmware region metadata */ -- for (i = 0; i < ARRAY_SIZE(mem_region); i++) { -- ret = mtk_wed_get_reserved_memory_region(wo, &mem_region[i]); -- if (ret) -- return ret; -- } -+ ret = mtk_wed_mcu_load_memory_regions(wo, mem_region); -+ if (ret) -+ return ret; - - wo->boot_regmap = syscon_regmap_lookup_by_phandle(wo->hw->node, - "mediatek,wo-cpuboot"); diff --git a/target/linux/mediatek/patches-5.15/944-net-ethernet-mtk_wed-move-dlm-a-dedicated-dts-node.patch b/target/linux/mediatek/patches-5.15/944-net-ethernet-mtk_wed-move-dlm-a-dedicated-dts-node.patch deleted file mode 100644 index eed97b476..000000000 --- a/target/linux/mediatek/patches-5.15/944-net-ethernet-mtk_wed-move-dlm-a-dedicated-dts-node.patch +++ /dev/null @@ -1,57 +0,0 @@ -From b74ba226be2c45091b93bd49192bdd6d2178729e Mon Sep 17 00:00:00 2001 -Message-Id: -In-Reply-To: -References: -From: Lorenzo Bianconi -Date: Mon, 13 Mar 2023 15:45:16 +0100 -Subject: [PATCH net-next 3/3] net: ethernet: mtk_wed: move dlm a dedicated dts - node - -Since the dlm memory region is not part of the RAM SoC, move dlm in a -deidicated syscon node. -This patch helps to keep backward-compatibility with older version of -uboot codebase where we have a limit of 8 reserved-memory dts child -nodes. -Keep backward-compatibility with older dts version where dlm was defined -as reserved-memory child node. - -Signed-off-by: Lorenzo Bianconi ---- - drivers/net/ethernet/mediatek/mtk_wed.c | 19 +++++++++++++++++++ - 1 file changed, 19 insertions(+) - ---- a/drivers/net/ethernet/mediatek/mtk_wed.c -+++ b/drivers/net/ethernet/mediatek/mtk_wed.c -@@ -821,6 +821,24 @@ mtk_wed_rro_alloc(struct mtk_wed_device - struct device_node *np; - int index; - -+ np = of_parse_phandle(dev->hw->node, "mediatek,wo-dlm", 0); -+ if (np) { -+ struct resource res; -+ int ret; -+ -+ ret = of_address_to_resource(np, 0, &res); -+ of_node_put(np); -+ -+ if (ret < 0) -+ return ret; -+ -+ dev->rro.miod_phys = res.start; -+ goto out; -+ } -+ -+ /* For backward compatibility, we need to check if DLM -+ * node is defined through reserved memory property. -+ */ - index = of_property_match_string(dev->hw->node, "memory-region-names", - "wo-dlm"); - if (index < 0) -@@ -837,6 +855,7 @@ mtk_wed_rro_alloc(struct mtk_wed_device - return -ENODEV; - - dev->rro.miod_phys = rmem->base; -+out: - dev->rro.fdbk_phys = MTK_WED_MIOD_COUNT + dev->rro.miod_phys; - - return mtk_wed_rro_ring_alloc(dev, &dev->rro.ring, diff --git a/target/linux/mediatek/patches-5.15/945-arm64-dts-mt7986-move-ilm-in-a-dedicated-node.patch b/target/linux/mediatek/patches-5.15/945-arm64-dts-mt7986-move-ilm-in-a-dedicated-node.patch deleted file mode 100644 index 36fe92783..000000000 --- a/target/linux/mediatek/patches-5.15/945-arm64-dts-mt7986-move-ilm-in-a-dedicated-node.patch +++ /dev/null @@ -1,83 +0,0 @@ -From 01561065af5bf1d2a4244896d897e3a1eafbcd46 Mon Sep 17 00:00:00 2001 -Message-Id: <01561065af5bf1d2a4244896d897e3a1eafbcd46.1678717704.git.lorenzo@kernel.org> -From: Lorenzo Bianconi -Date: Mon, 13 Mar 2023 15:10:56 +0100 -Subject: [PATCH net-next] arm64: dts: mt7986: move ilm in a dedicated node - -Since the ilm memory region is not part of the RAM SoC, move ilm in a -deidicated syscon node. -This patch helps to keep backward-compatibility with older version of -uboot codebase where we have a limit of 8 reserved-memory dts child -nodes. - -Signed-off-by: Lorenzo Bianconi ---- - arch/arm64/boot/dts/mediatek/mt7986a.dtsi | 34 +++++++++++------------ - 1 file changed, 16 insertions(+), 18 deletions(-) - ---- a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi -+++ b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi -@@ -97,16 +97,6 @@ - no-map; - }; - -- wo_ilm0: wo-ilm@151e0000 { -- reg = <0 0x151e0000 0 0x8000>; -- no-map; -- }; -- -- wo_ilm1: wo-ilm@151f0000 { -- reg = <0 0x151f0000 0 0x8000>; -- no-map; -- }; -- - wo_data: wo-data@4fd80000 { - reg = <0 0x4fd80000 0 0x240000>; - no-map; -@@ -511,11 +501,10 @@ - reg = <0 0x15010000 0 0x1000>; - interrupt-parent = <&gic>; - interrupts = ; -- memory-region = <&wo_emi0>, <&wo_ilm0>, <&wo_dlm0>, -- <&wo_data>; -- memory-region-names = "wo-emi", "wo-ilm", "wo-dlm", -- "wo-data"; -+ memory-region = <&wo_emi0>, <&wo_dlm0>, <&wo_data>; -+ memory-region-names = "wo-emi", "wo-dlm", "wo-data"; - mediatek,wo-ccif = <&wo_ccif0>; -+ mediatek,wo-ilm = <&wo_ilm0>; - mediatek,wo-cpuboot = <&wo_cpuboot>; - }; - -@@ -525,11 +514,10 @@ - reg = <0 0x15011000 0 0x1000>; - interrupt-parent = <&gic>; - interrupts = ; -- memory-region = <&wo_emi1>, <&wo_ilm1>, <&wo_dlm1>, -- <&wo_data>; -- memory-region-names = "wo-emi", "wo-ilm", "wo-dlm", -- "wo-data"; -+ memory-region = <&wo_emi1>, <&wo_dlm1>, <&wo_data>; -+ memory-region-names = "wo-emi", "wo-dlm", "wo-data"; - mediatek,wo-ccif = <&wo_ccif1>; -+ mediatek,wo-ilm = <&wo_ilm1>; - mediatek,wo-cpuboot = <&wo_cpuboot>; - }; - -@@ -547,6 +535,16 @@ - interrupts = ; - }; - -+ wo_ilm0: syscon@151e0000 { -+ compatible = "mediatek,mt7986-wo-ilm", "syscon"; -+ reg = <0 0x151e0000 0 0x8000>; -+ }; -+ -+ wo_ilm1: syscon@151f0000 { -+ compatible = "mediatek,mt7986-wo-ilm", "syscon"; -+ reg = <0 0x151f0000 0 0x8000>; -+ }; -+ - wo_cpuboot: syscon@15194000 { - compatible = "mediatek,mt7986-wo-cpuboot", "syscon"; - reg = <0 0x15194000 0 0x1000>; diff --git a/target/linux/mediatek/patches-5.15/946-arm64-dts-mt7986-move-dlm-in-a-dedicated-node.patch b/target/linux/mediatek/patches-5.15/946-arm64-dts-mt7986-move-dlm-in-a-dedicated-node.patch deleted file mode 100644 index 55f17286c..000000000 --- a/target/linux/mediatek/patches-5.15/946-arm64-dts-mt7986-move-dlm-in-a-dedicated-node.patch +++ /dev/null @@ -1,81 +0,0 @@ -From 9f76be683a8ec498563c294bc1cc279468058302 Mon Sep 17 00:00:00 2001 -Message-Id: <9f76be683a8ec498563c294bc1cc279468058302.1678719283.git.lorenzo@kernel.org> -From: Lorenzo Bianconi -Date: Mon, 13 Mar 2023 15:53:30 +0100 -Subject: [PATCH net-next] arm64: dts: mt7986: move dlm in a dedicated node - -Since the dlm memory region is not part of the RAM SoC, move dlm in a -deidicated syscon node. -This patch helps to keep backward-compatibility with older version of -uboot codebase where we have a limit of 8 reserved-memory dts child -nodes. - -Signed-off-by: Lorenzo Bianconi ---- - arch/arm64/boot/dts/mediatek/mt7986a.dtsi | 30 ++++++++++++----------- - 1 file changed, 16 insertions(+), 14 deletions(-) - ---- a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi -+++ b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi -@@ -101,16 +101,6 @@ - reg = <0 0x4fd80000 0 0x240000>; - no-map; - }; -- -- wo_dlm0: wo-dlm@151e8000 { -- reg = <0 0x151e8000 0 0x2000>; -- no-map; -- }; -- -- wo_dlm1: wo-dlm@151f8000 { -- reg = <0 0x151f8000 0 0x2000>; -- no-map; -- }; - }; - - timer { -@@ -501,10 +491,11 @@ - reg = <0 0x15010000 0 0x1000>; - interrupt-parent = <&gic>; - interrupts = ; -- memory-region = <&wo_emi0>, <&wo_dlm0>, <&wo_data>; -- memory-region-names = "wo-emi", "wo-dlm", "wo-data"; -+ memory-region = <&wo_emi0>, <&wo_data>; -+ memory-region-names = "wo-emi", "wo-data"; - mediatek,wo-ccif = <&wo_ccif0>; - mediatek,wo-ilm = <&wo_ilm0>; -+ mediatek,wo-dlm = <&wo_dlm0>; - mediatek,wo-cpuboot = <&wo_cpuboot>; - }; - -@@ -514,10 +505,11 @@ - reg = <0 0x15011000 0 0x1000>; - interrupt-parent = <&gic>; - interrupts = ; -- memory-region = <&wo_emi1>, <&wo_dlm1>, <&wo_data>; -- memory-region-names = "wo-emi", "wo-dlm", "wo-data"; -+ memory-region = <&wo_emi1>, <&wo_data>; -+ memory-region-names = "wo-emi", "wo-data"; - mediatek,wo-ccif = <&wo_ccif1>; - mediatek,wo-ilm = <&wo_ilm1>; -+ mediatek,wo-dlm = <&wo_dlm1>; - mediatek,wo-cpuboot = <&wo_cpuboot>; - }; - -@@ -545,6 +537,16 @@ - reg = <0 0x151f0000 0 0x8000>; - }; - -+ wo_dlm0: syscon@151e8000 { -+ compatible = "mediatek,mt7986-wo-dlm", "syscon"; -+ reg = <0 0x151e8000 0 0x2000>; -+ }; -+ -+ wo_dlm1: syscon@151f8000 { -+ compatible = "mediatek,mt7986-wo-dlm", "syscon"; -+ reg = <0 0x151f8000 0 0x2000>; -+ }; -+ - wo_cpuboot: syscon@15194000 { - compatible = "mediatek,mt7986-wo-cpuboot", "syscon"; - reg = <0 0x15194000 0 0x1000>; diff --git a/target/linux/mediatek/patches-6.1/000-v6.2-kbuild-Allow-DTB-overlays-to-built-from-.dtso-named-.patch b/target/linux/mediatek/patches-6.1/000-v6.2-kbuild-Allow-DTB-overlays-to-built-from-.dtso-named-.patch deleted file mode 100644 index 17c5c6098..000000000 --- a/target/linux/mediatek/patches-6.1/000-v6.2-kbuild-Allow-DTB-overlays-to-built-from-.dtso-named-.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 363547d2191cbc32ca954ba75d72908712398ff2 Mon Sep 17 00:00:00 2001 -From: Andrew Davis -Date: Mon, 24 Oct 2022 12:34:28 -0500 -Subject: [PATCH] kbuild: Allow DTB overlays to built from .dtso named source - files - -Currently DTB Overlays (.dtbo) are build from source files with the same -extension (.dts) as the base DTs (.dtb). This may become confusing and -even lead to wrong results. For example, a composite DTB (created from a -base DTB and a set of overlays) might have the same name as one of the -overlays that create it. - -Different files should be generated from differently named sources. - .dtb <-> .dts - .dtbo <-> .dtso - -We do not remove the ability to compile DTBO files from .dts files here, -only add a new rule allowing the .dtso file name. The current .dts named -overlays can be renamed with time. After all have been renamed we can -remove the other rule. - -Signed-off-by: Andrew Davis -Reviewed-by: Geert Uytterhoeven -Tested-by: Geert Uytterhoeven -Reviewed-by: Frank Rowand -Tested-by: Frank Rowand -Link: https://lore.kernel.org/r/20221024173434.32518-2-afd@ti.com -Signed-off-by: Rob Herring ---- - scripts/Makefile.lib | 3 +++ - 1 file changed, 3 insertions(+) - ---- a/scripts/Makefile.lib -+++ b/scripts/Makefile.lib -@@ -408,6 +408,9 @@ $(obj)/%.dtb: $(src)/%.dts $(DTC) $(DT_T - $(obj)/%.dtbo: $(src)/%.dts $(DTC) FORCE - $(call if_changed_dep,dtc) - -+$(obj)/%.dtbo: $(src)/%.dtso $(DTC) FORCE -+ $(call if_changed_dep,dtc) -+ - dtc-tmp = $(subst $(comma),_,$(dot-target).dts.tmp) - - # Bzip2 diff --git a/target/linux/mediatek/patches-6.1/001-v6.2-arm64-dts-mediatek-mt7986-add-support-for-RX-Wireles.patch b/target/linux/mediatek/patches-6.1/001-v6.2-arm64-dts-mediatek-mt7986-add-support-for-RX-Wireles.patch deleted file mode 100644 index e6c6eb616..000000000 --- a/target/linux/mediatek/patches-6.1/001-v6.2-arm64-dts-mediatek-mt7986-add-support-for-RX-Wireles.patch +++ /dev/null @@ -1,106 +0,0 @@ -From 2c4daed9580164522859fa100128be408cc69be2 Mon Sep 17 00:00:00 2001 -From: Lorenzo Bianconi -Date: Sat, 5 Nov 2022 23:36:16 +0100 -Subject: [PATCH 01/19] arm64: dts: mediatek: mt7986: add support for RX - Wireless Ethernet Dispatch - -Similar to TX Wireless Ethernet Dispatch, introduce RX Wireless Ethernet -Dispatch to offload traffic received by the wlan interface to lan/wan -one. - -Co-developed-by: Sujuan Chen -Signed-off-by: Sujuan Chen -Signed-off-by: Lorenzo Bianconi -Signed-off-by: David S. Miller ---- - arch/arm64/boot/dts/mediatek/mt7986a.dtsi | 65 +++++++++++++++++++++++ - 1 file changed, 65 insertions(+) - ---- a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi -+++ b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi -@@ -76,6 +76,47 @@ - no-map; - reg = <0 0x4fc00000 0 0x00100000>; - }; -+ -+ wo_emi0: wo-emi@4fd00000 { -+ reg = <0 0x4fd00000 0 0x40000>; -+ no-map; -+ }; -+ -+ wo_emi1: wo-emi@4fd40000 { -+ reg = <0 0x4fd40000 0 0x40000>; -+ no-map; -+ }; -+ -+ wo_ilm0: wo-ilm@151e0000 { -+ reg = <0 0x151e0000 0 0x8000>; -+ no-map; -+ }; -+ -+ wo_ilm1: wo-ilm@151f0000 { -+ reg = <0 0x151f0000 0 0x8000>; -+ no-map; -+ }; -+ -+ wo_data: wo-data@4fd80000 { -+ reg = <0 0x4fd80000 0 0x240000>; -+ no-map; -+ }; -+ -+ wo_dlm0: wo-dlm@151e8000 { -+ reg = <0 0x151e8000 0 0x2000>; -+ no-map; -+ }; -+ -+ wo_dlm1: wo-dlm@151f8000 { -+ reg = <0 0x151f8000 0 0x2000>; -+ no-map; -+ }; -+ -+ wo_boot: wo-boot@15194000 { -+ reg = <0 0x15194000 0 0x1000>; -+ no-map; -+ }; -+ - }; - - timer { -@@ -240,6 +281,11 @@ - reg = <0 0x15010000 0 0x1000>; - interrupt-parent = <&gic>; - interrupts = ; -+ memory-region = <&wo_emi0>, <&wo_ilm0>, <&wo_dlm0>, -+ <&wo_data>, <&wo_boot>; -+ memory-region-names = "wo-emi", "wo-ilm", "wo-dlm", -+ "wo-data", "wo-boot"; -+ mediatek,wo-ccif = <&wo_ccif0>; - }; - - wed1: wed@15011000 { -@@ -248,6 +294,25 @@ - reg = <0 0x15011000 0 0x1000>; - interrupt-parent = <&gic>; - interrupts = ; -+ memory-region = <&wo_emi1>, <&wo_ilm1>, <&wo_dlm1>, -+ <&wo_data>, <&wo_boot>; -+ memory-region-names = "wo-emi", "wo-ilm", "wo-dlm", -+ "wo-data", "wo-boot"; -+ mediatek,wo-ccif = <&wo_ccif1>; -+ }; -+ -+ wo_ccif0: syscon@151a5000 { -+ compatible = "mediatek,mt7986-wo-ccif", "syscon"; -+ reg = <0 0x151a5000 0 0x1000>; -+ interrupt-parent = <&gic>; -+ interrupts = ; -+ }; -+ -+ wo_ccif1: syscon@151ad000 { -+ compatible = "mediatek,mt7986-wo-ccif", "syscon"; -+ reg = <0 0x151ad000 0 0x1000>; -+ interrupt-parent = <&gic>; -+ interrupts = ; - }; - - eth: ethernet@15100000 { diff --git a/target/linux/mediatek/patches-6.1/002-v6.2-arm64-dts-mt7986-harmonize-device-node-order.patch b/target/linux/mediatek/patches-6.1/002-v6.2-arm64-dts-mt7986-harmonize-device-node-order.patch deleted file mode 100644 index b5091687a..000000000 --- a/target/linux/mediatek/patches-6.1/002-v6.2-arm64-dts-mt7986-harmonize-device-node-order.patch +++ /dev/null @@ -1,166 +0,0 @@ -From 438e53828c08cf0e8a65b61cf6ce1e4b6620551a Mon Sep 17 00:00:00 2001 -From: Sam Shih -Date: Sun, 6 Nov 2022 09:50:24 +0100 -Subject: [PATCH 02/19] arm64: dts: mt7986: harmonize device node order - -This arrange device tree nodes in alphabetical order. - -Signed-off-by: Sam Shih -Signed-off-by: Frank Wunderlich -Reviewed-by: AngeloGioacchino Del Regno -Link: https://lore.kernel.org/r/20221106085034.12582-2-linux@fw-web.de -Signed-off-by: Matthias Brugger ---- - arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts | 94 ++++++++++---------- - arch/arm64/boot/dts/mediatek/mt7986b-rfb.dts | 22 ++--- - 2 files changed, 58 insertions(+), 58 deletions(-) - ---- a/arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts -@@ -54,6 +54,53 @@ - }; - }; - -+&pio { -+ uart1_pins: uart1-pins { -+ mux { -+ function = "uart"; -+ groups = "uart1"; -+ }; -+ }; -+ -+ uart2_pins: uart2-pins { -+ mux { -+ function = "uart"; -+ groups = "uart2"; -+ }; -+ }; -+ -+ wf_2g_5g_pins: wf-2g-5g-pins { -+ mux { -+ function = "wifi"; -+ groups = "wf_2g", "wf_5g"; -+ }; -+ conf { -+ pins = "WF0_HB1", "WF0_HB2", "WF0_HB3", "WF0_HB4", -+ "WF0_HB0", "WF0_HB0_B", "WF0_HB5", "WF0_HB6", -+ "WF0_HB7", "WF0_HB8", "WF0_HB9", "WF0_HB10", -+ "WF0_TOP_CLK", "WF0_TOP_DATA", "WF1_HB1", -+ "WF1_HB2", "WF1_HB3", "WF1_HB4", "WF1_HB0", -+ "WF1_HB5", "WF1_HB6", "WF1_HB7", "WF1_HB8", -+ "WF1_TOP_CLK", "WF1_TOP_DATA"; -+ drive-strength = <4>; -+ }; -+ }; -+ -+ wf_dbdc_pins: wf-dbdc-pins { -+ mux { -+ function = "wifi"; -+ groups = "wf_dbdc"; -+ }; -+ conf { -+ pins = "WF0_HB1", "WF0_HB2", "WF0_HB3", "WF0_HB4", -+ "WF0_HB0", "WF0_HB0_B", "WF0_HB5", "WF0_HB6", -+ "WF0_HB7", "WF0_HB8", "WF0_HB9", "WF0_HB10", -+ "WF0_TOP_CLK", "WF0_TOP_DATA"; -+ drive-strength = <4>; -+ }; -+ }; -+}; -+ - &switch { - ports { - #address-cells = <1>; -@@ -121,50 +168,3 @@ - pinctrl-0 = <&wf_2g_5g_pins>; - pinctrl-1 = <&wf_dbdc_pins>; - }; -- --&pio { -- uart1_pins: uart1-pins { -- mux { -- function = "uart"; -- groups = "uart1"; -- }; -- }; -- -- uart2_pins: uart2-pins { -- mux { -- function = "uart"; -- groups = "uart2"; -- }; -- }; -- -- wf_2g_5g_pins: wf-2g-5g-pins { -- mux { -- function = "wifi"; -- groups = "wf_2g", "wf_5g"; -- }; -- conf { -- pins = "WF0_HB1", "WF0_HB2", "WF0_HB3", "WF0_HB4", -- "WF0_HB0", "WF0_HB0_B", "WF0_HB5", "WF0_HB6", -- "WF0_HB7", "WF0_HB8", "WF0_HB9", "WF0_HB10", -- "WF0_TOP_CLK", "WF0_TOP_DATA", "WF1_HB1", -- "WF1_HB2", "WF1_HB3", "WF1_HB4", "WF1_HB0", -- "WF1_HB5", "WF1_HB6", "WF1_HB7", "WF1_HB8", -- "WF1_TOP_CLK", "WF1_TOP_DATA"; -- drive-strength = <4>; -- }; -- }; -- -- wf_dbdc_pins: wf-dbdc-pins { -- mux { -- function = "wifi"; -- groups = "wf_dbdc"; -- }; -- conf { -- pins = "WF0_HB1", "WF0_HB2", "WF0_HB3", "WF0_HB4", -- "WF0_HB0", "WF0_HB0_B", "WF0_HB5", "WF0_HB6", -- "WF0_HB7", "WF0_HB8", "WF0_HB9", "WF0_HB10", -- "WF0_TOP_CLK", "WF0_TOP_DATA"; -- drive-strength = <4>; -- }; -- }; --}; ---- a/arch/arm64/boot/dts/mediatek/mt7986b-rfb.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7986b-rfb.dts -@@ -25,10 +25,6 @@ - }; - }; - --&uart0 { -- status = "okay"; --}; -- - ð { - status = "okay"; - -@@ -99,13 +95,6 @@ - }; - }; - --&wifi { -- status = "okay"; -- pinctrl-names = "default", "dbdc"; -- pinctrl-0 = <&wf_2g_5g_pins>; -- pinctrl-1 = <&wf_dbdc_pins>; --}; -- - &pio { - wf_2g_5g_pins: wf-2g-5g-pins { - mux { -@@ -138,3 +127,14 @@ - }; - }; - }; -+ -+&uart0 { -+ status = "okay"; -+}; -+ -+&wifi { -+ status = "okay"; -+ pinctrl-names = "default", "dbdc"; -+ pinctrl-0 = <&wf_2g_5g_pins>; -+ pinctrl-1 = <&wf_dbdc_pins>; -+}; diff --git a/target/linux/mediatek/patches-6.1/003-v6.2-arm64-dts-mt7986-add-crypto-related-device-nodes.patch b/target/linux/mediatek/patches-6.1/003-v6.2-arm64-dts-mt7986-add-crypto-related-device-nodes.patch deleted file mode 100644 index fec048e68..000000000 --- a/target/linux/mediatek/patches-6.1/003-v6.2-arm64-dts-mt7986-add-crypto-related-device-nodes.patch +++ /dev/null @@ -1,68 +0,0 @@ -From ffb05357b47f06b2b4d1e14ba89169e28feb727b Mon Sep 17 00:00:00 2001 -From: Sam Shih -Date: Sun, 6 Nov 2022 09:50:27 +0100 -Subject: [PATCH 03/19] arm64: dts: mt7986: add crypto related device nodes - -This patch adds crypto engine support for MT7986. - -Signed-off-by: Vic Wu -Signed-off-by: Sam Shih -Signed-off-by: Frank Wunderlich -Link: https://lore.kernel.org/r/20221106085034.12582-5-linux@fw-web.de -Signed-off-by: Matthias Brugger ---- - arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts | 4 ++++ - arch/arm64/boot/dts/mediatek/mt7986a.dtsi | 15 +++++++++++++++ - arch/arm64/boot/dts/mediatek/mt7986b-rfb.dts | 4 ++++ - 3 files changed, 23 insertions(+) - ---- a/arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts -@@ -25,6 +25,10 @@ - }; - }; - -+&crypto { -+ status = "okay"; -+}; -+ - ð { - status = "okay"; - ---- a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi -+++ b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi -@@ -224,6 +224,21 @@ - status = "disabled"; - }; - -+ crypto: crypto@10320000 { -+ compatible = "inside-secure,safexcel-eip97"; -+ reg = <0 0x10320000 0 0x40000>; -+ interrupts = , -+ , -+ , -+ ; -+ interrupt-names = "ring0", "ring1", "ring2", "ring3"; -+ clocks = <&infracfg CLK_INFRA_EIP97_CK>; -+ clock-names = "infra_eip97_ck"; -+ assigned-clocks = <&topckgen CLK_TOP_EIP_B_SEL>; -+ assigned-clock-parents = <&apmixedsys CLK_APMIXED_NET2PLL>; -+ status = "disabled"; -+ }; -+ - uart0: serial@11002000 { - compatible = "mediatek,mt7986-uart", - "mediatek,mt6577-uart"; ---- a/arch/arm64/boot/dts/mediatek/mt7986b-rfb.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7986b-rfb.dts -@@ -25,6 +25,10 @@ - }; - }; - -+&crypto { -+ status = "okay"; -+}; -+ - ð { - status = "okay"; - diff --git a/target/linux/mediatek/patches-6.1/004-v6.2-arm64-dts-mt7986-add-i2c-node.patch b/target/linux/mediatek/patches-6.1/004-v6.2-arm64-dts-mt7986-add-i2c-node.patch deleted file mode 100644 index 132940915..000000000 --- a/target/linux/mediatek/patches-6.1/004-v6.2-arm64-dts-mt7986-add-i2c-node.patch +++ /dev/null @@ -1,37 +0,0 @@ -From b49b7dc404ded1d89cbc568d875009a5c1ed4ef6 Mon Sep 17 00:00:00 2001 -From: Frank Wunderlich -Date: Sun, 6 Nov 2022 09:50:29 +0100 -Subject: [PATCH 04/19] arm64: dts: mt7986: add i2c node - -Add i2c Node to mt7986 devicetree. - -Signed-off-by: Frank Wunderlich -Link: https://lore.kernel.org/r/20221106085034.12582-7-linux@fw-web.de -Signed-off-by: Matthias Brugger ---- - arch/arm64/boot/dts/mediatek/mt7986a.dtsi | 14 ++++++++++++++ - 1 file changed, 14 insertions(+) - ---- a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi -+++ b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi -@@ -280,6 +280,20 @@ - status = "disabled"; - }; - -+ i2c0: i2c@11008000 { -+ compatible = "mediatek,mt7986-i2c"; -+ reg = <0 0x11008000 0 0x90>, -+ <0 0x10217080 0 0x80>; -+ interrupts = ; -+ clock-div = <5>; -+ clocks = <&infracfg CLK_INFRA_I2C0_CK>, -+ <&infracfg CLK_INFRA_AP_DMA_CK>; -+ clock-names = "main", "dma"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "disabled"; -+ }; -+ - ethsys: syscon@15000000 { - #address-cells = <1>; - #size-cells = <1>; diff --git a/target/linux/mediatek/patches-6.1/005-v6.2-arm64-dts-mediatek-mt7986-Add-SoC-compatible.patch b/target/linux/mediatek/patches-6.1/005-v6.2-arm64-dts-mediatek-mt7986-Add-SoC-compatible.patch deleted file mode 100644 index 8201b47df..000000000 --- a/target/linux/mediatek/patches-6.1/005-v6.2-arm64-dts-mediatek-mt7986-Add-SoC-compatible.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 2cd6022800d6da7822e169f3e6f7f790c1431445 Mon Sep 17 00:00:00 2001 -From: Matthias Brugger -Date: Mon, 14 Nov 2022 13:16:53 +0100 -Subject: [PATCH 05/19] arm64: dts: mediatek: mt7986: Add SoC compatible - -Missing SoC compatible in the board file causes dt bindings check. - -Signed-off-by: Matthias Brugger -Link: https://lore.kernel.org/r/20221114121653.14739-1-matthias.bgg@kernel.org -Signed-off-by: Matthias Brugger ---- - arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts | 2 +- - arch/arm64/boot/dts/mediatek/mt7986a.dtsi | 1 + - arch/arm64/boot/dts/mediatek/mt7986b-rfb.dts | 2 +- - arch/arm64/boot/dts/mediatek/mt7986b.dtsi | 3 +++ - 4 files changed, 6 insertions(+), 2 deletions(-) - ---- a/arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts -@@ -9,7 +9,7 @@ - - / { - model = "MediaTek MT7986a RFB"; -- compatible = "mediatek,mt7986a-rfb"; -+ compatible = "mediatek,mt7986a-rfb", "mediatek,mt7986a"; - - aliases { - serial0 = &uart0; ---- a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi -+++ b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi -@@ -10,6 +10,7 @@ - #include - - / { -+ compatible = "mediatek,mt7986a"; - interrupt-parent = <&gic>; - #address-cells = <2>; - #size-cells = <2>; ---- a/arch/arm64/boot/dts/mediatek/mt7986b-rfb.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7986b-rfb.dts -@@ -9,7 +9,7 @@ - - / { - model = "MediaTek MT7986b RFB"; -- compatible = "mediatek,mt7986b-rfb"; -+ compatible = "mediatek,mt7986b-rfb", "mediatek,mt7986b"; - - aliases { - serial0 = &uart0; ---- a/arch/arm64/boot/dts/mediatek/mt7986b.dtsi -+++ b/arch/arm64/boot/dts/mediatek/mt7986b.dtsi -@@ -5,6 +5,9 @@ - */ - - #include "mt7986a.dtsi" -+/ { -+ compatible = "mediatek,mt7986b"; -+}; - - &pio { - compatible = "mediatek,mt7986b-pinctrl"; diff --git a/target/linux/mediatek/patches-6.1/006-v6.2-arm64-dts-mt7986-add-spi-related-device-nodes.patch b/target/linux/mediatek/patches-6.1/006-v6.2-arm64-dts-mt7986-add-spi-related-device-nodes.patch deleted file mode 100644 index 619bfec09..000000000 --- a/target/linux/mediatek/patches-6.1/006-v6.2-arm64-dts-mt7986-add-spi-related-device-nodes.patch +++ /dev/null @@ -1,157 +0,0 @@ -From f4029538f063a845dc9aae46cce4cf386e6253a5 Mon Sep 17 00:00:00 2001 -From: Sam Shih -Date: Fri, 18 Nov 2022 20:01:21 +0100 -Subject: [PATCH 06/19] arm64: dts: mt7986: add spi related device nodes - -This patch adds spi support for MT7986. - -Signed-off-by: Sam Shih -Signed-off-by: Frank Wunderlich -Reviewed-by: AngeloGioacchino Del Regno -Link: https://lore.kernel.org/r/20221118190126.100895-7-linux@fw-web.de -Signed-off-by: Matthias Brugger ---- - arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts | 35 ++++++++++++++++++++ - arch/arm64/boot/dts/mediatek/mt7986a.dtsi | 28 ++++++++++++++++ - arch/arm64/boot/dts/mediatek/mt7986b-rfb.dts | 35 ++++++++++++++++++++ - 3 files changed, 98 insertions(+) - ---- a/arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts -@@ -59,6 +59,20 @@ - }; - - &pio { -+ spi_flash_pins: spi-flash-pins { -+ mux { -+ function = "spi"; -+ groups = "spi0", "spi0_wp_hold"; -+ }; -+ }; -+ -+ spic_pins: spic-pins { -+ mux { -+ function = "spi"; -+ groups = "spi1_2"; -+ }; -+ }; -+ - uart1_pins: uart1-pins { - mux { - function = "uart"; -@@ -105,6 +119,27 @@ - }; - }; - -+&spi0 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&spi_flash_pins>; -+ cs-gpios = <0>, <0>; -+ status = "okay"; -+ spi_nand: spi_nand@0 { -+ compatible = "spi-nand"; -+ reg = <0>; -+ spi-max-frequency = <10000000>; -+ spi-tx-buswidth = <4>; -+ spi-rx-buswidth = <4>; -+ }; -+}; -+ -+&spi1 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&spic_pins>; -+ cs-gpios = <0>, <0>; -+ status = "okay"; -+}; -+ - &switch { - ports { - #address-cells = <1>; ---- a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi -+++ b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi -@@ -295,6 +295,34 @@ - status = "disabled"; - }; - -+ spi0: spi@1100a000 { -+ compatible = "mediatek,mt7986-spi-ipm", "mediatek,spi-ipm"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ reg = <0 0x1100a000 0 0x100>; -+ interrupts = ; -+ clocks = <&topckgen CLK_TOP_MPLL_D2>, -+ <&topckgen CLK_TOP_SPI_SEL>, -+ <&infracfg CLK_INFRA_SPI0_CK>, -+ <&infracfg CLK_INFRA_SPI0_HCK_CK>; -+ clock-names = "parent-clk", "sel-clk", "spi-clk", "hclk"; -+ status = "disabled"; -+ }; -+ -+ spi1: spi@1100b000 { -+ compatible = "mediatek,mt7986-spi-ipm", "mediatek,spi-ipm"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ reg = <0 0x1100b000 0 0x100>; -+ interrupts = ; -+ clocks = <&topckgen CLK_TOP_MPLL_D2>, -+ <&topckgen CLK_TOP_SPIM_MST_SEL>, -+ <&infracfg CLK_INFRA_SPI1_CK>, -+ <&infracfg CLK_INFRA_SPI1_HCK_CK>; -+ clock-names = "parent-clk", "sel-clk", "spi-clk", "hclk"; -+ status = "disabled"; -+ }; -+ - ethsys: syscon@15000000 { - #address-cells = <1>; - #size-cells = <1>; ---- a/arch/arm64/boot/dts/mediatek/mt7986b-rfb.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7986b-rfb.dts -@@ -100,6 +100,20 @@ - }; - - &pio { -+ spi_flash_pins: spi-flash-pins { -+ mux { -+ function = "spi"; -+ groups = "spi0", "spi0_wp_hold"; -+ }; -+ }; -+ -+ spic_pins: spic-pins { -+ mux { -+ function = "spi"; -+ groups = "spi1_2"; -+ }; -+ }; -+ - wf_2g_5g_pins: wf-2g-5g-pins { - mux { - function = "wifi"; -@@ -132,6 +146,27 @@ - }; - }; - -+&spi0 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&spi_flash_pins>; -+ cs-gpios = <0>, <0>; -+ status = "okay"; -+ spi_nand: spi_nand@0 { -+ compatible = "spi-nand"; -+ reg = <0>; -+ spi-max-frequency = <10000000>; -+ spi-tx-buswidth = <4>; -+ spi-rx-buswidth = <4>; -+ }; -+}; -+ -+&spi1 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&spic_pins>; -+ cs-gpios = <0>, <0>; -+ status = "okay"; -+}; -+ - &uart0 { - status = "okay"; - }; diff --git a/target/linux/mediatek/patches-6.1/007-v6.3-arm64-dts-mt7986-add-usb-related-device-nodes.patch b/target/linux/mediatek/patches-6.1/007-v6.3-arm64-dts-mt7986-add-usb-related-device-nodes.patch deleted file mode 100644 index 603f33b15..000000000 --- a/target/linux/mediatek/patches-6.1/007-v6.3-arm64-dts-mt7986-add-usb-related-device-nodes.patch +++ /dev/null @@ -1,127 +0,0 @@ -From 9e8e24ab716098e617195ce29b88e84608bf2108 Mon Sep 17 00:00:00 2001 -From: Sam Shih -Date: Fri, 6 Jan 2023 16:28:42 +0100 -Subject: [PATCH 07/19] arm64: dts: mt7986: add usb related device nodes - -This patch adds USB support for MT7986. - -Signed-off-by: Sam Shih -Signed-off-by: Frank Wunderlich -Reviewed-by: Chunfeng Yun -Link: https://lore.kernel.org/r/20230106152845.88717-3-linux@fw-web.de -Signed-off-by: Matthias Brugger ---- - arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts | 8 +++ - arch/arm64/boot/dts/mediatek/mt7986a.dtsi | 55 ++++++++++++++++++++ - arch/arm64/boot/dts/mediatek/mt7986b-rfb.dts | 8 +++ - 3 files changed, 71 insertions(+) - ---- a/arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts -@@ -140,6 +140,10 @@ - status = "okay"; - }; - -+&ssusb { -+ status = "okay"; -+}; -+ - &switch { - ports { - #address-cells = <1>; -@@ -201,6 +205,10 @@ - status = "okay"; - }; - -+&usb_phy { -+ status = "okay"; -+}; -+ - &wifi { - status = "okay"; - pinctrl-names = "default", "dbdc"; ---- a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi -+++ b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi -@@ -323,6 +323,61 @@ - status = "disabled"; - }; - -+ ssusb: usb@11200000 { -+ compatible = "mediatek,mt7986-xhci", -+ "mediatek,mtk-xhci"; -+ reg = <0 0x11200000 0 0x2e00>, -+ <0 0x11203e00 0 0x0100>; -+ reg-names = "mac", "ippc"; -+ interrupts = ; -+ clocks = <&infracfg CLK_INFRA_IUSB_SYS_CK>, -+ <&infracfg CLK_INFRA_IUSB_CK>, -+ <&infracfg CLK_INFRA_IUSB_133_CK>, -+ <&infracfg CLK_INFRA_IUSB_66M_CK>, -+ <&topckgen CLK_TOP_U2U3_XHCI_SEL>; -+ clock-names = "sys_ck", -+ "ref_ck", -+ "mcu_ck", -+ "dma_ck", -+ "xhci_ck"; -+ phys = <&u2port0 PHY_TYPE_USB2>, -+ <&u3port0 PHY_TYPE_USB3>, -+ <&u2port1 PHY_TYPE_USB2>; -+ status = "disabled"; -+ }; -+ -+ usb_phy: t-phy@11e10000 { -+ compatible = "mediatek,mt7986-tphy", -+ "mediatek,generic-tphy-v2"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ ranges = <0 0 0x11e10000 0x1700>; -+ status = "disabled"; -+ -+ u2port0: usb-phy@0 { -+ reg = <0x0 0x700>; -+ clocks = <&topckgen CLK_TOP_DA_U2_REFSEL>, -+ <&topckgen CLK_TOP_DA_U2_CK_1P_SEL>; -+ clock-names = "ref", "da_ref"; -+ #phy-cells = <1>; -+ }; -+ -+ u3port0: usb-phy@700 { -+ reg = <0x700 0x900>; -+ clocks = <&topckgen CLK_TOP_USB3_PHY_SEL>; -+ clock-names = "ref"; -+ #phy-cells = <1>; -+ }; -+ -+ u2port1: usb-phy@1000 { -+ reg = <0x1000 0x700>; -+ clocks = <&topckgen CLK_TOP_DA_U2_REFSEL>, -+ <&topckgen CLK_TOP_DA_U2_CK_1P_SEL>; -+ clock-names = "ref", "da_ref"; -+ #phy-cells = <1>; -+ }; -+ }; -+ - ethsys: syscon@15000000 { - #address-cells = <1>; - #size-cells = <1>; ---- a/arch/arm64/boot/dts/mediatek/mt7986b-rfb.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7986b-rfb.dts -@@ -167,10 +167,18 @@ - status = "okay"; - }; - -+&ssusb { -+ status = "okay"; -+}; -+ - &uart0 { - status = "okay"; - }; - -+&usb_phy { -+ status = "okay"; -+}; -+ - &wifi { - status = "okay"; - pinctrl-names = "default", "dbdc"; diff --git a/target/linux/mediatek/patches-6.1/008-v6.3-arm64-dts-mt7986-add-mmc-related-device-nodes.patch b/target/linux/mediatek/patches-6.1/008-v6.3-arm64-dts-mt7986-add-mmc-related-device-nodes.patch deleted file mode 100644 index 40e71cd42..000000000 --- a/target/linux/mediatek/patches-6.1/008-v6.3-arm64-dts-mt7986-add-mmc-related-device-nodes.patch +++ /dev/null @@ -1,160 +0,0 @@ -From c1744e9e75a6a8abc7c893f349bcbf725b9c0d74 Mon Sep 17 00:00:00 2001 -From: Sam Shih -Date: Fri, 6 Jan 2023 16:28:43 +0100 -Subject: [PATCH 08/19] arm64: dts: mt7986: add mmc related device nodes - -This patch adds mmc support for MT7986. - -Signed-off-by: Sam Shih -Signed-off-by: Frank Wunderlich -Link: https://lore.kernel.org/r/20230106152845.88717-4-linux@fw-web.de -Signed-off-by: Matthias Brugger ---- - arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts | 96 ++++++++++++++++++++ - arch/arm64/boot/dts/mediatek/mt7986a.dtsi | 15 +++ - 2 files changed, 111 insertions(+) - ---- a/arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts -@@ -5,6 +5,8 @@ - */ - - /dts-v1/; -+#include -+ - #include "mt7986a.dtsi" - - / { -@@ -23,6 +25,24 @@ - device_type = "memory"; - reg = <0 0x40000000 0 0x40000000>; - }; -+ -+ reg_1p8v: regulator-1p8v { -+ compatible = "regulator-fixed"; -+ regulator-name = "fixed-1.8V"; -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <1800000>; -+ regulator-boot-on; -+ regulator-always-on; -+ }; -+ -+ reg_3p3v: regulator-3p3v { -+ compatible = "regulator-fixed"; -+ regulator-name = "fixed-3.3V"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-boot-on; -+ regulator-always-on; -+ }; - }; - - &crypto { -@@ -58,7 +78,83 @@ - }; - }; - -+&mmc0 { -+ pinctrl-names = "default", "state_uhs"; -+ pinctrl-0 = <&mmc0_pins_default>; -+ pinctrl-1 = <&mmc0_pins_uhs>; -+ bus-width = <8>; -+ max-frequency = <200000000>; -+ cap-mmc-highspeed; -+ mmc-hs200-1_8v; -+ mmc-hs400-1_8v; -+ hs400-ds-delay = <0x14014>; -+ vmmc-supply = <®_3p3v>; -+ vqmmc-supply = <®_1p8v>; -+ non-removable; -+ no-sd; -+ no-sdio; -+ status = "okay"; -+}; -+ - &pio { -+ mmc0_pins_default: mmc0-pins { -+ mux { -+ function = "emmc"; -+ groups = "emmc_51"; -+ }; -+ conf-cmd-dat { -+ pins = "EMMC_DATA_0", "EMMC_DATA_1", "EMMC_DATA_2", -+ "EMMC_DATA_3", "EMMC_DATA_4", "EMMC_DATA_5", -+ "EMMC_DATA_6", "EMMC_DATA_7", "EMMC_CMD"; -+ input-enable; -+ drive-strength = <4>; -+ bias-pull-up = ; /* pull-up 10K */ -+ }; -+ conf-clk { -+ pins = "EMMC_CK"; -+ drive-strength = <6>; -+ bias-pull-down = ; /* pull-down 50K */ -+ }; -+ conf-ds { -+ pins = "EMMC_DSL"; -+ bias-pull-down = ; /* pull-down 50K */ -+ }; -+ conf-rst { -+ pins = "EMMC_RSTB"; -+ drive-strength = <4>; -+ bias-pull-up = ; /* pull-up 10K */ -+ }; -+ }; -+ -+ mmc0_pins_uhs: mmc0-uhs-pins { -+ mux { -+ function = "emmc"; -+ groups = "emmc_51"; -+ }; -+ conf-cmd-dat { -+ pins = "EMMC_DATA_0", "EMMC_DATA_1", "EMMC_DATA_2", -+ "EMMC_DATA_3", "EMMC_DATA_4", "EMMC_DATA_5", -+ "EMMC_DATA_6", "EMMC_DATA_7", "EMMC_CMD"; -+ input-enable; -+ drive-strength = <4>; -+ bias-pull-up = ; /* pull-up 10K */ -+ }; -+ conf-clk { -+ pins = "EMMC_CK"; -+ drive-strength = <6>; -+ bias-pull-down = ; /* pull-down 50K */ -+ }; -+ conf-ds { -+ pins = "EMMC_DSL"; -+ bias-pull-down = ; /* pull-down 50K */ -+ }; -+ conf-rst { -+ pins = "EMMC_RSTB"; -+ drive-strength = <4>; -+ bias-pull-up = ; /* pull-up 10K */ -+ }; -+ }; -+ - spi_flash_pins: spi-flash-pins { - mux { - function = "spi"; ---- a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi -+++ b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi -@@ -346,6 +346,21 @@ - status = "disabled"; - }; - -+ mmc0: mmc@11230000 { -+ compatible = "mediatek,mt7986-mmc"; -+ reg = <0 0x11230000 0 0x1000>, -+ <0 0x11c20000 0 0x1000>; -+ interrupts = ; -+ clocks = <&topckgen CLK_TOP_EMMC_416M_SEL>, -+ <&infracfg CLK_INFRA_MSDC_HCK_CK>, -+ <&infracfg CLK_INFRA_MSDC_CK>, -+ <&infracfg CLK_INFRA_MSDC_133M_CK>, -+ <&infracfg CLK_INFRA_MSDC_66M_CK>; -+ clock-names = "source", "hclk", "source_cg", "bus_clk", -+ "sys_cg"; -+ status = "disabled"; -+ }; -+ - usb_phy: t-phy@11e10000 { - compatible = "mediatek,mt7986-tphy", - "mediatek,generic-tphy-v2"; diff --git a/target/linux/mediatek/patches-6.1/009-v6.3-arm64-dts-mt7986-add-pcie-related-device-nodes.patch b/target/linux/mediatek/patches-6.1/009-v6.3-arm64-dts-mt7986-add-pcie-related-device-nodes.patch deleted file mode 100644 index ab039c335..000000000 --- a/target/linux/mediatek/patches-6.1/009-v6.3-arm64-dts-mt7986-add-pcie-related-device-nodes.patch +++ /dev/null @@ -1,118 +0,0 @@ -From 87a42ef1d6cf602e4aa40555b4404cad6149a90f Mon Sep 17 00:00:00 2001 -From: Sam Shih -Date: Fri, 6 Jan 2023 16:28:44 +0100 -Subject: [PATCH 09/19] arm64: dts: mt7986: add pcie related device nodes - -This patch adds PCIe support for MT7986. - -Signed-off-by: Jieyy Yang -Signed-off-by: Sam Shih -Signed-off-by: Frank Wunderlich -Reviewed-by: AngeloGioacchino Del Regno -Link: https://lore.kernel.org/r/20230106152845.88717-5-linux@fw-web.de -Signed-off-by: Matthias Brugger ---- - arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts | 16 ++++++ - arch/arm64/boot/dts/mediatek/mt7986a.dtsi | 52 ++++++++++++++++++++ - 2 files changed, 68 insertions(+) - ---- a/arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts -@@ -93,6 +93,15 @@ - non-removable; - no-sd; - no-sdio; -+}; -+ -+&pcie { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pcie_pins>; -+ status = "okay"; -+}; -+ -+&pcie_phy { - status = "okay"; - }; - -@@ -155,6 +164,13 @@ - }; - }; - -+ pcie_pins: pcie-pins { -+ mux { -+ function = "pcie"; -+ groups = "pcie_clk", "pcie_wake", "pcie_pereset"; -+ }; -+ }; -+ - spi_flash_pins: spi-flash-pins { - mux { - function = "spi"; ---- a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi -+++ b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi -@@ -8,6 +8,7 @@ - #include - #include - #include -+#include - - / { - compatible = "mediatek,mt7986a"; -@@ -361,6 +362,57 @@ - status = "disabled"; - }; - -+ pcie: pcie@11280000 { -+ compatible = "mediatek,mt7986-pcie", -+ "mediatek,mt8192-pcie"; -+ device_type = "pci"; -+ #address-cells = <3>; -+ #size-cells = <2>; -+ reg = <0x00 0x11280000 0x00 0x4000>; -+ reg-names = "pcie-mac"; -+ interrupts = ; -+ bus-range = <0x00 0xff>; -+ ranges = <0x82000000 0x00 0x20000000 0x00 -+ 0x20000000 0x00 0x10000000>; -+ clocks = <&infracfg CLK_INFRA_IPCIE_PIPE_CK>, -+ <&infracfg CLK_INFRA_IPCIE_CK>, -+ <&infracfg CLK_INFRA_IPCIER_CK>, -+ <&infracfg CLK_INFRA_IPCIEB_CK>; -+ clock-names = "pl_250m", "tl_26m", "peri_26m", "top_133m"; -+ status = "disabled"; -+ -+ phys = <&pcie_port PHY_TYPE_PCIE>; -+ phy-names = "pcie-phy"; -+ -+ #interrupt-cells = <1>; -+ interrupt-map-mask = <0 0 0 0x7>; -+ interrupt-map = <0 0 0 1 &pcie_intc 0>, -+ <0 0 0 2 &pcie_intc 1>, -+ <0 0 0 3 &pcie_intc 2>, -+ <0 0 0 4 &pcie_intc 3>; -+ pcie_intc: interrupt-controller { -+ #address-cells = <0>; -+ #interrupt-cells = <1>; -+ interrupt-controller; -+ }; -+ }; -+ -+ pcie_phy: t-phy@11c00000 { -+ compatible = "mediatek,mt7986-tphy", -+ "mediatek,generic-tphy-v2"; -+ #address-cells = <2>; -+ #size-cells = <2>; -+ ranges; -+ status = "disabled"; -+ -+ pcie_port: pcie-phy@11c00000 { -+ reg = <0 0x11c00000 0 0x20000>; -+ clocks = <&clk40m>; -+ clock-names = "ref"; -+ #phy-cells = <1>; -+ }; -+ }; -+ - usb_phy: t-phy@11e10000 { - compatible = "mediatek,mt7986-tphy", - "mediatek,generic-tphy-v2"; diff --git a/target/linux/mediatek/patches-6.1/010-v6.3-arm64-dts-mt7986-add-Bananapi-R3.patch b/target/linux/mediatek/patches-6.1/010-v6.3-arm64-dts-mt7986-add-Bananapi-R3.patch deleted file mode 100644 index abe0b6e9b..000000000 --- a/target/linux/mediatek/patches-6.1/010-v6.3-arm64-dts-mt7986-add-Bananapi-R3.patch +++ /dev/null @@ -1,689 +0,0 @@ -From a751f7412e0098801673b80bc7a4738ae7d710ce Mon Sep 17 00:00:00 2001 -From: Frank Wunderlich -Date: Fri, 6 Jan 2023 16:28:45 +0100 -Subject: [PATCH 10/19] arm64: dts: mt7986: add Bananapi R3 - -Add support for Bananapi R3 SBC. - -- SD/eMMC support (switching first 4 bits of data-bus with sw6/D) -- SPI-NAND/NOR support (switched CS by sw5/C) -- all rj45 ports and both SFP working (eth1/lan4) -- all USB-Ports + SIM-Slot tested -- i2c and all uarts tested -- wifi tested (with eeprom calibration data) - -The device can boot from all 4 storage options. Both, SPI and MMC, can -be switched using hardware switches on the board, see -https://wiki.banana-pi.org/Banana_Pi_BPI-R3#Jumper_setting - -Signed-off-by: Frank Wunderlich -Link: https://lore.kernel.org/r/20230106152845.88717-6-linux@fw-web.de -Signed-off-by: Matthias Brugger ---- - arch/arm64/boot/dts/mediatek/Makefile | 5 + - .../mt7986a-bananapi-bpi-r3-emmc.dtso | 29 ++ - .../mt7986a-bananapi-bpi-r3-nand.dtso | 55 +++ - .../mediatek/mt7986a-bananapi-bpi-r3-nor.dtso | 68 +++ - .../mediatek/mt7986a-bananapi-bpi-r3-sd.dtso | 23 + - .../dts/mediatek/mt7986a-bananapi-bpi-r3.dts | 450 ++++++++++++++++++ - 6 files changed, 630 insertions(+) - create mode 100644 arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-emmc.dtso - create mode 100644 arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-nand.dtso - create mode 100644 arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-nor.dtso - create mode 100644 arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-sd.dtso - create mode 100644 arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts - ---- a/arch/arm64/boot/dts/mediatek/Makefile -+++ b/arch/arm64/boot/dts/mediatek/Makefile -@@ -7,6 +7,11 @@ dtb-$(CONFIG_ARCH_MEDIATEK) += mt6797-ev - dtb-$(CONFIG_ARCH_MEDIATEK) += mt6797-x20-dev.dtb - dtb-$(CONFIG_ARCH_MEDIATEK) += mt7622-rfb1.dtb - dtb-$(CONFIG_ARCH_MEDIATEK) += mt7622-bananapi-bpi-r64.dtb -+dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986a-bananapi-bpi-r3.dtb -+dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986a-bananapi-bpi-r3-emmc.dtbo -+dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986a-bananapi-bpi-r3-nand.dtbo -+dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986a-bananapi-bpi-r3-nor.dtbo -+dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986a-bananapi-bpi-r3-sd.dtbo - dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986a-rfb.dtb - dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986b-rfb.dtb - dtb-$(CONFIG_ARCH_MEDIATEK) += mt8167-pumpkin.dtb ---- /dev/null -+++ b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-emmc.dtso -@@ -0,0 +1,29 @@ -+// SPDX-License-Identifier: (GPL-2.0 OR MIT) -+/* -+ * Copyright (C) 2021 MediaTek Inc. -+ * Author: Sam.Shih -+ */ -+ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "bananapi,bpi-r3", "mediatek,mt7986a"; -+ -+ fragment@0 { -+ target-path = "/soc/mmc@11230000"; -+ __overlay__ { -+ bus-width = <8>; -+ max-frequency = <200000000>; -+ cap-mmc-highspeed; -+ mmc-hs200-1_8v; -+ mmc-hs400-1_8v; -+ hs400-ds-delay = <0x14014>; -+ non-removable; -+ no-sd; -+ no-sdio; -+ status = "okay"; -+ }; -+ }; -+}; -+ ---- /dev/null -+++ b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-nand.dtso -@@ -0,0 +1,55 @@ -+/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */ -+/* -+ * Authors: Daniel Golle -+ * Frank Wunderlich -+ */ -+ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "bananapi,bpi-r3", "mediatek,mt7986a"; -+ -+ fragment@0 { -+ target-path = "/soc/spi@1100a000"; -+ __overlay__ { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ spi_nand: spi_nand@0 { -+ compatible = "spi-nand"; -+ reg = <0>; -+ spi-max-frequency = <10000000>; -+ spi-tx-buswidth = <4>; -+ spi-rx-buswidth = <4>; -+ -+ partitions { -+ compatible = "fixed-partitions"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ partition@0 { -+ label = "bl2"; -+ reg = <0x0 0x80000>; -+ read-only; -+ }; -+ -+ partition@80000 { -+ label = "reserved"; -+ reg = <0x80000 0x300000>; -+ }; -+ -+ partition@380000 { -+ label = "fip"; -+ reg = <0x380000 0x200000>; -+ read-only; -+ }; -+ -+ partition@580000 { -+ label = "ubi"; -+ reg = <0x580000 0x7a80000>; -+ }; -+ }; -+ }; -+ }; -+ }; -+}; ---- /dev/null -+++ b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-nor.dtso -@@ -0,0 +1,68 @@ -+/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */ -+/* -+ * Authors: Daniel Golle -+ * Frank Wunderlich -+ */ -+ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "bananapi,bpi-r3", "mediatek,mt7986a"; -+ -+ fragment@0 { -+ target-path = "/soc/spi@1100a000"; -+ __overlay__ { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ flash@0 { -+ compatible = "jedec,spi-nor"; -+ reg = <0>; -+ spi-max-frequency = <10000000>; -+ -+ partitions { -+ compatible = "fixed-partitions"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ partition@0 { -+ label = "bl2"; -+ reg = <0x0 0x20000>; -+ read-only; -+ }; -+ -+ partition@20000 { -+ label = "reserved"; -+ reg = <0x20000 0x20000>; -+ }; -+ -+ partition@40000 { -+ label = "u-boot-env"; -+ reg = <0x40000 0x40000>; -+ }; -+ -+ partition@80000 { -+ label = "reserved2"; -+ reg = <0x80000 0x80000>; -+ }; -+ -+ partition@100000 { -+ label = "fip"; -+ reg = <0x100000 0x80000>; -+ read-only; -+ }; -+ -+ partition@180000 { -+ label = "recovery"; -+ reg = <0x180000 0xa80000>; -+ }; -+ -+ partition@c00000 { -+ label = "fit"; -+ reg = <0xc00000 0x1400000>; -+ }; -+ }; -+ }; -+ }; -+ }; -+}; ---- /dev/null -+++ b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-sd.dtso -@@ -0,0 +1,23 @@ -+// SPDX-License-Identifier: (GPL-2.0 OR MIT) -+/* -+ * Copyright (C) 2021 MediaTek Inc. -+ * Author: Sam.Shih -+ */ -+ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "bananapi,bpi-r3", "mediatek,mt7986a"; -+ -+ fragment@0 { -+ target-path = "/soc/mmc@11230000"; -+ __overlay__ { -+ bus-width = <4>; -+ max-frequency = <52000000>; -+ cap-sd-highspeed; -+ status = "okay"; -+ }; -+ }; -+}; -+ ---- /dev/null -+++ b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts -@@ -0,0 +1,450 @@ -+// SPDX-License-Identifier: (GPL-2.0 OR MIT) -+/* -+ * Copyright (C) 2021 MediaTek Inc. -+ * Authors: Sam.Shih -+ * Frank Wunderlich -+ * Daniel Golle -+ */ -+ -+/dts-v1/; -+#include -+#include -+#include -+#include -+ -+#include "mt7986a.dtsi" -+ -+/ { -+ model = "Bananapi BPI-R3"; -+ compatible = "bananapi,bpi-r3", "mediatek,mt7986a"; -+ -+ aliases { -+ serial0 = &uart0; -+ ethernet0 = &gmac0; -+ ethernet1 = &gmac1; -+ }; -+ -+ chosen { -+ stdout-path = "serial0:115200n8"; -+ }; -+ -+ dcin: regulator-12vd { -+ compatible = "regulator-fixed"; -+ regulator-name = "12vd"; -+ regulator-min-microvolt = <12000000>; -+ regulator-max-microvolt = <12000000>; -+ regulator-boot-on; -+ regulator-always-on; -+ }; -+ -+ gpio-keys { -+ compatible = "gpio-keys"; -+ -+ reset-key { -+ label = "reset"; -+ linux,code = ; -+ gpios = <&pio 9 GPIO_ACTIVE_LOW>; -+ }; -+ -+ wps-key { -+ label = "wps"; -+ linux,code = ; -+ gpios = <&pio 10 GPIO_ACTIVE_LOW>; -+ }; -+ }; -+ -+ /* i2c of the left SFP cage (wan) */ -+ i2c_sfp1: i2c-gpio-0 { -+ compatible = "i2c-gpio"; -+ sda-gpios = <&pio 16 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; -+ scl-gpios = <&pio 17 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; -+ i2c-gpio,delay-us = <2>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ }; -+ -+ /* i2c of the right SFP cage (lan) */ -+ i2c_sfp2: i2c-gpio-1 { -+ compatible = "i2c-gpio"; -+ sda-gpios = <&pio 18 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; -+ scl-gpios = <&pio 19 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; -+ i2c-gpio,delay-us = <2>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ }; -+ -+ leds { -+ compatible = "gpio-leds"; -+ -+ green_led: led-0 { -+ color = ; -+ function = LED_FUNCTION_POWER; -+ gpios = <&pio 69 GPIO_ACTIVE_HIGH>; -+ default-state = "on"; -+ }; -+ -+ blue_led: led-1 { -+ color = ; -+ function = LED_FUNCTION_STATUS; -+ gpios = <&pio 86 GPIO_ACTIVE_HIGH>; -+ default-state = "off"; -+ }; -+ }; -+ -+ reg_1p8v: regulator-1p8v { -+ compatible = "regulator-fixed"; -+ regulator-name = "1.8vd"; -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <1800000>; -+ regulator-boot-on; -+ regulator-always-on; -+ vin-supply = <&dcin>; -+ }; -+ -+ reg_3p3v: regulator-3p3v { -+ compatible = "regulator-fixed"; -+ regulator-name = "3.3vd"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-boot-on; -+ regulator-always-on; -+ vin-supply = <&dcin>; -+ }; -+ -+ /* left SFP cage (wan) */ -+ sfp1: sfp-1 { -+ compatible = "sff,sfp"; -+ i2c-bus = <&i2c_sfp1>; -+ los-gpios = <&pio 46 GPIO_ACTIVE_HIGH>; -+ mod-def0-gpios = <&pio 49 GPIO_ACTIVE_LOW>; -+ tx-disable-gpios = <&pio 20 GPIO_ACTIVE_HIGH>; -+ tx-fault-gpios = <&pio 7 GPIO_ACTIVE_HIGH>; -+ }; -+ -+ /* right SFP cage (lan) */ -+ sfp2: sfp-2 { -+ compatible = "sff,sfp"; -+ i2c-bus = <&i2c_sfp2>; -+ los-gpios = <&pio 31 GPIO_ACTIVE_HIGH>; -+ mod-def0-gpios = <&pio 47 GPIO_ACTIVE_LOW>; -+ tx-disable-gpios = <&pio 15 GPIO_ACTIVE_HIGH>; -+ tx-fault-gpios = <&pio 48 GPIO_ACTIVE_HIGH>; -+ }; -+}; -+ -+&crypto { -+ status = "okay"; -+}; -+ -+ð { -+ status = "okay"; -+ -+ gmac0: mac@0 { -+ compatible = "mediatek,eth-mac"; -+ reg = <0>; -+ phy-mode = "2500base-x"; -+ -+ fixed-link { -+ speed = <2500>; -+ full-duplex; -+ pause; -+ }; -+ }; -+ -+ gmac1: mac@1 { -+ compatible = "mediatek,eth-mac"; -+ reg = <1>; -+ phy-mode = "2500base-x"; -+ sfp = <&sfp1>; -+ managed = "in-band-status"; -+ }; -+ -+ mdio: mdio-bus { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ }; -+}; -+ -+&mdio { -+ switch: switch@31 { -+ compatible = "mediatek,mt7531"; -+ reg = <31>; -+ interrupt-controller; -+ #interrupt-cells = <1>; -+ interrupt-parent = <&pio>; -+ interrupts = <66 IRQ_TYPE_LEVEL_HIGH>; -+ reset-gpios = <&pio 5 GPIO_ACTIVE_HIGH>; -+ }; -+}; -+ -+&mmc0 { -+ pinctrl-names = "default", "state_uhs"; -+ pinctrl-0 = <&mmc0_pins_default>; -+ pinctrl-1 = <&mmc0_pins_uhs>; -+ vmmc-supply = <®_3p3v>; -+ vqmmc-supply = <®_1p8v>; -+}; -+ -+&i2c0 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&i2c_pins>; -+ status = "okay"; -+}; -+ -+&pcie { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pcie_pins>; -+ status = "okay"; -+}; -+ -+&pcie_phy { -+ status = "okay"; -+}; -+ -+&pio { -+ i2c_pins: i2c-pins { -+ mux { -+ function = "i2c"; -+ groups = "i2c"; -+ }; -+ }; -+ -+ mmc0_pins_default: mmc0-pins { -+ mux { -+ function = "emmc"; -+ groups = "emmc_51"; -+ }; -+ conf-cmd-dat { -+ pins = "EMMC_DATA_0", "EMMC_DATA_1", "EMMC_DATA_2", -+ "EMMC_DATA_3", "EMMC_DATA_4", "EMMC_DATA_5", -+ "EMMC_DATA_6", "EMMC_DATA_7", "EMMC_CMD"; -+ input-enable; -+ drive-strength = <4>; -+ bias-pull-up = ; /* pull-up 10K */ -+ }; -+ conf-clk { -+ pins = "EMMC_CK"; -+ drive-strength = <6>; -+ bias-pull-down = ; /* pull-down 50K */ -+ }; -+ conf-ds { -+ pins = "EMMC_DSL"; -+ bias-pull-down = ; /* pull-down 50K */ -+ }; -+ conf-rst { -+ pins = "EMMC_RSTB"; -+ drive-strength = <4>; -+ bias-pull-up = ; /* pull-up 10K */ -+ }; -+ }; -+ -+ mmc0_pins_uhs: mmc0-uhs-pins { -+ mux { -+ function = "emmc"; -+ groups = "emmc_51"; -+ }; -+ conf-cmd-dat { -+ pins = "EMMC_DATA_0", "EMMC_DATA_1", "EMMC_DATA_2", -+ "EMMC_DATA_3", "EMMC_DATA_4", "EMMC_DATA_5", -+ "EMMC_DATA_6", "EMMC_DATA_7", "EMMC_CMD"; -+ input-enable; -+ drive-strength = <4>; -+ bias-pull-up = ; /* pull-up 10K */ -+ }; -+ conf-clk { -+ pins = "EMMC_CK"; -+ drive-strength = <6>; -+ bias-pull-down = ; /* pull-down 50K */ -+ }; -+ conf-ds { -+ pins = "EMMC_DSL"; -+ bias-pull-down = ; /* pull-down 50K */ -+ }; -+ conf-rst { -+ pins = "EMMC_RSTB"; -+ drive-strength = <4>; -+ bias-pull-up = ; /* pull-up 10K */ -+ }; -+ }; -+ -+ pcie_pins: pcie-pins { -+ mux { -+ function = "pcie"; -+ groups = "pcie_clk", "pcie_pereset"; -+ }; -+ }; -+ -+ spi_flash_pins: spi-flash-pins { -+ mux { -+ function = "spi"; -+ groups = "spi0", "spi0_wp_hold"; -+ }; -+ }; -+ -+ spic_pins: spic-pins { -+ mux { -+ function = "spi"; -+ groups = "spi1_0"; -+ }; -+ }; -+ -+ uart1_pins: uart1-pins { -+ mux { -+ function = "uart"; -+ groups = "uart1_rx_tx"; -+ }; -+ }; -+ -+ uart2_pins: uart2-pins { -+ mux { -+ function = "uart"; -+ groups = "uart2_0_rx_tx"; -+ }; -+ }; -+ -+ wf_2g_5g_pins: wf-2g-5g-pins { -+ mux { -+ function = "wifi"; -+ groups = "wf_2g", "wf_5g"; -+ }; -+ conf { -+ pins = "WF0_HB1", "WF0_HB2", "WF0_HB3", "WF0_HB4", -+ "WF0_HB0", "WF0_HB0_B", "WF0_HB5", "WF0_HB6", -+ "WF0_HB7", "WF0_HB8", "WF0_HB9", "WF0_HB10", -+ "WF0_TOP_CLK", "WF0_TOP_DATA", "WF1_HB1", -+ "WF1_HB2", "WF1_HB3", "WF1_HB4", "WF1_HB0", -+ "WF1_HB5", "WF1_HB6", "WF1_HB7", "WF1_HB8", -+ "WF1_TOP_CLK", "WF1_TOP_DATA"; -+ drive-strength = <4>; -+ }; -+ }; -+ -+ wf_dbdc_pins: wf-dbdc-pins { -+ mux { -+ function = "wifi"; -+ groups = "wf_dbdc"; -+ }; -+ conf { -+ pins = "WF0_HB1", "WF0_HB2", "WF0_HB3", "WF0_HB4", -+ "WF0_HB0", "WF0_HB0_B", "WF0_HB5", "WF0_HB6", -+ "WF0_HB7", "WF0_HB8", "WF0_HB9", "WF0_HB10", -+ "WF0_TOP_CLK", "WF0_TOP_DATA", "WF1_HB1", -+ "WF1_HB2", "WF1_HB3", "WF1_HB4", "WF1_HB0", -+ "WF1_HB5", "WF1_HB6", "WF1_HB7", "WF1_HB8", -+ "WF1_TOP_CLK", "WF1_TOP_DATA"; -+ drive-strength = <4>; -+ }; -+ }; -+ -+ wf_led_pins: wf-led-pins { -+ mux { -+ function = "led"; -+ groups = "wifi_led"; -+ }; -+ }; -+}; -+ -+&spi0 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&spi_flash_pins>; -+ status = "okay"; -+}; -+ -+&spi1 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&spic_pins>; -+ status = "okay"; -+}; -+ -+&ssusb { -+ status = "okay"; -+}; -+ -+&switch { -+ ports { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ port@0 { -+ reg = <0>; -+ label = "wan"; -+ }; -+ -+ port@1 { -+ reg = <1>; -+ label = "lan0"; -+ }; -+ -+ port@2 { -+ reg = <2>; -+ label = "lan1"; -+ }; -+ -+ port@3 { -+ reg = <3>; -+ label = "lan2"; -+ }; -+ -+ port@4 { -+ reg = <4>; -+ label = "lan3"; -+ }; -+ -+ port5: port@5 { -+ reg = <5>; -+ label = "lan4"; -+ phy-mode = "2500base-x"; -+ sfp = <&sfp2>; -+ managed = "in-band-status"; -+ }; -+ -+ port@6 { -+ reg = <6>; -+ label = "cpu"; -+ ethernet = <&gmac0>; -+ phy-mode = "2500base-x"; -+ -+ fixed-link { -+ speed = <2500>; -+ full-duplex; -+ pause; -+ }; -+ }; -+ }; -+}; -+ -+&trng { -+ status = "okay"; -+}; -+ -+&uart0 { -+ status = "okay"; -+}; -+ -+&uart1 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&uart1_pins>; -+ status = "okay"; -+}; -+ -+&uart2 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&uart2_pins>; -+ status = "okay"; -+}; -+ -+&usb_phy { -+ status = "okay"; -+}; -+ -+&watchdog { -+ status = "okay"; -+}; -+ -+&wifi { -+ status = "okay"; -+ pinctrl-names = "default", "dbdc"; -+ pinctrl-0 = <&wf_2g_5g_pins>, <&wf_led_pins>; -+ pinctrl-1 = <&wf_dbdc_pins>, <&wf_led_pins>; -+}; -+ diff --git a/target/linux/mediatek/patches-6.1/011-v6.5-arm64-mediatek-Propagate-chassis-type-where-possible.patch b/target/linux/mediatek/patches-6.1/011-v6.5-arm64-mediatek-Propagate-chassis-type-where-possible.patch deleted file mode 100644 index 79038334c..000000000 --- a/target/linux/mediatek/patches-6.1/011-v6.5-arm64-mediatek-Propagate-chassis-type-where-possible.patch +++ /dev/null @@ -1,323 +0,0 @@ -From 4c2d5411f4b101f7aa0fd74f80109e3afd6dc967 Mon Sep 17 00:00:00 2001 -From: AngeloGioacchino Del Regno -Date: Wed, 17 May 2023 12:11:08 +0200 -Subject: [PATCH 11/19] arm64: mediatek: Propagate chassis-type where possible - -The chassis-type string identifies the form-factor of the system: -add this property to all device trees of devices for which the form -factor is known. - -Signed-off-by: AngeloGioacchino Del Regno -Link: https://lore.kernel.org/r/20230517101108.205654-1-angelogioacchino.delregno@collabora.com -Signed-off-by: Matthias Brugger ---- - arch/arm64/boot/dts/mediatek/mt2712-evb.dts | 1 + - arch/arm64/boot/dts/mediatek/mt6755-evb.dts | 1 + - arch/arm64/boot/dts/mediatek/mt6779-evb.dts | 1 + - arch/arm64/boot/dts/mediatek/mt6795-evb.dts | 1 + - arch/arm64/boot/dts/mediatek/mt6797-evb.dts | 1 + - arch/arm64/boot/dts/mediatek/mt6797-x20-dev.dts | 1 + - arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts | 1 + - arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts | 1 + - arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts | 1 + - arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts | 1 + - arch/arm64/boot/dts/mediatek/mt7986b-rfb.dts | 1 + - arch/arm64/boot/dts/mediatek/mt8167-pumpkin.dts | 1 + - arch/arm64/boot/dts/mediatek/mt8173-elm-hana-rev7.dts | 1 + - arch/arm64/boot/dts/mediatek/mt8173-elm-hana.dts | 1 + - arch/arm64/boot/dts/mediatek/mt8173-elm.dts | 1 + - arch/arm64/boot/dts/mediatek/mt8173-evb.dts | 1 + - arch/arm64/boot/dts/mediatek/mt8183-evb.dts | 1 + - arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-burnet.dts | 1 + - arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-damu.dts | 1 + - .../boot/dts/mediatek/mt8183-kukui-jacuzzi-juniper-sku16.dts | 1 + - arch/arm64/boot/dts/mediatek/mt8183-kukui-kakadu-sku22.dts | 1 + - arch/arm64/boot/dts/mediatek/mt8183-kukui-kakadu.dts | 1 + - arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama-sku16.dts | 1 + - arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama-sku272.dts | 1 + - arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama-sku288.dts | 1 + - arch/arm64/boot/dts/mediatek/mt8183-kukui-krane-sku0.dts | 1 + - arch/arm64/boot/dts/mediatek/mt8183-kukui-krane-sku176.dts | 1 + - arch/arm64/boot/dts/mediatek/mt8186-evb.dts | 1 + - 28 files changed, 28 insertions(+) - ---- a/arch/arm64/boot/dts/mediatek/mt2712-evb.dts -+++ b/arch/arm64/boot/dts/mediatek/mt2712-evb.dts -@@ -11,6 +11,7 @@ - - / { - model = "MediaTek MT2712 evaluation board"; -+ chassis-type = "embedded"; - compatible = "mediatek,mt2712-evb", "mediatek,mt2712"; - - aliases { ---- a/arch/arm64/boot/dts/mediatek/mt6755-evb.dts -+++ b/arch/arm64/boot/dts/mediatek/mt6755-evb.dts -@@ -9,6 +9,7 @@ - - / { - model = "MediaTek MT6755 EVB"; -+ chassis-type = "embedded"; - compatible = "mediatek,mt6755-evb", "mediatek,mt6755"; - - aliases { ---- a/arch/arm64/boot/dts/mediatek/mt6779-evb.dts -+++ b/arch/arm64/boot/dts/mediatek/mt6779-evb.dts -@@ -10,6 +10,7 @@ - - / { - model = "MediaTek MT6779 EVB"; -+ chassis-type = "embedded"; - compatible = "mediatek,mt6779-evb", "mediatek,mt6779"; - - aliases { ---- a/arch/arm64/boot/dts/mediatek/mt6795-evb.dts -+++ b/arch/arm64/boot/dts/mediatek/mt6795-evb.dts -@@ -9,6 +9,7 @@ - - / { - model = "MediaTek MT6795 Evaluation Board"; -+ chassis-type = "embedded"; - compatible = "mediatek,mt6795-evb", "mediatek,mt6795"; - - aliases { ---- a/arch/arm64/boot/dts/mediatek/mt6797-evb.dts -+++ b/arch/arm64/boot/dts/mediatek/mt6797-evb.dts -@@ -9,6 +9,7 @@ - - / { - model = "MediaTek MT6797 Evaluation Board"; -+ chassis-type = "embedded"; - compatible = "mediatek,mt6797-evb", "mediatek,mt6797"; - - aliases { ---- a/arch/arm64/boot/dts/mediatek/mt6797-x20-dev.dts -+++ b/arch/arm64/boot/dts/mediatek/mt6797-x20-dev.dts -@@ -12,6 +12,7 @@ - - / { - model = "Mediatek X20 Development Board"; -+ chassis-type = "embedded"; - compatible = "archermind,mt6797-x20-dev", "mediatek,mt6797"; - - aliases { ---- a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts -@@ -15,6 +15,7 @@ - - / { - model = "Bananapi BPI-R64"; -+ chassis-type = "embedded"; - compatible = "bananapi,bpi-r64", "mediatek,mt7622"; - - aliases { ---- a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts -@@ -15,6 +15,7 @@ - - / { - model = "MediaTek MT7622 RFB1 board"; -+ chassis-type = "embedded"; - compatible = "mediatek,mt7622-rfb1", "mediatek,mt7622"; - - aliases { ---- a/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts -@@ -16,6 +16,7 @@ - - / { - model = "Bananapi BPI-R3"; -+ chassis-type = "embedded"; - compatible = "bananapi,bpi-r3", "mediatek,mt7986a"; - - aliases { ---- a/arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts -@@ -11,6 +11,7 @@ - - / { - model = "MediaTek MT7986a RFB"; -+ chassis-type = "embedded"; - compatible = "mediatek,mt7986a-rfb", "mediatek,mt7986a"; - - aliases { ---- a/arch/arm64/boot/dts/mediatek/mt7986b-rfb.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7986b-rfb.dts -@@ -9,6 +9,7 @@ - - / { - model = "MediaTek MT7986b RFB"; -+ chassis-type = "embedded"; - compatible = "mediatek,mt7986b-rfb", "mediatek,mt7986b"; - - aliases { ---- a/arch/arm64/boot/dts/mediatek/mt8167-pumpkin.dts -+++ b/arch/arm64/boot/dts/mediatek/mt8167-pumpkin.dts -@@ -11,6 +11,7 @@ - - / { - model = "Pumpkin MT8167"; -+ chassis-type = "embedded"; - compatible = "mediatek,mt8167-pumpkin", "mediatek,mt8167"; - - memory@40000000 { ---- a/arch/arm64/boot/dts/mediatek/mt8173-elm-hana-rev7.dts -+++ b/arch/arm64/boot/dts/mediatek/mt8173-elm-hana-rev7.dts -@@ -8,6 +8,7 @@ - - / { - model = "Google Hanawl"; -+ chassis-type = "laptop"; - compatible = "google,hana-rev7", "mediatek,mt8173"; - }; - ---- a/arch/arm64/boot/dts/mediatek/mt8173-elm-hana.dts -+++ b/arch/arm64/boot/dts/mediatek/mt8173-elm-hana.dts -@@ -8,6 +8,7 @@ - - / { - model = "Google Hana"; -+ chassis-type = "laptop"; - compatible = "google,hana-rev6", "google,hana-rev5", - "google,hana-rev4", "google,hana-rev3", - "google,hana", "mediatek,mt8173"; ---- a/arch/arm64/boot/dts/mediatek/mt8173-elm.dts -+++ b/arch/arm64/boot/dts/mediatek/mt8173-elm.dts -@@ -8,6 +8,7 @@ - - / { - model = "Google Elm"; -+ chassis-type = "laptop"; - compatible = "google,elm-rev8", "google,elm-rev7", "google,elm-rev6", - "google,elm-rev5", "google,elm-rev4", "google,elm-rev3", - "google,elm", "mediatek,mt8173"; ---- a/arch/arm64/boot/dts/mediatek/mt8173-evb.dts -+++ b/arch/arm64/boot/dts/mediatek/mt8173-evb.dts -@@ -10,6 +10,7 @@ - - / { - model = "MediaTek MT8173 evaluation board"; -+ chassis-type = "embedded"; - compatible = "mediatek,mt8173-evb", "mediatek,mt8173"; - - aliases { ---- a/arch/arm64/boot/dts/mediatek/mt8183-evb.dts -+++ b/arch/arm64/boot/dts/mediatek/mt8183-evb.dts -@@ -11,6 +11,7 @@ - - / { - model = "MediaTek MT8183 evaluation board"; -+ chassis-type = "embedded"; - compatible = "mediatek,mt8183-evb", "mediatek,mt8183"; - - aliases { ---- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-burnet.dts -+++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-burnet.dts -@@ -9,6 +9,7 @@ - - / { - model = "Google burnet board"; -+ chassis-type = "convertible"; - compatible = "google,burnet", "mediatek,mt8183"; - }; - ---- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-damu.dts -+++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-damu.dts -@@ -9,6 +9,7 @@ - - / { - model = "Google damu board"; -+ chassis-type = "convertible"; - compatible = "google,damu", "mediatek,mt8183"; - }; - ---- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-juniper-sku16.dts -+++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-juniper-sku16.dts -@@ -9,6 +9,7 @@ - - / { - model = "Google juniper sku16 board"; -+ chassis-type = "convertible"; - compatible = "google,juniper-sku16", "google,juniper", "mediatek,mt8183"; - }; - ---- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-kakadu-sku22.dts -+++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-kakadu-sku22.dts -@@ -9,6 +9,7 @@ - - / { - model = "MediaTek kakadu board sku22"; -+ chassis-type = "tablet"; - compatible = "google,kakadu-rev3-sku22", "google,kakadu-rev2-sku22", - "google,kakadu", "mediatek,mt8183"; - }; ---- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-kakadu.dts -+++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-kakadu.dts -@@ -9,6 +9,7 @@ - - / { - model = "MediaTek kakadu board"; -+ chassis-type = "tablet"; - compatible = "google,kakadu-rev3", "google,kakadu-rev2", - "google,kakadu", "mediatek,mt8183"; - }; ---- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama-sku16.dts -+++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama-sku16.dts -@@ -12,6 +12,7 @@ - - / { - model = "MediaTek kodama sku16 board"; -+ chassis-type = "tablet"; - compatible = "google,kodama-sku16", "google,kodama", "mediatek,mt8183"; - }; - ---- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama-sku272.dts -+++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama-sku272.dts -@@ -12,6 +12,7 @@ - - / { - model = "MediaTek kodama sku272 board"; -+ chassis-type = "tablet"; - compatible = "google,kodama-sku272", "google,kodama", "mediatek,mt8183"; - }; - ---- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama-sku288.dts -+++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama-sku288.dts -@@ -12,6 +12,7 @@ - - / { - model = "MediaTek kodama sku288 board"; -+ chassis-type = "tablet"; - compatible = "google,kodama-sku288", "google,kodama", "mediatek,mt8183"; - }; - ---- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-krane-sku0.dts -+++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-krane-sku0.dts -@@ -14,6 +14,7 @@ - - / { - model = "MediaTek krane sku0 board"; -+ chassis-type = "tablet"; - compatible = "google,krane-sku0", "google,krane", "mediatek,mt8183"; - }; - ---- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-krane-sku176.dts -+++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-krane-sku176.dts -@@ -14,6 +14,7 @@ - - / { - model = "MediaTek krane sku176 board"; -+ chassis-type = "tablet"; - compatible = "google,krane-sku176", "google,krane", "mediatek,mt8183"; - }; - ---- a/arch/arm64/boot/dts/mediatek/mt8186-evb.dts -+++ b/arch/arm64/boot/dts/mediatek/mt8186-evb.dts -@@ -7,6 +7,7 @@ - - / { - model = "MediaTek MT8186 evaluation board"; -+ chassis-type = "embedded"; - compatible = "mediatek,mt8186-evb", "mediatek,mt8186"; - - aliases { diff --git a/target/linux/mediatek/patches-6.1/012-v6.5-arm64-dts-mt7986-add-PWM.patch b/target/linux/mediatek/patches-6.1/012-v6.5-arm64-dts-mt7986-add-PWM.patch deleted file mode 100644 index 915da7984..000000000 --- a/target/linux/mediatek/patches-6.1/012-v6.5-arm64-dts-mt7986-add-PWM.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 3b92c547e3d4a35c6214b3e7fa1103d0749d83b1 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Fri, 21 Apr 2023 15:20:44 +0200 -Subject: [PATCH 12/19] arm64: dts: mt7986: add PWM - -This adds pwm node to mt7986. - -Signed-off-by: Daniel Golle -Signed-off-by: Frank Wunderlich -Link: https://lore.kernel.org/r/20230421132047.42166-5-linux@fw-web.de -Signed-off-by: Matthias Brugger ---- - arch/arm64/boot/dts/mediatek/mt7986a.dtsi | 14 ++++++++++++++ - 1 file changed, 14 insertions(+) - ---- a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi -+++ b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi -@@ -241,6 +241,20 @@ - status = "disabled"; - }; - -+ pwm: pwm@10048000 { -+ compatible = "mediatek,mt7986-pwm"; -+ reg = <0 0x10048000 0 0x1000>; -+ #clock-cells = <1>; -+ #pwm-cells = <2>; -+ interrupts = ; -+ clocks = <&topckgen CLK_TOP_PWM_SEL>, -+ <&infracfg CLK_INFRA_PWM_STA>, -+ <&infracfg CLK_INFRA_PWM1_CK>, -+ <&infracfg CLK_INFRA_PWM2_CK>; -+ clock-names = "top", "main", "pwm1", "pwm2"; -+ status = "disabled"; -+ }; -+ - uart0: serial@11002000 { - compatible = "mediatek,mt7986-uart", - "mediatek,mt6577-uart"; diff --git a/target/linux/mediatek/patches-6.1/013-v6.5-arm64-dts-mt7986-add-PWM-to-BPI-R3.patch b/target/linux/mediatek/patches-6.1/013-v6.5-arm64-dts-mt7986-add-PWM-to-BPI-R3.patch deleted file mode 100644 index ce908e3d3..000000000 --- a/target/linux/mediatek/patches-6.1/013-v6.5-arm64-dts-mt7986-add-PWM-to-BPI-R3.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 35e482bb599df010b4869017ff576dbb7a4d4c2e Mon Sep 17 00:00:00 2001 -From: Frank Wunderlich -Date: Fri, 21 Apr 2023 15:20:45 +0200 -Subject: [PATCH 13/19] arm64: dts: mt7986: add PWM to BPI-R3 - -Add pwm node and pinctrl to BananaPi R3 devicetree. - -Signed-off-by: Frank Wunderlich -Link: https://lore.kernel.org/r/20230421132047.42166-6-linux@fw-web.de -Signed-off-by: Matthias Brugger ---- - .../boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts | 13 +++++++++++++ - 1 file changed, 13 insertions(+) - ---- a/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts -@@ -275,6 +275,13 @@ - }; - }; - -+ pwm_pins: pwm-pins { -+ mux { -+ function = "pwm"; -+ groups = "pwm0", "pwm1_0"; -+ }; -+ }; -+ - spi_flash_pins: spi-flash-pins { - mux { - function = "spi"; -@@ -345,6 +352,12 @@ - }; - }; - -+&pwm { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pwm_pins>; -+ status = "okay"; -+}; -+ - &spi0 { - pinctrl-names = "default"; - pinctrl-0 = <&spi_flash_pins>; diff --git a/target/linux/mediatek/patches-6.1/014-v6.5-arm64-dts-mt7986-set-Wifi-Leds-low-active-for-BPI-R3.patch b/target/linux/mediatek/patches-6.1/014-v6.5-arm64-dts-mt7986-set-Wifi-Leds-low-active-for-BPI-R3.patch deleted file mode 100644 index c7b38484f..000000000 --- a/target/linux/mediatek/patches-6.1/014-v6.5-arm64-dts-mt7986-set-Wifi-Leds-low-active-for-BPI-R3.patch +++ /dev/null @@ -1,27 +0,0 @@ -From ccdda5714446db8690505371442f7807f5d7c6fc Mon Sep 17 00:00:00 2001 -From: Frank Wunderlich -Date: Sun, 5 Feb 2023 18:48:33 +0100 -Subject: [PATCH 14/19] arm64: dts: mt7986: set Wifi Leds low-active for BPI-R3 - -Leds for Wifi are low-active, so add property to devicetree. - -Signed-off-by: Frank Wunderlich -Reviewed-by: AngeloGioacchino Del Regno -Link: https://lore.kernel.org/r/20230205174833.107050-1-linux@fw-web.de -Signed-off-by: Matthias Brugger ---- - arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts | 4 ++++ - 1 file changed, 4 insertions(+) - ---- a/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts -@@ -460,5 +460,9 @@ - pinctrl-names = "default", "dbdc"; - pinctrl-0 = <&wf_2g_5g_pins>, <&wf_led_pins>; - pinctrl-1 = <&wf_dbdc_pins>, <&wf_led_pins>; -+ -+ led { -+ led-active-low; -+ }; - }; - diff --git a/target/linux/mediatek/patches-6.1/015-v6.5-arm64-dts-mt7986-use-size-of-reserved-partition-for-.patch b/target/linux/mediatek/patches-6.1/015-v6.5-arm64-dts-mt7986-use-size-of-reserved-partition-for-.patch deleted file mode 100644 index 0b84f1463..000000000 --- a/target/linux/mediatek/patches-6.1/015-v6.5-arm64-dts-mt7986-use-size-of-reserved-partition-for-.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 1423b4b780adcf3994e63a5988a62d5d1d509bb1 Mon Sep 17 00:00:00 2001 -From: Frank Wunderlich -Date: Sun, 28 May 2023 13:33:42 +0200 -Subject: [PATCH 15/19] arm64: dts: mt7986: use size of reserved partition for - bl2 - -To store uncompressed bl2 more space is required than partition is -actually defined. - -There is currently no known usage of this reserved partition. -Openwrt uses same partition layout. - -We added same change to u-boot with commit d7bb1099 [1]. - -[1] https://source.denx.de/u-boot/u-boot/-/commit/d7bb109900c1ca754a0198b9afb50e3161ffc21e - -Cc: stable@vger.kernel.org -Fixes: 8e01fb15b815 ("arm64: dts: mt7986: add Bananapi R3") -Signed-off-by: Frank Wunderlich -Reviewed-by: AngeloGioacchino Del Regno -Reviewed-by: Daniel Golle -Link: https://lore.kernel.org/r/20230528113343.7649-1-linux@fw-web.de -Signed-off-by: Matthias Brugger ---- - .../boot/dts/mediatek/mt7986a-bananapi-bpi-r3-nor.dtso | 7 +------ - 1 file changed, 1 insertion(+), 6 deletions(-) - ---- a/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-nor.dtso -+++ b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-nor.dtso -@@ -27,15 +27,10 @@ - - partition@0 { - label = "bl2"; -- reg = <0x0 0x20000>; -+ reg = <0x0 0x40000>; - read-only; - }; - -- partition@20000 { -- label = "reserved"; -- reg = <0x20000 0x20000>; -- }; -- - partition@40000 { - label = "u-boot-env"; - reg = <0x40000 0x40000>; diff --git a/target/linux/mediatek/patches-6.1/016-v6.5-arm64-dts-mt7986-add-thermal-and-efuse.patch b/target/linux/mediatek/patches-6.1/016-v6.5-arm64-dts-mt7986-add-thermal-and-efuse.patch deleted file mode 100644 index f1cb0eaf0..000000000 --- a/target/linux/mediatek/patches-6.1/016-v6.5-arm64-dts-mt7986-add-thermal-and-efuse.patch +++ /dev/null @@ -1,80 +0,0 @@ -From 40a5a767d698ef7a71f8be851ea18b0a7a8b47bd Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Tue, 30 May 2023 22:12:33 +0200 -Subject: [PATCH 16/19] arm64: dts: mt7986: add thermal and efuse - -Add thermal related nodes to mt7986 devicetree. - -Signed-off-by: Daniel Golle -Signed-off-by: Frank Wunderlich -Reviewed-by: AngeloGioacchino Del Regno -Link: https://lore.kernel.org/r/20230530201235.22330-3-linux@fw-web.de -Signed-off-by: Matthias Brugger ---- - arch/arm64/boot/dts/mediatek/mt7986a.dtsi | 36 ++++++++++++++++++++++- - 1 file changed, 35 insertions(+), 1 deletion(-) - ---- a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi -+++ b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi -@@ -338,6 +338,15 @@ - status = "disabled"; - }; - -+ auxadc: adc@1100d000 { -+ compatible = "mediatek,mt7986-auxadc"; -+ reg = <0 0x1100d000 0 0x1000>; -+ clocks = <&infracfg CLK_INFRA_ADC_26M_CK>; -+ clock-names = "main"; -+ #io-channel-cells = <1>; -+ status = "disabled"; -+ }; -+ - ssusb: usb@11200000 { - compatible = "mediatek,mt7986-xhci", - "mediatek,mtk-xhci"; -@@ -376,6 +385,21 @@ - status = "disabled"; - }; - -+ thermal: thermal@1100c800 { -+ #thermal-sensor-cells = <1>; -+ compatible = "mediatek,mt7986-thermal"; -+ reg = <0 0x1100c800 0 0x800>; -+ interrupts = ; -+ clocks = <&infracfg CLK_INFRA_THERM_CK>, -+ <&infracfg CLK_INFRA_ADC_26M_CK>, -+ <&infracfg CLK_INFRA_ADC_FRC_CK>; -+ clock-names = "therm", "auxadc", "adc_32k"; -+ mediatek,auxadc = <&auxadc>; -+ mediatek,apmixedsys = <&apmixedsys>; -+ nvmem-cells = <&thermal_calibration>; -+ nvmem-cell-names = "calibration-data"; -+ }; -+ - pcie: pcie@11280000 { - compatible = "mediatek,mt7986-pcie", - "mediatek,mt8192-pcie"; -@@ -427,6 +451,17 @@ - }; - }; - -+ efuse: efuse@11d00000 { -+ compatible = "mediatek,mt7986-efuse", "mediatek,efuse"; -+ reg = <0 0x11d00000 0 0x1000>; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ thermal_calibration: calib@274 { -+ reg = <0x274 0xc>; -+ }; -+ }; -+ - usb_phy: t-phy@11e10000 { - compatible = "mediatek,mt7986-tphy", - "mediatek,generic-tphy-v2"; -@@ -568,5 +603,4 @@ - memory-region = <&wmcpu_emi>; - }; - }; -- - }; diff --git a/target/linux/mediatek/patches-6.1/017-v6.5-arm64-dts-mt7986-add-thermal-zones.patch b/target/linux/mediatek/patches-6.1/017-v6.5-arm64-dts-mt7986-add-thermal-zones.patch deleted file mode 100644 index ad21fb8c3..000000000 --- a/target/linux/mediatek/patches-6.1/017-v6.5-arm64-dts-mt7986-add-thermal-zones.patch +++ /dev/null @@ -1,51 +0,0 @@ -From bb78d0cf5117517f1ed296ae71048945d9107675 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Tue, 30 May 2023 22:12:34 +0200 -Subject: [PATCH 17/19] arm64: dts: mt7986: add thermal-zones - -Add thermal-zones to mt7986 devicetree. - -Signed-off-by: Daniel Golle -Signed-off-by: Frank Wunderlich -Reviewed-by: AngeloGioacchino Del Regno -Link: https://lore.kernel.org/r/20230530201235.22330-4-linux@fw-web.de -Signed-off-by: Matthias Brugger ---- - arch/arm64/boot/dts/mediatek/mt7986a.dtsi | 28 +++++++++++++++++++++++ - 1 file changed, 28 insertions(+) - ---- a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi -+++ b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi -@@ -603,4 +603,32 @@ - memory-region = <&wmcpu_emi>; - }; - }; -+ -+ thermal-zones { -+ cpu_thermal: cpu-thermal { -+ polling-delay-passive = <1000>; -+ polling-delay = <1000>; -+ thermal-sensors = <&thermal 0>; -+ -+ trips { -+ cpu_trip_active_high: active-high { -+ temperature = <115000>; -+ hysteresis = <2000>; -+ type = "active"; -+ }; -+ -+ cpu_trip_active_low: active-low { -+ temperature = <85000>; -+ hysteresis = <2000>; -+ type = "active"; -+ }; -+ -+ cpu_trip_passive: passive { -+ temperature = <40000>; -+ hysteresis = <2000>; -+ type = "passive"; -+ }; -+ }; -+ }; -+ }; - }; diff --git a/target/linux/mediatek/patches-6.1/018-v6.5-arm64-dts-mt7986-add-pwm-fan-and-cooling-maps-to-BPI.patch b/target/linux/mediatek/patches-6.1/018-v6.5-arm64-dts-mt7986-add-pwm-fan-and-cooling-maps-to-BPI.patch deleted file mode 100644 index ca7d872a1..000000000 --- a/target/linux/mediatek/patches-6.1/018-v6.5-arm64-dts-mt7986-add-pwm-fan-and-cooling-maps-to-BPI.patch +++ /dev/null @@ -1,64 +0,0 @@ -From 5d90603b09e5814ffc38c47e79ccf9bc564f9296 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Tue, 30 May 2023 22:12:35 +0200 -Subject: [PATCH 18/19] arm64: dts: mt7986: add pwm-fan and cooling-maps to - BPI-R3 dts - -Add pwm-fan and cooling-maps to BananaPi-R3 devicetree. - -Signed-off-by: Daniel Golle -Signed-off-by: Frank Wunderlich -Reviewed-by: AngeloGioacchino Del Regno -Link: https://lore.kernel.org/r/20230530201235.22330-5-linux@fw-web.de -Signed-off-by: Matthias Brugger ---- - .../dts/mediatek/mt7986a-bananapi-bpi-r3.dts | 31 +++++++++++++++++++ - 1 file changed, 31 insertions(+) - ---- a/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts -@@ -38,6 +38,15 @@ - regulator-always-on; - }; - -+ fan: pwm-fan { -+ compatible = "pwm-fan"; -+ #cooling-cells = <2>; -+ /* cooling level (0, 1, 2) - pwm inverted */ -+ cooling-levels = <255 96 0>; -+ pwms = <&pwm 0 10000 0>; -+ status = "okay"; -+ }; -+ - gpio-keys { - compatible = "gpio-keys"; - -@@ -133,6 +142,28 @@ - }; - }; - -+&cpu_thermal { -+ cooling-maps { -+ cpu-active-high { -+ /* active: set fan to cooling level 2 */ -+ cooling-device = <&fan 2 2>; -+ trip = <&cpu_trip_active_high>; -+ }; -+ -+ cpu-active-low { -+ /* active: set fan to cooling level 1 */ -+ cooling-device = <&fan 1 1>; -+ trip = <&cpu_trip_active_low>; -+ }; -+ -+ cpu-passive { -+ /* passive: set fan to cooling level 0 */ -+ cooling-device = <&fan 0 0>; -+ trip = <&cpu_trip_passive>; -+ }; -+ }; -+}; -+ - &crypto { - status = "okay"; - }; diff --git a/target/linux/mediatek/patches-6.1/019-v6.5-arm64-dts-mt7986-increase-bl2-partition-on-NAND-of-B.patch b/target/linux/mediatek/patches-6.1/019-v6.5-arm64-dts-mt7986-increase-bl2-partition-on-NAND-of-B.patch deleted file mode 100644 index 9cc6cad0a..000000000 --- a/target/linux/mediatek/patches-6.1/019-v6.5-arm64-dts-mt7986-increase-bl2-partition-on-NAND-of-B.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 6dd3b939370094eb79529683be84500f3c757404 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Tue, 6 Jun 2023 16:43:20 +0100 -Subject: [PATCH 19/19] arm64: dts: mt7986: increase bl2 partition on NAND of - Bananapi R3 - -The bootrom burned into the MT7986 SoC will try multiple locations on -the SPI-NAND flash to load bl2 in case the bl2 image located at the the -previously attempted offset is corrupt. - -Use 0x100000 instead of 0x80000 as partition size for bl2 on SPI-NAND, -allowing for up to four redundant copies of bl2 (typically sized a -bit less than 0x40000). - -Fixes: 8e01fb15b8157 ("arm64: dts: mt7986: add Bananapi R3") -Signed-off-by: Daniel Golle -Link: https://lore.kernel.org/r/ZH9UGF99RgzrHZ88@makrotopia.org -Signed-off-by: Matthias Brugger ---- - .../boot/dts/mediatek/mt7986a-bananapi-bpi-r3-nand.dtso | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - ---- a/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-nand.dtso -+++ b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-nand.dtso -@@ -29,13 +29,13 @@ - - partition@0 { - label = "bl2"; -- reg = <0x0 0x80000>; -+ reg = <0x0 0x100000>; - read-only; - }; - -- partition@80000 { -+ partition@100000 { - label = "reserved"; -- reg = <0x80000 0x300000>; -+ reg = <0x100000 0x280000>; - }; - - partition@380000 { diff --git a/target/linux/mediatek/patches-6.1/020-arm64-dts-mt7986-define-3W-max-power-to-both-SFP-on-.patch b/target/linux/mediatek/patches-6.1/020-arm64-dts-mt7986-define-3W-max-power-to-both-SFP-on-.patch deleted file mode 100644 index 8cba3b205..000000000 --- a/target/linux/mediatek/patches-6.1/020-arm64-dts-mt7986-define-3W-max-power-to-both-SFP-on-.patch +++ /dev/null @@ -1,34 +0,0 @@ -From f8ed4088ed9c61ae92193da6130d04c37e7b19f2 Mon Sep 17 00:00:00 2001 -From: Frank Wunderlich -Date: Sun, 20 Aug 2023 17:31:33 +0200 -Subject: [PATCH 20/22] arm64: dts: mt7986: define 3W max power to both SFP on - BPI-R3 - -All SFP power supplies are connected to the system VDD33 which is 3v3/8A. -Set 3A per SFP slot to allow SFPs work which need more power than the -default 1W. - -Fixes: 8e01fb15b815 ("arm64: dts: mt7986: add Bananapi R3") -Signed-off-by: Frank Wunderlich ---- - arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts | 2 ++ - 1 file changed, 2 insertions(+) - ---- a/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts -@@ -126,6 +126,7 @@ - compatible = "sff,sfp"; - i2c-bus = <&i2c_sfp1>; - los-gpios = <&pio 46 GPIO_ACTIVE_HIGH>; -+ maximum-power-milliwatt = <3000>; - mod-def0-gpios = <&pio 49 GPIO_ACTIVE_LOW>; - tx-disable-gpios = <&pio 20 GPIO_ACTIVE_HIGH>; - tx-fault-gpios = <&pio 7 GPIO_ACTIVE_HIGH>; -@@ -137,6 +138,7 @@ - i2c-bus = <&i2c_sfp2>; - los-gpios = <&pio 31 GPIO_ACTIVE_HIGH>; - mod-def0-gpios = <&pio 47 GPIO_ACTIVE_LOW>; -+ maximum-power-milliwatt = <3000>; - tx-disable-gpios = <&pio 15 GPIO_ACTIVE_HIGH>; - tx-fault-gpios = <&pio 48 GPIO_ACTIVE_HIGH>; - }; diff --git a/target/linux/mediatek/patches-6.1/021-arm64-dts-mt7986-change-cooling-trips.patch b/target/linux/mediatek/patches-6.1/021-arm64-dts-mt7986-change-cooling-trips.patch deleted file mode 100644 index 318ca43e1..000000000 --- a/target/linux/mediatek/patches-6.1/021-arm64-dts-mt7986-change-cooling-trips.patch +++ /dev/null @@ -1,59 +0,0 @@ -From aa3d6df9803c267725dc72286bb91602b7579882 Mon Sep 17 00:00:00 2001 -From: Frank Wunderlich -Date: Sun, 20 Aug 2023 17:31:34 +0200 -Subject: [PATCH 21/22] arm64: dts: mt7986: change cooling trips - -Add Critical and hot trips for emergency system shutdown and limiting -system load. - -Change passive trip to active to make sure fan is activated on the -lowest trip. - -Fixes: 1f5be05132f3 ("arm64: dts: mt7986: add thermal-zones") -Suggested-by: Daniel Golle -Signed-off-by: Frank Wunderlich ---- - arch/arm64/boot/dts/mediatek/mt7986a.dtsi | 20 ++++++++++++++++---- - 1 file changed, 16 insertions(+), 4 deletions(-) - ---- a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi -+++ b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi -@@ -611,22 +611,34 @@ - thermal-sensors = <&thermal 0>; - - trips { -+ cpu_trip_crit: crit { -+ temperature = <125000>; -+ hysteresis = <2000>; -+ type = "critical"; -+ }; -+ -+ cpu_trip_hot: hot { -+ temperature = <120000>; -+ hysteresis = <2000>; -+ type = "hot"; -+ }; -+ - cpu_trip_active_high: active-high { - temperature = <115000>; - hysteresis = <2000>; - type = "active"; - }; - -- cpu_trip_active_low: active-low { -+ cpu_trip_active_med: active-med { - temperature = <85000>; - hysteresis = <2000>; - type = "active"; - }; - -- cpu_trip_passive: passive { -- temperature = <40000>; -+ cpu_trip_active_low: active-low { -+ temperature = <60000>; - hysteresis = <2000>; -- type = "passive"; -+ type = "active"; - }; - }; - }; diff --git a/target/linux/mediatek/patches-6.1/022-arm64-dts-mt7986-change-thermal-trips-on-BPI-R3.patch b/target/linux/mediatek/patches-6.1/022-arm64-dts-mt7986-change-thermal-trips-on-BPI-R3.patch deleted file mode 100644 index 7166ab6a1..000000000 --- a/target/linux/mediatek/patches-6.1/022-arm64-dts-mt7986-change-thermal-trips-on-BPI-R3.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 6ddf23526955b8dbedfeaa57e691261fd73f9d4e Mon Sep 17 00:00:00 2001 -From: Frank Wunderlich -Date: Sun, 20 Aug 2023 17:31:35 +0200 -Subject: [PATCH 22/22] arm64: dts: mt7986: change thermal trips on BPI-R3 - -Apply new naming after mt7986 thermal trips were changed. - -Fixes: c26f779a2295 ("arm64: dts: mt7986: add pwm-fan and cooling-maps to BPI-R3 dts") -Suggested-by: Daniel Golle -Signed-off-by: Frank Wunderlich ---- - .../boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts | 10 +++++----- - 1 file changed, 5 insertions(+), 5 deletions(-) - ---- a/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts -@@ -152,16 +152,16 @@ - trip = <&cpu_trip_active_high>; - }; - -- cpu-active-low { -+ cpu-active-med { - /* active: set fan to cooling level 1 */ - cooling-device = <&fan 1 1>; -- trip = <&cpu_trip_active_low>; -+ trip = <&cpu_trip_active_med>; - }; - -- cpu-passive { -- /* passive: set fan to cooling level 0 */ -+ cpu-active-low { -+ /* active: set fan to cooling level 0 */ - cooling-device = <&fan 0 0>; -- trip = <&cpu_trip_passive>; -+ trip = <&cpu_trip_active_low>; - }; - }; - }; diff --git a/target/linux/mediatek/patches-6.1/100-dts-update-mt7622-rfb1.patch b/target/linux/mediatek/patches-6.1/100-dts-update-mt7622-rfb1.patch deleted file mode 100644 index 1eeed82c1..000000000 --- a/target/linux/mediatek/patches-6.1/100-dts-update-mt7622-rfb1.patch +++ /dev/null @@ -1,107 +0,0 @@ ---- a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts -@@ -1,7 +1,6 @@ - /* -- * Copyright (c) 2017 MediaTek Inc. -- * Author: Ming Huang -- * Sean Wang -+ * Copyright (c) 2018 MediaTek Inc. -+ * Author: Ryder Lee - * - * SPDX-License-Identifier: (GPL-2.0 OR MIT) - */ -@@ -24,7 +23,7 @@ - - chosen { - stdout-path = "serial0:115200n8"; -- bootargs = "earlycon=uart8250,mmio32,0x11002000 swiotlb=512"; -+ bootargs = "earlycon=uart8250,mmio32,0x11002000 console=ttyS0,115200n1 swiotlb=512"; - }; - - cpus { -@@ -45,18 +44,18 @@ - key-factory { - label = "factory"; - linux,code = ; -- gpios = <&pio 0 0>; -+ gpios = <&pio 0 GPIO_ACTIVE_LOW>; - }; - - key-wps { - label = "wps"; - linux,code = ; -- gpios = <&pio 102 0>; -+ gpios = <&pio 102 GPIO_ACTIVE_LOW>; - }; - }; - - memory@40000000 { -- reg = <0 0x40000000 0 0x20000000>; -+ reg = <0 0x40000000 0 0x40000000>; - device_type = "memory"; - }; - -@@ -133,22 +132,22 @@ - - port@0 { - reg = <0>; -- label = "lan0"; -+ label = "lan1"; - }; - - port@1 { - reg = <1>; -- label = "lan1"; -+ label = "lan2"; - }; - - port@2 { - reg = <2>; -- label = "lan2"; -+ label = "lan3"; - }; - - port@3 { - reg = <3>; -- label = "lan3"; -+ label = "lan4"; - }; - - port@4 { -@@ -241,7 +240,22 @@ - status = "okay"; - }; - -+&pcie1 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pcie1_pins>; -+ status = "okay"; -+}; -+ - &pio { -+ /* Attention: GPIO 90 is used to switch between PCIe@1,0 and -+ * SATA functions. i.e. output-high: PCIe, output-low: SATA -+ */ -+ asm_sel { -+ gpio-hog; -+ gpios = <90 GPIO_ACTIVE_HIGH>; -+ output-high; -+ }; -+ - /* eMMC is shared pin with parallel NAND */ - emmc_pins_default: emmc-pins-default { - mux { -@@ -518,11 +532,11 @@ - }; - - &sata { -- status = "okay"; -+ status = "disabled"; - }; - - &sata_phy { -- status = "okay"; -+ status = "disabled"; - }; - - &spi0 { diff --git a/target/linux/mediatek/patches-6.1/101-dts-update-mt7629-rfb.patch b/target/linux/mediatek/patches-6.1/101-dts-update-mt7629-rfb.patch deleted file mode 100644 index b1770371b..000000000 --- a/target/linux/mediatek/patches-6.1/101-dts-update-mt7629-rfb.patch +++ /dev/null @@ -1,60 +0,0 @@ ---- a/arch/arm/boot/dts/mt7629-rfb.dts -+++ b/arch/arm/boot/dts/mt7629-rfb.dts -@@ -18,6 +18,7 @@ - - chosen { - stdout-path = "serial0:115200n8"; -+ bootargs = "earlycon=uart8250,mmio32,0x11002000 console=ttyS0,115200n8"; - }; - - gpio-keys { -@@ -70,6 +71,10 @@ - compatible = "mediatek,eth-mac"; - reg = <0>; - phy-mode = "2500base-x"; -+ -+ nvmem-cells = <&macaddr_factory_2a>; -+ nvmem-cell-names = "mac-address"; -+ - fixed-link { - speed = <2500>; - full-duplex; -@@ -82,6 +87,9 @@ - reg = <1>; - phy-mode = "gmii"; - phy-handle = <&phy0>; -+ -+ nvmem-cells = <&macaddr_factory_24>; -+ nvmem-cell-names = "mac-address"; - }; - - mdio: mdio-bus { -@@ -133,8 +141,9 @@ - }; - - partition@b0000 { -- label = "kernel"; -+ label = "firmware"; - reg = <0xb0000 0xb50000>; -+ compatible = "denx,fit"; - }; - }; - }; -@@ -273,3 +282,17 @@ - pinctrl-0 = <&watchdog_pins>; - status = "okay"; - }; -+ -+&factory { -+ compatible = "nvmem-cells"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ macaddr_factory_24: macaddr@24 { -+ reg = <0x24 0x6>; -+ }; -+ -+ macaddr_factory_2a: macaddr@2a { -+ reg = <0x2a 0x6>; -+ }; -+}; diff --git a/target/linux/mediatek/patches-6.1/103-mt7623-enable-arch-timer.patch b/target/linux/mediatek/patches-6.1/103-mt7623-enable-arch-timer.patch deleted file mode 100644 index 04df7b927..000000000 --- a/target/linux/mediatek/patches-6.1/103-mt7623-enable-arch-timer.patch +++ /dev/null @@ -1,20 +0,0 @@ -From d6a596012150960f0f3a214d31bbac4b607dbd1e Mon Sep 17 00:00:00 2001 -From: Chuanhong Guo -Date: Fri, 29 Apr 2022 10:40:56 +0800 -Subject: [PATCH] arm: mediatek: select arch timer for mt7623 - -Signed-off-by: Chuanhong Guo ---- - arch/arm/mach-mediatek/Kconfig | 1 + - 1 file changed, 1 insertion(+) - ---- a/arch/arm/mach-mediatek/Kconfig -+++ b/arch/arm/mach-mediatek/Kconfig -@@ -26,6 +26,7 @@ config MACH_MT6592 - config MACH_MT7623 - bool "MediaTek MT7623 SoCs support" - default ARCH_MEDIATEK -+ select HAVE_ARM_ARCH_TIMER - - config MACH_MT7629 - bool "MediaTek MT7629 SoCs support" diff --git a/target/linux/mediatek/patches-6.1/104-mt7622-add-snor-irq.patch b/target/linux/mediatek/patches-6.1/104-mt7622-add-snor-irq.patch deleted file mode 100644 index d15d989e9..000000000 --- a/target/linux/mediatek/patches-6.1/104-mt7622-add-snor-irq.patch +++ /dev/null @@ -1,10 +0,0 @@ ---- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi -+++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi -@@ -575,6 +575,7 @@ - compatible = "mediatek,mt7622-nor", - "mediatek,mt8173-nor"; - reg = <0 0x11014000 0 0xe0>; -+ interrupts = ; - clocks = <&pericfg CLK_PERI_FLASH_PD>, - <&topckgen CLK_TOP_FLASH_SEL>; - clock-names = "spi", "sf"; diff --git a/target/linux/mediatek/patches-6.1/105-dts-mt7622-enable-pstore.patch b/target/linux/mediatek/patches-6.1/105-dts-mt7622-enable-pstore.patch deleted file mode 100644 index 93da722e7..000000000 --- a/target/linux/mediatek/patches-6.1/105-dts-mt7622-enable-pstore.patch +++ /dev/null @@ -1,16 +0,0 @@ ---- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi -+++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi -@@ -134,6 +134,13 @@ - #size-cells = <2>; - ranges; - -+ /* 64 KiB reserved for ramoops/pstore */ -+ ramoops@42ff0000 { -+ compatible = "ramoops"; -+ reg = <0 0x42ff0000 0 0x10000>; -+ record-size = <0x1000>; -+ }; -+ - /* 192 KiB reserved for ARM Trusted Firmware (BL31) */ - secmon_reserved: secmon@43000000 { - reg = <0 0x43000000 0 0x30000>; diff --git a/target/linux/mediatek/patches-6.1/110-dts-fix-bpi2-console.patch b/target/linux/mediatek/patches-6.1/110-dts-fix-bpi2-console.patch deleted file mode 100644 index 8dc53d298..000000000 --- a/target/linux/mediatek/patches-6.1/110-dts-fix-bpi2-console.patch +++ /dev/null @@ -1,10 +0,0 @@ ---- a/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts -+++ b/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts -@@ -19,6 +19,7 @@ - - chosen { - stdout-path = "serial2:115200n8"; -+ bootargs = "console=ttyS2,115200n8 console=tty1"; - }; - - connector { diff --git a/target/linux/mediatek/patches-6.1/111-dts-fix-bpi64-console.patch b/target/linux/mediatek/patches-6.1/111-dts-fix-bpi64-console.patch deleted file mode 100644 index f77f10cb9..000000000 --- a/target/linux/mediatek/patches-6.1/111-dts-fix-bpi64-console.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts -@@ -24,7 +24,7 @@ - - chosen { - stdout-path = "serial0:115200n8"; -- bootargs = "earlycon=uart8250,mmio32,0x11002000 swiotlb=512"; -+ bootargs = "earlycon=uart8250,mmio32,0x11002000 console=ttyS0,115200n1 swiotlb=512"; - }; - - cpus { diff --git a/target/linux/mediatek/patches-6.1/112-dts-fix-bpi64-lan-names.patch b/target/linux/mediatek/patches-6.1/112-dts-fix-bpi64-lan-names.patch deleted file mode 100644 index 7f97ef4ae..000000000 --- a/target/linux/mediatek/patches-6.1/112-dts-fix-bpi64-lan-names.patch +++ /dev/null @@ -1,37 +0,0 @@ ---- a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts -@@ -20,6 +20,7 @@ - - aliases { - serial0 = &uart0; -+ ethernet0 = &gmac0; - }; - - chosen { -@@ -165,22 +166,22 @@ - - port@1 { - reg = <1>; -- label = "lan0"; -+ label = "lan1"; - }; - - port@2 { - reg = <2>; -- label = "lan1"; -+ label = "lan2"; - }; - - port@3 { - reg = <3>; -- label = "lan2"; -+ label = "lan3"; - }; - - port@4 { - reg = <4>; -- label = "lan3"; -+ label = "lan4"; - }; - - port@6 { diff --git a/target/linux/mediatek/patches-6.1/113-dts-fix-bpi64-leds-and-buttons.patch b/target/linux/mediatek/patches-6.1/113-dts-fix-bpi64-leds-and-buttons.patch deleted file mode 100644 index bf1912a91..000000000 --- a/target/linux/mediatek/patches-6.1/113-dts-fix-bpi64-leds-and-buttons.patch +++ /dev/null @@ -1,47 +0,0 @@ ---- a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts -@@ -21,6 +21,10 @@ - aliases { - serial0 = &uart0; - ethernet0 = &gmac0; -+ led-boot = &led_system_green; -+ led-failsafe = &led_system_blue; -+ led-running = &led_system_green; -+ led-upgrade = &led_system_blue; - }; - - chosen { -@@ -44,8 +48,8 @@ - compatible = "gpio-keys"; - - factory-key { -- label = "factory"; -- linux,code = ; -+ label = "reset"; -+ linux,code = ; - gpios = <&pio 0 GPIO_ACTIVE_HIGH>; - }; - -@@ -59,17 +63,17 @@ - leds { - compatible = "gpio-leds"; - -- led-0 { -+ led_system_green: led-0 { - label = "bpi-r64:pio:green"; - color = ; - gpios = <&pio 89 GPIO_ACTIVE_HIGH>; - default-state = "off"; - }; - -- led-1 { -- label = "bpi-r64:pio:red"; -- color = ; -- gpios = <&pio 88 GPIO_ACTIVE_HIGH>; -+ led_system_blue: led-1 { -+ label = "bpi-r64:pio:blue"; -+ color = ; -+ gpios = <&pio 85 GPIO_ACTIVE_HIGH>; - default-state = "off"; - }; - }; diff --git a/target/linux/mediatek/patches-6.1/114-dts-bpi64-disable-rtc.patch b/target/linux/mediatek/patches-6.1/114-dts-bpi64-disable-rtc.patch deleted file mode 100644 index 261579bf3..000000000 --- a/target/linux/mediatek/patches-6.1/114-dts-bpi64-disable-rtc.patch +++ /dev/null @@ -1,21 +0,0 @@ ---- a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts -@@ -559,12 +559,16 @@ - status = "okay"; - }; - -+&rtc { -+ status = "disabled"; -+}; -+ - &sata { -- status = "disable"; -+ status = "disabled"; - }; - - &sata_phy { -- status = "disable"; -+ status = "disabled"; - }; - - &spi0 { diff --git a/target/linux/mediatek/patches-6.1/115-dts-bpi64-add-snand-support.patch b/target/linux/mediatek/patches-6.1/115-dts-bpi64-add-snand-support.patch deleted file mode 100644 index 20b0d90b2..000000000 --- a/target/linux/mediatek/patches-6.1/115-dts-bpi64-add-snand-support.patch +++ /dev/null @@ -1,50 +0,0 @@ ---- a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts -@@ -256,14 +256,42 @@ - status = "disabled"; - }; - --&nor_flash { -- pinctrl-names = "default"; -- pinctrl-0 = <&spi_nor_pins>; -- status = "disabled"; -+&bch { -+ status = "okay"; -+}; - -+&snfi { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&serial_nand_pins>; -+ status = "okay"; - flash@0 { -- compatible = "jedec,spi-nor"; -+ compatible = "spi-nand"; - reg = <0>; -+ spi-tx-bus-width = <4>; -+ spi-rx-bus-width = <4>; -+ nand-ecc-engine = <&snfi>; -+ partitions { -+ compatible = "fixed-partitions"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ partition@0 { -+ label = "bl2"; -+ reg = <0x0 0x80000>; -+ read-only; -+ }; -+ -+ partition@80000 { -+ label = "fip"; -+ reg = <0x80000 0x200000>; -+ read-only; -+ }; -+ -+ partition@280000 { -+ label = "ubi"; -+ reg = <0x280000 0x7d80000>; -+ }; -+ }; - }; - }; - diff --git a/target/linux/mediatek/patches-6.1/121-hack-spi-nand-1b-bbm.patch b/target/linux/mediatek/patches-6.1/121-hack-spi-nand-1b-bbm.patch deleted file mode 100644 index ff5521c44..000000000 --- a/target/linux/mediatek/patches-6.1/121-hack-spi-nand-1b-bbm.patch +++ /dev/null @@ -1,20 +0,0 @@ ---- a/drivers/mtd/nand/spi/core.c -+++ b/drivers/mtd/nand/spi/core.c -@@ -724,7 +724,7 @@ static int spinand_mtd_write(struct mtd_ - static bool spinand_isbad(struct nand_device *nand, const struct nand_pos *pos) - { - struct spinand_device *spinand = nand_to_spinand(nand); -- u8 marker[2] = { }; -+ u8 marker[1] = { }; - struct nand_page_io_req req = { - .pos = *pos, - .ooblen = sizeof(marker), -@@ -735,7 +735,7 @@ static bool spinand_isbad(struct nand_de - - spinand_select_target(spinand, pos->target); - spinand_read_page(spinand, &req); -- if (marker[0] != 0xff || marker[1] != 0xff) -+ if (marker[0] != 0xff) - return true; - - return false; diff --git a/target/linux/mediatek/patches-6.1/130-dts-mt7629-add-snand-support.patch b/target/linux/mediatek/patches-6.1/130-dts-mt7629-add-snand-support.patch deleted file mode 100644 index 82654e683..000000000 --- a/target/linux/mediatek/patches-6.1/130-dts-mt7629-add-snand-support.patch +++ /dev/null @@ -1,94 +0,0 @@ -From c813fbe806257c574240770ef716fbee19f7dbfa Mon Sep 17 00:00:00 2001 -From: Xiangsheng Hou -Date: Thu, 6 Jun 2019 16:29:04 +0800 -Subject: [PATCH] spi: spi-mem: Mediatek: Add SPI Nand support for MT7629 - -Signed-off-by: Xiangsheng Hou ---- - arch/arm/boot/dts/mt7629-rfb.dts | 45 ++++++++++++++++++++++++++++++++ - arch/arm/boot/dts/mt7629.dtsi | 22 ++++++++++++++++ - 3 files changed, 79 insertions(+) - ---- a/arch/arm/boot/dts/mt7629.dtsi -+++ b/arch/arm/boot/dts/mt7629.dtsi -@@ -272,6 +272,27 @@ - status = "disabled"; - }; - -+ snfi: spi@1100d000 { -+ compatible = "mediatek,mt7629-snand"; -+ reg = <0x1100d000 0x1000>; -+ interrupts = ; -+ clocks = <&pericfg CLK_PERI_NFI_PD>, <&pericfg CLK_PERI_SNFI_PD>; -+ clock-names = "nfi_clk", "pad_clk"; -+ nand-ecc-engine = <&bch>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "disabled"; -+ }; -+ -+ bch: ecc@1100e000 { -+ compatible = "mediatek,mt7622-ecc"; -+ reg = <0x1100e000 0x1000>; -+ interrupts = ; -+ clocks = <&pericfg CLK_PERI_NFIECC_PD>; -+ clock-names = "nfiecc_clk"; -+ status = "disabled"; -+ }; -+ - spi: spi@1100a000 { - compatible = "mediatek,mt7629-spi", - "mediatek,mt7622-spi"; ---- a/arch/arm/boot/dts/mt7629-rfb.dts -+++ b/arch/arm/boot/dts/mt7629-rfb.dts -@@ -255,6 +255,50 @@ - }; - }; - -+&bch { -+ status = "okay"; -+}; -+ -+&snfi { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&serial_nand_pins>; -+ status = "okay"; -+ flash@0 { -+ compatible = "spi-nand"; -+ reg = <0>; -+ spi-tx-bus-width = <4>; -+ spi-rx-bus-width = <4>; -+ nand-ecc-engine = <&snfi>; -+ -+ partitions { -+ compatible = "fixed-partitions"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ partition@0 { -+ label = "Bootloader"; -+ reg = <0x00000 0x0100000>; -+ read-only; -+ }; -+ -+ partition@100000 { -+ label = "Config"; -+ reg = <0x100000 0x0040000>; -+ }; -+ -+ partition@140000 { -+ label = "factory"; -+ reg = <0x140000 0x0080000>; -+ }; -+ -+ partition@1c0000 { -+ label = "firmware"; -+ reg = <0x1c0000 0x1000000>; -+ }; -+ }; -+ }; -+}; -+ - &spi { - pinctrl-names = "default"; - pinctrl-0 = <&spi_pins>; diff --git a/target/linux/mediatek/patches-6.1/131-dts-mt7622-add-snand-support.patch b/target/linux/mediatek/patches-6.1/131-dts-mt7622-add-snand-support.patch deleted file mode 100644 index 134e5997e..000000000 --- a/target/linux/mediatek/patches-6.1/131-dts-mt7622-add-snand-support.patch +++ /dev/null @@ -1,68 +0,0 @@ ---- a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts -@@ -539,6 +539,65 @@ - status = "disabled"; - }; - -+&bch { -+ status = "okay"; -+}; -+ -+&snfi { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&serial_nand_pins>; -+ status = "okay"; -+ flash@0 { -+ compatible = "spi-nand"; -+ reg = <0>; -+ spi-tx-bus-width = <4>; -+ spi-rx-bus-width = <4>; -+ nand-ecc-engine = <&snfi>; -+ -+ partitions { -+ compatible = "fixed-partitions"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ partition@0 { -+ label = "Preloader"; -+ reg = <0x00000 0x0080000>; -+ read-only; -+ }; -+ -+ partition@80000 { -+ label = "ATF"; -+ reg = <0x80000 0x0040000>; -+ }; -+ -+ partition@c0000 { -+ label = "Bootloader"; -+ reg = <0xc0000 0x0080000>; -+ }; -+ -+ partition@140000 { -+ label = "Config"; -+ reg = <0x140000 0x0080000>; -+ }; -+ -+ partition@1c0000 { -+ label = "Factory"; -+ reg = <0x1c0000 0x0100000>; -+ }; -+ -+ partition@200000 { -+ label = "firmware"; -+ reg = <0x2c0000 0x2000000>; -+ }; -+ -+ partition@2200000 { -+ label = "User_data"; -+ reg = <0x22c0000 0x4000000>; -+ }; -+ }; -+ }; -+}; -+ - &spi0 { - pinctrl-names = "default"; - pinctrl-0 = <&spic0_pins>; diff --git a/target/linux/mediatek/patches-6.1/140-dts-fix-wmac-support-for-mt7622-rfb1.patch b/target/linux/mediatek/patches-6.1/140-dts-fix-wmac-support-for-mt7622-rfb1.patch deleted file mode 100644 index 8e6935b43..000000000 --- a/target/linux/mediatek/patches-6.1/140-dts-fix-wmac-support-for-mt7622-rfb1.patch +++ /dev/null @@ -1,18 +0,0 @@ ---- a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts -@@ -580,7 +580,7 @@ - reg = <0x140000 0x0080000>; - }; - -- partition@1c0000 { -+ factory: partition@1c0000 { - label = "Factory"; - reg = <0x1c0000 0x0100000>; - }; -@@ -641,5 +641,6 @@ - &wmac { - pinctrl-names = "default"; - pinctrl-0 = <&wmac_pins>; -+ mediatek,mtd-eeprom = <&factory 0x0000>; - status = "okay"; - }; diff --git a/target/linux/mediatek/patches-6.1/150-dts-mt7623-eip97-inside-secure-support.patch b/target/linux/mediatek/patches-6.1/150-dts-mt7623-eip97-inside-secure-support.patch deleted file mode 100644 index 0860a22c3..000000000 --- a/target/linux/mediatek/patches-6.1/150-dts-mt7623-eip97-inside-secure-support.patch +++ /dev/null @@ -1,24 +0,0 @@ ---- a/arch/arm/boot/dts/mt7623.dtsi -+++ b/arch/arm/boot/dts/mt7623.dtsi -@@ -984,17 +984,15 @@ - }; - - crypto: crypto@1b240000 { -- compatible = "mediatek,eip97-crypto"; -+ compatible = "inside-secure,safexcel-eip97"; - reg = <0 0x1b240000 0 0x20000>; - interrupts = , - , - , -- , -- ; -+ ; -+ interrupt-names = "ring0", "ring1", "ring2", "ring3"; - clocks = <ðsys CLK_ETHSYS_CRYPTO>; -- clock-names = "cryp"; -- power-domains = <&scpsys MT2701_POWER_DOMAIN_ETH>; -- status = "disabled"; -+ status = "okay"; - }; - - bdpsys: syscon@1c000000 { diff --git a/target/linux/mediatek/patches-6.1/160-dts-mt7623-bpi-r2-earlycon.patch b/target/linux/mediatek/patches-6.1/160-dts-mt7623-bpi-r2-earlycon.patch deleted file mode 100644 index 091cffc3c..000000000 --- a/target/linux/mediatek/patches-6.1/160-dts-mt7623-bpi-r2-earlycon.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts -+++ b/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts -@@ -19,7 +19,7 @@ - - chosen { - stdout-path = "serial2:115200n8"; -- bootargs = "console=ttyS2,115200n8 console=tty1"; -+ bootargs = "earlycon=uart8250,mmio32,0x11004000 console=ttyS2,115200n8 console=tty1"; - }; - - connector { diff --git a/target/linux/mediatek/patches-6.1/161-dts-mt7623-bpi-r2-mmc-device-order.patch b/target/linux/mediatek/patches-6.1/161-dts-mt7623-bpi-r2-mmc-device-order.patch deleted file mode 100644 index d1bafc152..000000000 --- a/target/linux/mediatek/patches-6.1/161-dts-mt7623-bpi-r2-mmc-device-order.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts -+++ b/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts -@@ -15,6 +15,8 @@ - - aliases { - serial2 = &uart2; -+ mmc0 = &mmc0; -+ mmc1 = &mmc1; - }; - - chosen { diff --git a/target/linux/mediatek/patches-6.1/162-dts-mt7623-bpi-r2-led-aliases.patch b/target/linux/mediatek/patches-6.1/162-dts-mt7623-bpi-r2-led-aliases.patch deleted file mode 100644 index f6745add5..000000000 --- a/target/linux/mediatek/patches-6.1/162-dts-mt7623-bpi-r2-led-aliases.patch +++ /dev/null @@ -1,29 +0,0 @@ ---- a/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts -+++ b/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts -@@ -17,6 +17,10 @@ - serial2 = &uart2; - mmc0 = &mmc0; - mmc1 = &mmc1; -+ led-boot = &led_system_green; -+ led-failsafe = &led_system_blue; -+ led-running = &led_system_green; -+ led-upgrade = &led_system_blue; - }; - - chosen { -@@ -112,13 +116,13 @@ - pinctrl-names = "default"; - pinctrl-0 = <&led_pins_a>; - -- blue { -+ led_system_blue: blue { - label = "bpi-r2:pio:blue"; - gpios = <&pio 240 GPIO_ACTIVE_LOW>; - default-state = "off"; - }; - -- green { -+ led_system_green: green { - label = "bpi-r2:pio:green"; - gpios = <&pio 241 GPIO_ACTIVE_LOW>; - default-state = "off"; diff --git a/target/linux/mediatek/patches-6.1/163-dts-mt7623-bpi-r2-ethernet-alias.patch b/target/linux/mediatek/patches-6.1/163-dts-mt7623-bpi-r2-ethernet-alias.patch deleted file mode 100644 index b1dd75a41..000000000 --- a/target/linux/mediatek/patches-6.1/163-dts-mt7623-bpi-r2-ethernet-alias.patch +++ /dev/null @@ -1,10 +0,0 @@ ---- a/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts -+++ b/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts -@@ -15,6 +15,7 @@ - - aliases { - serial2 = &uart2; -+ ethernet0 = &gmac0; - mmc0 = &mmc0; - mmc1 = &mmc1; - led-boot = &led_system_green; diff --git a/target/linux/mediatek/patches-6.1/180-dts-mt7622-bpi-r64-add-mt7531-irq.patch b/target/linux/mediatek/patches-6.1/180-dts-mt7622-bpi-r64-add-mt7531-irq.patch deleted file mode 100644 index 3452b108f..000000000 --- a/target/linux/mediatek/patches-6.1/180-dts-mt7622-bpi-r64-add-mt7531-irq.patch +++ /dev/null @@ -1,13 +0,0 @@ ---- a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts -@@ -157,6 +157,10 @@ - switch@0 { - compatible = "mediatek,mt7531"; - reg = <0>; -+ interrupt-controller; -+ #interrupt-cells = <1>; -+ interrupt-parent = <&pio>; -+ interrupts = <53 IRQ_TYPE_LEVEL_HIGH>; - reset-gpios = <&pio 54 0>; - - ports { diff --git a/target/linux/mediatek/patches-6.1/190-arm64-dts-mediatek-mt7622-fix-GICv2-range.patch b/target/linux/mediatek/patches-6.1/190-arm64-dts-mediatek-mt7622-fix-GICv2-range.patch deleted file mode 100644 index 9da8ffe32..000000000 --- a/target/linux/mediatek/patches-6.1/190-arm64-dts-mediatek-mt7622-fix-GICv2-range.patch +++ /dev/null @@ -1,106 +0,0 @@ -From patchwork Tue Apr 26 19:51:36 2022 -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 7bit -X-Patchwork-Submitter: Daniel Golle -X-Patchwork-Id: 12827872 -Return-Path: - -X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on - aws-us-west-2-korg-lkml-1.web.codeaurora.org -Received: from bombadil.infradead.org (bombadil.infradead.org - [198.137.202.133]) - (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) - (No client certificate requested) - by smtp.lore.kernel.org (Postfix) with ESMTPS id BACF3C433EF - for ; - Tue, 26 Apr 2022 19:53:05 +0000 (UTC) -DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; - d=lists.infradead.org; s=bombadil.20210309; h=Sender: - Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: - List-Archive:List-Unsubscribe:List-Id:MIME-Version:Message-ID:Subject:Cc:To: - From:Date:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: - Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:References: - List-Owner; bh=OWGSxvlKoyPWz6b629RNINucULo6oOdFssAIiJETWRg=; b=T0HEjee0FX3hlb - x5jl7xLK5sKM0pkE2oRgwzthbFlNg8ST1j/2GkgcgT0S2Bi0vRfFxHeu/RKzS9RmiVnKJnPGL8ctg - WoBLyO5i+NcmosGoy6MmoOjGTNhj/+3q3Z1jRLBSJ4ySSP22X77YeuJTmVzySPUllQhWvDhjMVCR9 - QBRmQdc6gCAg3IYGEbWwS2TG+UHveDCeZRWxMzrwI8UPadNCRFROwugmiQ3mdU41lHCTDpnlfuRJh - o1igLKfMBLz+D8rFYvDh7FfkcKkY6lNoswA2HKUun1MEzgoyQKmITPnG2maX/BvJJuj/B3ZJShh4k - AZHmXoQxq1mrsm2FxfnQ==; -Received: from localhost ([::1] helo=bombadil.infradead.org) - by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) - id 1njRE5-00G05D-9z; Tue, 26 Apr 2022 19:51:57 +0000 -Received: from fudo.makrotopia.org ([2a07:2ec0:3002::71]) - by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) - id 1njRE1-00G03h-9H; Tue, 26 Apr 2022 19:51:55 +0000 -Received: from local - by fudo.makrotopia.org with esmtpsa (TLS1.3:TLS_AES_256_GCM_SHA384:256) - (Exim 4.94.2) (envelope-from ) - id 1njRDu-0006aF-4F; Tue, 26 Apr 2022 21:51:46 +0200 -Date: Tue, 26 Apr 2022 20:51:36 +0100 -From: Daniel Golle -To: devicetree@vger.kernel.org, linux-mediatek@lists.infradead.org, - linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org -Cc: Rob Herring , - Krzysztof Kozlowski , - Matthias Brugger -Subject: [PATCH] arm64: dts: mediatek: mt7622: fix GICv2 range -Message-ID: -MIME-Version: 1.0 -Content-Disposition: inline -X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 -X-CRM114-CacheID: sfid-20220426_125153_359242_EA3D452C -X-CRM114-Status: GOOD ( 12.45 ) -X-BeenThere: linux-arm-kernel@lists.infradead.org -X-Mailman-Version: 2.1.34 -Precedence: list -List-Id: -List-Unsubscribe: - , - -List-Archive: -List-Post: -List-Help: -List-Subscribe: - , - -Sender: "linux-arm-kernel" -Errors-To: - linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org - -With the current range specified for the CPU interface there is an -error message at boot: - -GIC: GICv2 detected, but range too small and irqchip.gicv2_force_probe not set - -Setting irqchip.gicv2_force_probe=1 in bootargs results in: - -GIC: Aliased GICv2 at 0x0000000010320000, trying to find the canonical range over 128kB -GIC: Adjusting CPU interface base to 0x000000001032f000 -GIC: Using split EOI/Deactivate mode - -Using the adjusted CPU interface base and 8K size results in only the -final line remaining and fully working system as well as /proc/interrupts -showing additional IPI3,4,5,6: - -IPI3: 0 0 CPU stop (for crash dump) interrupts -IPI4: 0 0 Timer broadcast interrupts -IPI5: 0 0 IRQ work interrupts -IPI6: 0 0 CPU wake-up interrupts - -Signed-off-by: Daniel Golle ---- - arch/arm64/boot/dts/mediatek/mt7622.dtsi | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi -+++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi -@@ -344,7 +344,7 @@ - #interrupt-cells = <3>; - interrupt-parent = <&gic>; - reg = <0 0x10310000 0 0x1000>, -- <0 0x10320000 0 0x1000>, -+ <0 0x1032f000 0 0x2000>, - <0 0x10340000 0 0x2000>, - <0 0x10360000 0 0x2000>; - }; diff --git a/target/linux/mediatek/patches-6.1/193-dts-mt7623-thermal_zone_fix.patch b/target/linux/mediatek/patches-6.1/193-dts-mt7623-thermal_zone_fix.patch deleted file mode 100644 index 1cfb53d62..000000000 --- a/target/linux/mediatek/patches-6.1/193-dts-mt7623-thermal_zone_fix.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 824d56e753a588fcfd650db1822e34a02a48bb77 Mon Sep 17 00:00:00 2001 -From: Bruno Umuarama -Date: Thu, 13 Oct 2022 21:18:21 +0000 -Subject: [PATCH] mediatek: mt7623: fix thermal zone -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Raising the temperatures for passive and active trips. @VA1DER -proposed at issue 9396 to remove passive trip. This commit relates to -his suggestion. - -Without this patch. the CPU will be throttled all the way down to 98MHz -if the temperature rises even a degree above the trip point, and it was -further discovered that if the internal temperature of the device is -above the first trip point temperature when it boots then it will start -in a throttled state and even -$ echo disabled > /sys/class/thermal/thermal_zone0/mode -will have no effect. - -The patch increases the passive trip point and active cooling map. The -throttling temperature will then be at 77°C and 82°C, which is still a -low enough temperature for ARM devices to not be in the real danger -zone, and gives some operational headroom. - -Signed-off-by: Bruno Umuarama ---- - arch/arm/boot/dts/mt7623.dtsi | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/arch/arm/boot/dts/mt7623.dtsi -+++ b/arch/arm/boot/dts/mt7623.dtsi -@@ -160,13 +160,13 @@ - - trips { - cpu_passive: cpu-passive { -- temperature = <57000>; -+ temperature = <77000>; - hysteresis = <2000>; - type = "passive"; - }; - - cpu_active: cpu-active { -- temperature = <67000>; -+ temperature = <82000>; - hysteresis = <2000>; - type = "active"; - }; diff --git a/target/linux/mediatek/patches-6.1/194-dts-mt7968a-add-ramoops.patch b/target/linux/mediatek/patches-6.1/194-dts-mt7968a-add-ramoops.patch deleted file mode 100644 index 161c1e751..000000000 --- a/target/linux/mediatek/patches-6.1/194-dts-mt7968a-add-ramoops.patch +++ /dev/null @@ -1,17 +0,0 @@ ---- a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi -+++ b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi -@@ -68,6 +68,14 @@ - #address-cells = <2>; - #size-cells = <2>; - ranges; -+ -+ /* 64 KiB reserved for ramoops/pstore */ -+ ramoops@42ff0000 { -+ compatible = "ramoops"; -+ reg = <0 0x42ff0000 0 0x10000>; -+ record-size = <0x1000>; -+ }; -+ - /* 192 KiB reserved for ARM Trusted Firmware (BL31) */ - secmon_reserved: secmon@43000000 { - reg = <0 0x43000000 0 0x30000>; diff --git a/target/linux/mediatek/patches-6.1/195-dts-mt7986a-bpi-r3-leds-port-names-and-wifi-eeprom.patch b/target/linux/mediatek/patches-6.1/195-dts-mt7986a-bpi-r3-leds-port-names-and-wifi-eeprom.patch deleted file mode 100644 index 336920baf..000000000 --- a/target/linux/mediatek/patches-6.1/195-dts-mt7986a-bpi-r3-leds-port-names-and-wifi-eeprom.patch +++ /dev/null @@ -1,196 +0,0 @@ ---- a/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts -@@ -23,6 +23,10 @@ - serial0 = &uart0; - ethernet0 = &gmac0; - ethernet1 = &gmac1; -+ led-boot = &green_led; -+ led-failsafe = &green_led; -+ led-running = &green_led; -+ led-upgrade = &blue_led; - }; - - chosen { -@@ -419,27 +423,27 @@ - - port@1 { - reg = <1>; -- label = "lan0"; -+ label = "lan1"; - }; - - port@2 { - reg = <2>; -- label = "lan1"; -+ label = "lan2"; - }; - - port@3 { - reg = <3>; -- label = "lan2"; -+ label = "lan3"; - }; - - port@4 { - reg = <4>; -- label = "lan3"; -+ label = "lan4"; - }; - - port5: port@5 { - reg = <5>; -- label = "lan4"; -+ label = "sfp2"; - phy-mode = "2500base-x"; - sfp = <&sfp2>; - managed = "in-band-status"; -@@ -490,9 +494,137 @@ - - &wifi { - status = "okay"; -- pinctrl-names = "default", "dbdc"; -+ pinctrl-names = "default"; - pinctrl-0 = <&wf_2g_5g_pins>, <&wf_led_pins>; -- pinctrl-1 = <&wf_dbdc_pins>, <&wf_led_pins>; -+ -+ mediatek,eeprom-data = <0x86790900 0x000c4326 0x60000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x01000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000800 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x24649090 0x00280000 0x05100000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00021e00 0x021e0002 0x1e00021e 0x00022800 0x02280002 0x28000228 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00008080 0x8080fdf7 -+ 0x0903150d 0x80808080 0x80808080 0x05050d0d 0x1313c6c6 0xc3c3c200 0x00c200c2 0x00008182 -+ 0x8585c2c2 0x82828282 0x858500c2 0xc2000081 0x82858587 0x87c2c200 0x81818285 0x858787c2 -+ 0xc2000081 0x82858587 0x87c2c200 0x00818285 0x858787c2 0xc2000081 0x82858587 0x87c4c4c2 -+ 0xc100c300 0xc3c3c100 0x818383c3 0xc3c3c100 0x81838300 0xc2c2c2c0 0x81828484 0x000000c3 -+ 0xc3c3c100 0x81838386 0x86c3c3c3 0xc1008183 0x838686c2 0xc2c2c081 0x82848486 0x86c3c3c3 -+ 0xc1008183 0x838686c3 0xc3c3c100 0x81838386 0x86c3c3c3 0xc1008183 0x83868622 0x28002228 -+ 0x00222800 0x22280000 0xdddddddd 0xdddddddd 0xddbbbbbb 0xccccccdd 0xdddddddd 0xdddddddd -+ 0xeeeeeecc 0xccccdddd 0xdddddddd 0x004a5662 0x0000004a 0x56620000 0x004a5662 0x0000004a -+ 0x56620000 0x88888888 0x33333326 0x26262626 0x26262600 0x33333326 0x26262626 0x26262600 -+ 0x33333326 0x26262626 0x26262600 0x33333326 0x26262626 0x26262600 0x00000000 0xf0f0cc00 -+ 0x00000000 0x0000aaaa 0xaabbbbbb 0xcccccccc 0xccccbbbb 0xbbbbbbbb 0xbbbbbbaa 0xaaaabbbb -+ 0xbbaaaaaa 0x999999aa 0xaaaabbbb 0xbbcccccc 0x00000000 0x0000aaaa 0xaa000000 0xbbbbbbbb -+ 0xbbbbaaaa 0xaa999999 0xaaaaaaaa 0xaaaaaaaa 0xaaaaaaaa 0xaaaaaaaa 0xaaaabbbb 0xbbbbbbbb -+ 0x00000000 0x00000000 0x00000000 0x99999999 0x9999aaaa 0xaaaaaaaa 0x999999aa 0xaaaaaaaa -+ 0xaaaaaaaa 0xaaaaaaaa 0xaaaabbbb 0xbbbbbbbb 0x00000000 0x0000eeee 0xeeffffff 0xcccccccc -+ 0xccccdddd 0xddbbbbbb 0xccccccbb 0xbbbbbbbb 0xbbbbbbbb 0xbbbbbbbb 0xbbbbcccc 0xccdddddd -+ 0x00516200 0x686e0051 0x6200686e 0x00516200 0x686e0051 0x6200686e 0x00516200 0x686e0051 -+ 0x6200686e 0x00516200 0x686e0051 0x6200686e 0x00516200 0x686e0051 0x6200686e 0x00516200 -+ 0x686e0051 0x6200686e 0x00516200 0x686e0051 0x6200686e 0x00516200 0x686e0051 0x6200686e -+ 0x00516200 0x686e0051 0x6200686e 0x00516200 0x686e0051 0x6200686e 0x00516200 0x686e0051 -+ 0x6200686e 0x00516200 0x686e0051 0x6200686e 0x00516200 0x686e0051 0x6200686e 0x00516200 -+ 0x686e0051 0x6200686e 0x00516200 0x686e0051 0x6200686e 0x00516200 0x686e0051 0x6200686e -+ 0x88888888 0x88888888 0x88888888 0x88888888 0x88888888 0x88888888 0x88888888 0x88888888 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000001 0x06000100 0x01050002 0x00ff0300 -+ 0xf900fe03 0x00000000 0x00000000 0x0000009b 0x6e370000 0x00000000 0x00fc0009 0x0a00fe00 -+ 0x060700fe 0x00070800 0x05000b0a 0x00000000 0x00000000 0x000000e2 0x96460000 0x00000000 -+ 0x000400f7 0xf8000300 0xfcfe0003 0x00fbfc00 0xee00e3f2 0x00000000 0x00000000 0x00000011 -+ 0xbb550000 0x00000000 0x000600f6 0xfc000300 0xfbfe0004 0x00fafe00 0xf600ecf2 0x00000000 -+ 0x00000000 0x0000001f 0xbf580000 0x00000000 0x000600f5 0xf6000400 0xf8f90004 0x00f7f800 -+ 0xf700f0f4 0x00000000 0x00000000 0x00000024 0xbe570000 0x00000000 0x000800f8 0xfe000600 -+ 0xf8fd0007 0x00f9fe00 0xf500f0f4 0x00000000 0x00000000 0x0000002d 0xd6610000 0x00000000 -+ 0x000400f7 0xfc000500 0xf7fc0005 0x00f7fc00 0xf900f5f8 0x00000000 0x00000000 0x00000026 -+ 0xd96e0000 0x00000000 0x000400f7 0xf9000600 0xf5f70005 0x00f5f800 0xf900f4f7 0x00000000 -+ 0x00000000 0x0000001b 0xce690000 0x00000000 0x000300f8 0xf8000600 0xf6f60004 0x00f6f700 -+ 0xf900f4f7 0x00000000 0x00000000 0x00000018 0xd8720000 0x00000000 0x00000000 0x02404002 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0xc1c2c1c2 0x41c341c3 0x3fc13fc1 0x40c13fc2 0x3fc240c1 0x41c040c0 0x3fc23fc2 0x40c13fc2 -+ 0x3fc140c0 0x41c040c0 0x3fc33fc3 0x40c23fc2 0x3fc240c1 0x41c040c0 0x3fc23fc2 0x40c23fc2 -+ 0x3fc140c1 0x41c040c0 0x00000000 0x00000000 0x41c741c7 0xc1c7c1c7 0x00000000 0x00000000 -+ 0x3fc03fc0 0x3fc03fc0 0x3fc03fc0 0x3fc03fc0 0x3fc03fc0 0x3fc03fc0 0x3fc03fc0 0x3fc03fc0 -+ 0x3fc03fc0 0x3fc03fc0 0x3fc03fc0 0x3fc03fc0 0x3fc03fc0 0x3fc03fc0 0x3fc03fc0 0x3fc03fc0 -+ 0x00a0ce00 0x00000000 0xb6840000 0x00000000 0x00000000 0x00000000 0x18181818 0x18181818 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x004b5763 0x0000004b 0x57630000 0x004b5763 0x0000004b 0x57630000 0x88888888 0x08474759 -+ 0x69780849 0x49596d7a 0x0849495a 0x6d790848 0x48596c78 0x08484858 0x6a780848 0x48586a78 -+ 0x08484858 0x6c78084a 0x4a5b6d79 0x08474759 0x697a0848 0x48596b79 0x08484859 0x6c7a0848 -+ 0x48586c79 0x08484857 0x68770848 0x48576877 0x08484857 0x6a77084a 0x4a5a6a77 0x08464659 -+ 0x69790848 0x48586b79 0x08484858 0x6c7a0848 0x48596c79 0x08484857 0x68770848 0x48576877 -+ 0x08494958 0x6d7a084b 0x4b5c6c77 0x0847475a 0x6a7b0849 0x495a6e7c 0x0849495a 0x6e7c0849 -+ 0x495b6e7c 0x08494959 0x6a7a0849 0x49596a7a 0x084a4a5a 0x6f7d084b 0x4b5c6e7b 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x85848484 -+ 0xc3c4c4c5 0xc4c3c33f 0xc3c3c2c2 0xc2c2c03f 0xc3c3c3c4 0xc4c4c33f 0xc2c2c2c2 0xc1c3c1c1 -+ 0xc0c08282 0x83848686 0x88880000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00001111 0x00000000 -+ 0x8080f703 0x10808080 0x80050d13 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x000000a4 0xce000000 0x0000b684 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 -+ 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000>; - - led { - led-active-low; ---- a/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-nor.dtso -+++ b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-nor.dtso -@@ -55,6 +55,7 @@ - partition@c00000 { - label = "fit"; - reg = <0xc00000 0x1400000>; -+ compatible = "denx,fit"; - }; - }; - }; diff --git a/target/linux/mediatek/patches-6.1/200-phy-phy-mtk-tphy-Add-hifsys-support.patch b/target/linux/mediatek/patches-6.1/200-phy-phy-mtk-tphy-Add-hifsys-support.patch deleted file mode 100644 index 6347533aa..000000000 --- a/target/linux/mediatek/patches-6.1/200-phy-phy-mtk-tphy-Add-hifsys-support.patch +++ /dev/null @@ -1,66 +0,0 @@ -From 28f9a5e2a3f5441ab5594669ed82da11e32277a9 Mon Sep 17 00:00:00 2001 -From: Kristian Evensen -Date: Mon, 30 Apr 2018 14:38:01 +0200 -Subject: [PATCH] phy: phy-mtk-tphy: Add hifsys-support - ---- - drivers/phy/mediatek/phy-mtk-tphy.c | 20 ++++++++++++++++++++ - 1 file changed, 20 insertions(+) - ---- a/drivers/phy/mediatek/phy-mtk-tphy.c -+++ b/drivers/phy/mediatek/phy-mtk-tphy.c -@@ -17,6 +17,8 @@ - #include - #include - #include -+#include -+#include - - #include "phy-mtk-io.h" - -@@ -264,6 +266,9 @@ - - #define TPHY_CLKS_CNT 2 - -+#define HIF_SYSCFG1 0x14 -+#define HIF_SYSCFG1_PHY2_MASK (0x3 << 20) -+ - enum mtk_phy_version { - MTK_PHY_V1 = 1, - MTK_PHY_V2, -@@ -331,6 +336,7 @@ struct mtk_tphy { - void __iomem *sif_base; /* only shared sif */ - const struct mtk_phy_pdata *pdata; - struct mtk_phy_instance **phys; -+ struct regmap *hif; - int nphys; - int src_ref_clk; /* MHZ, reference clock for slew rate calibrate */ - int src_coef; /* coefficient for slew rate calibrate */ -@@ -596,6 +602,10 @@ static void pcie_phy_instance_init(struc - if (tphy->pdata->version != MTK_PHY_V1) - return; - -+ if (tphy->hif) -+ regmap_update_bits(tphy->hif, HIF_SYSCFG1, -+ HIF_SYSCFG1_PHY2_MASK, 0); -+ - mtk_phy_update_bits(phya + U3P_U3_PHYA_DA_REG0, - P3A_RG_XTAL_EXT_PE1H | P3A_RG_XTAL_EXT_PE2H, - FIELD_PREP(P3A_RG_XTAL_EXT_PE1H, 0x2) | -@@ -1241,6 +1251,16 @@ static int mtk_tphy_probe(struct platfor - &tphy->src_coef); - } - -+ if (of_find_property(np, "mediatek,phy-switch", NULL)) { -+ tphy->hif = syscon_regmap_lookup_by_phandle(np, -+ "mediatek,phy-switch"); -+ if (IS_ERR(tphy->hif)) { -+ dev_err(&pdev->dev, -+ "missing \"mediatek,phy-switch\" phandle\n"); -+ return PTR_ERR(tphy->hif); -+ } -+ } -+ - port = 0; - for_each_child_of_node(np, child_np) { - struct mtk_phy_instance *instance; diff --git a/target/linux/mediatek/patches-6.1/210-v6.2-pinctrl-mt7986-allow-configuring-uart-rx-tx-and-rts-.patch b/target/linux/mediatek/patches-6.1/210-v6.2-pinctrl-mt7986-allow-configuring-uart-rx-tx-and-rts-.patch deleted file mode 100644 index 3e16a533e..000000000 --- a/target/linux/mediatek/patches-6.1/210-v6.2-pinctrl-mt7986-allow-configuring-uart-rx-tx-and-rts-.patch +++ /dev/null @@ -1,88 +0,0 @@ -From f76e8bc416bebb0f7b9f57b1247eae945421c0b9 Mon Sep 17 00:00:00 2001 -From: Sam Shih -Date: Sat, 8 Oct 2022 18:48:06 +0200 -Subject: [PATCH 1/2] pinctrl: mt7986: allow configuring uart rx/tx and rts/cts - separately - -Some mt7986 boards use uart rts/cts pins as gpio, -This patch allows to change rts/cts to gpio mode, but keep -rx/tx as UART function. - -Signed-off-by: Frank Wunderlich -Signed-off-by: Sam Shih -Link: https://lore.kernel.org/r/20221008164807.113590-1-linux@fw-web.de -Signed-off-by: Linus Walleij ---- - drivers/pinctrl/mediatek/pinctrl-mt7986.c | 32 ++++++++++++++++++----- - 1 file changed, 25 insertions(+), 7 deletions(-) - ---- a/drivers/pinctrl/mediatek/pinctrl-mt7986.c -+++ b/drivers/pinctrl/mediatek/pinctrl-mt7986.c -@@ -675,11 +675,17 @@ static int mt7986_uart1_1_funcs[] = { 4, - static int mt7986_spi1_2_pins[] = { 29, 30, 31, 32, }; - static int mt7986_spi1_2_funcs[] = { 1, 1, 1, 1, }; - --static int mt7986_uart1_2_pins[] = { 29, 30, 31, 32, }; --static int mt7986_uart1_2_funcs[] = { 3, 3, 3, 3, }; -+static int mt7986_uart1_2_rx_tx_pins[] = { 29, 30, }; -+static int mt7986_uart1_2_rx_tx_funcs[] = { 3, 3, }; - --static int mt7986_uart2_0_pins[] = { 29, 30, 31, 32, }; --static int mt7986_uart2_0_funcs[] = { 4, 4, 4, 4, }; -+static int mt7986_uart1_2_cts_rts_pins[] = { 31, 32, }; -+static int mt7986_uart1_2_cts_rts_funcs[] = { 3, 3, }; -+ -+static int mt7986_uart2_0_rx_tx_pins[] = { 29, 30, }; -+static int mt7986_uart2_0_rx_tx_funcs[] = { 4, 4, }; -+ -+static int mt7986_uart2_0_cts_rts_pins[] = { 31, 32, }; -+static int mt7986_uart2_0_cts_rts_funcs[] = { 4, 4, }; - - static int mt7986_spi0_pins[] = { 33, 34, 35, 36, }; - static int mt7986_spi0_funcs[] = { 1, 1, 1, 1, }; -@@ -708,6 +714,12 @@ static int mt7986_pcie_reset_funcs[] = { - static int mt7986_uart1_pins[] = { 42, 43, 44, 45, }; - static int mt7986_uart1_funcs[] = { 1, 1, 1, 1, }; - -+static int mt7986_uart1_rx_tx_pins[] = { 42, 43, }; -+static int mt7986_uart1_rx_tx_funcs[] = { 1, 1, }; -+ -+static int mt7986_uart1_cts_rts_pins[] = { 44, 45, }; -+static int mt7986_uart1_cts_rts_funcs[] = { 1, 1, }; -+ - static int mt7986_uart2_pins[] = { 46, 47, 48, 49, }; - static int mt7986_uart2_funcs[] = { 1, 1, 1, 1, }; - -@@ -749,6 +761,8 @@ static const struct group_desc mt7986_gr - PINCTRL_PIN_GROUP("wifi_led", mt7986_wifi_led), - PINCTRL_PIN_GROUP("i2c", mt7986_i2c), - PINCTRL_PIN_GROUP("uart1_0", mt7986_uart1_0), -+ PINCTRL_PIN_GROUP("uart1_rx_tx", mt7986_uart1_rx_tx), -+ PINCTRL_PIN_GROUP("uart1_cts_rts", mt7986_uart1_cts_rts), - PINCTRL_PIN_GROUP("pcie_clk", mt7986_pcie_clk), - PINCTRL_PIN_GROUP("pcie_wake", mt7986_pcie_wake), - PINCTRL_PIN_GROUP("spi1_0", mt7986_spi1_0), -@@ -760,8 +774,10 @@ static const struct group_desc mt7986_gr - PINCTRL_PIN_GROUP("spi1_1", mt7986_spi1_1), - PINCTRL_PIN_GROUP("uart1_1", mt7986_uart1_1), - PINCTRL_PIN_GROUP("spi1_2", mt7986_spi1_2), -- PINCTRL_PIN_GROUP("uart1_2", mt7986_uart1_2), -- PINCTRL_PIN_GROUP("uart2_0", mt7986_uart2_0), -+ PINCTRL_PIN_GROUP("uart1_2_rx_tx", mt7986_uart1_2_rx_tx), -+ PINCTRL_PIN_GROUP("uart1_2_cts_rts", mt7986_uart1_2_cts_rts), -+ PINCTRL_PIN_GROUP("uart2_0_rx_tx", mt7986_uart2_0_rx_tx), -+ PINCTRL_PIN_GROUP("uart2_0_cts_rts", mt7986_uart2_0_cts_rts), - PINCTRL_PIN_GROUP("spi0", mt7986_spi0), - PINCTRL_PIN_GROUP("spi0_wp_hold", mt7986_spi0_wp_hold), - PINCTRL_PIN_GROUP("uart2_1", mt7986_uart2_1), -@@ -800,7 +816,9 @@ static const char *mt7986_pwm_groups[] = - static const char *mt7986_spi_groups[] = { - "spi0", "spi0_wp_hold", "spi1_0", "spi1_1", "spi1_2", "spi1_3", }; - static const char *mt7986_uart_groups[] = { -- "uart1_0", "uart1_1", "uart1_2", "uart1_3_rx_tx", "uart1_3_cts_rts", -+ "uart1_0", "uart1_1", "uart1_rx_tx", "uart1_cts_rts", -+ "uart1_2_rx_tx", "uart1_2_cts_rts", -+ "uart1_3_rx_tx", "uart1_3_cts_rts", "uart2_0_rx_tx", "uart2_0_cts_rts", - "uart2_0", "uart2_1", "uart0", "uart1", "uart2", - }; - static const char *mt7986_wdt_groups[] = { "watchdog", }; diff --git a/target/linux/mediatek/patches-6.1/211-v6.2-pinctrl-mediatek-add-pull_type-attribute-for-mediate.patch b/target/linux/mediatek/patches-6.1/211-v6.2-pinctrl-mediatek-add-pull_type-attribute-for-mediate.patch deleted file mode 100644 index 47ded1aeb..000000000 --- a/target/linux/mediatek/patches-6.1/211-v6.2-pinctrl-mediatek-add-pull_type-attribute-for-mediate.patch +++ /dev/null @@ -1,100 +0,0 @@ -From 822d774abbcc66b811e28c68b59b40b964ba5b46 Mon Sep 17 00:00:00 2001 -From: Sam Shih -Date: Sun, 6 Nov 2022 09:01:13 +0100 -Subject: [PATCH 2/2] pinctrl: mediatek: add pull_type attribute for mediatek - MT7986 SoC - -Commit fb34a9ae383a ("pinctrl: mediatek: support rsel feature") -add SoC specify 'pull_type' attribute for bias configuration. - -This patch add pull_type attribute to pinctrl-mt7986.c, and make -bias_set_combo and bias_get_combo available to mediatek MT7986 SoC. - -Signed-off-by: Sam Shih -Signed-off-by: Frank Wunderlich -Reviewed-by: AngeloGioacchino Del Regno -Link: https://lore.kernel.org/r/20221106080114.7426-7-linux@fw-web.de -Signed-off-by: Linus Walleij ---- - drivers/pinctrl/mediatek/pinctrl-mt7986.c | 56 +++++++++++++++++++++++ - 1 file changed, 56 insertions(+) - ---- a/drivers/pinctrl/mediatek/pinctrl-mt7986.c -+++ b/drivers/pinctrl/mediatek/pinctrl-mt7986.c -@@ -407,6 +407,60 @@ static const struct mtk_pin_field_calc m - PIN_FIELD_BASE(66, 68, IOCFG_LB_BASE, 0x60, 0x10, 2, 1), - }; - -+static const unsigned int mt7986_pull_type[] = { -+ MTK_PULL_PUPD_R1R0_TYPE,/*0*/ MTK_PULL_PUPD_R1R0_TYPE,/*1*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*2*/ MTK_PULL_PUPD_R1R0_TYPE,/*3*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*4*/ MTK_PULL_PUPD_R1R0_TYPE,/*5*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*6*/ MTK_PULL_PUPD_R1R0_TYPE,/*7*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*8*/ MTK_PULL_PUPD_R1R0_TYPE,/*9*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*10*/ MTK_PULL_PUPD_R1R0_TYPE,/*11*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*12*/ MTK_PULL_PUPD_R1R0_TYPE,/*13*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*14*/ MTK_PULL_PUPD_R1R0_TYPE,/*15*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*16*/ MTK_PULL_PUPD_R1R0_TYPE,/*17*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*18*/ MTK_PULL_PUPD_R1R0_TYPE,/*19*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*20*/ MTK_PULL_PUPD_R1R0_TYPE,/*21*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*22*/ MTK_PULL_PUPD_R1R0_TYPE,/*23*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*24*/ MTK_PULL_PUPD_R1R0_TYPE,/*25*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*26*/ MTK_PULL_PUPD_R1R0_TYPE,/*27*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*28*/ MTK_PULL_PUPD_R1R0_TYPE,/*29*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*30*/ MTK_PULL_PUPD_R1R0_TYPE,/*31*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*32*/ MTK_PULL_PUPD_R1R0_TYPE,/*33*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*34*/ MTK_PULL_PUPD_R1R0_TYPE,/*35*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*36*/ MTK_PULL_PUPD_R1R0_TYPE,/*37*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*38*/ MTK_PULL_PUPD_R1R0_TYPE,/*39*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*40*/ MTK_PULL_PUPD_R1R0_TYPE,/*41*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*42*/ MTK_PULL_PUPD_R1R0_TYPE,/*43*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*44*/ MTK_PULL_PUPD_R1R0_TYPE,/*45*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*46*/ MTK_PULL_PUPD_R1R0_TYPE,/*47*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*48*/ MTK_PULL_PUPD_R1R0_TYPE,/*49*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*50*/ MTK_PULL_PUPD_R1R0_TYPE,/*51*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*52*/ MTK_PULL_PUPD_R1R0_TYPE,/*53*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*54*/ MTK_PULL_PUPD_R1R0_TYPE,/*55*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*56*/ MTK_PULL_PUPD_R1R0_TYPE,/*57*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*58*/ MTK_PULL_PUPD_R1R0_TYPE,/*59*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*60*/ MTK_PULL_PUPD_R1R0_TYPE,/*61*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*62*/ MTK_PULL_PUPD_R1R0_TYPE,/*63*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*64*/ MTK_PULL_PUPD_R1R0_TYPE,/*65*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*66*/ MTK_PULL_PUPD_R1R0_TYPE,/*67*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*68*/ MTK_PULL_PU_PD_TYPE,/*69*/ -+ MTK_PULL_PU_PD_TYPE,/*70*/ MTK_PULL_PU_PD_TYPE,/*71*/ -+ MTK_PULL_PU_PD_TYPE,/*72*/ MTK_PULL_PU_PD_TYPE,/*73*/ -+ MTK_PULL_PU_PD_TYPE,/*74*/ MTK_PULL_PU_PD_TYPE,/*75*/ -+ MTK_PULL_PU_PD_TYPE,/*76*/ MTK_PULL_PU_PD_TYPE,/*77*/ -+ MTK_PULL_PU_PD_TYPE,/*78*/ MTK_PULL_PU_PD_TYPE,/*79*/ -+ MTK_PULL_PU_PD_TYPE,/*80*/ MTK_PULL_PU_PD_TYPE,/*81*/ -+ MTK_PULL_PU_PD_TYPE,/*82*/ MTK_PULL_PU_PD_TYPE,/*83*/ -+ MTK_PULL_PU_PD_TYPE,/*84*/ MTK_PULL_PU_PD_TYPE,/*85*/ -+ MTK_PULL_PU_PD_TYPE,/*86*/ MTK_PULL_PU_PD_TYPE,/*87*/ -+ MTK_PULL_PU_PD_TYPE,/*88*/ MTK_PULL_PU_PD_TYPE,/*89*/ -+ MTK_PULL_PU_PD_TYPE,/*90*/ MTK_PULL_PU_PD_TYPE,/*91*/ -+ MTK_PULL_PU_PD_TYPE,/*92*/ MTK_PULL_PU_PD_TYPE,/*93*/ -+ MTK_PULL_PU_PD_TYPE,/*94*/ MTK_PULL_PU_PD_TYPE,/*95*/ -+ MTK_PULL_PU_PD_TYPE,/*96*/ MTK_PULL_PU_PD_TYPE,/*97*/ -+ MTK_PULL_PU_PD_TYPE,/*98*/ MTK_PULL_PU_PD_TYPE,/*99*/ -+ MTK_PULL_PU_PD_TYPE,/*100*/ -+}; -+ - static const struct mtk_pin_reg_calc mt7986_reg_cals[] = { - [PINCTRL_PIN_REG_MODE] = MTK_RANGE(mt7986_pin_mode_range), - [PINCTRL_PIN_REG_DIR] = MTK_RANGE(mt7986_pin_dir_range), -@@ -868,6 +922,7 @@ static struct mtk_pin_soc mt7986a_data = - .ies_present = false, - .base_names = mt7986_pinctrl_register_base_names, - .nbase_names = ARRAY_SIZE(mt7986_pinctrl_register_base_names), -+ .pull_type = mt7986_pull_type, - .bias_set_combo = mtk_pinconf_bias_set_combo, - .bias_get_combo = mtk_pinconf_bias_get_combo, - .drive_set = mtk_pinconf_drive_set_rev1, -@@ -889,6 +944,7 @@ static struct mtk_pin_soc mt7986b_data = - .ies_present = false, - .base_names = mt7986_pinctrl_register_base_names, - .nbase_names = ARRAY_SIZE(mt7986_pinctrl_register_base_names), -+ .pull_type = mt7986_pull_type, - .bias_set_combo = mtk_pinconf_bias_set_combo, - .bias_get_combo = mtk_pinconf_bias_get_combo, - .drive_set = mtk_pinconf_drive_set_rev1, diff --git a/target/linux/mediatek/patches-6.1/215-v6.3-pinctrl-add-mt7981-pinctrl-driver.patch b/target/linux/mediatek/patches-6.1/215-v6.3-pinctrl-add-mt7981-pinctrl-driver.patch deleted file mode 100644 index 46dfa24b7..000000000 --- a/target/linux/mediatek/patches-6.1/215-v6.3-pinctrl-add-mt7981-pinctrl-driver.patch +++ /dev/null @@ -1,1094 +0,0 @@ -From 6c83b2d94fcca735cf7d8aa7a55a4957eb404a9d Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Thu, 26 Jan 2023 00:34:56 +0000 -Subject: [PATCH] pinctrl: add mt7981 pinctrl driver - -Add pinctrl driver for the MediaTek MT7981 SoC, based on the driver -which can also be found the SDK. - -Signed-off-by: Daniel Golle -Reviewed-by: Rob Herring -Link: https://lore.kernel.org/r/ef5112946d16cacc67e65e439ba7b52a9950c1bb.1674693008.git.daniel@makrotopia.org -Signed-off-by: Linus Walleij ---- - drivers/pinctrl/mediatek/Kconfig | 5 + - drivers/pinctrl/mediatek/Makefile | 1 + - drivers/pinctrl/mediatek/pinctrl-mt7981.c | 1048 +++++++++++++++++++++ - 3 files changed, 1054 insertions(+) - create mode 100644 drivers/pinctrl/mediatek/pinctrl-mt7981.c - ---- a/drivers/pinctrl/mediatek/Kconfig -+++ b/drivers/pinctrl/mediatek/Kconfig -@@ -127,6 +127,11 @@ config PINCTRL_MT7622 - default ARM64 && ARCH_MEDIATEK - select PINCTRL_MTK_MOORE - -+config PINCTRL_MT7981 -+ bool "Mediatek MT7981 pin control" -+ depends on OF -+ select PINCTRL_MTK_MOORE -+ - config PINCTRL_MT7986 - bool "Mediatek MT7986 pin control" - depends on OF ---- a/drivers/pinctrl/mediatek/Makefile -+++ b/drivers/pinctrl/mediatek/Makefile -@@ -18,6 +18,7 @@ obj-$(CONFIG_PINCTRL_MT6797) += pinctrl- - obj-$(CONFIG_PINCTRL_MT7622) += pinctrl-mt7622.o - obj-$(CONFIG_PINCTRL_MT7623) += pinctrl-mt7623.o - obj-$(CONFIG_PINCTRL_MT7629) += pinctrl-mt7629.o -+obj-$(CONFIG_PINCTRL_MT7981) += pinctrl-mt7981.o - obj-$(CONFIG_PINCTRL_MT7986) += pinctrl-mt7986.o - obj-$(CONFIG_PINCTRL_MT8167) += pinctrl-mt8167.o - obj-$(CONFIG_PINCTRL_MT8173) += pinctrl-mt8173.o ---- /dev/null -+++ b/drivers/pinctrl/mediatek/pinctrl-mt7981.c -@@ -0,0 +1,1048 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * The MT7981 driver based on Linux generic pinctrl binding. -+ * -+ * Copyright (C) 2020 MediaTek Inc. -+ * Author: Sam Shih -+ */ -+ -+#include "pinctrl-moore.h" -+ -+#define MT7981_PIN(_number, _name) \ -+ MTK_PIN(_number, _name, 0, _number, DRV_GRP4) -+ -+#define PIN_FIELD_BASE(_s_pin, _e_pin, _i_base, _s_addr, _x_addrs, _s_bit, _x_bits) \ -+ PIN_FIELD_CALC(_s_pin, _e_pin, _i_base, _s_addr, _x_addrs, _s_bit, \ -+ _x_bits, 32, 0) -+ -+#define PINS_FIELD_BASE(_s_pin, _e_pin, _i_base, _s_addr, _x_addrs, _s_bit, _x_bits) \ -+ PIN_FIELD_CALC(_s_pin, _e_pin, _i_base, _s_addr, _x_addrs, _s_bit, \ -+ _x_bits, 32, 1) -+ -+static const struct mtk_pin_field_calc mt7981_pin_mode_range[] = { -+ PIN_FIELD(0, 56, 0x300, 0x10, 0, 4), -+}; -+ -+static const struct mtk_pin_field_calc mt7981_pin_dir_range[] = { -+ PIN_FIELD(0, 56, 0x0, 0x10, 0, 1), -+}; -+ -+static const struct mtk_pin_field_calc mt7981_pin_di_range[] = { -+ PIN_FIELD(0, 56, 0x200, 0x10, 0, 1), -+}; -+ -+static const struct mtk_pin_field_calc mt7981_pin_do_range[] = { -+ PIN_FIELD(0, 56, 0x100, 0x10, 0, 1), -+}; -+ -+static const struct mtk_pin_field_calc mt7981_pin_ies_range[] = { -+ PIN_FIELD_BASE(0, 0, 1, 0x10, 0x10, 1, 1), -+ PIN_FIELD_BASE(1, 1, 1, 0x10, 0x10, 0, 1), -+ PIN_FIELD_BASE(2, 2, 5, 0x20, 0x10, 6, 1), -+ PIN_FIELD_BASE(3, 3, 4, 0x20, 0x10, 6, 1), -+ PIN_FIELD_BASE(4, 4, 4, 0x20, 0x10, 2, 1), -+ PIN_FIELD_BASE(5, 5, 4, 0x20, 0x10, 1, 1), -+ PIN_FIELD_BASE(6, 6, 4, 0x20, 0x10, 3, 1), -+ PIN_FIELD_BASE(7, 7, 4, 0x20, 0x10, 0, 1), -+ PIN_FIELD_BASE(8, 8, 4, 0x20, 0x10, 4, 1), -+ -+ PIN_FIELD_BASE(9, 9, 5, 0x20, 0x10, 9, 1), -+ PIN_FIELD_BASE(10, 10, 5, 0x20, 0x10, 8, 1), -+ PIN_FIELD_BASE(11, 11, 5, 0x40, 0x10, 10, 1), -+ PIN_FIELD_BASE(12, 12, 5, 0x20, 0x10, 7, 1), -+ PIN_FIELD_BASE(13, 13, 5, 0x20, 0x10, 11, 1), -+ -+ PIN_FIELD_BASE(14, 14, 4, 0x20, 0x10, 8, 1), -+ -+ PIN_FIELD_BASE(15, 15, 2, 0x20, 0x10, 0, 1), -+ PIN_FIELD_BASE(16, 16, 2, 0x20, 0x10, 1, 1), -+ PIN_FIELD_BASE(17, 17, 2, 0x20, 0x10, 5, 1), -+ PIN_FIELD_BASE(18, 18, 2, 0x20, 0x10, 4, 1), -+ PIN_FIELD_BASE(19, 19, 2, 0x20, 0x10, 2, 1), -+ PIN_FIELD_BASE(20, 20, 2, 0x20, 0x10, 3, 1), -+ PIN_FIELD_BASE(21, 21, 2, 0x20, 0x10, 6, 1), -+ PIN_FIELD_BASE(22, 22, 2, 0x20, 0x10, 7, 1), -+ PIN_FIELD_BASE(23, 23, 2, 0x20, 0x10, 10, 1), -+ PIN_FIELD_BASE(24, 24, 2, 0x20, 0x10, 9, 1), -+ PIN_FIELD_BASE(25, 25, 2, 0x20, 0x10, 8, 1), -+ -+ PIN_FIELD_BASE(26, 26, 5, 0x20, 0x10, 0, 1), -+ PIN_FIELD_BASE(27, 27, 5, 0x20, 0x10, 4, 1), -+ PIN_FIELD_BASE(28, 28, 5, 0x20, 0x10, 3, 1), -+ PIN_FIELD_BASE(29, 29, 5, 0x20, 0x10, 1, 1), -+ PIN_FIELD_BASE(30, 30, 5, 0x20, 0x10, 2, 1), -+ PIN_FIELD_BASE(31, 31, 5, 0x20, 0x10, 5, 1), -+ -+ PIN_FIELD_BASE(32, 32, 1, 0x10, 0x10, 2, 1), -+ PIN_FIELD_BASE(33, 33, 1, 0x10, 0x10, 3, 1), -+ -+ PIN_FIELD_BASE(34, 34, 4, 0x20, 0x10, 5, 1), -+ PIN_FIELD_BASE(35, 35, 4, 0x20, 0x10, 7, 1), -+ -+ PIN_FIELD_BASE(36, 36, 3, 0x10, 0x10, 2, 1), -+ PIN_FIELD_BASE(37, 37, 3, 0x10, 0x10, 3, 1), -+ PIN_FIELD_BASE(38, 38, 3, 0x10, 0x10, 0, 1), -+ PIN_FIELD_BASE(39, 39, 3, 0x10, 0x10, 1, 1), -+ -+ PIN_FIELD_BASE(40, 40, 7, 0x30, 0x10, 1, 1), -+ PIN_FIELD_BASE(41, 41, 7, 0x30, 0x10, 0, 1), -+ PIN_FIELD_BASE(42, 42, 7, 0x30, 0x10, 9, 1), -+ PIN_FIELD_BASE(43, 43, 7, 0x30, 0x10, 7, 1), -+ PIN_FIELD_BASE(44, 44, 7, 0x30, 0x10, 8, 1), -+ PIN_FIELD_BASE(45, 45, 7, 0x30, 0x10, 3, 1), -+ PIN_FIELD_BASE(46, 46, 7, 0x30, 0x10, 4, 1), -+ PIN_FIELD_BASE(47, 47, 7, 0x30, 0x10, 5, 1), -+ PIN_FIELD_BASE(48, 48, 7, 0x30, 0x10, 6, 1), -+ PIN_FIELD_BASE(49, 49, 7, 0x30, 0x10, 2, 1), -+ -+ PIN_FIELD_BASE(50, 50, 6, 0x10, 0x10, 0, 1), -+ PIN_FIELD_BASE(51, 51, 6, 0x10, 0x10, 2, 1), -+ PIN_FIELD_BASE(52, 52, 6, 0x10, 0x10, 3, 1), -+ PIN_FIELD_BASE(53, 53, 6, 0x10, 0x10, 4, 1), -+ PIN_FIELD_BASE(54, 54, 6, 0x10, 0x10, 5, 1), -+ PIN_FIELD_BASE(55, 55, 6, 0x10, 0x10, 6, 1), -+ PIN_FIELD_BASE(56, 56, 6, 0x10, 0x10, 1, 1), -+}; -+ -+static const struct mtk_pin_field_calc mt7981_pin_smt_range[] = { -+ PIN_FIELD_BASE(0, 0, 1, 0x60, 0x10, 1, 1), -+ PIN_FIELD_BASE(1, 1, 1, 0x60, 0x10, 0, 1), -+ PIN_FIELD_BASE(2, 2, 5, 0x90, 0x10, 6, 1), -+ PIN_FIELD_BASE(3, 3, 4, 0x80, 0x10, 6, 1), -+ PIN_FIELD_BASE(4, 4, 4, 0x80, 0x10, 2, 1), -+ PIN_FIELD_BASE(5, 5, 4, 0x80, 0x10, 1, 1), -+ PIN_FIELD_BASE(6, 6, 4, 0x80, 0x10, 3, 1), -+ PIN_FIELD_BASE(7, 7, 4, 0x80, 0x10, 0, 1), -+ PIN_FIELD_BASE(8, 8, 4, 0x80, 0x10, 4, 1), -+ -+ PIN_FIELD_BASE(9, 9, 5, 0x90, 0x10, 9, 1), -+ PIN_FIELD_BASE(10, 10, 5, 0x90, 0x10, 8, 1), -+ PIN_FIELD_BASE(11, 11, 5, 0x90, 0x10, 10, 1), -+ PIN_FIELD_BASE(12, 12, 5, 0x90, 0x10, 7, 1), -+ PIN_FIELD_BASE(13, 13, 5, 0x90, 0x10, 11, 1), -+ -+ PIN_FIELD_BASE(14, 14, 4, 0x80, 0x10, 8, 1), -+ -+ PIN_FIELD_BASE(15, 15, 2, 0x90, 0x10, 0, 1), -+ PIN_FIELD_BASE(16, 16, 2, 0x90, 0x10, 1, 1), -+ PIN_FIELD_BASE(17, 17, 2, 0x90, 0x10, 5, 1), -+ PIN_FIELD_BASE(18, 18, 2, 0x90, 0x10, 4, 1), -+ PIN_FIELD_BASE(19, 19, 2, 0x90, 0x10, 2, 1), -+ PIN_FIELD_BASE(20, 20, 2, 0x90, 0x10, 3, 1), -+ PIN_FIELD_BASE(21, 21, 2, 0x90, 0x10, 6, 1), -+ PIN_FIELD_BASE(22, 22, 2, 0x90, 0x10, 7, 1), -+ PIN_FIELD_BASE(23, 23, 2, 0x90, 0x10, 10, 1), -+ PIN_FIELD_BASE(24, 24, 2, 0x90, 0x10, 9, 1), -+ PIN_FIELD_BASE(25, 25, 2, 0x90, 0x10, 8, 1), -+ -+ PIN_FIELD_BASE(26, 26, 5, 0x90, 0x10, 0, 1), -+ PIN_FIELD_BASE(27, 27, 5, 0x90, 0x10, 4, 1), -+ PIN_FIELD_BASE(28, 28, 5, 0x90, 0x10, 3, 1), -+ PIN_FIELD_BASE(29, 29, 5, 0x90, 0x10, 1, 1), -+ PIN_FIELD_BASE(30, 30, 5, 0x90, 0x10, 2, 1), -+ PIN_FIELD_BASE(31, 31, 5, 0x90, 0x10, 5, 1), -+ -+ PIN_FIELD_BASE(32, 32, 1, 0x60, 0x10, 2, 1), -+ PIN_FIELD_BASE(33, 33, 1, 0x60, 0x10, 3, 1), -+ -+ PIN_FIELD_BASE(34, 34, 4, 0x80, 0x10, 5, 1), -+ PIN_FIELD_BASE(35, 35, 4, 0x80, 0x10, 7, 1), -+ -+ PIN_FIELD_BASE(36, 36, 3, 0x60, 0x10, 2, 1), -+ PIN_FIELD_BASE(37, 37, 3, 0x60, 0x10, 3, 1), -+ PIN_FIELD_BASE(38, 38, 3, 0x60, 0x10, 0, 1), -+ PIN_FIELD_BASE(39, 39, 3, 0x60, 0x10, 1, 1), -+ -+ PIN_FIELD_BASE(40, 40, 7, 0x70, 0x10, 1, 1), -+ PIN_FIELD_BASE(41, 41, 7, 0x70, 0x10, 0, 1), -+ PIN_FIELD_BASE(42, 42, 7, 0x70, 0x10, 9, 1), -+ PIN_FIELD_BASE(43, 43, 7, 0x70, 0x10, 7, 1), -+ PIN_FIELD_BASE(44, 44, 7, 0x30, 0x10, 8, 1), -+ PIN_FIELD_BASE(45, 45, 7, 0x70, 0x10, 3, 1), -+ PIN_FIELD_BASE(46, 46, 7, 0x70, 0x10, 4, 1), -+ PIN_FIELD_BASE(47, 47, 7, 0x70, 0x10, 5, 1), -+ PIN_FIELD_BASE(48, 48, 7, 0x70, 0x10, 6, 1), -+ PIN_FIELD_BASE(49, 49, 7, 0x70, 0x10, 2, 1), -+ -+ PIN_FIELD_BASE(50, 50, 6, 0x50, 0x10, 0, 1), -+ PIN_FIELD_BASE(51, 51, 6, 0x50, 0x10, 2, 1), -+ PIN_FIELD_BASE(52, 52, 6, 0x50, 0x10, 3, 1), -+ PIN_FIELD_BASE(53, 53, 6, 0x50, 0x10, 4, 1), -+ PIN_FIELD_BASE(54, 54, 6, 0x50, 0x10, 5, 1), -+ PIN_FIELD_BASE(55, 55, 6, 0x50, 0x10, 6, 1), -+ PIN_FIELD_BASE(56, 56, 6, 0x50, 0x10, 1, 1), -+}; -+ -+static const struct mtk_pin_field_calc mt7981_pin_pu_range[] = { -+ PIN_FIELD_BASE(40, 40, 7, 0x50, 0x10, 1, 1), -+ PIN_FIELD_BASE(41, 41, 7, 0x50, 0x10, 0, 1), -+ PIN_FIELD_BASE(42, 42, 7, 0x50, 0x10, 9, 1), -+ PIN_FIELD_BASE(43, 43, 7, 0x50, 0x10, 7, 1), -+ PIN_FIELD_BASE(44, 44, 7, 0x50, 0x10, 8, 1), -+ PIN_FIELD_BASE(45, 45, 7, 0x50, 0x10, 3, 1), -+ PIN_FIELD_BASE(46, 46, 7, 0x50, 0x10, 4, 1), -+ PIN_FIELD_BASE(47, 47, 7, 0x50, 0x10, 5, 1), -+ PIN_FIELD_BASE(48, 48, 7, 0x50, 0x10, 6, 1), -+ PIN_FIELD_BASE(49, 49, 7, 0x50, 0x10, 2, 1), -+ -+ PIN_FIELD_BASE(50, 50, 6, 0x30, 0x10, 0, 1), -+ PIN_FIELD_BASE(51, 51, 6, 0x30, 0x10, 2, 1), -+ PIN_FIELD_BASE(52, 52, 6, 0x30, 0x10, 3, 1), -+ PIN_FIELD_BASE(53, 53, 6, 0x30, 0x10, 4, 1), -+ PIN_FIELD_BASE(54, 54, 6, 0x30, 0x10, 5, 1), -+ PIN_FIELD_BASE(55, 55, 6, 0x30, 0x10, 6, 1), -+ PIN_FIELD_BASE(56, 56, 6, 0x30, 0x10, 1, 1), -+}; -+ -+static const struct mtk_pin_field_calc mt7981_pin_pd_range[] = { -+ PIN_FIELD_BASE(40, 40, 7, 0x40, 0x10, 1, 1), -+ PIN_FIELD_BASE(41, 41, 7, 0x40, 0x10, 0, 1), -+ PIN_FIELD_BASE(42, 42, 7, 0x40, 0x10, 9, 1), -+ PIN_FIELD_BASE(43, 43, 7, 0x40, 0x10, 7, 1), -+ PIN_FIELD_BASE(44, 44, 7, 0x40, 0x10, 8, 1), -+ PIN_FIELD_BASE(45, 45, 7, 0x40, 0x10, 3, 1), -+ PIN_FIELD_BASE(46, 46, 7, 0x40, 0x10, 4, 1), -+ PIN_FIELD_BASE(47, 47, 7, 0x40, 0x10, 5, 1), -+ PIN_FIELD_BASE(48, 48, 7, 0x40, 0x10, 6, 1), -+ PIN_FIELD_BASE(49, 49, 7, 0x40, 0x10, 2, 1), -+ -+ PIN_FIELD_BASE(50, 50, 6, 0x20, 0x10, 0, 1), -+ PIN_FIELD_BASE(51, 51, 6, 0x20, 0x10, 2, 1), -+ PIN_FIELD_BASE(52, 52, 6, 0x20, 0x10, 3, 1), -+ PIN_FIELD_BASE(53, 53, 6, 0x20, 0x10, 4, 1), -+ PIN_FIELD_BASE(54, 54, 6, 0x20, 0x10, 5, 1), -+ PIN_FIELD_BASE(55, 55, 6, 0x20, 0x10, 6, 1), -+ PIN_FIELD_BASE(56, 56, 6, 0x20, 0x10, 1, 1), -+}; -+ -+static const struct mtk_pin_field_calc mt7981_pin_drv_range[] = { -+ PIN_FIELD_BASE(0, 0, 1, 0x00, 0x10, 3, 3), -+ PIN_FIELD_BASE(1, 1, 1, 0x00, 0x10, 0, 3), -+ -+ PIN_FIELD_BASE(2, 2, 5, 0x00, 0x10, 18, 3), -+ -+ PIN_FIELD_BASE(3, 3, 4, 0x00, 0x10, 18, 1), -+ PIN_FIELD_BASE(4, 4, 4, 0x00, 0x10, 6, 1), -+ PIN_FIELD_BASE(5, 5, 4, 0x00, 0x10, 3, 3), -+ PIN_FIELD_BASE(6, 6, 4, 0x00, 0x10, 9, 3), -+ PIN_FIELD_BASE(7, 7, 4, 0x00, 0x10, 0, 3), -+ PIN_FIELD_BASE(8, 8, 4, 0x00, 0x10, 12, 3), -+ -+ PIN_FIELD_BASE(9, 9, 5, 0x00, 0x10, 27, 3), -+ PIN_FIELD_BASE(10, 10, 5, 0x00, 0x10, 24, 3), -+ PIN_FIELD_BASE(11, 11, 5, 0x00, 0x10, 0, 3), -+ PIN_FIELD_BASE(12, 12, 5, 0x00, 0x10, 21, 3), -+ PIN_FIELD_BASE(13, 13, 5, 0x00, 0x10, 3, 3), -+ -+ PIN_FIELD_BASE(14, 14, 4, 0x00, 0x10, 27, 3), -+ -+ PIN_FIELD_BASE(15, 15, 2, 0x00, 0x10, 0, 3), -+ PIN_FIELD_BASE(16, 16, 2, 0x00, 0x10, 3, 3), -+ PIN_FIELD_BASE(17, 17, 2, 0x00, 0x10, 15, 3), -+ PIN_FIELD_BASE(18, 18, 2, 0x00, 0x10, 12, 3), -+ PIN_FIELD_BASE(19, 19, 2, 0x00, 0x10, 6, 3), -+ PIN_FIELD_BASE(20, 20, 2, 0x00, 0x10, 9, 3), -+ PIN_FIELD_BASE(21, 21, 2, 0x00, 0x10, 18, 3), -+ PIN_FIELD_BASE(22, 22, 2, 0x00, 0x10, 21, 3), -+ PIN_FIELD_BASE(23, 23, 2, 0x00, 0x10, 0, 3), -+ PIN_FIELD_BASE(24, 24, 2, 0x00, 0x10, 27, 3), -+ PIN_FIELD_BASE(25, 25, 2, 0x00, 0x10, 24, 3), -+ -+ PIN_FIELD_BASE(26, 26, 5, 0x00, 0x10, 0, 3), -+ PIN_FIELD_BASE(27, 27, 5, 0x00, 0x10, 12, 3), -+ PIN_FIELD_BASE(28, 28, 5, 0x00, 0x10, 9, 3), -+ PIN_FIELD_BASE(29, 29, 5, 0x00, 0x10, 3, 3), -+ PIN_FIELD_BASE(30, 30, 5, 0x00, 0x10, 6, 3), -+ PIN_FIELD_BASE(31, 31, 5, 0x00, 0x10, 15, 3), -+ -+ PIN_FIELD_BASE(32, 32, 1, 0x00, 0x10, 9, 3), -+ PIN_FIELD_BASE(33, 33, 1, 0x00, 0x10, 12, 3), -+ -+ PIN_FIELD_BASE(34, 34, 4, 0x00, 0x10, 15, 3), -+ PIN_FIELD_BASE(35, 35, 4, 0x00, 0x10, 21, 3), -+ -+ PIN_FIELD_BASE(36, 36, 3, 0x00, 0x10, 6, 3), -+ PIN_FIELD_BASE(37, 37, 3, 0x00, 0x10, 9, 3), -+ PIN_FIELD_BASE(38, 38, 3, 0x00, 0x10, 0, 3), -+ PIN_FIELD_BASE(39, 39, 3, 0x00, 0x10, 3, 3), -+ -+ PIN_FIELD_BASE(40, 40, 7, 0x00, 0x10, 3, 3), -+ PIN_FIELD_BASE(41, 41, 7, 0x00, 0x10, 0, 3), -+ PIN_FIELD_BASE(42, 42, 7, 0x00, 0x10, 27, 3), -+ PIN_FIELD_BASE(43, 43, 7, 0x00, 0x10, 21, 3), -+ PIN_FIELD_BASE(44, 44, 7, 0x00, 0x10, 24, 3), -+ PIN_FIELD_BASE(45, 45, 7, 0x00, 0x10, 9, 3), -+ PIN_FIELD_BASE(46, 46, 7, 0x00, 0x10, 12, 3), -+ PIN_FIELD_BASE(47, 47, 7, 0x00, 0x10, 15, 3), -+ PIN_FIELD_BASE(48, 48, 7, 0x00, 0x10, 18, 3), -+ PIN_FIELD_BASE(49, 49, 7, 0x00, 0x10, 6, 3), -+ -+ PIN_FIELD_BASE(50, 50, 6, 0x00, 0x10, 0, 3), -+ PIN_FIELD_BASE(51, 51, 6, 0x00, 0x10, 6, 3), -+ PIN_FIELD_BASE(52, 52, 6, 0x00, 0x10, 9, 3), -+ PIN_FIELD_BASE(53, 53, 6, 0x00, 0x10, 12, 3), -+ PIN_FIELD_BASE(54, 54, 6, 0x00, 0x10, 15, 3), -+ PIN_FIELD_BASE(55, 55, 6, 0x00, 0x10, 18, 3), -+ PIN_FIELD_BASE(56, 56, 6, 0x00, 0x10, 3, 3), -+}; -+ -+static const struct mtk_pin_field_calc mt7981_pin_pupd_range[] = { -+ PIN_FIELD_BASE(0, 0, 1, 0x20, 0x10, 1, 1), -+ PIN_FIELD_BASE(1, 1, 1, 0x20, 0x10, 0, 1), -+ PIN_FIELD_BASE(2, 2, 5, 0x30, 0x10, 6, 1), -+ PIN_FIELD_BASE(3, 3, 4, 0x30, 0x10, 6, 1), -+ PIN_FIELD_BASE(4, 4, 4, 0x30, 0x10, 2, 1), -+ PIN_FIELD_BASE(5, 5, 4, 0x30, 0x10, 1, 1), -+ PIN_FIELD_BASE(6, 6, 4, 0x30, 0x10, 3, 1), -+ PIN_FIELD_BASE(7, 7, 4, 0x30, 0x10, 0, 1), -+ PIN_FIELD_BASE(8, 8, 4, 0x30, 0x10, 4, 1), -+ -+ PIN_FIELD_BASE(9, 9, 5, 0x30, 0x10, 9, 1), -+ PIN_FIELD_BASE(10, 10, 5, 0x30, 0x10, 8, 1), -+ PIN_FIELD_BASE(11, 11, 5, 0x30, 0x10, 10, 1), -+ PIN_FIELD_BASE(12, 12, 5, 0x30, 0x10, 7, 1), -+ PIN_FIELD_BASE(13, 13, 5, 0x30, 0x10, 11, 1), -+ -+ PIN_FIELD_BASE(14, 14, 4, 0x30, 0x10, 8, 1), -+ -+ PIN_FIELD_BASE(15, 15, 2, 0x30, 0x10, 0, 1), -+ PIN_FIELD_BASE(16, 16, 2, 0x30, 0x10, 1, 1), -+ PIN_FIELD_BASE(17, 17, 2, 0x30, 0x10, 5, 1), -+ PIN_FIELD_BASE(18, 18, 2, 0x30, 0x10, 4, 1), -+ PIN_FIELD_BASE(19, 19, 2, 0x30, 0x10, 2, 1), -+ PIN_FIELD_BASE(20, 20, 2, 0x90, 0x10, 3, 1), -+ PIN_FIELD_BASE(21, 21, 2, 0x30, 0x10, 6, 1), -+ PIN_FIELD_BASE(22, 22, 2, 0x30, 0x10, 7, 1), -+ PIN_FIELD_BASE(23, 23, 2, 0x30, 0x10, 10, 1), -+ PIN_FIELD_BASE(24, 24, 2, 0x30, 0x10, 9, 1), -+ PIN_FIELD_BASE(25, 25, 2, 0x30, 0x10, 8, 1), -+ -+ PIN_FIELD_BASE(26, 26, 5, 0x30, 0x10, 0, 1), -+ PIN_FIELD_BASE(27, 27, 5, 0x30, 0x10, 4, 1), -+ PIN_FIELD_BASE(28, 28, 5, 0x30, 0x10, 3, 1), -+ PIN_FIELD_BASE(29, 29, 5, 0x30, 0x10, 1, 1), -+ PIN_FIELD_BASE(30, 30, 5, 0x30, 0x10, 2, 1), -+ PIN_FIELD_BASE(31, 31, 5, 0x30, 0x10, 5, 1), -+ -+ PIN_FIELD_BASE(32, 32, 1, 0x20, 0x10, 2, 1), -+ PIN_FIELD_BASE(33, 33, 1, 0x20, 0x10, 3, 1), -+ -+ PIN_FIELD_BASE(34, 34, 4, 0x30, 0x10, 5, 1), -+ PIN_FIELD_BASE(35, 35, 4, 0x30, 0x10, 7, 1), -+ -+ PIN_FIELD_BASE(36, 36, 3, 0x20, 0x10, 2, 1), -+ PIN_FIELD_BASE(37, 37, 3, 0x20, 0x10, 3, 1), -+ PIN_FIELD_BASE(38, 38, 3, 0x20, 0x10, 0, 1), -+ PIN_FIELD_BASE(39, 39, 3, 0x20, 0x10, 1, 1), -+}; -+ -+static const struct mtk_pin_field_calc mt7981_pin_r0_range[] = { -+ PIN_FIELD_BASE(0, 0, 1, 0x30, 0x10, 1, 1), -+ PIN_FIELD_BASE(1, 1, 1, 0x30, 0x10, 0, 1), -+ PIN_FIELD_BASE(2, 2, 5, 0x40, 0x10, 6, 1), -+ PIN_FIELD_BASE(3, 3, 4, 0x40, 0x10, 6, 1), -+ PIN_FIELD_BASE(4, 4, 4, 0x40, 0x10, 2, 1), -+ PIN_FIELD_BASE(5, 5, 4, 0x40, 0x10, 1, 1), -+ PIN_FIELD_BASE(6, 6, 4, 0x40, 0x10, 3, 1), -+ PIN_FIELD_BASE(7, 7, 4, 0x40, 0x10, 0, 1), -+ PIN_FIELD_BASE(8, 8, 4, 0x40, 0x10, 4, 1), -+ -+ PIN_FIELD_BASE(9, 9, 5, 0x40, 0x10, 9, 1), -+ PIN_FIELD_BASE(10, 10, 5, 0x40, 0x10, 8, 1), -+ PIN_FIELD_BASE(11, 11, 5, 0x40, 0x10, 10, 1), -+ PIN_FIELD_BASE(12, 12, 5, 0x40, 0x10, 7, 1), -+ PIN_FIELD_BASE(13, 13, 5, 0x40, 0x10, 11, 1), -+ -+ PIN_FIELD_BASE(14, 14, 4, 0x40, 0x10, 8, 1), -+ -+ PIN_FIELD_BASE(15, 15, 2, 0x40, 0x10, 0, 1), -+ PIN_FIELD_BASE(16, 16, 2, 0x40, 0x10, 1, 1), -+ PIN_FIELD_BASE(17, 17, 2, 0x40, 0x10, 5, 1), -+ PIN_FIELD_BASE(18, 18, 2, 0x40, 0x10, 4, 1), -+ PIN_FIELD_BASE(19, 19, 2, 0x40, 0x10, 2, 1), -+ PIN_FIELD_BASE(20, 20, 2, 0x40, 0x10, 3, 1), -+ PIN_FIELD_BASE(21, 21, 2, 0x40, 0x10, 6, 1), -+ PIN_FIELD_BASE(22, 22, 2, 0x40, 0x10, 7, 1), -+ PIN_FIELD_BASE(23, 23, 2, 0x40, 0x10, 10, 1), -+ PIN_FIELD_BASE(24, 24, 2, 0x40, 0x10, 9, 1), -+ PIN_FIELD_BASE(25, 25, 2, 0x40, 0x10, 8, 1), -+ -+ PIN_FIELD_BASE(26, 26, 5, 0x40, 0x10, 0, 1), -+ PIN_FIELD_BASE(27, 27, 5, 0x40, 0x10, 4, 1), -+ PIN_FIELD_BASE(28, 28, 5, 0x40, 0x10, 3, 1), -+ PIN_FIELD_BASE(29, 29, 5, 0x40, 0x10, 1, 1), -+ PIN_FIELD_BASE(30, 30, 5, 0x40, 0x10, 2, 1), -+ PIN_FIELD_BASE(31, 31, 5, 0x40, 0x10, 5, 1), -+ -+ PIN_FIELD_BASE(32, 32, 1, 0x30, 0x10, 2, 1), -+ PIN_FIELD_BASE(33, 33, 1, 0x30, 0x10, 3, 1), -+ -+ PIN_FIELD_BASE(34, 34, 4, 0x40, 0x10, 5, 1), -+ PIN_FIELD_BASE(35, 35, 4, 0x40, 0x10, 7, 1), -+ -+ PIN_FIELD_BASE(36, 36, 3, 0x30, 0x10, 2, 1), -+ PIN_FIELD_BASE(37, 37, 3, 0x30, 0x10, 3, 1), -+ PIN_FIELD_BASE(38, 38, 3, 0x30, 0x10, 0, 1), -+ PIN_FIELD_BASE(39, 39, 3, 0x30, 0x10, 1, 1), -+}; -+ -+static const struct mtk_pin_field_calc mt7981_pin_r1_range[] = { -+ PIN_FIELD_BASE(0, 0, 1, 0x40, 0x10, 1, 1), -+ PIN_FIELD_BASE(1, 1, 1, 0x40, 0x10, 0, 1), -+ PIN_FIELD_BASE(2, 2, 5, 0x50, 0x10, 6, 1), -+ PIN_FIELD_BASE(3, 3, 4, 0x50, 0x10, 6, 1), -+ PIN_FIELD_BASE(4, 4, 4, 0x50, 0x10, 2, 1), -+ PIN_FIELD_BASE(5, 5, 4, 0x50, 0x10, 1, 1), -+ PIN_FIELD_BASE(6, 6, 4, 0x50, 0x10, 3, 1), -+ PIN_FIELD_BASE(7, 7, 4, 0x50, 0x10, 0, 1), -+ PIN_FIELD_BASE(8, 8, 4, 0x50, 0x10, 4, 1), -+ -+ PIN_FIELD_BASE(9, 9, 5, 0x50, 0x10, 9, 1), -+ PIN_FIELD_BASE(10, 10, 5, 0x50, 0x10, 8, 1), -+ PIN_FIELD_BASE(11, 11, 5, 0x50, 0x10, 10, 1), -+ PIN_FIELD_BASE(12, 12, 5, 0x50, 0x10, 7, 1), -+ PIN_FIELD_BASE(13, 13, 5, 0x50, 0x10, 11, 1), -+ -+ PIN_FIELD_BASE(14, 14, 4, 0x50, 0x10, 8, 1), -+ -+ PIN_FIELD_BASE(15, 15, 2, 0x50, 0x10, 0, 1), -+ PIN_FIELD_BASE(16, 16, 2, 0x50, 0x10, 1, 1), -+ PIN_FIELD_BASE(17, 17, 2, 0x50, 0x10, 5, 1), -+ PIN_FIELD_BASE(18, 18, 2, 0x50, 0x10, 4, 1), -+ PIN_FIELD_BASE(19, 19, 2, 0x50, 0x10, 2, 1), -+ PIN_FIELD_BASE(20, 20, 2, 0x50, 0x10, 3, 1), -+ PIN_FIELD_BASE(21, 21, 2, 0x50, 0x10, 6, 1), -+ PIN_FIELD_BASE(22, 22, 2, 0x50, 0x10, 7, 1), -+ PIN_FIELD_BASE(23, 23, 2, 0x50, 0x10, 10, 1), -+ PIN_FIELD_BASE(24, 24, 2, 0x50, 0x10, 9, 1), -+ PIN_FIELD_BASE(25, 25, 2, 0x50, 0x10, 8, 1), -+ -+ PIN_FIELD_BASE(26, 26, 5, 0x50, 0x10, 0, 1), -+ PIN_FIELD_BASE(27, 27, 5, 0x50, 0x10, 4, 1), -+ PIN_FIELD_BASE(28, 28, 5, 0x50, 0x10, 3, 1), -+ PIN_FIELD_BASE(29, 29, 5, 0x50, 0x10, 1, 1), -+ PIN_FIELD_BASE(30, 30, 5, 0x50, 0x10, 2, 1), -+ PIN_FIELD_BASE(31, 31, 5, 0x50, 0x10, 5, 1), -+ -+ PIN_FIELD_BASE(32, 32, 1, 0x40, 0x10, 2, 1), -+ PIN_FIELD_BASE(33, 33, 1, 0x40, 0x10, 3, 1), -+ -+ PIN_FIELD_BASE(34, 34, 4, 0x50, 0x10, 5, 1), -+ PIN_FIELD_BASE(35, 35, 4, 0x50, 0x10, 7, 1), -+ -+ PIN_FIELD_BASE(36, 36, 3, 0x40, 0x10, 2, 1), -+ PIN_FIELD_BASE(37, 37, 3, 0x40, 0x10, 3, 1), -+ PIN_FIELD_BASE(38, 38, 3, 0x40, 0x10, 0, 1), -+ PIN_FIELD_BASE(39, 39, 3, 0x40, 0x10, 1, 1), -+}; -+ -+static const unsigned int mt7981_pull_type[] = { -+ MTK_PULL_PUPD_R1R0_TYPE,/*0*/ MTK_PULL_PUPD_R1R0_TYPE,/*1*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*2*/ MTK_PULL_PUPD_R1R0_TYPE,/*3*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*4*/ MTK_PULL_PUPD_R1R0_TYPE,/*5*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*6*/ MTK_PULL_PUPD_R1R0_TYPE,/*7*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*8*/ MTK_PULL_PUPD_R1R0_TYPE,/*9*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*10*/ MTK_PULL_PUPD_R1R0_TYPE,/*11*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*12*/ MTK_PULL_PUPD_R1R0_TYPE,/*13*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*14*/ MTK_PULL_PUPD_R1R0_TYPE,/*15*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*16*/ MTK_PULL_PUPD_R1R0_TYPE,/*17*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*18*/ MTK_PULL_PUPD_R1R0_TYPE,/*19*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*20*/ MTK_PULL_PUPD_R1R0_TYPE,/*21*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*22*/ MTK_PULL_PUPD_R1R0_TYPE,/*23*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*24*/ MTK_PULL_PUPD_R1R0_TYPE,/*25*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*26*/ MTK_PULL_PUPD_R1R0_TYPE,/*27*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*28*/ MTK_PULL_PUPD_R1R0_TYPE,/*29*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*30*/ MTK_PULL_PUPD_R1R0_TYPE,/*31*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*32*/ MTK_PULL_PUPD_R1R0_TYPE,/*33*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*34*/ MTK_PULL_PUPD_R1R0_TYPE,/*35*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*36*/ MTK_PULL_PUPD_R1R0_TYPE,/*37*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*38*/ MTK_PULL_PUPD_R1R0_TYPE,/*39*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*40*/ MTK_PULL_PUPD_R1R0_TYPE,/*41*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*42*/ MTK_PULL_PUPD_R1R0_TYPE,/*43*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*44*/ MTK_PULL_PUPD_R1R0_TYPE,/*45*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*46*/ MTK_PULL_PUPD_R1R0_TYPE,/*47*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*48*/ MTK_PULL_PUPD_R1R0_TYPE,/*49*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*50*/ MTK_PULL_PUPD_R1R0_TYPE,/*51*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*52*/ MTK_PULL_PUPD_R1R0_TYPE,/*53*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*54*/ MTK_PULL_PUPD_R1R0_TYPE,/*55*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*56*/ MTK_PULL_PUPD_R1R0_TYPE,/*57*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*58*/ MTK_PULL_PUPD_R1R0_TYPE,/*59*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*60*/ MTK_PULL_PUPD_R1R0_TYPE,/*61*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*62*/ MTK_PULL_PUPD_R1R0_TYPE,/*63*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*64*/ MTK_PULL_PUPD_R1R0_TYPE,/*65*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*66*/ MTK_PULL_PUPD_R1R0_TYPE,/*67*/ -+ MTK_PULL_PUPD_R1R0_TYPE,/*68*/ MTK_PULL_PU_PD_TYPE,/*69*/ -+ MTK_PULL_PU_PD_TYPE,/*70*/ MTK_PULL_PU_PD_TYPE,/*71*/ -+ MTK_PULL_PU_PD_TYPE,/*72*/ MTK_PULL_PU_PD_TYPE,/*73*/ -+ MTK_PULL_PU_PD_TYPE,/*74*/ MTK_PULL_PU_PD_TYPE,/*75*/ -+ MTK_PULL_PU_PD_TYPE,/*76*/ MTK_PULL_PU_PD_TYPE,/*77*/ -+ MTK_PULL_PU_PD_TYPE,/*78*/ MTK_PULL_PU_PD_TYPE,/*79*/ -+ MTK_PULL_PU_PD_TYPE,/*80*/ MTK_PULL_PU_PD_TYPE,/*81*/ -+ MTK_PULL_PU_PD_TYPE,/*82*/ MTK_PULL_PU_PD_TYPE,/*83*/ -+ MTK_PULL_PU_PD_TYPE,/*84*/ MTK_PULL_PU_PD_TYPE,/*85*/ -+ MTK_PULL_PU_PD_TYPE,/*86*/ MTK_PULL_PU_PD_TYPE,/*87*/ -+ MTK_PULL_PU_PD_TYPE,/*88*/ MTK_PULL_PU_PD_TYPE,/*89*/ -+ MTK_PULL_PU_PD_TYPE,/*90*/ MTK_PULL_PU_PD_TYPE,/*91*/ -+ MTK_PULL_PU_PD_TYPE,/*92*/ MTK_PULL_PU_PD_TYPE,/*93*/ -+ MTK_PULL_PU_PD_TYPE,/*94*/ MTK_PULL_PU_PD_TYPE,/*95*/ -+ MTK_PULL_PU_PD_TYPE,/*96*/ MTK_PULL_PU_PD_TYPE,/*97*/ -+ MTK_PULL_PU_PD_TYPE,/*98*/ MTK_PULL_PU_PD_TYPE,/*99*/ -+ MTK_PULL_PU_PD_TYPE,/*100*/ -+}; -+ -+static const struct mtk_pin_reg_calc mt7981_reg_cals[] = { -+ [PINCTRL_PIN_REG_MODE] = MTK_RANGE(mt7981_pin_mode_range), -+ [PINCTRL_PIN_REG_DIR] = MTK_RANGE(mt7981_pin_dir_range), -+ [PINCTRL_PIN_REG_DI] = MTK_RANGE(mt7981_pin_di_range), -+ [PINCTRL_PIN_REG_DO] = MTK_RANGE(mt7981_pin_do_range), -+ [PINCTRL_PIN_REG_SMT] = MTK_RANGE(mt7981_pin_smt_range), -+ [PINCTRL_PIN_REG_IES] = MTK_RANGE(mt7981_pin_ies_range), -+ [PINCTRL_PIN_REG_PU] = MTK_RANGE(mt7981_pin_pu_range), -+ [PINCTRL_PIN_REG_PD] = MTK_RANGE(mt7981_pin_pd_range), -+ [PINCTRL_PIN_REG_DRV] = MTK_RANGE(mt7981_pin_drv_range), -+ [PINCTRL_PIN_REG_PUPD] = MTK_RANGE(mt7981_pin_pupd_range), -+ [PINCTRL_PIN_REG_R0] = MTK_RANGE(mt7981_pin_r0_range), -+ [PINCTRL_PIN_REG_R1] = MTK_RANGE(mt7981_pin_r1_range), -+}; -+ -+static const struct mtk_pin_desc mt7981_pins[] = { -+ MT7981_PIN(0, "GPIO_WPS"), -+ MT7981_PIN(1, "GPIO_RESET"), -+ MT7981_PIN(2, "SYS_WATCHDOG"), -+ MT7981_PIN(3, "PCIE_PERESET_N"), -+ MT7981_PIN(4, "JTAG_JTDO"), -+ MT7981_PIN(5, "JTAG_JTDI"), -+ MT7981_PIN(6, "JTAG_JTMS"), -+ MT7981_PIN(7, "JTAG_JTCLK"), -+ MT7981_PIN(8, "JTAG_JTRST_N"), -+ MT7981_PIN(9, "WO_JTAG_JTDO"), -+ MT7981_PIN(10, "WO_JTAG_JTDI"), -+ MT7981_PIN(11, "WO_JTAG_JTMS"), -+ MT7981_PIN(12, "WO_JTAG_JTCLK"), -+ MT7981_PIN(13, "WO_JTAG_JTRST_N"), -+ MT7981_PIN(14, "USB_VBUS"), -+ MT7981_PIN(15, "PWM0"), -+ MT7981_PIN(16, "SPI0_CLK"), -+ MT7981_PIN(17, "SPI0_MOSI"), -+ MT7981_PIN(18, "SPI0_MISO"), -+ MT7981_PIN(19, "SPI0_CS"), -+ MT7981_PIN(20, "SPI0_HOLD"), -+ MT7981_PIN(21, "SPI0_WP"), -+ MT7981_PIN(22, "SPI1_CLK"), -+ MT7981_PIN(23, "SPI1_MOSI"), -+ MT7981_PIN(24, "SPI1_MISO"), -+ MT7981_PIN(25, "SPI1_CS"), -+ MT7981_PIN(26, "SPI2_CLK"), -+ MT7981_PIN(27, "SPI2_MOSI"), -+ MT7981_PIN(28, "SPI2_MISO"), -+ MT7981_PIN(29, "SPI2_CS"), -+ MT7981_PIN(30, "SPI2_HOLD"), -+ MT7981_PIN(31, "SPI2_WP"), -+ MT7981_PIN(32, "UART0_RXD"), -+ MT7981_PIN(33, "UART0_TXD"), -+ MT7981_PIN(34, "PCIE_CLK_REQ"), -+ MT7981_PIN(35, "PCIE_WAKE_N"), -+ MT7981_PIN(36, "SMI_MDC"), -+ MT7981_PIN(37, "SMI_MDIO"), -+ MT7981_PIN(38, "GBE_INT"), -+ MT7981_PIN(39, "GBE_RESET"), -+ MT7981_PIN(40, "WF_DIG_RESETB"), -+ MT7981_PIN(41, "WF_CBA_RESETB"), -+ MT7981_PIN(42, "WF_XO_REQ"), -+ MT7981_PIN(43, "WF_TOP_CLK"), -+ MT7981_PIN(44, "WF_TOP_DATA"), -+ MT7981_PIN(45, "WF_HB1"), -+ MT7981_PIN(46, "WF_HB2"), -+ MT7981_PIN(47, "WF_HB3"), -+ MT7981_PIN(48, "WF_HB4"), -+ MT7981_PIN(49, "WF_HB0"), -+ MT7981_PIN(50, "WF_HB0_B"), -+ MT7981_PIN(51, "WF_HB5"), -+ MT7981_PIN(52, "WF_HB6"), -+ MT7981_PIN(53, "WF_HB7"), -+ MT7981_PIN(54, "WF_HB8"), -+ MT7981_PIN(55, "WF_HB9"), -+ MT7981_PIN(56, "WF_HB10"), -+}; -+ -+/* List all groups consisting of these pins dedicated to the enablement of -+ * certain hardware block and the corresponding mode for all of the pins. -+ * The hardware probably has multiple combinations of these pinouts. -+ */ -+ -+/* WA_AICE */ -+static int mt7981_wa_aice1_pins[] = { 0, 1, }; -+static int mt7981_wa_aice1_funcs[] = { 2, 2, }; -+ -+static int mt7981_wa_aice2_pins[] = { 0, 1, }; -+static int mt7981_wa_aice2_funcs[] = { 3, 3, }; -+ -+static int mt7981_wa_aice3_pins[] = { 28, 29, }; -+static int mt7981_wa_aice3_funcs[] = { 3, 3, }; -+ -+static int mt7981_wm_aice1_pins[] = { 9, 10, }; -+static int mt7981_wm_aice1_funcs[] = { 2, 2, }; -+ -+static int mt7981_wm_aice2_pins[] = { 30, 31, }; -+static int mt7981_wm_aice2_funcs[] = { 5, 5, }; -+ -+/* WM_UART */ -+static int mt7981_wm_uart_0_pins[] = { 0, 1, }; -+static int mt7981_wm_uart_0_funcs[] = { 5, 5, }; -+ -+static int mt7981_wm_uart_1_pins[] = { 20, 21, }; -+static int mt7981_wm_uart_1_funcs[] = { 4, 4, }; -+ -+static int mt7981_wm_uart_2_pins[] = { 30, 31, }; -+static int mt7981_wm_uart_2_funcs[] = { 3, 3, }; -+ -+/* DFD */ -+static int mt7981_dfd_pins[] = { 0, 1, 4, 5, }; -+static int mt7981_dfd_funcs[] = { 5, 5, 6, 6, }; -+ -+/* SYS_WATCHDOG */ -+static int mt7981_watchdog_pins[] = { 2, }; -+static int mt7981_watchdog_funcs[] = { 1, }; -+ -+static int mt7981_watchdog1_pins[] = { 13, }; -+static int mt7981_watchdog1_funcs[] = { 5, }; -+ -+/* PCIE_PERESET_N */ -+static int mt7981_pcie_pereset_pins[] = { 3, }; -+static int mt7981_pcie_pereset_funcs[] = { 1, }; -+ -+/* JTAG */ -+static int mt7981_jtag_pins[] = { 4, 5, 6, 7, 8, }; -+static int mt7981_jtag_funcs[] = { 1, 1, 1, 1, 1, }; -+ -+/* WM_JTAG */ -+static int mt7981_wm_jtag_0_pins[] = { 4, 5, 6, 7, 8, }; -+static int mt7981_wm_jtag_0_funcs[] = { 2, 2, 2, 2, 2, }; -+ -+static int mt7981_wm_jtag_1_pins[] = { 20, 21, 22, 23, 24, }; -+static int mt7981_wm_jtag_1_funcs[] = { 5, 5, 5, 5, 5, }; -+ -+/* WO0_JTAG */ -+static int mt7981_wo0_jtag_0_pins[] = { 9, 10, 11, 12, 13, }; -+static int mt7981_wo0_jtag_0_funcs[] = { 1, 1, 1, 1, 1, }; -+ -+static int mt7981_wo0_jtag_1_pins[] = { 25, 26, 27, 28, 29, }; -+static int mt7981_wo0_jtag_1_funcs[] = { 5, 5, 5, 5, 5, }; -+ -+/* UART2 */ -+static int mt7981_uart2_0_pins[] = { 4, 5, 6, 7, }; -+static int mt7981_uart2_0_funcs[] = { 3, 3, 3, 3, }; -+ -+/* GBE_LED0 */ -+static int mt7981_gbe_led0_pins[] = { 8, }; -+static int mt7981_gbe_led0_funcs[] = { 3, }; -+ -+/* PTA_EXT */ -+static int mt7981_pta_ext_0_pins[] = { 4, 5, 6, }; -+static int mt7981_pta_ext_0_funcs[] = { 4, 4, 4, }; -+ -+static int mt7981_pta_ext_1_pins[] = { 22, 23, 24, }; -+static int mt7981_pta_ext_1_funcs[] = { 4, 4, 4, }; -+ -+/* PWM2 */ -+static int mt7981_pwm2_pins[] = { 7, }; -+static int mt7981_pwm2_funcs[] = { 4, }; -+ -+/* NET_WO0_UART_TXD */ -+static int mt7981_net_wo0_uart_txd_0_pins[] = { 8, }; -+static int mt7981_net_wo0_uart_txd_0_funcs[] = { 4, }; -+ -+static int mt7981_net_wo0_uart_txd_1_pins[] = { 14, }; -+static int mt7981_net_wo0_uart_txd_1_funcs[] = { 3, }; -+ -+static int mt7981_net_wo0_uart_txd_2_pins[] = { 15, }; -+static int mt7981_net_wo0_uart_txd_2_funcs[] = { 4, }; -+ -+/* SPI1 */ -+static int mt7981_spi1_0_pins[] = { 4, 5, 6, 7, }; -+static int mt7981_spi1_0_funcs[] = { 5, 5, 5, 5, }; -+ -+/* I2C */ -+static int mt7981_i2c0_0_pins[] = { 6, 7, }; -+static int mt7981_i2c0_0_funcs[] = { 6, 6, }; -+ -+static int mt7981_i2c0_1_pins[] = { 30, 31, }; -+static int mt7981_i2c0_1_funcs[] = { 4, 4, }; -+ -+static int mt7981_i2c0_2_pins[] = { 36, 37, }; -+static int mt7981_i2c0_2_funcs[] = { 2, 2, }; -+ -+static int mt7981_u2_phy_i2c_pins[] = { 30, 31, }; -+static int mt7981_u2_phy_i2c_funcs[] = { 6, 6, }; -+ -+static int mt7981_u3_phy_i2c_pins[] = { 32, 33, }; -+static int mt7981_u3_phy_i2c_funcs[] = { 3, 3, }; -+ -+static int mt7981_sgmii1_phy_i2c_pins[] = { 32, 33, }; -+static int mt7981_sgmii1_phy_i2c_funcs[] = { 2, 2, }; -+ -+static int mt7981_sgmii0_phy_i2c_pins[] = { 32, 33, }; -+static int mt7981_sgmii0_phy_i2c_funcs[] = { 5, 5, }; -+ -+/* DFD_NTRST */ -+static int mt7981_dfd_ntrst_pins[] = { 8, }; -+static int mt7981_dfd_ntrst_funcs[] = { 6, }; -+ -+/* PWM0 */ -+static int mt7981_pwm0_0_pins[] = { 13, }; -+static int mt7981_pwm0_0_funcs[] = { 2, }; -+ -+static int mt7981_pwm0_1_pins[] = { 15, }; -+static int mt7981_pwm0_1_funcs[] = { 1, }; -+ -+/* PWM1 */ -+static int mt7981_pwm1_0_pins[] = { 14, }; -+static int mt7981_pwm1_0_funcs[] = { 2, }; -+ -+static int mt7981_pwm1_1_pins[] = { 15, }; -+static int mt7981_pwm1_1_funcs[] = { 3, }; -+ -+/* GBE_LED1 */ -+static int mt7981_gbe_led1_pins[] = { 13, }; -+static int mt7981_gbe_led1_funcs[] = { 3, }; -+ -+/* PCM */ -+static int mt7981_pcm_pins[] = { 9, 10, 11, 12, 13, 25 }; -+static int mt7981_pcm_funcs[] = { 4, 4, 4, 4, 4, 4, }; -+ -+/* UDI */ -+static int mt7981_udi_pins[] = { 9, 10, 11, 12, 13, }; -+static int mt7981_udi_funcs[] = { 6, 6, 6, 6, 6, }; -+ -+/* DRV_VBUS */ -+static int mt7981_drv_vbus_pins[] = { 14, }; -+static int mt7981_drv_vbus_funcs[] = { 1, }; -+ -+/* EMMC */ -+static int mt7981_emmc_45_pins[] = { 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, }; -+static int mt7981_emmc_45_funcs[] = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, }; -+ -+/* SNFI */ -+static int mt7981_snfi_pins[] = { 16, 17, 18, 19, 20, 21, }; -+static int mt7981_snfi_funcs[] = { 3, 3, 3, 3, 3, 3, }; -+ -+/* SPI0 */ -+static int mt7981_spi0_pins[] = { 16, 17, 18, 19, }; -+static int mt7981_spi0_funcs[] = { 1, 1, 1, 1, }; -+ -+/* SPI0 */ -+static int mt7981_spi0_wp_hold_pins[] = { 20, 21, }; -+static int mt7981_spi0_wp_hold_funcs[] = { 1, 1, }; -+ -+/* SPI1 */ -+static int mt7981_spi1_1_pins[] = { 22, 23, 24, 25, }; -+static int mt7981_spi1_1_funcs[] = { 1, 1, 1, 1, }; -+ -+/* SPI2 */ -+static int mt7981_spi2_pins[] = { 26, 27, 28, 29, }; -+static int mt7981_spi2_funcs[] = { 1, 1, 1, 1, }; -+ -+/* SPI2 */ -+static int mt7981_spi2_wp_hold_pins[] = { 30, 31, }; -+static int mt7981_spi2_wp_hold_funcs[] = { 1, 1, }; -+ -+/* UART1 */ -+static int mt7981_uart1_0_pins[] = { 16, 17, 18, 19, }; -+static int mt7981_uart1_0_funcs[] = { 4, 4, 4, 4, }; -+ -+static int mt7981_uart1_1_pins[] = { 26, 27, 28, 29, }; -+static int mt7981_uart1_1_funcs[] = { 2, 2, 2, 2, }; -+ -+/* UART2 */ -+static int mt7981_uart2_1_pins[] = { 22, 23, 24, 25, }; -+static int mt7981_uart2_1_funcs[] = { 3, 3, 3, 3, }; -+ -+/* UART0 */ -+static int mt7981_uart0_pins[] = { 32, 33, }; -+static int mt7981_uart0_funcs[] = { 1, 1, }; -+ -+/* PCIE_CLK_REQ */ -+static int mt7981_pcie_clk_pins[] = { 34, }; -+static int mt7981_pcie_clk_funcs[] = { 2, }; -+ -+/* PCIE_WAKE_N */ -+static int mt7981_pcie_wake_pins[] = { 35, }; -+static int mt7981_pcie_wake_funcs[] = { 2, }; -+ -+/* MDC_MDIO */ -+static int mt7981_smi_mdc_mdio_pins[] = { 36, 37, }; -+static int mt7981_smi_mdc_mdio_funcs[] = { 1, 1, }; -+ -+static int mt7981_gbe_ext_mdc_mdio_pins[] = { 36, 37, }; -+static int mt7981_gbe_ext_mdc_mdio_funcs[] = { 3, 3, }; -+ -+/* WF0_MODE1 */ -+static int mt7981_wf0_mode1_pins[] = { 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56 }; -+static int mt7981_wf0_mode1_funcs[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; -+ -+/* WF0_MODE3 */ -+static int mt7981_wf0_mode3_pins[] = { 45, 46, 47, 48, 49, 51 }; -+static int mt7981_wf0_mode3_funcs[] = { 2, 2, 2, 2, 2, 2 }; -+ -+/* WF2G_LED */ -+static int mt7981_wf2g_led0_pins[] = { 30, }; -+static int mt7981_wf2g_led0_funcs[] = { 2, }; -+ -+static int mt7981_wf2g_led1_pins[] = { 34, }; -+static int mt7981_wf2g_led1_funcs[] = { 1, }; -+ -+/* WF5G_LED */ -+static int mt7981_wf5g_led0_pins[] = { 31, }; -+static int mt7981_wf5g_led0_funcs[] = { 2, }; -+ -+static int mt7981_wf5g_led1_pins[] = { 35, }; -+static int mt7981_wf5g_led1_funcs[] = { 1, }; -+ -+/* MT7531_INT */ -+static int mt7981_mt7531_int_pins[] = { 38, }; -+static int mt7981_mt7531_int_funcs[] = { 1, }; -+ -+/* ANT_SEL */ -+static int mt7981_ant_sel_pins[] = { 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 34, 35 }; -+static int mt7981_ant_sel_funcs[] = { 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6 }; -+ -+static const struct group_desc mt7981_groups[] = { -+ /* @GPIO(0,1): WA_AICE(2) */ -+ PINCTRL_PIN_GROUP("wa_aice1", mt7981_wa_aice1), -+ /* @GPIO(0,1): WA_AICE(3) */ -+ PINCTRL_PIN_GROUP("wa_aice2", mt7981_wa_aice2), -+ /* @GPIO(0,1): WM_UART(5) */ -+ PINCTRL_PIN_GROUP("wm_uart_0", mt7981_wm_uart_0), -+ /* @GPIO(0,1,4,5): DFD(6) */ -+ PINCTRL_PIN_GROUP("dfd", mt7981_dfd), -+ /* @GPIO(2): SYS_WATCHDOG(1) */ -+ PINCTRL_PIN_GROUP("watchdog", mt7981_watchdog), -+ /* @GPIO(3): PCIE_PERESET_N(1) */ -+ PINCTRL_PIN_GROUP("pcie_pereset", mt7981_pcie_pereset), -+ /* @GPIO(4,8) JTAG(1) */ -+ PINCTRL_PIN_GROUP("jtag", mt7981_jtag), -+ /* @GPIO(4,8) WM_JTAG(2) */ -+ PINCTRL_PIN_GROUP("wm_jtag_0", mt7981_wm_jtag_0), -+ /* @GPIO(9,13) WO0_JTAG(1) */ -+ PINCTRL_PIN_GROUP("wo0_jtag_0", mt7981_wo0_jtag_0), -+ /* @GPIO(4,7) WM_JTAG(3) */ -+ PINCTRL_PIN_GROUP("uart2_0", mt7981_uart2_0), -+ /* @GPIO(8) GBE_LED0(3) */ -+ PINCTRL_PIN_GROUP("gbe_led0", mt7981_gbe_led0), -+ /* @GPIO(4,6) PTA_EXT(4) */ -+ PINCTRL_PIN_GROUP("pta_ext_0", mt7981_pta_ext_0), -+ /* @GPIO(7) PWM2(4) */ -+ PINCTRL_PIN_GROUP("pwm2", mt7981_pwm2), -+ /* @GPIO(8) NET_WO0_UART_TXD(4) */ -+ PINCTRL_PIN_GROUP("net_wo0_uart_txd_0", mt7981_net_wo0_uart_txd_0), -+ /* @GPIO(4,7) SPI1(5) */ -+ PINCTRL_PIN_GROUP("spi1_0", mt7981_spi1_0), -+ /* @GPIO(6,7) I2C(5) */ -+ PINCTRL_PIN_GROUP("i2c0_0", mt7981_i2c0_0), -+ /* @GPIO(0,1,4,5): DFD_NTRST(6) */ -+ PINCTRL_PIN_GROUP("dfd_ntrst", mt7981_dfd_ntrst), -+ /* @GPIO(9,10): WM_AICE(2) */ -+ PINCTRL_PIN_GROUP("wm_aice1", mt7981_wm_aice1), -+ /* @GPIO(13): PWM0(2) */ -+ PINCTRL_PIN_GROUP("pwm0_0", mt7981_pwm0_0), -+ /* @GPIO(15): PWM0(1) */ -+ PINCTRL_PIN_GROUP("pwm0_1", mt7981_pwm0_1), -+ /* @GPIO(14): PWM1(2) */ -+ PINCTRL_PIN_GROUP("pwm1_0", mt7981_pwm1_0), -+ /* @GPIO(15): PWM1(3) */ -+ PINCTRL_PIN_GROUP("pwm1_1", mt7981_pwm1_1), -+ /* @GPIO(14) NET_WO0_UART_TXD(3) */ -+ PINCTRL_PIN_GROUP("net_wo0_uart_txd_1", mt7981_net_wo0_uart_txd_1), -+ /* @GPIO(15) NET_WO0_UART_TXD(4) */ -+ PINCTRL_PIN_GROUP("net_wo0_uart_txd_2", mt7981_net_wo0_uart_txd_2), -+ /* @GPIO(13) GBE_LED0(3) */ -+ PINCTRL_PIN_GROUP("gbe_led1", mt7981_gbe_led1), -+ /* @GPIO(9,13) PCM(4) */ -+ PINCTRL_PIN_GROUP("pcm", mt7981_pcm), -+ /* @GPIO(13): SYS_WATCHDOG1(5) */ -+ PINCTRL_PIN_GROUP("watchdog1", mt7981_watchdog1), -+ /* @GPIO(9,13) UDI(4) */ -+ PINCTRL_PIN_GROUP("udi", mt7981_udi), -+ /* @GPIO(14) DRV_VBUS(1) */ -+ PINCTRL_PIN_GROUP("drv_vbus", mt7981_drv_vbus), -+ /* @GPIO(15,25): EMMC(2) */ -+ PINCTRL_PIN_GROUP("emmc_45", mt7981_emmc_45), -+ /* @GPIO(16,21): SNFI(3) */ -+ PINCTRL_PIN_GROUP("snfi", mt7981_snfi), -+ /* @GPIO(16,19): SPI0(1) */ -+ PINCTRL_PIN_GROUP("spi0", mt7981_spi0), -+ /* @GPIO(20,21): SPI0(1) */ -+ PINCTRL_PIN_GROUP("spi0_wp_hold", mt7981_spi0_wp_hold), -+ /* @GPIO(22,25) SPI1(1) */ -+ PINCTRL_PIN_GROUP("spi1_1", mt7981_spi1_1), -+ /* @GPIO(26,29): SPI2(1) */ -+ PINCTRL_PIN_GROUP("spi2", mt7981_spi2), -+ /* @GPIO(30,31): SPI0(1) */ -+ PINCTRL_PIN_GROUP("spi2_wp_hold", mt7981_spi2_wp_hold), -+ /* @GPIO(16,19): UART1(4) */ -+ PINCTRL_PIN_GROUP("uart1_0", mt7981_uart1_0), -+ /* @GPIO(26,29): UART1(2) */ -+ PINCTRL_PIN_GROUP("uart1_1", mt7981_uart1_1), -+ /* @GPIO(22,25): UART1(3) */ -+ PINCTRL_PIN_GROUP("uart2_1", mt7981_uart2_1), -+ /* @GPIO(22,24) PTA_EXT(4) */ -+ PINCTRL_PIN_GROUP("pta_ext_1", mt7981_pta_ext_1), -+ /* @GPIO(20,21): WM_UART(4) */ -+ PINCTRL_PIN_GROUP("wm_aurt_1", mt7981_wm_uart_1), -+ /* @GPIO(30,31): WM_UART(3) */ -+ PINCTRL_PIN_GROUP("wm_aurt_2", mt7981_wm_uart_2), -+ /* @GPIO(20,24) WM_JTAG(5) */ -+ PINCTRL_PIN_GROUP("wm_jtag_1", mt7981_wm_jtag_1), -+ /* @GPIO(25,29) WO0_JTAG(5) */ -+ PINCTRL_PIN_GROUP("wo0_jtag_1", mt7981_wo0_jtag_1), -+ /* @GPIO(28,29): WA_AICE(3) */ -+ PINCTRL_PIN_GROUP("wa_aice3", mt7981_wa_aice3), -+ /* @GPIO(30,31): WM_AICE(5) */ -+ PINCTRL_PIN_GROUP("wm_aice2", mt7981_wm_aice2), -+ /* @GPIO(30,31): I2C(4) */ -+ PINCTRL_PIN_GROUP("i2c0_1", mt7981_i2c0_1), -+ /* @GPIO(30,31): I2C(6) */ -+ PINCTRL_PIN_GROUP("u2_phy_i2c", mt7981_u2_phy_i2c), -+ /* @GPIO(32,33): I2C(1) */ -+ PINCTRL_PIN_GROUP("uart0", mt7981_uart0), -+ /* @GPIO(32,33): I2C(2) */ -+ PINCTRL_PIN_GROUP("sgmii1_phy_i2c", mt7981_sgmii1_phy_i2c), -+ /* @GPIO(32,33): I2C(3) */ -+ PINCTRL_PIN_GROUP("u3_phy_i2c", mt7981_u3_phy_i2c), -+ /* @GPIO(32,33): I2C(5) */ -+ PINCTRL_PIN_GROUP("sgmii0_phy_i2c", mt7981_sgmii0_phy_i2c), -+ /* @GPIO(34): PCIE_CLK_REQ(2) */ -+ PINCTRL_PIN_GROUP("pcie_clk", mt7981_pcie_clk), -+ /* @GPIO(35): PCIE_WAKE_N(2) */ -+ PINCTRL_PIN_GROUP("pcie_wake", mt7981_pcie_wake), -+ /* @GPIO(36,37): I2C(2) */ -+ PINCTRL_PIN_GROUP("i2c0_2", mt7981_i2c0_2), -+ /* @GPIO(36,37): MDC_MDIO(1) */ -+ PINCTRL_PIN_GROUP("smi_mdc_mdio", mt7981_smi_mdc_mdio), -+ /* @GPIO(36,37): MDC_MDIO(3) */ -+ PINCTRL_PIN_GROUP("gbe_ext_mdc_mdio", mt7981_gbe_ext_mdc_mdio), -+ /* @GPIO(69,85): WF0_MODE1(1) */ -+ PINCTRL_PIN_GROUP("wf0_mode1", mt7981_wf0_mode1), -+ /* @GPIO(74,80): WF0_MODE3(3) */ -+ PINCTRL_PIN_GROUP("wf0_mode3", mt7981_wf0_mode3), -+ /* @GPIO(30): WF2G_LED(2) */ -+ PINCTRL_PIN_GROUP("wf2g_led0", mt7981_wf2g_led0), -+ /* @GPIO(34): WF2G_LED(1) */ -+ PINCTRL_PIN_GROUP("wf2g_led1", mt7981_wf2g_led1), -+ /* @GPIO(31): WF5G_LED(2) */ -+ PINCTRL_PIN_GROUP("wf5g_led0", mt7981_wf5g_led0), -+ /* @GPIO(35): WF5G_LED(1) */ -+ PINCTRL_PIN_GROUP("wf5g_led1", mt7981_wf5g_led1), -+ /* @GPIO(38): MT7531_INT(1) */ -+ PINCTRL_PIN_GROUP("mt7531_int", mt7981_mt7531_int), -+ /* @GPIO(14,15,26,17,18,19,20,21,22,23,24,25,34,35): ANT_SEL(1) */ -+ PINCTRL_PIN_GROUP("ant_sel", mt7981_ant_sel), -+}; -+ -+/* Joint those groups owning the same capability in user point of view which -+ * allows that people tend to use through the device tree. -+ */ -+static const char *mt7981_wa_aice_groups[] = { "wa_aice1", "wa_aice2", "wm_aice1_1", -+ "wa_aice3", "wm_aice1_2", }; -+static const char *mt7981_uart_groups[] = { "wm_uart_0", "uart2_0", -+ "net_wo0_uart_txd_0", "net_wo0_uart_txd_1", "net_wo0_uart_txd_2", -+ "uart1_0", "uart1_1", "uart2_1", "wm_aurt_1", "wm_aurt_2", "uart0", }; -+static const char *mt7981_dfd_groups[] = { "dfd", "dfd_ntrst", }; -+static const char *mt7981_wdt_groups[] = { "watchdog", "watchdog1", }; -+static const char *mt7981_pcie_groups[] = { "pcie_pereset", "pcie_clk", "pcie_wake", }; -+static const char *mt7981_jtag_groups[] = { "jtag", "wm_jtag_0", "wo0_jtag_0", -+ "wo0_jtag_1", "wm_jtag_1", }; -+static const char *mt7981_led_groups[] = { "gbe_led0", "gbe_led1", "wf2g_led0", -+ "wf2g_led1", "wf5g_led0", "wf5g_led1", }; -+static const char *mt7981_pta_groups[] = { "pta_ext_0", "pta_ext_1", }; -+static const char *mt7981_pwm_groups[] = { "pwm2", "pwm0_0", "pwm0_1", -+ "pwm1_0", "pwm1_1", }; -+static const char *mt7981_spi_groups[] = { "spi1_0", "spi0", "spi0_wp_hold", "spi1_1", "spi2", -+ "spi2_wp_hold", }; -+static const char *mt7981_i2c_groups[] = { "i2c0_0", "i2c0_1", "u2_phy_i2c", -+ "sgmii1_phy_i2c", "u3_phy_i2c", "sgmii0_phy_i2c", "i2c0_2", }; -+static const char *mt7981_pcm_groups[] = { "pcm", }; -+static const char *mt7981_udi_groups[] = { "udi", }; -+static const char *mt7981_usb_groups[] = { "drv_vbus", }; -+static const char *mt7981_flash_groups[] = { "emmc_45", "snfi", }; -+static const char *mt7981_ethernet_groups[] = { "smi_mdc_mdio", "gbe_ext_mdc_mdio", -+ "wf0_mode1", "wf0_mode3", "mt7531_int", }; -+static const char *mt7981_ant_groups[] = { "ant_sel", }; -+ -+static const struct function_desc mt7981_functions[] = { -+ {"wa_aice", mt7981_wa_aice_groups, ARRAY_SIZE(mt7981_wa_aice_groups)}, -+ {"dfd", mt7981_dfd_groups, ARRAY_SIZE(mt7981_dfd_groups)}, -+ {"jtag", mt7981_jtag_groups, ARRAY_SIZE(mt7981_jtag_groups)}, -+ {"pta", mt7981_pta_groups, ARRAY_SIZE(mt7981_pta_groups)}, -+ {"pcm", mt7981_pcm_groups, ARRAY_SIZE(mt7981_pcm_groups)}, -+ {"udi", mt7981_udi_groups, ARRAY_SIZE(mt7981_udi_groups)}, -+ {"usb", mt7981_usb_groups, ARRAY_SIZE(mt7981_usb_groups)}, -+ {"ant", mt7981_ant_groups, ARRAY_SIZE(mt7981_ant_groups)}, -+ {"eth", mt7981_ethernet_groups, ARRAY_SIZE(mt7981_ethernet_groups)}, -+ {"i2c", mt7981_i2c_groups, ARRAY_SIZE(mt7981_i2c_groups)}, -+ {"led", mt7981_led_groups, ARRAY_SIZE(mt7981_led_groups)}, -+ {"pwm", mt7981_pwm_groups, ARRAY_SIZE(mt7981_pwm_groups)}, -+ {"spi", mt7981_spi_groups, ARRAY_SIZE(mt7981_spi_groups)}, -+ {"uart", mt7981_uart_groups, ARRAY_SIZE(mt7981_uart_groups)}, -+ {"watchdog", mt7981_wdt_groups, ARRAY_SIZE(mt7981_wdt_groups)}, -+ {"flash", mt7981_flash_groups, ARRAY_SIZE(mt7981_flash_groups)}, -+ {"pcie", mt7981_pcie_groups, ARRAY_SIZE(mt7981_pcie_groups)}, -+}; -+ -+static const struct mtk_eint_hw mt7981_eint_hw = { -+ .port_mask = 7, -+ .ports = 7, -+ .ap_num = ARRAY_SIZE(mt7981_pins), -+ .db_cnt = 16, -+}; -+ -+static const char * const mt7981_pinctrl_register_base_names[] = { -+ "gpio", "iocfg_rt", "iocfg_rm", "iocfg_rb", -+ "iocfg_lb", "iocfg_bl", "iocfg_tm", "iocfg_tl", -+}; -+ -+static struct mtk_pin_soc mt7981_data = { -+ .reg_cal = mt7981_reg_cals, -+ .pins = mt7981_pins, -+ .npins = ARRAY_SIZE(mt7981_pins), -+ .grps = mt7981_groups, -+ .ngrps = ARRAY_SIZE(mt7981_groups), -+ .funcs = mt7981_functions, -+ .nfuncs = ARRAY_SIZE(mt7981_functions), -+ .eint_hw = &mt7981_eint_hw, -+ .gpio_m = 0, -+ .ies_present = false, -+ .base_names = mt7981_pinctrl_register_base_names, -+ .nbase_names = ARRAY_SIZE(mt7981_pinctrl_register_base_names), -+ .pull_type = mt7981_pull_type, -+ .bias_set_combo = mtk_pinconf_bias_set_combo, -+ .bias_get_combo = mtk_pinconf_bias_get_combo, -+ .drive_set = mtk_pinconf_drive_set_rev1, -+ .drive_get = mtk_pinconf_drive_get_rev1, -+ .adv_pull_get = mtk_pinconf_adv_pull_get, -+ .adv_pull_set = mtk_pinconf_adv_pull_set, -+}; -+ -+static const struct of_device_id mt7981_pinctrl_of_match[] = { -+ { .compatible = "mediatek,mt7981-pinctrl", }, -+ {} -+}; -+ -+static int mt7981_pinctrl_probe(struct platform_device *pdev) -+{ -+ return mtk_moore_pinctrl_probe(pdev, &mt7981_data); -+} -+ -+static struct platform_driver mt7981_pinctrl_driver = { -+ .driver = { -+ .name = "mt7981-pinctrl", -+ .of_match_table = mt7981_pinctrl_of_match, -+ }, -+ .probe = mt7981_pinctrl_probe, -+}; -+ -+static int __init mt7981_pinctrl_init(void) -+{ -+ return platform_driver_register(&mt7981_pinctrl_driver); -+} -+arch_initcall(mt7981_pinctrl_init); diff --git a/target/linux/mediatek/patches-6.1/216-v6.3-pinctrl-mediatek-add-missing-options-to-PINCTRL_MT79.patch b/target/linux/mediatek/patches-6.1/216-v6.3-pinctrl-mediatek-add-missing-options-to-PINCTRL_MT79.patch deleted file mode 100644 index 995e0dc7e..000000000 --- a/target/linux/mediatek/patches-6.1/216-v6.3-pinctrl-mediatek-add-missing-options-to-PINCTRL_MT79.patch +++ /dev/null @@ -1,30 +0,0 @@ -From c0ad453e94e5c404efbcf668648d07eaa1a71ed7 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= -Date: Sat, 18 Feb 2023 09:51:06 +0300 -Subject: [PATCH] pinctrl: mediatek: add missing options to PINCTRL_MT7981 -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -There are options missing from PINCTRL_MT7981 whilst being on every other -pin controller. Add them. - -Signed-off-by: Arınç ÜNAL -Acked-by: Daniel Golle -Link: https://lore.kernel.org/r/20230218065108.8958-1-arinc.unal@arinc9.com -Signed-off-by: Linus Walleij ---- - drivers/pinctrl/mediatek/Kconfig | 2 ++ - 1 file changed, 2 insertions(+) - ---- a/drivers/pinctrl/mediatek/Kconfig -+++ b/drivers/pinctrl/mediatek/Kconfig -@@ -130,6 +130,8 @@ config PINCTRL_MT7622 - config PINCTRL_MT7981 - bool "Mediatek MT7981 pin control" - depends on OF -+ depends on ARM64 || COMPILE_TEST -+ default ARM64 && ARCH_MEDIATEK - select PINCTRL_MTK_MOORE - - config PINCTRL_MT7986 diff --git a/target/linux/mediatek/patches-6.1/217-v6.5-pinctrl-mediatek-fix-pull_type-data-for-MT7981.patch b/target/linux/mediatek/patches-6.1/217-v6.5-pinctrl-mediatek-fix-pull_type-data-for-MT7981.patch deleted file mode 100644 index db2561695..000000000 --- a/target/linux/mediatek/patches-6.1/217-v6.5-pinctrl-mediatek-fix-pull_type-data-for-MT7981.patch +++ /dev/null @@ -1,76 +0,0 @@ -From 8f6f16fe1553ce63edfb98a39ef9d4754a0c39bf Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Fri, 18 Aug 2023 04:02:35 +0100 -Subject: [PATCH] pinctrl: mediatek: fix pull_type data for MT7981 - -MediaTek has released pull_type data for MT7981 in their SDK. -Use it and set functions to configure pin bias. - -Fixes: 6c83b2d94fcc ("pinctrl: add mt7981 pinctrl driver") -Signed-off-by: Daniel Golle -Link: https://lore.kernel.org/r/7bcc8ead25dbfabc7f5a85d066224a926fbb4941.1692327317.git.daniel@makrotopia.org -Signed-off-by: Linus Walleij ---- - drivers/pinctrl/mediatek/pinctrl-mt7981.c | 44 +++++++---------------- - 1 file changed, 13 insertions(+), 31 deletions(-) - ---- a/drivers/pinctrl/mediatek/pinctrl-mt7981.c -+++ b/drivers/pinctrl/mediatek/pinctrl-mt7981.c -@@ -457,37 +457,15 @@ static const unsigned int mt7981_pull_ty - MTK_PULL_PUPD_R1R0_TYPE,/*34*/ MTK_PULL_PUPD_R1R0_TYPE,/*35*/ - MTK_PULL_PUPD_R1R0_TYPE,/*36*/ MTK_PULL_PUPD_R1R0_TYPE,/*37*/ - MTK_PULL_PUPD_R1R0_TYPE,/*38*/ MTK_PULL_PUPD_R1R0_TYPE,/*39*/ -- MTK_PULL_PUPD_R1R0_TYPE,/*40*/ MTK_PULL_PUPD_R1R0_TYPE,/*41*/ -- MTK_PULL_PUPD_R1R0_TYPE,/*42*/ MTK_PULL_PUPD_R1R0_TYPE,/*43*/ -- MTK_PULL_PUPD_R1R0_TYPE,/*44*/ MTK_PULL_PUPD_R1R0_TYPE,/*45*/ -- MTK_PULL_PUPD_R1R0_TYPE,/*46*/ MTK_PULL_PUPD_R1R0_TYPE,/*47*/ -- MTK_PULL_PUPD_R1R0_TYPE,/*48*/ MTK_PULL_PUPD_R1R0_TYPE,/*49*/ -- MTK_PULL_PUPD_R1R0_TYPE,/*50*/ MTK_PULL_PUPD_R1R0_TYPE,/*51*/ -- MTK_PULL_PUPD_R1R0_TYPE,/*52*/ MTK_PULL_PUPD_R1R0_TYPE,/*53*/ -- MTK_PULL_PUPD_R1R0_TYPE,/*54*/ MTK_PULL_PUPD_R1R0_TYPE,/*55*/ -- MTK_PULL_PUPD_R1R0_TYPE,/*56*/ MTK_PULL_PUPD_R1R0_TYPE,/*57*/ -- MTK_PULL_PUPD_R1R0_TYPE,/*58*/ MTK_PULL_PUPD_R1R0_TYPE,/*59*/ -- MTK_PULL_PUPD_R1R0_TYPE,/*60*/ MTK_PULL_PUPD_R1R0_TYPE,/*61*/ -- MTK_PULL_PUPD_R1R0_TYPE,/*62*/ MTK_PULL_PUPD_R1R0_TYPE,/*63*/ -- MTK_PULL_PUPD_R1R0_TYPE,/*64*/ MTK_PULL_PUPD_R1R0_TYPE,/*65*/ -- MTK_PULL_PUPD_R1R0_TYPE,/*66*/ MTK_PULL_PUPD_R1R0_TYPE,/*67*/ -- MTK_PULL_PUPD_R1R0_TYPE,/*68*/ MTK_PULL_PU_PD_TYPE,/*69*/ -- MTK_PULL_PU_PD_TYPE,/*70*/ MTK_PULL_PU_PD_TYPE,/*71*/ -- MTK_PULL_PU_PD_TYPE,/*72*/ MTK_PULL_PU_PD_TYPE,/*73*/ -- MTK_PULL_PU_PD_TYPE,/*74*/ MTK_PULL_PU_PD_TYPE,/*75*/ -- MTK_PULL_PU_PD_TYPE,/*76*/ MTK_PULL_PU_PD_TYPE,/*77*/ -- MTK_PULL_PU_PD_TYPE,/*78*/ MTK_PULL_PU_PD_TYPE,/*79*/ -- MTK_PULL_PU_PD_TYPE,/*80*/ MTK_PULL_PU_PD_TYPE,/*81*/ -- MTK_PULL_PU_PD_TYPE,/*82*/ MTK_PULL_PU_PD_TYPE,/*83*/ -- MTK_PULL_PU_PD_TYPE,/*84*/ MTK_PULL_PU_PD_TYPE,/*85*/ -- MTK_PULL_PU_PD_TYPE,/*86*/ MTK_PULL_PU_PD_TYPE,/*87*/ -- MTK_PULL_PU_PD_TYPE,/*88*/ MTK_PULL_PU_PD_TYPE,/*89*/ -- MTK_PULL_PU_PD_TYPE,/*90*/ MTK_PULL_PU_PD_TYPE,/*91*/ -- MTK_PULL_PU_PD_TYPE,/*92*/ MTK_PULL_PU_PD_TYPE,/*93*/ -- MTK_PULL_PU_PD_TYPE,/*94*/ MTK_PULL_PU_PD_TYPE,/*95*/ -- MTK_PULL_PU_PD_TYPE,/*96*/ MTK_PULL_PU_PD_TYPE,/*97*/ -- MTK_PULL_PU_PD_TYPE,/*98*/ MTK_PULL_PU_PD_TYPE,/*99*/ -- MTK_PULL_PU_PD_TYPE,/*100*/ -+ MTK_PULL_PU_PD_TYPE,/*40*/ MTK_PULL_PU_PD_TYPE,/*41*/ -+ MTK_PULL_PU_PD_TYPE,/*42*/ MTK_PULL_PU_PD_TYPE,/*43*/ -+ MTK_PULL_PU_PD_TYPE,/*44*/ MTK_PULL_PU_PD_TYPE,/*45*/ -+ MTK_PULL_PU_PD_TYPE,/*46*/ MTK_PULL_PU_PD_TYPE,/*47*/ -+ MTK_PULL_PU_PD_TYPE,/*48*/ MTK_PULL_PU_PD_TYPE,/*49*/ -+ MTK_PULL_PU_PD_TYPE,/*50*/ MTK_PULL_PU_PD_TYPE,/*51*/ -+ MTK_PULL_PU_PD_TYPE,/*52*/ MTK_PULL_PU_PD_TYPE,/*53*/ -+ MTK_PULL_PU_PD_TYPE,/*54*/ MTK_PULL_PU_PD_TYPE,/*55*/ -+ MTK_PULL_PU_PD_TYPE,/*56*/ - }; - - static const struct mtk_pin_reg_calc mt7981_reg_cals[] = { -@@ -1014,6 +992,10 @@ static struct mtk_pin_soc mt7981_data = - .ies_present = false, - .base_names = mt7981_pinctrl_register_base_names, - .nbase_names = ARRAY_SIZE(mt7981_pinctrl_register_base_names), -+ .bias_disable_set = mtk_pinconf_bias_disable_set, -+ .bias_disable_get = mtk_pinconf_bias_disable_get, -+ .bias_set = mtk_pinconf_bias_set, -+ .bias_get = mtk_pinconf_bias_get, - .pull_type = mt7981_pull_type, - .bias_set_combo = mtk_pinconf_bias_set_combo, - .bias_get_combo = mtk_pinconf_bias_get_combo, diff --git a/target/linux/mediatek/patches-6.1/218-pinctrl-mediatek-mt7981-add-additional-uart-groups.patch b/target/linux/mediatek/patches-6.1/218-pinctrl-mediatek-mt7981-add-additional-uart-groups.patch deleted file mode 100644 index d2f055836..000000000 --- a/target/linux/mediatek/patches-6.1/218-pinctrl-mediatek-mt7981-add-additional-uart-groups.patch +++ /dev/null @@ -1,65 +0,0 @@ -From 11db447f257231e08065989100311df57b7f1f1c Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Sat, 26 Aug 2023 21:06:14 +0100 -Subject: [PATCH] pinctrl: mediatek: mt7981: add additional uart groups - -Add uart2_0_tx_rx (pin 4, 5) and uart1_2 (pins 9, 10) groups. - -Signed-off-by: Daniel Golle ---- - drivers/pinctrl/mediatek/pinctrl-mt7981.c | 16 +++++++++++++--- - 1 file changed, 13 insertions(+), 3 deletions(-) - ---- a/drivers/pinctrl/mediatek/pinctrl-mt7981.c -+++ b/drivers/pinctrl/mediatek/pinctrl-mt7981.c -@@ -611,6 +611,9 @@ static int mt7981_wo0_jtag_1_funcs[] = { - static int mt7981_uart2_0_pins[] = { 4, 5, 6, 7, }; - static int mt7981_uart2_0_funcs[] = { 3, 3, 3, 3, }; - -+static int mt7981_uart2_0_tx_rx_pins[] = { 4, 5, }; -+static int mt7981_uart2_0_tx_rx_funcs[] = { 3, 3, }; -+ - /* GBE_LED0 */ - static int mt7981_gbe_led0_pins[] = { 8, }; - static int mt7981_gbe_led0_funcs[] = { 3, }; -@@ -731,6 +734,9 @@ static int mt7981_uart1_0_funcs[] = { 4, - static int mt7981_uart1_1_pins[] = { 26, 27, 28, 29, }; - static int mt7981_uart1_1_funcs[] = { 2, 2, 2, 2, }; - -+static int mt7981_uart1_2_pins[] = { 9, 10, }; -+static int mt7981_uart1_2_funcs[] = { 2, 2, }; -+ - /* UART2 */ - static int mt7981_uart2_1_pins[] = { 22, 23, 24, 25, }; - static int mt7981_uart2_1_funcs[] = { 3, 3, 3, 3, }; -@@ -805,6 +811,8 @@ static const struct group_desc mt7981_gr - PINCTRL_PIN_GROUP("wo0_jtag_0", mt7981_wo0_jtag_0), - /* @GPIO(4,7) WM_JTAG(3) */ - PINCTRL_PIN_GROUP("uart2_0", mt7981_uart2_0), -+ /* @GPIO(4,5) WM_JTAG(4) */ -+ PINCTRL_PIN_GROUP("uart2_0_tx_rx", mt7981_uart2_0_tx_rx), - /* @GPIO(8) GBE_LED0(3) */ - PINCTRL_PIN_GROUP("gbe_led0", mt7981_gbe_led0), - /* @GPIO(4,6) PTA_EXT(4) */ -@@ -861,6 +869,8 @@ static const struct group_desc mt7981_gr - PINCTRL_PIN_GROUP("uart1_0", mt7981_uart1_0), - /* @GPIO(26,29): UART1(2) */ - PINCTRL_PIN_GROUP("uart1_1", mt7981_uart1_1), -+ /* @GPIO(9,10): UART1(2) */ -+ PINCTRL_PIN_GROUP("uart1_2", mt7981_uart1_2), - /* @GPIO(22,25): UART1(3) */ - PINCTRL_PIN_GROUP("uart2_1", mt7981_uart2_1), - /* @GPIO(22,24) PTA_EXT(4) */ -@@ -922,9 +932,9 @@ static const struct group_desc mt7981_gr - */ - static const char *mt7981_wa_aice_groups[] = { "wa_aice1", "wa_aice2", "wm_aice1_1", - "wa_aice3", "wm_aice1_2", }; --static const char *mt7981_uart_groups[] = { "wm_uart_0", "uart2_0", -- "net_wo0_uart_txd_0", "net_wo0_uart_txd_1", "net_wo0_uart_txd_2", -- "uart1_0", "uart1_1", "uart2_1", "wm_aurt_1", "wm_aurt_2", "uart0", }; -+static const char *mt7981_uart_groups[] = { "net_wo0_uart_txd_0", "net_wo0_uart_txd_1", -+ "net_wo0_uart_txd_2", "uart0", "uart1_0", "uart1_1", "uart1_2", "uart2_0", -+ "uart2_0_tx_rx", "uart2_1", "wm_uart_0", "wm_aurt_1", "wm_aurt_2", }; - static const char *mt7981_dfd_groups[] = { "dfd", "dfd_ntrst", }; - static const char *mt7981_wdt_groups[] = { "watchdog", "watchdog1", }; - static const char *mt7981_pcie_groups[] = { "pcie_pereset", "pcie_clk", "pcie_wake", }; diff --git a/target/linux/mediatek/patches-6.1/219-pinctrl-mediatek-assign-functions-to-configure-pin-b.patch b/target/linux/mediatek/patches-6.1/219-pinctrl-mediatek-assign-functions-to-configure-pin-b.patch deleted file mode 100644 index 7992a0267..000000000 --- a/target/linux/mediatek/patches-6.1/219-pinctrl-mediatek-assign-functions-to-configure-pin-b.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 0d8387fba9f151220e48dc3dcdc2335539708f13 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Fri, 18 Aug 2023 04:03:26 +0100 -Subject: [PATCH] pinctrl: mediatek: assign functions to configure pin bias on - MT7986 - -Assign bias_disable_get/set and bias_get/set functions to allow -configuring pin bias on MT7986. - -Fixes: 2c58d8dc9cd0 ("pinctrl: mediatek: add pull_type attribute for mediatek MT7986 SoC") -Signed-off-by: Daniel Golle -Link: https://lore.kernel.org/r/47f72372354312a839b9337e09476aadcc206e8b.1692327317.git.daniel@makrotopia.org -Signed-off-by: Linus Walleij ---- - drivers/pinctrl/mediatek/pinctrl-mt7986.c | 8 ++++++++ - 1 file changed, 8 insertions(+) - ---- a/drivers/pinctrl/mediatek/pinctrl-mt7986.c -+++ b/drivers/pinctrl/mediatek/pinctrl-mt7986.c -@@ -922,6 +922,10 @@ static struct mtk_pin_soc mt7986a_data = - .ies_present = false, - .base_names = mt7986_pinctrl_register_base_names, - .nbase_names = ARRAY_SIZE(mt7986_pinctrl_register_base_names), -+ .bias_disable_set = mtk_pinconf_bias_disable_set, -+ .bias_disable_get = mtk_pinconf_bias_disable_get, -+ .bias_set = mtk_pinconf_bias_set, -+ .bias_get = mtk_pinconf_bias_get, - .pull_type = mt7986_pull_type, - .bias_set_combo = mtk_pinconf_bias_set_combo, - .bias_get_combo = mtk_pinconf_bias_get_combo, -@@ -944,6 +948,10 @@ static struct mtk_pin_soc mt7986b_data = - .ies_present = false, - .base_names = mt7986_pinctrl_register_base_names, - .nbase_names = ARRAY_SIZE(mt7986_pinctrl_register_base_names), -+ .bias_disable_set = mtk_pinconf_bias_disable_set, -+ .bias_disable_get = mtk_pinconf_bias_disable_get, -+ .bias_set = mtk_pinconf_bias_set, -+ .bias_get = mtk_pinconf_bias_get, - .pull_type = mt7986_pull_type, - .bias_set_combo = mtk_pinconf_bias_set_combo, - .bias_get_combo = mtk_pinconf_bias_get_combo, diff --git a/target/linux/mediatek/patches-6.1/221-v6.3-clk-mediatek-cpumux-Propagate-struct-device-where-po.patch b/target/linux/mediatek/patches-6.1/221-v6.3-clk-mediatek-cpumux-Propagate-struct-device-where-po.patch deleted file mode 100644 index c7f37718a..000000000 --- a/target/linux/mediatek/patches-6.1/221-v6.3-clk-mediatek-cpumux-Propagate-struct-device-where-po.patch +++ /dev/null @@ -1,140 +0,0 @@ -From b888303c7d23d7bd0c8667cfc657669e5d153fea Mon Sep 17 00:00:00 2001 -From: AngeloGioacchino Del Regno -Date: Fri, 20 Jan 2023 10:20:34 +0100 -Subject: [PATCH 02/15] clk: mediatek: cpumux: Propagate struct device where - possible - -Take a pointer to a struct device in mtk_clk_register_cpumuxes() and -propagate the same to mtk_clk_register_cpumux() => clk_hw_register(). -Even though runtime pm is unlikely to be used with CPU muxes, this -helps with code consistency and possibly opens to commonization of -some mtk_clk_register_(x) functions. - -Signed-off-by: AngeloGioacchino Del Regno -Reviewed-by: Chen-Yu Tsai -Reviewed-by: Markus Schneider-Pargmann -Tested-by: Miles Chen -Link: https://lore.kernel.org/r/20230120092053.182923-5-angelogioacchino.delregno@collabora.com -Tested-by: Mingming Su -Signed-off-by: Stephen Boyd ---- - drivers/clk/mediatek/clk-cpumux.c | 8 ++++---- - drivers/clk/mediatek/clk-cpumux.h | 2 +- - drivers/clk/mediatek/clk-mt2701.c | 2 +- - drivers/clk/mediatek/clk-mt6795-infracfg.c | 3 ++- - drivers/clk/mediatek/clk-mt7622.c | 4 ++-- - drivers/clk/mediatek/clk-mt7629.c | 4 ++-- - drivers/clk/mediatek/clk-mt8173.c | 4 ++-- - 7 files changed, 14 insertions(+), 13 deletions(-) - ---- a/drivers/clk/mediatek/clk-cpumux.c -+++ b/drivers/clk/mediatek/clk-cpumux.c -@@ -58,7 +58,7 @@ static const struct clk_ops clk_cpumux_o - }; - - static struct clk_hw * --mtk_clk_register_cpumux(const struct mtk_composite *mux, -+mtk_clk_register_cpumux(struct device *dev, const struct mtk_composite *mux, - struct regmap *regmap) - { - struct mtk_clk_cpumux *cpumux; -@@ -81,7 +81,7 @@ mtk_clk_register_cpumux(const struct mtk - cpumux->regmap = regmap; - cpumux->hw.init = &init; - -- ret = clk_hw_register(NULL, &cpumux->hw); -+ ret = clk_hw_register(dev, &cpumux->hw); - if (ret) { - kfree(cpumux); - return ERR_PTR(ret); -@@ -102,7 +102,7 @@ static void mtk_clk_unregister_cpumux(st - kfree(cpumux); - } - --int mtk_clk_register_cpumuxes(struct device_node *node, -+int mtk_clk_register_cpumuxes(struct device *dev, struct device_node *node, - const struct mtk_composite *clks, int num, - struct clk_hw_onecell_data *clk_data) - { -@@ -125,7 +125,7 @@ int mtk_clk_register_cpumuxes(struct dev - continue; - } - -- hw = mtk_clk_register_cpumux(mux, regmap); -+ hw = mtk_clk_register_cpumux(dev, mux, regmap); - if (IS_ERR(hw)) { - pr_err("Failed to register clk %s: %pe\n", mux->name, - hw); ---- a/drivers/clk/mediatek/clk-cpumux.h -+++ b/drivers/clk/mediatek/clk-cpumux.h -@@ -11,7 +11,7 @@ struct clk_hw_onecell_data; - struct device_node; - struct mtk_composite; - --int mtk_clk_register_cpumuxes(struct device_node *node, -+int mtk_clk_register_cpumuxes(struct device *dev, struct device_node *node, - const struct mtk_composite *clks, int num, - struct clk_hw_onecell_data *clk_data); - ---- a/drivers/clk/mediatek/clk-mt2701.c -+++ b/drivers/clk/mediatek/clk-mt2701.c -@@ -762,7 +762,7 @@ static void __init mtk_infrasys_init_ear - mtk_clk_register_factors(infra_fixed_divs, ARRAY_SIZE(infra_fixed_divs), - infra_clk_data); - -- mtk_clk_register_cpumuxes(node, cpu_muxes, ARRAY_SIZE(cpu_muxes), -+ mtk_clk_register_cpumuxes(NULL, node, cpu_muxes, ARRAY_SIZE(cpu_muxes), - infra_clk_data); - - r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, ---- a/drivers/clk/mediatek/clk-mt6795-infracfg.c -+++ b/drivers/clk/mediatek/clk-mt6795-infracfg.c -@@ -106,7 +106,8 @@ static int clk_mt6795_infracfg_probe(str - if (ret) - goto free_clk_data; - -- ret = mtk_clk_register_cpumuxes(node, cpu_muxes, ARRAY_SIZE(cpu_muxes), clk_data); -+ ret = mtk_clk_register_cpumuxes(&pdev->dev, node, cpu_muxes, -+ ARRAY_SIZE(cpu_muxes), clk_data); - if (ret) - goto unregister_gates; - ---- a/drivers/clk/mediatek/clk-mt7622.c -+++ b/drivers/clk/mediatek/clk-mt7622.c -@@ -639,8 +639,8 @@ static int mtk_infrasys_init(struct plat - mtk_clk_register_gates(&pdev->dev, node, infra_clks, - ARRAY_SIZE(infra_clks), clk_data); - -- mtk_clk_register_cpumuxes(node, infra_muxes, ARRAY_SIZE(infra_muxes), -- clk_data); -+ mtk_clk_register_cpumuxes(&pdev->dev, node, infra_muxes, -+ ARRAY_SIZE(infra_muxes), clk_data); - - r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, - clk_data); ---- a/drivers/clk/mediatek/clk-mt7629.c -+++ b/drivers/clk/mediatek/clk-mt7629.c -@@ -589,8 +589,8 @@ static int mtk_infrasys_init(struct plat - mtk_clk_register_gates(&pdev->dev, node, infra_clks, - ARRAY_SIZE(infra_clks), clk_data); - -- mtk_clk_register_cpumuxes(node, infra_muxes, ARRAY_SIZE(infra_muxes), -- clk_data); -+ mtk_clk_register_cpumuxes(&pdev->dev, node, infra_muxes, -+ ARRAY_SIZE(infra_muxes), clk_data); - - return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, - clk_data); ---- a/drivers/clk/mediatek/clk-mt8173.c -+++ b/drivers/clk/mediatek/clk-mt8173.c -@@ -893,8 +893,8 @@ static void __init mtk_infrasys_init(str - ARRAY_SIZE(infra_clks), clk_data); - mtk_clk_register_factors(infra_divs, ARRAY_SIZE(infra_divs), clk_data); - -- mtk_clk_register_cpumuxes(node, cpu_muxes, ARRAY_SIZE(cpu_muxes), -- clk_data); -+ mtk_clk_register_cpumuxes(NULL, node, cpu_muxes, -+ ARRAY_SIZE(cpu_muxes), clk_data); - - r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); - if (r) diff --git a/target/linux/mediatek/patches-6.1/224-v6.3-clk-mediatek-clk-mtk-Add-dummy-clock-ops.patch b/target/linux/mediatek/patches-6.1/224-v6.3-clk-mediatek-clk-mtk-Add-dummy-clock-ops.patch deleted file mode 100644 index c7de44fcf..000000000 --- a/target/linux/mediatek/patches-6.1/224-v6.3-clk-mediatek-clk-mtk-Add-dummy-clock-ops.patch +++ /dev/null @@ -1,74 +0,0 @@ -From b8eb1081d267708ba976525a1fe2162901b34f3a Mon Sep 17 00:00:00 2001 -From: AngeloGioacchino Del Regno -Date: Fri, 20 Jan 2023 10:20:37 +0100 -Subject: [PATCH] clk: mediatek: clk-mtk: Add dummy clock ops - -In order to migrate some (few) old clock drivers to the common -mtk_clk_simple_probe() function, add dummy clock ops to be able -to insert a dummy clock with ID 0 at the beginning of the list. - -Signed-off-by: AngeloGioacchino Del Regno -Reviewed-by: Miles Chen -Reviewed-by: Chen-Yu Tsai -Tested-by: Miles Chen -Link: https://lore.kernel.org/r/20230120092053.182923-8-angelogioacchino.delregno@collabora.com -Tested-by: Mingming Su -Signed-off-by: Stephen Boyd ---- - drivers/clk/mediatek/clk-mtk.c | 16 ++++++++++++++++ - drivers/clk/mediatek/clk-mtk.h | 19 +++++++++++++++++++ - 2 files changed, 35 insertions(+) - ---- a/drivers/clk/mediatek/clk-mtk.c -+++ b/drivers/clk/mediatek/clk-mtk.c -@@ -21,6 +21,22 @@ - #include "clk-gate.h" - #include "clk-mux.h" - -+const struct mtk_gate_regs cg_regs_dummy = { 0, 0, 0 }; -+EXPORT_SYMBOL_GPL(cg_regs_dummy); -+ -+static int mtk_clk_dummy_enable(struct clk_hw *hw) -+{ -+ return 0; -+} -+ -+static void mtk_clk_dummy_disable(struct clk_hw *hw) { } -+ -+const struct clk_ops mtk_clk_dummy_ops = { -+ .enable = mtk_clk_dummy_enable, -+ .disable = mtk_clk_dummy_disable, -+}; -+EXPORT_SYMBOL_GPL(mtk_clk_dummy_ops); -+ - static void mtk_init_clk_data(struct clk_hw_onecell_data *clk_data, - unsigned int clk_num) - { ---- a/drivers/clk/mediatek/clk-mtk.h -+++ b/drivers/clk/mediatek/clk-mtk.h -@@ -22,6 +22,25 @@ - - struct platform_device; - -+/* -+ * We need the clock IDs to start from zero but to maintain devicetree -+ * backwards compatibility we can't change bindings to start from zero. -+ * Only a few platforms are affected, so we solve issues given by the -+ * commonized MTK clocks probe function(s) by adding a dummy clock at -+ * the beginning where needed. -+ */ -+#define CLK_DUMMY 0 -+ -+extern const struct clk_ops mtk_clk_dummy_ops; -+extern const struct mtk_gate_regs cg_regs_dummy; -+ -+#define GATE_DUMMY(_id, _name) { \ -+ .id = _id, \ -+ .name = _name, \ -+ .regs = &cg_regs_dummy, \ -+ .ops = &mtk_clk_dummy_ops, \ -+ } -+ - struct mtk_fixed_clk { - int id; - const char *name; diff --git a/target/linux/mediatek/patches-6.1/225-v6.3-clk-mediatek-Switch-to-mtk_clk_simple_probe-where-po.patch b/target/linux/mediatek/patches-6.1/225-v6.3-clk-mediatek-Switch-to-mtk_clk_simple_probe-where-po.patch deleted file mode 100644 index becfcd0ed..000000000 --- a/target/linux/mediatek/patches-6.1/225-v6.3-clk-mediatek-Switch-to-mtk_clk_simple_probe-where-po.patch +++ /dev/null @@ -1,790 +0,0 @@ -From c26e28015b74af73e0b299f6ad3ff22931e600b4 Mon Sep 17 00:00:00 2001 -From: AngeloGioacchino Del Regno -Date: Fri, 20 Jan 2023 10:20:41 +0100 -Subject: [PATCH 05/15] clk: mediatek: Switch to mtk_clk_simple_probe() where - possible - -mtk_clk_simple_probe() is a function that registers mtk gate clocks -and, if reset data is present, a reset controller and across all of -the MTK clock drivers, such a function is duplicated many times: -switch to the common mtk_clk_simple_probe() function for all of the -clock drivers that are registering as platform drivers. - -Signed-off-by: AngeloGioacchino Del Regno -Reviewed-by: Miles Chen -Tested-by: Miles Chen -Link: https://lore.kernel.org/r/20230120092053.182923-12-angelogioacchino.delregno@collabora.com -Tested-by: Mingming Su -Signed-off-by: Stephen Boyd - -[daniel@makrotopia.org: removed parts not relevant for OpenWrt] ---- - drivers/clk/mediatek/clk-mt2701-aud.c | 31 ++++++---- - drivers/clk/mediatek/clk-mt2701-eth.c | 36 ++++-------- - drivers/clk/mediatek/clk-mt2701-g3d.c | 56 ++++-------------- - drivers/clk/mediatek/clk-mt2701-hif.c | 38 ++++-------- - drivers/clk/mediatek/clk-mt2712.c | 83 ++++++++++---------------- - drivers/clk/mediatek/clk-mt7622-aud.c | 54 ++++++----------- - drivers/clk/mediatek/clk-mt7622-eth.c | 82 +++++--------------------- - drivers/clk/mediatek/clk-mt7622-hif.c | 85 +++++---------------------- - drivers/clk/mediatek/clk-mt7629-hif.c | 85 +++++---------------------- - 9 files changed, 144 insertions(+), 406 deletions(-) - ---- a/drivers/clk/mediatek/clk-mt2701-aud.c -+++ b/drivers/clk/mediatek/clk-mt2701-aud.c -@@ -52,6 +52,7 @@ static const struct mtk_gate_regs audio3 - }; - - static const struct mtk_gate audio_clks[] = { -+ GATE_DUMMY(CLK_DUMMY, "aud_dummy"), - /* AUDIO0 */ - GATE_AUDIO0(CLK_AUD_AFE, "audio_afe", "aud_intbus_sel", 2), - GATE_AUDIO0(CLK_AUD_HDMI, "audio_hdmi", "audpll_sel", 20), -@@ -114,29 +115,27 @@ static const struct mtk_gate audio_clks[ - GATE_AUDIO3(CLK_AUD_MEM_ASRC5, "audio_mem_asrc5", "asm_h_sel", 14), - }; - -+static const struct mtk_clk_desc audio_desc = { -+ .clks = audio_clks, -+ .num_clks = ARRAY_SIZE(audio_clks), -+}; -+ - static const struct of_device_id of_match_clk_mt2701_aud[] = { -- { .compatible = "mediatek,mt2701-audsys", }, -- {} -+ { .compatible = "mediatek,mt2701-audsys", .data = &audio_desc }, -+ { /* sentinel */ } - }; - - static int clk_mt2701_aud_probe(struct platform_device *pdev) - { -- struct clk_hw_onecell_data *clk_data; -- struct device_node *node = pdev->dev.of_node; - int r; - -- clk_data = mtk_alloc_clk_data(CLK_AUD_NR); -- -- mtk_clk_register_gates(&pdev->dev, node, audio_clks, -- ARRAY_SIZE(audio_clks), clk_data); -- -- r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); -+ r = mtk_clk_simple_probe(pdev); - if (r) { - dev_err(&pdev->dev, - "could not register clock provider: %s: %d\n", - pdev->name, r); - -- goto err_clk_provider; -+ return r; - } - - r = devm_of_platform_populate(&pdev->dev); -@@ -146,13 +145,19 @@ static int clk_mt2701_aud_probe(struct p - return 0; - - err_plat_populate: -- of_clk_del_provider(node); --err_clk_provider: -+ mtk_clk_simple_remove(pdev); - return r; - } - -+static int clk_mt2701_aud_remove(struct platform_device *pdev) -+{ -+ of_platform_depopulate(&pdev->dev); -+ return mtk_clk_simple_remove(pdev); -+} -+ - static struct platform_driver clk_mt2701_aud_drv = { - .probe = clk_mt2701_aud_probe, -+ .remove = clk_mt2701_aud_remove, - .driver = { - .name = "clk-mt2701-aud", - .of_match_table = of_match_clk_mt2701_aud, ---- a/drivers/clk/mediatek/clk-mt2701-eth.c -+++ b/drivers/clk/mediatek/clk-mt2701-eth.c -@@ -20,6 +20,7 @@ static const struct mtk_gate_regs eth_cg - GATE_MTK(_id, _name, _parent, ð_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr_inv) - - static const struct mtk_gate eth_clks[] = { -+ GATE_DUMMY(CLK_DUMMY, "eth_dummy"), - GATE_ETH(CLK_ETHSYS_HSDMA, "hsdma_clk", "ethif_sel", 5), - GATE_ETH(CLK_ETHSYS_ESW, "esw_clk", "ethpll_500m_ck", 6), - GATE_ETH(CLK_ETHSYS_GP2, "gp2_clk", "trgpll", 7), -@@ -38,35 +39,20 @@ static const struct mtk_clk_rst_desc clk - .rst_bank_nr = ARRAY_SIZE(rst_ofs), - }; - --static const struct of_device_id of_match_clk_mt2701_eth[] = { -- { .compatible = "mediatek,mt2701-ethsys", }, -- {} -+static const struct mtk_clk_desc eth_desc = { -+ .clks = eth_clks, -+ .num_clks = ARRAY_SIZE(eth_clks), -+ .rst_desc = &clk_rst_desc, - }; - --static int clk_mt2701_eth_probe(struct platform_device *pdev) --{ -- struct clk_hw_onecell_data *clk_data; -- int r; -- struct device_node *node = pdev->dev.of_node; -- -- clk_data = mtk_alloc_clk_data(CLK_ETHSYS_NR); -- -- mtk_clk_register_gates(&pdev->dev, node, eth_clks, -- ARRAY_SIZE(eth_clks), clk_data); -- -- r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); -- if (r) -- dev_err(&pdev->dev, -- "could not register clock provider: %s: %d\n", -- pdev->name, r); -- -- mtk_register_reset_controller_with_dev(&pdev->dev, &clk_rst_desc); -- -- return r; --} -+static const struct of_device_id of_match_clk_mt2701_eth[] = { -+ { .compatible = "mediatek,mt2701-ethsys", .data = ð_desc }, -+ { /* sentinel */ } -+}; - - static struct platform_driver clk_mt2701_eth_drv = { -- .probe = clk_mt2701_eth_probe, -+ .probe = mtk_clk_simple_probe, -+ .remove = mtk_clk_simple_remove, - .driver = { - .name = "clk-mt2701-eth", - .of_match_table = of_match_clk_mt2701_eth, ---- a/drivers/clk/mediatek/clk-mt2701-g3d.c -+++ b/drivers/clk/mediatek/clk-mt2701-g3d.c -@@ -26,6 +26,7 @@ static const struct mtk_gate_regs g3d_cg - }; - - static const struct mtk_gate g3d_clks[] = { -+ GATE_DUMMY(CLK_DUMMY, "g3d_dummy"), - GATE_G3D(CLK_G3DSYS_CORE, "g3d_core", "mfg_sel", 0), - }; - -@@ -37,57 +38,20 @@ static const struct mtk_clk_rst_desc clk - .rst_bank_nr = ARRAY_SIZE(rst_ofs), - }; - --static int clk_mt2701_g3dsys_init(struct platform_device *pdev) --{ -- struct clk_hw_onecell_data *clk_data; -- struct device_node *node = pdev->dev.of_node; -- int r; -- -- clk_data = mtk_alloc_clk_data(CLK_G3DSYS_NR); -- -- mtk_clk_register_gates(&pdev->dev, node, g3d_clks, ARRAY_SIZE(g3d_clks), -- clk_data); -- -- r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); -- if (r) -- dev_err(&pdev->dev, -- "could not register clock provider: %s: %d\n", -- pdev->name, r); -- -- mtk_register_reset_controller_with_dev(&pdev->dev, &clk_rst_desc); -- -- return r; --} -+static const struct mtk_clk_desc g3d_desc = { -+ .clks = g3d_clks, -+ .num_clks = ARRAY_SIZE(g3d_clks), -+ .rst_desc = &clk_rst_desc, -+}; - - static const struct of_device_id of_match_clk_mt2701_g3d[] = { -- { -- .compatible = "mediatek,mt2701-g3dsys", -- .data = clk_mt2701_g3dsys_init, -- }, { -- /* sentinel */ -- } -+ { .compatible = "mediatek,mt2701-g3dsys", .data = &g3d_desc }, -+ { /* sentinel */ } - }; - --static int clk_mt2701_g3d_probe(struct platform_device *pdev) --{ -- int (*clk_init)(struct platform_device *); -- int r; -- -- clk_init = of_device_get_match_data(&pdev->dev); -- if (!clk_init) -- return -EINVAL; -- -- r = clk_init(pdev); -- if (r) -- dev_err(&pdev->dev, -- "could not register clock provider: %s: %d\n", -- pdev->name, r); -- -- return r; --} -- - static struct platform_driver clk_mt2701_g3d_drv = { -- .probe = clk_mt2701_g3d_probe, -+ .probe = mtk_clk_simple_probe, -+ .remove = mtk_clk_simple_remove, - .driver = { - .name = "clk-mt2701-g3d", - .of_match_table = of_match_clk_mt2701_g3d, ---- a/drivers/clk/mediatek/clk-mt2701-hif.c -+++ b/drivers/clk/mediatek/clk-mt2701-hif.c -@@ -20,6 +20,7 @@ static const struct mtk_gate_regs hif_cg - GATE_MTK(_id, _name, _parent, &hif_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr_inv) - - static const struct mtk_gate hif_clks[] = { -+ GATE_DUMMY(CLK_DUMMY, "hif_dummy"), - GATE_HIF(CLK_HIFSYS_USB0PHY, "usb0_phy_clk", "ethpll_500m_ck", 21), - GATE_HIF(CLK_HIFSYS_USB1PHY, "usb1_phy_clk", "ethpll_500m_ck", 22), - GATE_HIF(CLK_HIFSYS_PCIE0, "pcie0_clk", "ethpll_500m_ck", 24), -@@ -35,37 +36,20 @@ static const struct mtk_clk_rst_desc clk - .rst_bank_nr = ARRAY_SIZE(rst_ofs), - }; - --static const struct of_device_id of_match_clk_mt2701_hif[] = { -- { .compatible = "mediatek,mt2701-hifsys", }, -- {} -+static const struct mtk_clk_desc hif_desc = { -+ .clks = hif_clks, -+ .num_clks = ARRAY_SIZE(hif_clks), -+ .rst_desc = &clk_rst_desc, - }; - --static int clk_mt2701_hif_probe(struct platform_device *pdev) --{ -- struct clk_hw_onecell_data *clk_data; -- int r; -- struct device_node *node = pdev->dev.of_node; -- -- clk_data = mtk_alloc_clk_data(CLK_HIFSYS_NR); -- -- mtk_clk_register_gates(&pdev->dev, node, hif_clks, -- ARRAY_SIZE(hif_clks), clk_data); -- -- r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); -- if (r) { -- dev_err(&pdev->dev, -- "could not register clock provider: %s: %d\n", -- pdev->name, r); -- return r; -- } -- -- mtk_register_reset_controller_with_dev(&pdev->dev, &clk_rst_desc); -- -- return 0; --} -+static const struct of_device_id of_match_clk_mt2701_hif[] = { -+ { .compatible = "mediatek,mt2701-hifsys", .data = &hif_desc }, -+ { /* sentinel */ } -+}; - - static struct platform_driver clk_mt2701_hif_drv = { -- .probe = clk_mt2701_hif_probe, -+ .probe = mtk_clk_simple_probe, -+ .remove = mtk_clk_simple_remove, - .driver = { - .name = "clk-mt2701-hif", - .of_match_table = of_match_clk_mt2701_hif, ---- a/drivers/clk/mediatek/clk-mt2712.c -+++ b/drivers/clk/mediatek/clk-mt2712.c -@@ -1337,50 +1337,6 @@ static int clk_mt2712_top_probe(struct p - return r; - } - --static int clk_mt2712_infra_probe(struct platform_device *pdev) --{ -- struct clk_hw_onecell_data *clk_data; -- int r; -- struct device_node *node = pdev->dev.of_node; -- -- clk_data = mtk_alloc_clk_data(CLK_INFRA_NR_CLK); -- -- mtk_clk_register_gates(&pdev->dev, node, infra_clks, -- ARRAY_SIZE(infra_clks), clk_data); -- -- r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); -- -- if (r != 0) -- pr_err("%s(): could not register clock provider: %d\n", -- __func__, r); -- -- mtk_register_reset_controller_with_dev(&pdev->dev, &clk_rst_desc[0]); -- -- return r; --} -- --static int clk_mt2712_peri_probe(struct platform_device *pdev) --{ -- struct clk_hw_onecell_data *clk_data; -- int r; -- struct device_node *node = pdev->dev.of_node; -- -- clk_data = mtk_alloc_clk_data(CLK_PERI_NR_CLK); -- -- mtk_clk_register_gates(&pdev->dev, node, peri_clks, -- ARRAY_SIZE(peri_clks), clk_data); -- -- r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); -- -- if (r != 0) -- pr_err("%s(): could not register clock provider: %d\n", -- __func__, r); -- -- mtk_register_reset_controller_with_dev(&pdev->dev, &clk_rst_desc[1]); -- -- return r; --} -- - static int clk_mt2712_mcu_probe(struct platform_device *pdev) - { - struct clk_hw_onecell_data *clk_data; -@@ -1419,12 +1375,6 @@ static const struct of_device_id of_matc - .compatible = "mediatek,mt2712-topckgen", - .data = clk_mt2712_top_probe, - }, { -- .compatible = "mediatek,mt2712-infracfg", -- .data = clk_mt2712_infra_probe, -- }, { -- .compatible = "mediatek,mt2712-pericfg", -- .data = clk_mt2712_peri_probe, -- }, { - .compatible = "mediatek,mt2712-mcucfg", - .data = clk_mt2712_mcu_probe, - }, { -@@ -1450,6 +1400,33 @@ static int clk_mt2712_probe(struct platf - return r; - } - -+static const struct mtk_clk_desc infra_desc = { -+ .clks = infra_clks, -+ .num_clks = ARRAY_SIZE(infra_clks), -+ .rst_desc = &clk_rst_desc[0], -+}; -+ -+static const struct mtk_clk_desc peri_desc = { -+ .clks = peri_clks, -+ .num_clks = ARRAY_SIZE(peri_clks), -+ .rst_desc = &clk_rst_desc[1], -+}; -+ -+static const struct of_device_id of_match_clk_mt2712_simple[] = { -+ { .compatible = "mediatek,mt2712-infracfg", .data = &infra_desc }, -+ { .compatible = "mediatek,mt2712-pericfg", .data = &peri_desc, }, -+ { /* sentinel */ } -+}; -+ -+static struct platform_driver clk_mt2712_simple_drv = { -+ .probe = mtk_clk_simple_probe, -+ .remove = mtk_clk_simple_remove, -+ .driver = { -+ .name = "clk-mt2712-simple", -+ .of_match_table = of_match_clk_mt2712_simple, -+ }, -+}; -+ - static struct platform_driver clk_mt2712_drv = { - .probe = clk_mt2712_probe, - .driver = { -@@ -1460,7 +1437,11 @@ static struct platform_driver clk_mt2712 - - static int __init clk_mt2712_init(void) - { -- return platform_driver_register(&clk_mt2712_drv); -+ int ret = platform_driver_register(&clk_mt2712_drv); -+ -+ if (ret) -+ return ret; -+ return platform_driver_register(&clk_mt2712_simple_drv); - } - - arch_initcall(clk_mt2712_init); ---- a/drivers/clk/mediatek/clk-mt7622-aud.c -+++ b/drivers/clk/mediatek/clk-mt7622-aud.c -@@ -106,24 +106,22 @@ static const struct mtk_gate audio_clks[ - GATE_AUDIO3(CLK_AUDIO_MEM_ASRC5, "audio_mem_asrc5", "asm_h_sel", 14), - }; - --static int clk_mt7622_audiosys_init(struct platform_device *pdev) -+static const struct mtk_clk_desc audio_desc = { -+ .clks = audio_clks, -+ .num_clks = ARRAY_SIZE(audio_clks), -+}; -+ -+static int clk_mt7622_aud_probe(struct platform_device *pdev) - { -- struct clk_hw_onecell_data *clk_data; -- struct device_node *node = pdev->dev.of_node; - int r; - -- clk_data = mtk_alloc_clk_data(CLK_AUDIO_NR_CLK); -- -- mtk_clk_register_gates(&pdev->dev, node, audio_clks, -- ARRAY_SIZE(audio_clks), clk_data); -- -- r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); -+ r = mtk_clk_simple_probe(pdev); - if (r) { - dev_err(&pdev->dev, - "could not register clock provider: %s: %d\n", - pdev->name, r); - -- goto err_clk_provider; -+ return r; - } - - r = devm_of_platform_populate(&pdev->dev); -@@ -133,40 +131,24 @@ static int clk_mt7622_audiosys_init(stru - return 0; - - err_plat_populate: -- of_clk_del_provider(node); --err_clk_provider: -+ mtk_clk_simple_remove(pdev); - return r; - } - --static const struct of_device_id of_match_clk_mt7622_aud[] = { -- { -- .compatible = "mediatek,mt7622-audsys", -- .data = clk_mt7622_audiosys_init, -- }, { -- /* sentinel */ -- } --}; -- --static int clk_mt7622_aud_probe(struct platform_device *pdev) -+static int clk_mt7622_aud_remove(struct platform_device *pdev) - { -- int (*clk_init)(struct platform_device *); -- int r; -- -- clk_init = of_device_get_match_data(&pdev->dev); -- if (!clk_init) -- return -EINVAL; -- -- r = clk_init(pdev); -- if (r) -- dev_err(&pdev->dev, -- "could not register clock provider: %s: %d\n", -- pdev->name, r); -- -- return r; -+ of_platform_depopulate(&pdev->dev); -+ return mtk_clk_simple_remove(pdev); - } - -+static const struct of_device_id of_match_clk_mt7622_aud[] = { -+ { .compatible = "mediatek,mt7622-audsys", .data = &audio_desc }, -+ { /* sentinel */ } -+}; -+ - static struct platform_driver clk_mt7622_aud_drv = { - .probe = clk_mt7622_aud_probe, -+ .remove = clk_mt7622_aud_remove, - .driver = { - .name = "clk-mt7622-aud", - .of_match_table = of_match_clk_mt7622_aud, ---- a/drivers/clk/mediatek/clk-mt7622-eth.c -+++ b/drivers/clk/mediatek/clk-mt7622-eth.c -@@ -61,80 +61,26 @@ static const struct mtk_clk_rst_desc clk - .rst_bank_nr = ARRAY_SIZE(rst_ofs), - }; - --static int clk_mt7622_ethsys_init(struct platform_device *pdev) --{ -- struct clk_hw_onecell_data *clk_data; -- struct device_node *node = pdev->dev.of_node; -- int r; -- -- clk_data = mtk_alloc_clk_data(CLK_ETH_NR_CLK); -- -- mtk_clk_register_gates(&pdev->dev, node, eth_clks, -- ARRAY_SIZE(eth_clks), clk_data); -- -- r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); -- if (r) -- dev_err(&pdev->dev, -- "could not register clock provider: %s: %d\n", -- pdev->name, r); -- -- mtk_register_reset_controller_with_dev(&pdev->dev, &clk_rst_desc); -- -- return r; --} -- --static int clk_mt7622_sgmiisys_init(struct platform_device *pdev) --{ -- struct clk_hw_onecell_data *clk_data; -- struct device_node *node = pdev->dev.of_node; -- int r; -- -- clk_data = mtk_alloc_clk_data(CLK_SGMII_NR_CLK); -- -- mtk_clk_register_gates(&pdev->dev, node, sgmii_clks, -- ARRAY_SIZE(sgmii_clks), clk_data); -- -- r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); -- if (r) -- dev_err(&pdev->dev, -- "could not register clock provider: %s: %d\n", -- pdev->name, r); -+static const struct mtk_clk_desc eth_desc = { -+ .clks = eth_clks, -+ .num_clks = ARRAY_SIZE(eth_clks), -+ .rst_desc = &clk_rst_desc, -+}; - -- return r; --} -+static const struct mtk_clk_desc sgmii_desc = { -+ .clks = sgmii_clks, -+ .num_clks = ARRAY_SIZE(sgmii_clks), -+}; - - static const struct of_device_id of_match_clk_mt7622_eth[] = { -- { -- .compatible = "mediatek,mt7622-ethsys", -- .data = clk_mt7622_ethsys_init, -- }, { -- .compatible = "mediatek,mt7622-sgmiisys", -- .data = clk_mt7622_sgmiisys_init, -- }, { -- /* sentinel */ -- } -+ { .compatible = "mediatek,mt7622-ethsys", .data = ð_desc }, -+ { .compatible = "mediatek,mt7622-sgmiisys", .data = &sgmii_desc }, -+ { /* sentinel */ } - }; - --static int clk_mt7622_eth_probe(struct platform_device *pdev) --{ -- int (*clk_init)(struct platform_device *); -- int r; -- -- clk_init = of_device_get_match_data(&pdev->dev); -- if (!clk_init) -- return -EINVAL; -- -- r = clk_init(pdev); -- if (r) -- dev_err(&pdev->dev, -- "could not register clock provider: %s: %d\n", -- pdev->name, r); -- -- return r; --} -- - static struct platform_driver clk_mt7622_eth_drv = { -- .probe = clk_mt7622_eth_probe, -+ .probe = mtk_clk_simple_probe, -+ .remove = mtk_clk_simple_remove, - .driver = { - .name = "clk-mt7622-eth", - .of_match_table = of_match_clk_mt7622_eth, ---- a/drivers/clk/mediatek/clk-mt7622-hif.c -+++ b/drivers/clk/mediatek/clk-mt7622-hif.c -@@ -72,82 +72,27 @@ static const struct mtk_clk_rst_desc clk - .rst_bank_nr = ARRAY_SIZE(rst_ofs), - }; - --static int clk_mt7622_ssusbsys_init(struct platform_device *pdev) --{ -- struct clk_hw_onecell_data *clk_data; -- struct device_node *node = pdev->dev.of_node; -- int r; -- -- clk_data = mtk_alloc_clk_data(CLK_SSUSB_NR_CLK); -- -- mtk_clk_register_gates(&pdev->dev, node, ssusb_clks, -- ARRAY_SIZE(ssusb_clks), clk_data); -- -- r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); -- if (r) -- dev_err(&pdev->dev, -- "could not register clock provider: %s: %d\n", -- pdev->name, r); -- -- mtk_register_reset_controller_with_dev(&pdev->dev, &clk_rst_desc); -- -- return r; --} -- --static int clk_mt7622_pciesys_init(struct platform_device *pdev) --{ -- struct clk_hw_onecell_data *clk_data; -- struct device_node *node = pdev->dev.of_node; -- int r; -- -- clk_data = mtk_alloc_clk_data(CLK_PCIE_NR_CLK); -- -- mtk_clk_register_gates(&pdev->dev, node, pcie_clks, -- ARRAY_SIZE(pcie_clks), clk_data); -- -- r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); -- if (r) -- dev_err(&pdev->dev, -- "could not register clock provider: %s: %d\n", -- pdev->name, r); -- -- mtk_register_reset_controller_with_dev(&pdev->dev, &clk_rst_desc); -+static const struct mtk_clk_desc ssusb_desc = { -+ .clks = ssusb_clks, -+ .num_clks = ARRAY_SIZE(ssusb_clks), -+ .rst_desc = &clk_rst_desc, -+}; - -- return r; --} -+static const struct mtk_clk_desc pcie_desc = { -+ .clks = pcie_clks, -+ .num_clks = ARRAY_SIZE(pcie_clks), -+ .rst_desc = &clk_rst_desc, -+}; - - static const struct of_device_id of_match_clk_mt7622_hif[] = { -- { -- .compatible = "mediatek,mt7622-pciesys", -- .data = clk_mt7622_pciesys_init, -- }, { -- .compatible = "mediatek,mt7622-ssusbsys", -- .data = clk_mt7622_ssusbsys_init, -- }, { -- /* sentinel */ -- } -+ { .compatible = "mediatek,mt7622-pciesys", .data = &pcie_desc }, -+ { .compatible = "mediatek,mt7622-ssusbsys", .data = &ssusb_desc }, -+ { /* sentinel */ } - }; - --static int clk_mt7622_hif_probe(struct platform_device *pdev) --{ -- int (*clk_init)(struct platform_device *); -- int r; -- -- clk_init = of_device_get_match_data(&pdev->dev); -- if (!clk_init) -- return -EINVAL; -- -- r = clk_init(pdev); -- if (r) -- dev_err(&pdev->dev, -- "could not register clock provider: %s: %d\n", -- pdev->name, r); -- -- return r; --} -- - static struct platform_driver clk_mt7622_hif_drv = { -- .probe = clk_mt7622_hif_probe, -+ .probe = mtk_clk_simple_probe, -+ .remove = mtk_clk_simple_remove, - .driver = { - .name = "clk-mt7622-hif", - .of_match_table = of_match_clk_mt7622_hif, ---- a/drivers/clk/mediatek/clk-mt7629-hif.c -+++ b/drivers/clk/mediatek/clk-mt7629-hif.c -@@ -67,82 +67,27 @@ static const struct mtk_clk_rst_desc clk - .rst_bank_nr = ARRAY_SIZE(rst_ofs), - }; - --static int clk_mt7629_ssusbsys_init(struct platform_device *pdev) --{ -- struct clk_hw_onecell_data *clk_data; -- struct device_node *node = pdev->dev.of_node; -- int r; -- -- clk_data = mtk_alloc_clk_data(CLK_SSUSB_NR_CLK); -- -- mtk_clk_register_gates(&pdev->dev, node, ssusb_clks, -- ARRAY_SIZE(ssusb_clks), clk_data); -- -- r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); -- if (r) -- dev_err(&pdev->dev, -- "could not register clock provider: %s: %d\n", -- pdev->name, r); -- -- mtk_register_reset_controller_with_dev(&pdev->dev, &clk_rst_desc); -- -- return r; --} -- --static int clk_mt7629_pciesys_init(struct platform_device *pdev) --{ -- struct clk_hw_onecell_data *clk_data; -- struct device_node *node = pdev->dev.of_node; -- int r; -- -- clk_data = mtk_alloc_clk_data(CLK_PCIE_NR_CLK); -- -- mtk_clk_register_gates(&pdev->dev, node, pcie_clks, -- ARRAY_SIZE(pcie_clks), clk_data); -- -- r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); -- if (r) -- dev_err(&pdev->dev, -- "could not register clock provider: %s: %d\n", -- pdev->name, r); -- -- mtk_register_reset_controller_with_dev(&pdev->dev, &clk_rst_desc); -+static const struct mtk_clk_desc ssusb_desc = { -+ .clks = ssusb_clks, -+ .num_clks = ARRAY_SIZE(ssusb_clks), -+ .rst_desc = &clk_rst_desc, -+}; - -- return r; --} -+static const struct mtk_clk_desc pcie_desc = { -+ .clks = pcie_clks, -+ .num_clks = ARRAY_SIZE(pcie_clks), -+ .rst_desc = &clk_rst_desc, -+}; - - static const struct of_device_id of_match_clk_mt7629_hif[] = { -- { -- .compatible = "mediatek,mt7629-pciesys", -- .data = clk_mt7629_pciesys_init, -- }, { -- .compatible = "mediatek,mt7629-ssusbsys", -- .data = clk_mt7629_ssusbsys_init, -- }, { -- /* sentinel */ -- } -+ { .compatible = "mediatek,mt7629-pciesys", .data = &pcie_desc }, -+ { .compatible = "mediatek,mt7629-ssusbsys", .data = &ssusb_desc }, -+ { /* sentinel */ } - }; - --static int clk_mt7629_hif_probe(struct platform_device *pdev) --{ -- int (*clk_init)(struct platform_device *); -- int r; -- -- clk_init = of_device_get_match_data(&pdev->dev); -- if (!clk_init) -- return -EINVAL; -- -- r = clk_init(pdev); -- if (r) -- dev_err(&pdev->dev, -- "could not register clock provider: %s: %d\n", -- pdev->name, r); -- -- return r; --} -- - static struct platform_driver clk_mt7629_hif_drv = { -- .probe = clk_mt7629_hif_probe, -+ .probe = mtk_clk_simple_probe, -+ .remove = mtk_clk_simple_remove, - .driver = { - .name = "clk-mt7629-hif", - .of_match_table = of_match_clk_mt7629_hif, diff --git a/target/linux/mediatek/patches-6.1/227-v6.3-clk-mediatek-clk-mt7986-topckgen-Properly-keep-some-.patch b/target/linux/mediatek/patches-6.1/227-v6.3-clk-mediatek-clk-mt7986-topckgen-Properly-keep-some-.patch deleted file mode 100644 index bf9a17292..000000000 --- a/target/linux/mediatek/patches-6.1/227-v6.3-clk-mediatek-clk-mt7986-topckgen-Properly-keep-some-.patch +++ /dev/null @@ -1,97 +0,0 @@ -From 3511004225ce917a4aa6e6ac61481ac60f08f401 Mon Sep 17 00:00:00 2001 -From: AngeloGioacchino Del Regno -Date: Fri, 20 Jan 2023 10:20:52 +0100 -Subject: [PATCH 06/15] clk: mediatek: clk-mt7986-topckgen: Properly keep some - clocks enabled - -Instead of calling clk_prepare_enable() on a bunch of clocks at probe -time, set the CLK_IS_CRITICAL flag to the same as these are required -to be always on, and this is the right way of achieving that. - -Signed-off-by: AngeloGioacchino Del Regno -Reviewed-by: Chen-Yu Tsai -Reviewed-by: Miles Chen -Link: https://lore.kernel.org/r/20230120092053.182923-23-angelogioacchino.delregno@collabora.com -Tested-by: Mingming Su -Signed-off-by: Stephen Boyd ---- - drivers/clk/mediatek/clk-mt7986-topckgen.c | 46 +++++++++++----------- - 1 file changed, 24 insertions(+), 22 deletions(-) - ---- a/drivers/clk/mediatek/clk-mt7986-topckgen.c -+++ b/drivers/clk/mediatek/clk-mt7986-topckgen.c -@@ -202,16 +202,23 @@ static const struct mtk_mux top_muxes[] - MUX_GATE_CLR_SET_UPD(CLK_TOP_F_26M_ADC_SEL, "f_26m_adc_sel", - f_26m_adc_parents, 0x020, 0x024, 0x028, 16, 1, 23, - 0x1C0, 10), -- MUX_GATE_CLR_SET_UPD(CLK_TOP_DRAMC_SEL, "dramc_sel", f_26m_adc_parents, -- 0x020, 0x024, 0x028, 24, 1, 31, 0x1C0, 11), -+ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_DRAMC_SEL, "dramc_sel", -+ f_26m_adc_parents, 0x020, 0x024, 0x028, -+ 24, 1, 31, 0x1C0, 11, -+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), - /* CLK_CFG_3 */ -- MUX_GATE_CLR_SET_UPD(CLK_TOP_DRAMC_MD32_SEL, "dramc_md32_sel", -- dramc_md32_parents, 0x030, 0x034, 0x038, 0, 1, 7, -- 0x1C0, 12), -- MUX_GATE_CLR_SET_UPD(CLK_TOP_SYSAXI_SEL, "sysaxi_sel", sysaxi_parents, -- 0x030, 0x034, 0x038, 8, 2, 15, 0x1C0, 13), -- MUX_GATE_CLR_SET_UPD(CLK_TOP_SYSAPB_SEL, "sysapb_sel", sysapb_parents, -- 0x030, 0x034, 0x038, 16, 2, 23, 0x1C0, 14), -+ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_DRAMC_MD32_SEL, "dramc_md32_sel", -+ dramc_md32_parents, 0x030, 0x034, 0x038, -+ 0, 1, 7, 0x1C0, 12, -+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), -+ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SYSAXI_SEL, "sysaxi_sel", -+ sysaxi_parents, 0x030, 0x034, 0x038, -+ 8, 2, 15, 0x1C0, 13, -+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), -+ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SYSAPB_SEL, "sysapb_sel", -+ sysapb_parents, 0x030, 0x034, 0x038, -+ 16, 2, 23, 0x1C0, 14, -+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), - MUX_GATE_CLR_SET_UPD(CLK_TOP_ARM_DB_MAIN_SEL, "arm_db_main_sel", - arm_db_main_parents, 0x030, 0x034, 0x038, 24, 1, - 31, 0x1C0, 15), -@@ -234,9 +241,10 @@ static const struct mtk_mux top_muxes[] - MUX_GATE_CLR_SET_UPD(CLK_TOP_SGM_325M_SEL, "sgm_325m_sel", - sgm_325m_parents, 0x050, 0x054, 0x058, 8, 1, 15, - 0x1C0, 21), -- MUX_GATE_CLR_SET_UPD(CLK_TOP_SGM_REG_SEL, "sgm_reg_sel", -- sgm_reg_parents, 0x050, 0x054, 0x058, 16, 1, 23, -- 0x1C0, 22), -+ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SGM_REG_SEL, "sgm_reg_sel", -+ sgm_reg_parents, 0x050, 0x054, 0x058, -+ 16, 1, 23, 0x1C0, 22, -+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), - MUX_GATE_CLR_SET_UPD(CLK_TOP_A1SYS_SEL, "a1sys_sel", a1sys_parents, - 0x050, 0x054, 0x058, 24, 1, 31, 0x1C0, 23), - /* CLK_CFG_6 */ -@@ -252,9 +260,10 @@ static const struct mtk_mux top_muxes[] - f_26m_adc_parents, 0x060, 0x064, 0x068, 24, 1, 31, - 0x1C0, 27), - /* CLK_CFG_7 */ -- MUX_GATE_CLR_SET_UPD(CLK_TOP_F26M_SEL, "csw_f26m_sel", -- f_26m_adc_parents, 0x070, 0x074, 0x078, 0, 1, 7, -- 0x1C0, 28), -+ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_F26M_SEL, "csw_f26m_sel", -+ f_26m_adc_parents, 0x070, 0x074, 0x078, -+ 0, 1, 7, 0x1C0, 28, -+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), - MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_L_SEL, "aud_l_sel", aud_l_parents, - 0x070, 0x074, 0x078, 8, 2, 15, 0x1C0, 29), - MUX_GATE_CLR_SET_UPD(CLK_TOP_A_TUNER_SEL, "a_tuner_sel", -@@ -307,13 +316,6 @@ static int clk_mt7986_topckgen_probe(str - ARRAY_SIZE(top_muxes), node, - &mt7986_clk_lock, clk_data); - -- clk_prepare_enable(clk_data->hws[CLK_TOP_SYSAXI_SEL]->clk); -- clk_prepare_enable(clk_data->hws[CLK_TOP_SYSAPB_SEL]->clk); -- clk_prepare_enable(clk_data->hws[CLK_TOP_DRAMC_SEL]->clk); -- clk_prepare_enable(clk_data->hws[CLK_TOP_DRAMC_MD32_SEL]->clk); -- clk_prepare_enable(clk_data->hws[CLK_TOP_F26M_SEL]->clk); -- clk_prepare_enable(clk_data->hws[CLK_TOP_SGM_REG_SEL]->clk); -- - r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); - - if (r) { diff --git a/target/linux/mediatek/patches-6.1/228-v6.3-clk-mediatek-clk-mt7986-topckgen-Migrate-to-mtk_clk_.patch b/target/linux/mediatek/patches-6.1/228-v6.3-clk-mediatek-clk-mt7986-topckgen-Migrate-to-mtk_clk_.patch deleted file mode 100644 index d77b859f0..000000000 --- a/target/linux/mediatek/patches-6.1/228-v6.3-clk-mediatek-clk-mt7986-topckgen-Migrate-to-mtk_clk_.patch +++ /dev/null @@ -1,88 +0,0 @@ -From 9ce3b4e4719d4eec38b2c8da939c073835573d1d Mon Sep 17 00:00:00 2001 -From: AngeloGioacchino Del Regno -Date: Fri, 20 Jan 2023 10:20:53 +0100 -Subject: [PATCH 07/15] clk: mediatek: clk-mt7986-topckgen: Migrate to - mtk_clk_simple_probe() - -There are no more non-common calls in clk_mt7986_topckgen_probe(): -migrate this driver to mtk_clk_simple_probe(). - -Signed-off-by: AngeloGioacchino Del Regno -Reviewed-by: Miles Chen -Reviewed-by: Chen-Yu Tsai -Link: https://lore.kernel.org/r/20230120092053.182923-24-angelogioacchino.delregno@collabora.com -Tested-by: Mingming Su -Signed-off-by: Stephen Boyd ---- - drivers/clk/mediatek/clk-mt7986-topckgen.c | 55 +++++----------------- - 1 file changed, 13 insertions(+), 42 deletions(-) - ---- a/drivers/clk/mediatek/clk-mt7986-topckgen.c -+++ b/drivers/clk/mediatek/clk-mt7986-topckgen.c -@@ -290,53 +290,24 @@ static const struct mtk_mux top_muxes[] - 0x1C4, 5), - }; - --static int clk_mt7986_topckgen_probe(struct platform_device *pdev) --{ -- struct clk_hw_onecell_data *clk_data; -- struct device_node *node = pdev->dev.of_node; -- int r; -- void __iomem *base; -- int nr = ARRAY_SIZE(top_fixed_clks) + ARRAY_SIZE(top_divs) + -- ARRAY_SIZE(top_muxes); -- -- base = of_iomap(node, 0); -- if (!base) { -- pr_err("%s(): ioremap failed\n", __func__); -- return -ENOMEM; -- } -- -- clk_data = mtk_alloc_clk_data(nr); -- if (!clk_data) -- return -ENOMEM; -- -- mtk_clk_register_fixed_clks(top_fixed_clks, ARRAY_SIZE(top_fixed_clks), -- clk_data); -- mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), clk_data); -- mtk_clk_register_muxes(&pdev->dev, top_muxes, -- ARRAY_SIZE(top_muxes), node, -- &mt7986_clk_lock, clk_data); -- -- r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); -- -- if (r) { -- pr_err("%s(): could not register clock provider: %d\n", -- __func__, r); -- goto free_topckgen_data; -- } -- return r; -- --free_topckgen_data: -- mtk_free_clk_data(clk_data); -- return r; --} -+static const struct mtk_clk_desc topck_desc = { -+ .fixed_clks = top_fixed_clks, -+ .num_fixed_clks = ARRAY_SIZE(top_fixed_clks), -+ .factor_clks = top_divs, -+ .num_factor_clks = ARRAY_SIZE(top_divs), -+ .mux_clks = top_muxes, -+ .num_mux_clks = ARRAY_SIZE(top_muxes), -+ .clk_lock = &mt7986_clk_lock, -+}; - - static const struct of_device_id of_match_clk_mt7986_topckgen[] = { -- { .compatible = "mediatek,mt7986-topckgen", }, -- {} -+ { .compatible = "mediatek,mt7986-topckgen", .data = &topck_desc }, -+ { /* sentinel */ } - }; - - static struct platform_driver clk_mt7986_topckgen_drv = { -- .probe = clk_mt7986_topckgen_probe, -+ .probe = mtk_clk_simple_probe, -+ .remove = mtk_clk_simple_remove, - .driver = { - .name = "clk-mt7986-topckgen", - .of_match_table = of_match_clk_mt7986_topckgen, diff --git a/target/linux/mediatek/patches-6.1/229-v6.4-clk-mediatek-mt7986-apmixed-Use-PLL_AO-flag-to-set-c.patch b/target/linux/mediatek/patches-6.1/229-v6.4-clk-mediatek-mt7986-apmixed-Use-PLL_AO-flag-to-set-c.patch deleted file mode 100644 index a47dd4b05..000000000 --- a/target/linux/mediatek/patches-6.1/229-v6.4-clk-mediatek-mt7986-apmixed-Use-PLL_AO-flag-to-set-c.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 06abdc84080729dc2c54946e1712c5ee1589ca1c Mon Sep 17 00:00:00 2001 -From: AngeloGioacchino Del Regno -Date: Mon, 6 Mar 2023 15:05:21 +0100 -Subject: [PATCH 13/15] clk: mediatek: mt7986-apmixed: Use PLL_AO flag to set - critical clock - -Instead of calling clk_prepare_enable() at probe time, add the PLL_AO -flag to CLK_APMIXED_ARMPLL clock: this will set CLK_IS_CRITICAL. - -Signed-off-by: AngeloGioacchino Del Regno -Reviewed-by: Chen-Yu Tsai -Tested-by: Daniel Golle -Link: https://lore.kernel.org/r/20230306140543.1813621-33-angelogioacchino.delregno@collabora.com -Signed-off-by: Stephen Boyd ---- - drivers/clk/mediatek/clk-mt7986-apmixed.c | 4 +--- - 1 file changed, 1 insertion(+), 3 deletions(-) - ---- a/drivers/clk/mediatek/clk-mt7986-apmixed.c -+++ b/drivers/clk/mediatek/clk-mt7986-apmixed.c -@@ -42,7 +42,7 @@ - "clkxtal") - - static const struct mtk_pll_data plls[] = { -- PLL(CLK_APMIXED_ARMPLL, "armpll", 0x0200, 0x020C, 0x0, 0, 32, -+ PLL(CLK_APMIXED_ARMPLL, "armpll", 0x0200, 0x020C, 0x0, PLL_AO, 32, - 0x0200, 4, 0, 0x0204, 0), - PLL(CLK_APMIXED_NET2PLL, "net2pll", 0x0210, 0x021C, 0x0, 0, 32, - 0x0210, 4, 0, 0x0214, 0), -@@ -77,8 +77,6 @@ static int clk_mt7986_apmixed_probe(stru - - mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data); - -- clk_prepare_enable(clk_data->hws[CLK_APMIXED_ARMPLL]->clk); -- - r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); - if (r) { - pr_err("%s(): could not register clock provider: %d\n", diff --git a/target/linux/mediatek/patches-6.1/230-v6.4-dt-bindings-clock-mediatek-add-mt7981-clock-IDs.patch b/target/linux/mediatek/patches-6.1/230-v6.4-dt-bindings-clock-mediatek-add-mt7981-clock-IDs.patch deleted file mode 100644 index ae76940e1..000000000 --- a/target/linux/mediatek/patches-6.1/230-v6.4-dt-bindings-clock-mediatek-add-mt7981-clock-IDs.patch +++ /dev/null @@ -1,237 +0,0 @@ -From a6473d0f9f07b1196f3a67099826f50a2a4e84e8 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Thu, 26 Jan 2023 03:34:05 +0000 -Subject: [PATCH] dt-bindings: clock: mediatek: add mt7981 clock IDs - -Add MT7981 clock dt-bindings, include topckgen, apmixedsys, -infracfg, and ethernet subsystem clocks. - -Acked-by: Krzysztof Kozlowski -Signed-off-by: Jianhui Zhao -Signed-off-by: Daniel Golle -Link: https://lore.kernel.org/r/e353d32b5a4481766519a037afe1ed44e31ece1a.1674703830.git.daniel@makrotopia.org -Reviewed-by: AngeloGioacchino Del Regno -Signed-off-by: Stephen Boyd ---- - .../dt-bindings/clock/mediatek,mt7981-clk.h | 215 ++++++++++++++++++ - 1 file changed, 215 insertions(+) - create mode 100644 include/dt-bindings/clock/mediatek,mt7981-clk.h - ---- /dev/null -+++ b/include/dt-bindings/clock/mediatek,mt7981-clk.h -@@ -0,0 +1,215 @@ -+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ -+/* -+ * Copyright (c) 2021 MediaTek Inc. -+ * Author: Wenzhen.Yu -+ * Author: Jianhui Zhao -+ * Author: Daniel Golle -+ */ -+ -+#ifndef _DT_BINDINGS_CLK_MT7981_H -+#define _DT_BINDINGS_CLK_MT7981_H -+ -+/* TOPCKGEN */ -+#define CLK_TOP_CB_CKSQ_40M 0 -+#define CLK_TOP_CB_M_416M 1 -+#define CLK_TOP_CB_M_D2 2 -+#define CLK_TOP_CB_M_D3 3 -+#define CLK_TOP_M_D3_D2 4 -+#define CLK_TOP_CB_M_D4 5 -+#define CLK_TOP_CB_M_D8 6 -+#define CLK_TOP_M_D8_D2 7 -+#define CLK_TOP_CB_MM_720M 8 -+#define CLK_TOP_CB_MM_D2 9 -+#define CLK_TOP_CB_MM_D3 10 -+#define CLK_TOP_CB_MM_D3_D5 11 -+#define CLK_TOP_CB_MM_D4 12 -+#define CLK_TOP_CB_MM_D6 13 -+#define CLK_TOP_MM_D6_D2 14 -+#define CLK_TOP_CB_MM_D8 15 -+#define CLK_TOP_CB_APLL2_196M 16 -+#define CLK_TOP_APLL2_D2 17 -+#define CLK_TOP_APLL2_D4 18 -+#define CLK_TOP_NET1_2500M 19 -+#define CLK_TOP_CB_NET1_D4 20 -+#define CLK_TOP_CB_NET1_D5 21 -+#define CLK_TOP_NET1_D5_D2 22 -+#define CLK_TOP_NET1_D5_D4 23 -+#define CLK_TOP_CB_NET1_D8 24 -+#define CLK_TOP_NET1_D8_D2 25 -+#define CLK_TOP_NET1_D8_D4 26 -+#define CLK_TOP_CB_NET2_800M 27 -+#define CLK_TOP_CB_NET2_D2 28 -+#define CLK_TOP_CB_NET2_D4 29 -+#define CLK_TOP_NET2_D4_D2 30 -+#define CLK_TOP_NET2_D4_D4 31 -+#define CLK_TOP_CB_NET2_D6 32 -+#define CLK_TOP_CB_WEDMCU_208M 33 -+#define CLK_TOP_CB_SGM_325M 34 -+#define CLK_TOP_CKSQ_40M_D2 35 -+#define CLK_TOP_CB_RTC_32K 36 -+#define CLK_TOP_CB_RTC_32P7K 37 -+#define CLK_TOP_USB_TX250M 38 -+#define CLK_TOP_FAUD 39 -+#define CLK_TOP_NFI1X 40 -+#define CLK_TOP_USB_EQ_RX250M 41 -+#define CLK_TOP_USB_CDR_CK 42 -+#define CLK_TOP_USB_LN0_CK 43 -+#define CLK_TOP_SPINFI_BCK 44 -+#define CLK_TOP_SPI 45 -+#define CLK_TOP_SPIM_MST 46 -+#define CLK_TOP_UART_BCK 47 -+#define CLK_TOP_PWM_BCK 48 -+#define CLK_TOP_I2C_BCK 49 -+#define CLK_TOP_PEXTP_TL 50 -+#define CLK_TOP_EMMC_208M 51 -+#define CLK_TOP_EMMC_400M 52 -+#define CLK_TOP_DRAMC_REF 53 -+#define CLK_TOP_DRAMC_MD32 54 -+#define CLK_TOP_SYSAXI 55 -+#define CLK_TOP_SYSAPB 56 -+#define CLK_TOP_ARM_DB_MAIN 57 -+#define CLK_TOP_AP2CNN_HOST 58 -+#define CLK_TOP_NETSYS 59 -+#define CLK_TOP_NETSYS_500M 60 -+#define CLK_TOP_NETSYS_WED_MCU 61 -+#define CLK_TOP_NETSYS_2X 62 -+#define CLK_TOP_SGM_325M 63 -+#define CLK_TOP_SGM_REG 64 -+#define CLK_TOP_F26M 65 -+#define CLK_TOP_EIP97B 66 -+#define CLK_TOP_USB3_PHY 67 -+#define CLK_TOP_AUD 68 -+#define CLK_TOP_A1SYS 69 -+#define CLK_TOP_AUD_L 70 -+#define CLK_TOP_A_TUNER 71 -+#define CLK_TOP_U2U3_REF 72 -+#define CLK_TOP_U2U3_SYS 73 -+#define CLK_TOP_U2U3_XHCI 74 -+#define CLK_TOP_USB_FRMCNT 75 -+#define CLK_TOP_NFI1X_SEL 76 -+#define CLK_TOP_SPINFI_SEL 77 -+#define CLK_TOP_SPI_SEL 78 -+#define CLK_TOP_SPIM_MST_SEL 79 -+#define CLK_TOP_UART_SEL 80 -+#define CLK_TOP_PWM_SEL 81 -+#define CLK_TOP_I2C_SEL 82 -+#define CLK_TOP_PEXTP_TL_SEL 83 -+#define CLK_TOP_EMMC_208M_SEL 84 -+#define CLK_TOP_EMMC_400M_SEL 85 -+#define CLK_TOP_F26M_SEL 86 -+#define CLK_TOP_DRAMC_SEL 87 -+#define CLK_TOP_DRAMC_MD32_SEL 88 -+#define CLK_TOP_SYSAXI_SEL 89 -+#define CLK_TOP_SYSAPB_SEL 90 -+#define CLK_TOP_ARM_DB_MAIN_SEL 91 -+#define CLK_TOP_AP2CNN_HOST_SEL 92 -+#define CLK_TOP_NETSYS_SEL 93 -+#define CLK_TOP_NETSYS_500M_SEL 94 -+#define CLK_TOP_NETSYS_MCU_SEL 95 -+#define CLK_TOP_NETSYS_2X_SEL 96 -+#define CLK_TOP_SGM_325M_SEL 97 -+#define CLK_TOP_SGM_REG_SEL 98 -+#define CLK_TOP_EIP97B_SEL 99 -+#define CLK_TOP_USB3_PHY_SEL 100 -+#define CLK_TOP_AUD_SEL 101 -+#define CLK_TOP_A1SYS_SEL 102 -+#define CLK_TOP_AUD_L_SEL 103 -+#define CLK_TOP_A_TUNER_SEL 104 -+#define CLK_TOP_U2U3_SEL 105 -+#define CLK_TOP_U2U3_SYS_SEL 106 -+#define CLK_TOP_U2U3_XHCI_SEL 107 -+#define CLK_TOP_USB_FRMCNT_SEL 108 -+#define CLK_TOP_AUD_I2S_M 109 -+ -+/* INFRACFG */ -+#define CLK_INFRA_66M_MCK 0 -+#define CLK_INFRA_UART0_SEL 1 -+#define CLK_INFRA_UART1_SEL 2 -+#define CLK_INFRA_UART2_SEL 3 -+#define CLK_INFRA_SPI0_SEL 4 -+#define CLK_INFRA_SPI1_SEL 5 -+#define CLK_INFRA_SPI2_SEL 6 -+#define CLK_INFRA_PWM1_SEL 7 -+#define CLK_INFRA_PWM2_SEL 8 -+#define CLK_INFRA_PWM3_SEL 9 -+#define CLK_INFRA_PWM_BSEL 10 -+#define CLK_INFRA_PCIE_SEL 11 -+#define CLK_INFRA_GPT_STA 12 -+#define CLK_INFRA_PWM_HCK 13 -+#define CLK_INFRA_PWM_STA 14 -+#define CLK_INFRA_PWM1_CK 15 -+#define CLK_INFRA_PWM2_CK 16 -+#define CLK_INFRA_PWM3_CK 17 -+#define CLK_INFRA_CQ_DMA_CK 18 -+#define CLK_INFRA_AUD_BUS_CK 19 -+#define CLK_INFRA_AUD_26M_CK 20 -+#define CLK_INFRA_AUD_L_CK 21 -+#define CLK_INFRA_AUD_AUD_CK 22 -+#define CLK_INFRA_AUD_EG2_CK 23 -+#define CLK_INFRA_DRAMC_26M_CK 24 -+#define CLK_INFRA_DBG_CK 25 -+#define CLK_INFRA_AP_DMA_CK 26 -+#define CLK_INFRA_SEJ_CK 27 -+#define CLK_INFRA_SEJ_13M_CK 28 -+#define CLK_INFRA_THERM_CK 29 -+#define CLK_INFRA_I2C0_CK 30 -+#define CLK_INFRA_UART0_CK 31 -+#define CLK_INFRA_UART1_CK 32 -+#define CLK_INFRA_UART2_CK 33 -+#define CLK_INFRA_SPI2_CK 34 -+#define CLK_INFRA_SPI2_HCK_CK 35 -+#define CLK_INFRA_NFI1_CK 36 -+#define CLK_INFRA_SPINFI1_CK 37 -+#define CLK_INFRA_NFI_HCK_CK 38 -+#define CLK_INFRA_SPI0_CK 39 -+#define CLK_INFRA_SPI1_CK 40 -+#define CLK_INFRA_SPI0_HCK_CK 41 -+#define CLK_INFRA_SPI1_HCK_CK 42 -+#define CLK_INFRA_FRTC_CK 43 -+#define CLK_INFRA_MSDC_CK 44 -+#define CLK_INFRA_MSDC_HCK_CK 45 -+#define CLK_INFRA_MSDC_133M_CK 46 -+#define CLK_INFRA_MSDC_66M_CK 47 -+#define CLK_INFRA_ADC_26M_CK 48 -+#define CLK_INFRA_ADC_FRC_CK 49 -+#define CLK_INFRA_FBIST2FPC_CK 50 -+#define CLK_INFRA_I2C_MCK_CK 51 -+#define CLK_INFRA_I2C_PCK_CK 52 -+#define CLK_INFRA_IUSB_133_CK 53 -+#define CLK_INFRA_IUSB_66M_CK 54 -+#define CLK_INFRA_IUSB_SYS_CK 55 -+#define CLK_INFRA_IUSB_CK 56 -+#define CLK_INFRA_IPCIE_CK 57 -+#define CLK_INFRA_IPCIE_PIPE_CK 58 -+#define CLK_INFRA_IPCIER_CK 59 -+#define CLK_INFRA_IPCIEB_CK 60 -+ -+/* APMIXEDSYS */ -+#define CLK_APMIXED_ARMPLL 0 -+#define CLK_APMIXED_NET2PLL 1 -+#define CLK_APMIXED_MMPLL 2 -+#define CLK_APMIXED_SGMPLL 3 -+#define CLK_APMIXED_WEDMCUPLL 4 -+#define CLK_APMIXED_NET1PLL 5 -+#define CLK_APMIXED_MPLL 6 -+#define CLK_APMIXED_APLL2 7 -+ -+/* SGMIISYS_0 */ -+#define CLK_SGM0_TX_EN 0 -+#define CLK_SGM0_RX_EN 1 -+#define CLK_SGM0_CK0_EN 2 -+#define CLK_SGM0_CDR_CK0_EN 3 -+ -+/* SGMIISYS_1 */ -+#define CLK_SGM1_TX_EN 0 -+#define CLK_SGM1_RX_EN 1 -+#define CLK_SGM1_CK1_EN 2 -+#define CLK_SGM1_CDR_CK1_EN 3 -+ -+/* ETHSYS */ -+#define CLK_ETH_FE_EN 0 -+#define CLK_ETH_GP2_EN 1 -+#define CLK_ETH_GP1_EN 2 -+#define CLK_ETH_WOCPU0_EN 3 -+ -+#endif /* _DT_BINDINGS_CLK_MT7981_H */ diff --git a/target/linux/mediatek/patches-6.1/231-v6.4-clk-mediatek-add-MT7981-clock-support.patch b/target/linux/mediatek/patches-6.1/231-v6.4-clk-mediatek-add-MT7981-clock-support.patch deleted file mode 100644 index f9dd94a78..000000000 --- a/target/linux/mediatek/patches-6.1/231-v6.4-clk-mediatek-add-MT7981-clock-support.patch +++ /dev/null @@ -1,932 +0,0 @@ -From 8efeeb9c8b4ecf4fb4a74be9403aba951403bbaa Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Thu, 26 Jan 2023 03:34:24 +0000 -Subject: [PATCH] clk: mediatek: add MT7981 clock support - -Add MT7981 clock support, include topckgen, apmixedsys, infracfg and -ethernet subsystem clocks. - -The drivers are based on clk-mt7981.c which can be found in MediaTek's -SDK sources. To be fit for upstream inclusion the driver has been split -into clock domains and the infracfg part has been significantly -de-bloated by removing all the 1:1 factors (aliases). - -Signed-off-by: Jianhui Zhao -Signed-off-by: Daniel Golle -Link: https://lore.kernel.org/r/8136eb5b2049177bc2f6d3e0f2aefecc342d626f.1674703830.git.daniel@makrotopia.org -Reviewed-by: AngeloGioacchino Del Regno -[sboyd@kernel.org: Add module license] -Signed-off-by: Stephen Boyd ---- - drivers/clk/mediatek/Kconfig | 17 + - drivers/clk/mediatek/Makefile | 4 + - drivers/clk/mediatek/clk-mt7981-apmixed.c | 102 +++++ - drivers/clk/mediatek/clk-mt7981-eth.c | 118 ++++++ - drivers/clk/mediatek/clk-mt7981-infracfg.c | 207 ++++++++++ - drivers/clk/mediatek/clk-mt7981-topckgen.c | 422 +++++++++++++++++++++ - 6 files changed, 870 insertions(+) - create mode 100644 drivers/clk/mediatek/clk-mt7981-apmixed.c - create mode 100644 drivers/clk/mediatek/clk-mt7981-eth.c - create mode 100644 drivers/clk/mediatek/clk-mt7981-infracfg.c - create mode 100644 drivers/clk/mediatek/clk-mt7981-topckgen.c - ---- a/drivers/clk/mediatek/Kconfig -+++ b/drivers/clk/mediatek/Kconfig -@@ -381,6 +381,23 @@ config COMMON_CLK_MT7629_HIFSYS - This driver supports MediaTek MT7629 HIFSYS clocks providing - to PCI-E and USB. - -+config COMMON_CLK_MT7981 -+ bool "Clock driver for MediaTek MT7981" -+ depends on ARCH_MEDIATEK || COMPILE_TEST -+ select COMMON_CLK_MEDIATEK -+ default ARCH_MEDIATEK -+ help -+ This driver supports MediaTek MT7981 basic clocks and clocks -+ required for various peripherals found on this SoC. -+ -+config COMMON_CLK_MT7981_ETHSYS -+ tristate "Clock driver for MediaTek MT7981 ETHSYS" -+ depends on COMMON_CLK_MT7981 -+ default COMMON_CLK_MT7981 -+ help -+ This driver adds support for clocks for Ethernet and SGMII -+ required on MediaTek MT7981 SoC. -+ - config COMMON_CLK_MT7986 - bool "Clock driver for MediaTek MT7986" - depends on ARCH_MEDIATEK || COMPILE_TEST ---- a/drivers/clk/mediatek/Makefile -+++ b/drivers/clk/mediatek/Makefile -@@ -52,6 +52,10 @@ obj-$(CONFIG_COMMON_CLK_MT7622_AUDSYS) + - obj-$(CONFIG_COMMON_CLK_MT7629) += clk-mt7629.o - obj-$(CONFIG_COMMON_CLK_MT7629_ETHSYS) += clk-mt7629-eth.o - obj-$(CONFIG_COMMON_CLK_MT7629_HIFSYS) += clk-mt7629-hif.o -+obj-$(CONFIG_COMMON_CLK_MT7981) += clk-mt7981-apmixed.o -+obj-$(CONFIG_COMMON_CLK_MT7981) += clk-mt7981-topckgen.o -+obj-$(CONFIG_COMMON_CLK_MT7981) += clk-mt7981-infracfg.o -+obj-$(CONFIG_COMMON_CLK_MT7981_ETHSYS) += clk-mt7981-eth.o - obj-$(CONFIG_COMMON_CLK_MT7986) += clk-mt7986-apmixed.o - obj-$(CONFIG_COMMON_CLK_MT7986) += clk-mt7986-topckgen.o - obj-$(CONFIG_COMMON_CLK_MT7986) += clk-mt7986-infracfg.o ---- /dev/null -+++ b/drivers/clk/mediatek/clk-mt7981-apmixed.c -@@ -0,0 +1,102 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (c) 2021 MediaTek Inc. -+ * Author: Sam Shih -+ * Author: Wenzhen Yu -+ * Author: Jianhui Zhao -+ * Author: Daniel Golle -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include "clk-gate.h" -+#include "clk-mtk.h" -+#include "clk-mux.h" -+#include "clk-pll.h" -+ -+#include -+#include -+ -+#define MT7981_PLL_FMAX (2500UL * MHZ) -+#define CON0_MT7981_RST_BAR BIT(27) -+ -+#define PLL_xtal(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \ -+ _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, _pcw_shift, \ -+ _div_table, _parent_name) \ -+ { \ -+ .id = _id, .name = _name, .reg = _reg, .pwr_reg = _pwr_reg, \ -+ .en_mask = _en_mask, .flags = _flags, \ -+ .rst_bar_mask = CON0_MT7981_RST_BAR, .fmax = MT7981_PLL_FMAX, \ -+ .pcwbits = _pcwbits, .pd_reg = _pd_reg, .pd_shift = _pd_shift, \ -+ .tuner_reg = _tuner_reg, .pcw_reg = _pcw_reg, \ -+ .pcw_shift = _pcw_shift, .div_table = _div_table, \ -+ .parent_name = _parent_name, \ -+ } -+ -+#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, _pd_reg, \ -+ _pd_shift, _tuner_reg, _pcw_reg, _pcw_shift) \ -+ PLL_xtal(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \ -+ _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, _pcw_shift, NULL, \ -+ "clkxtal") -+ -+static const struct mtk_pll_data plls[] = { -+ PLL(CLK_APMIXED_ARMPLL, "armpll", 0x0200, 0x020C, 0x00000001, PLL_AO, -+ 32, 0x0200, 4, 0, 0x0204, 0), -+ PLL(CLK_APMIXED_NET2PLL, "net2pll", 0x0210, 0x021C, 0x00000001, 0, 32, -+ 0x0210, 4, 0, 0x0214, 0), -+ PLL(CLK_APMIXED_MMPLL, "mmpll", 0x0220, 0x022C, 0x00000001, 0, 32, -+ 0x0220, 4, 0, 0x0224, 0), -+ PLL(CLK_APMIXED_SGMPLL, "sgmpll", 0x0230, 0x023C, 0x00000001, 0, 32, -+ 0x0230, 4, 0, 0x0234, 0), -+ PLL(CLK_APMIXED_WEDMCUPLL, "wedmcupll", 0x0240, 0x024C, 0x00000001, 0, 32, -+ 0x0240, 4, 0, 0x0244, 0), -+ PLL(CLK_APMIXED_NET1PLL, "net1pll", 0x0250, 0x025C, 0x00000001, 0, 32, -+ 0x0250, 4, 0, 0x0254, 0), -+ PLL(CLK_APMIXED_MPLL, "mpll", 0x0260, 0x0270, 0x00000001, 0, 32, -+ 0x0260, 4, 0, 0x0264, 0), -+ PLL(CLK_APMIXED_APLL2, "apll2", 0x0278, 0x0288, 0x00000001, 0, 32, -+ 0x0278, 4, 0, 0x027C, 0), -+}; -+ -+static const struct of_device_id of_match_clk_mt7981_apmixed[] = { -+ { .compatible = "mediatek,mt7981-apmixedsys", }, -+ { /* sentinel */ } -+}; -+ -+static int clk_mt7981_apmixed_probe(struct platform_device *pdev) -+{ -+ struct clk_hw_onecell_data *clk_data; -+ struct device_node *node = pdev->dev.of_node; -+ int r; -+ -+ clk_data = mtk_alloc_clk_data(ARRAY_SIZE(plls)); -+ if (!clk_data) -+ return -ENOMEM; -+ -+ mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data); -+ -+ r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); -+ if (r) { -+ pr_err("%s(): could not register clock provider: %d\n", -+ __func__, r); -+ goto free_apmixed_data; -+ } -+ return r; -+ -+free_apmixed_data: -+ mtk_free_clk_data(clk_data); -+ return r; -+} -+ -+static struct platform_driver clk_mt7981_apmixed_drv = { -+ .probe = clk_mt7981_apmixed_probe, -+ .driver = { -+ .name = "clk-mt7981-apmixed", -+ .of_match_table = of_match_clk_mt7981_apmixed, -+ }, -+}; -+builtin_platform_driver(clk_mt7981_apmixed_drv); ---- /dev/null -+++ b/drivers/clk/mediatek/clk-mt7981-eth.c -@@ -0,0 +1,118 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (c) 2021 MediaTek Inc. -+ * Author: Sam Shih -+ * Author: Wenzhen Yu -+ * Author: Jianhui Zhao -+ * Author: Daniel Golle -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include "clk-mtk.h" -+#include "clk-gate.h" -+ -+#include -+ -+static const struct mtk_gate_regs sgmii0_cg_regs = { -+ .set_ofs = 0xE4, -+ .clr_ofs = 0xE4, -+ .sta_ofs = 0xE4, -+}; -+ -+#define GATE_SGMII0(_id, _name, _parent, _shift) { \ -+ .id = _id, \ -+ .name = _name, \ -+ .parent_name = _parent, \ -+ .regs = &sgmii0_cg_regs, \ -+ .shift = _shift, \ -+ .ops = &mtk_clk_gate_ops_no_setclr_inv, \ -+ } -+ -+static const struct mtk_gate sgmii0_clks[] __initconst = { -+ GATE_SGMII0(CLK_SGM0_TX_EN, "sgm0_tx_en", "usb_tx250m", 2), -+ GATE_SGMII0(CLK_SGM0_RX_EN, "sgm0_rx_en", "usb_eq_rx250m", 3), -+ GATE_SGMII0(CLK_SGM0_CK0_EN, "sgm0_ck0_en", "usb_ln0", 4), -+ GATE_SGMII0(CLK_SGM0_CDR_CK0_EN, "sgm0_cdr_ck0_en", "usb_cdr", 5), -+}; -+ -+static const struct mtk_gate_regs sgmii1_cg_regs = { -+ .set_ofs = 0xE4, -+ .clr_ofs = 0xE4, -+ .sta_ofs = 0xE4, -+}; -+ -+#define GATE_SGMII1(_id, _name, _parent, _shift) { \ -+ .id = _id, \ -+ .name = _name, \ -+ .parent_name = _parent, \ -+ .regs = &sgmii1_cg_regs, \ -+ .shift = _shift, \ -+ .ops = &mtk_clk_gate_ops_no_setclr_inv, \ -+ } -+ -+static const struct mtk_gate sgmii1_clks[] __initconst = { -+ GATE_SGMII1(CLK_SGM1_TX_EN, "sgm1_tx_en", "usb_tx250m", 2), -+ GATE_SGMII1(CLK_SGM1_RX_EN, "sgm1_rx_en", "usb_eq_rx250m", 3), -+ GATE_SGMII1(CLK_SGM1_CK1_EN, "sgm1_ck1_en", "usb_ln0", 4), -+ GATE_SGMII1(CLK_SGM1_CDR_CK1_EN, "sgm1_cdr_ck1_en", "usb_cdr", 5), -+}; -+ -+static const struct mtk_gate_regs eth_cg_regs = { -+ .set_ofs = 0x30, -+ .clr_ofs = 0x30, -+ .sta_ofs = 0x30, -+}; -+ -+#define GATE_ETH(_id, _name, _parent, _shift) { \ -+ .id = _id, \ -+ .name = _name, \ -+ .parent_name = _parent, \ -+ .regs = ð_cg_regs, \ -+ .shift = _shift, \ -+ .ops = &mtk_clk_gate_ops_no_setclr_inv, \ -+ } -+ -+static const struct mtk_gate eth_clks[] __initconst = { -+ GATE_ETH(CLK_ETH_FE_EN, "eth_fe_en", "netsys_2x", 6), -+ GATE_ETH(CLK_ETH_GP2_EN, "eth_gp2_en", "sgm_325m", 7), -+ GATE_ETH(CLK_ETH_GP1_EN, "eth_gp1_en", "sgm_325m", 8), -+ GATE_ETH(CLK_ETH_WOCPU0_EN, "eth_wocpu0_en", "netsys_wed_mcu", 15), -+}; -+ -+static const struct mtk_clk_desc eth_desc = { -+ .clks = eth_clks, -+ .num_clks = ARRAY_SIZE(eth_clks), -+}; -+ -+static const struct mtk_clk_desc sgmii0_desc = { -+ .clks = sgmii0_clks, -+ .num_clks = ARRAY_SIZE(sgmii0_clks), -+}; -+ -+static const struct mtk_clk_desc sgmii1_desc = { -+ .clks = sgmii1_clks, -+ .num_clks = ARRAY_SIZE(sgmii1_clks), -+}; -+ -+static const struct of_device_id of_match_clk_mt7981_eth[] = { -+ { .compatible = "mediatek,mt7981-ethsys", .data = ð_desc }, -+ { .compatible = "mediatek,mt7981-sgmiisys_0", .data = &sgmii0_desc }, -+ { .compatible = "mediatek,mt7981-sgmiisys_1", .data = &sgmii1_desc }, -+ { /* sentinel */ } -+}; -+ -+static struct platform_driver clk_mt7981_eth_drv = { -+ .probe = mtk_clk_simple_probe, -+ .remove = mtk_clk_simple_remove, -+ .driver = { -+ .name = "clk-mt7981-eth", -+ .of_match_table = of_match_clk_mt7981_eth, -+ }, -+}; -+module_platform_driver(clk_mt7981_eth_drv); -+MODULE_LICENSE("GPL v2"); ---- /dev/null -+++ b/drivers/clk/mediatek/clk-mt7981-infracfg.c -@@ -0,0 +1,207 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (c) 2021 MediaTek Inc. -+ * Author: Sam Shih -+ * Author: Wenzhen Yu -+ * Author: Jianhui Zhao -+ * Author: Daniel Golle -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include "clk-mtk.h" -+#include "clk-gate.h" -+#include "clk-mux.h" -+ -+#include -+#include -+ -+static DEFINE_SPINLOCK(mt7981_clk_lock); -+ -+static const struct mtk_fixed_factor infra_divs[] = { -+ FACTOR(CLK_INFRA_66M_MCK, "infra_66m_mck", "sysaxi_sel", 1, 2), -+}; -+ -+static const char *const infra_uart_parent[] __initconst = { "csw_f26m_sel", -+ "uart_sel" }; -+ -+static const char *const infra_spi0_parents[] __initconst = { "i2c_sel", -+ "spi_sel" }; -+ -+static const char *const infra_spi1_parents[] __initconst = { "i2c_sel", -+ "spim_mst_sel" }; -+ -+static const char *const infra_pwm1_parents[] __initconst = { "pwm_sel" }; -+ -+static const char *const infra_pwm_bsel_parents[] __initconst = { -+ "cb_rtc_32p7k", "csw_f26m_sel", "infra_66m_mck", "pwm_sel" -+}; -+ -+static const char *const infra_pcie_parents[] __initconst = { -+ "cb_rtc_32p7k", "csw_f26m_sel", "cb_cksq_40m", "pextp_tl_ck_sel" -+}; -+ -+static const struct mtk_mux infra_muxes[] = { -+ /* MODULE_CLK_SEL_0 */ -+ MUX_GATE_CLR_SET_UPD(CLK_INFRA_UART0_SEL, "infra_uart0_sel", -+ infra_uart_parent, 0x0018, 0x0010, 0x0014, 0, 1, -+ -1, -1, -1), -+ MUX_GATE_CLR_SET_UPD(CLK_INFRA_UART1_SEL, "infra_uart1_sel", -+ infra_uart_parent, 0x0018, 0x0010, 0x0014, 1, 1, -+ -1, -1, -1), -+ MUX_GATE_CLR_SET_UPD(CLK_INFRA_UART2_SEL, "infra_uart2_sel", -+ infra_uart_parent, 0x0018, 0x0010, 0x0014, 2, 1, -+ -1, -1, -1), -+ MUX_GATE_CLR_SET_UPD(CLK_INFRA_SPI0_SEL, "infra_spi0_sel", -+ infra_spi0_parents, 0x0018, 0x0010, 0x0014, 4, 1, -+ -1, -1, -1), -+ MUX_GATE_CLR_SET_UPD(CLK_INFRA_SPI1_SEL, "infra_spi1_sel", -+ infra_spi1_parents, 0x0018, 0x0010, 0x0014, 5, 1, -+ -1, -1, -1), -+ MUX_GATE_CLR_SET_UPD(CLK_INFRA_SPI2_SEL, "infra_spi2_sel", -+ infra_spi0_parents, 0x0018, 0x0010, 0x0014, 6, 1, -+ -1, -1, -1), -+ MUX_GATE_CLR_SET_UPD(CLK_INFRA_PWM1_SEL, "infra_pwm1_sel", -+ infra_pwm1_parents, 0x0018, 0x0010, 0x0014, 9, 1, -+ -1, -1, -1), -+ MUX_GATE_CLR_SET_UPD(CLK_INFRA_PWM2_SEL, "infra_pwm2_sel", -+ infra_pwm1_parents, 0x0018, 0x0010, 0x0014, 11, 1, -+ -1, -1, -1), -+ MUX_GATE_CLR_SET_UPD(CLK_INFRA_PWM3_SEL, "infra_pwm3_sel", -+ infra_pwm1_parents, 0x0018, 0x0010, 0x0014, 15, 1, -+ -1, -1, -1), -+ MUX_GATE_CLR_SET_UPD(CLK_INFRA_PWM_BSEL, "infra_pwm_bsel", -+ infra_pwm_bsel_parents, 0x0018, 0x0010, 0x0014, 13, -+ 2, -1, -1, -1), -+ /* MODULE_CLK_SEL_1 */ -+ MUX_GATE_CLR_SET_UPD(CLK_INFRA_PCIE_SEL, "infra_pcie_sel", -+ infra_pcie_parents, 0x0028, 0x0020, 0x0024, 0, 2, -+ -1, -1, -1), -+}; -+ -+static const struct mtk_gate_regs infra0_cg_regs = { -+ .set_ofs = 0x40, -+ .clr_ofs = 0x44, -+ .sta_ofs = 0x48, -+}; -+ -+static const struct mtk_gate_regs infra1_cg_regs = { -+ .set_ofs = 0x50, -+ .clr_ofs = 0x54, -+ .sta_ofs = 0x58, -+}; -+ -+static const struct mtk_gate_regs infra2_cg_regs = { -+ .set_ofs = 0x60, -+ .clr_ofs = 0x64, -+ .sta_ofs = 0x68, -+}; -+ -+#define GATE_INFRA0(_id, _name, _parent, _shift) \ -+ { \ -+ .id = _id, .name = _name, .parent_name = _parent, \ -+ .regs = &infra0_cg_regs, .shift = _shift, \ -+ .ops = &mtk_clk_gate_ops_setclr, \ -+ } -+ -+#define GATE_INFRA1(_id, _name, _parent, _shift) \ -+ { \ -+ .id = _id, .name = _name, .parent_name = _parent, \ -+ .regs = &infra1_cg_regs, .shift = _shift, \ -+ .ops = &mtk_clk_gate_ops_setclr, \ -+ } -+ -+#define GATE_INFRA2(_id, _name, _parent, _shift) \ -+ { \ -+ .id = _id, .name = _name, .parent_name = _parent, \ -+ .regs = &infra2_cg_regs, .shift = _shift, \ -+ .ops = &mtk_clk_gate_ops_setclr, \ -+ } -+ -+static const struct mtk_gate infra_clks[] = { -+ /* INFRA0 */ -+ GATE_INFRA0(CLK_INFRA_GPT_STA, "infra_gpt_sta", "infra_66m_mck", 0), -+ GATE_INFRA0(CLK_INFRA_PWM_HCK, "infra_pwm_hck", "infra_66m_mck", 1), -+ GATE_INFRA0(CLK_INFRA_PWM_STA, "infra_pwm_sta", "infra_pwm_bsel", 2), -+ GATE_INFRA0(CLK_INFRA_PWM1_CK, "infra_pwm1", "infra_pwm1_sel", 3), -+ GATE_INFRA0(CLK_INFRA_PWM2_CK, "infra_pwm2", "infra_pwm2_sel", 4), -+ GATE_INFRA0(CLK_INFRA_CQ_DMA_CK, "infra_cq_dma", "sysaxi", 6), -+ -+ GATE_INFRA0(CLK_INFRA_AUD_BUS_CK, "infra_aud_bus", "sysaxi", 8), -+ GATE_INFRA0(CLK_INFRA_AUD_26M_CK, "infra_aud_26m", "csw_f26m_sel", 9), -+ GATE_INFRA0(CLK_INFRA_AUD_L_CK, "infra_aud_l", "aud_l", 10), -+ GATE_INFRA0(CLK_INFRA_AUD_AUD_CK, "infra_aud_aud", "a1sys", 11), -+ GATE_INFRA0(CLK_INFRA_AUD_EG2_CK, "infra_aud_eg2", "a_tuner", 13), -+ GATE_INFRA0(CLK_INFRA_DRAMC_26M_CK, "infra_dramc_26m", "csw_f26m_sel", -+ 14), -+ GATE_INFRA0(CLK_INFRA_DBG_CK, "infra_dbg", "infra_66m_mck", 15), -+ GATE_INFRA0(CLK_INFRA_AP_DMA_CK, "infra_ap_dma", "infra_66m_mck", 16), -+ GATE_INFRA0(CLK_INFRA_SEJ_CK, "infra_sej", "infra_66m_mck", 24), -+ GATE_INFRA0(CLK_INFRA_SEJ_13M_CK, "infra_sej_13m", "csw_f26m_sel", 25), -+ GATE_INFRA0(CLK_INFRA_PWM3_CK, "infra_pwm3", "infra_pwm3_sel", 27), -+ /* INFRA1 */ -+ GATE_INFRA1(CLK_INFRA_THERM_CK, "infra_therm", "csw_f26m_sel", 0), -+ GATE_INFRA1(CLK_INFRA_I2C0_CK, "infra_i2c0", "i2c_bck", 1), -+ GATE_INFRA1(CLK_INFRA_UART0_CK, "infra_uart0", "infra_uart0_sel", 2), -+ GATE_INFRA1(CLK_INFRA_UART1_CK, "infra_uart1", "infra_uart1_sel", 3), -+ GATE_INFRA1(CLK_INFRA_UART2_CK, "infra_uart2", "infra_uart2_sel", 4), -+ GATE_INFRA1(CLK_INFRA_SPI2_CK, "infra_spi2", "infra_spi2_sel", 6), -+ GATE_INFRA1(CLK_INFRA_SPI2_HCK_CK, "infra_spi2_hck", "infra_66m_mck", 7), -+ GATE_INFRA1(CLK_INFRA_NFI1_CK, "infra_nfi1", "nfi1x", 8), -+ GATE_INFRA1(CLK_INFRA_SPINFI1_CK, "infra_spinfi1", "spinfi_bck", 9), -+ GATE_INFRA1(CLK_INFRA_NFI_HCK_CK, "infra_nfi_hck", "infra_66m_mck", 10), -+ GATE_INFRA1(CLK_INFRA_SPI0_CK, "infra_spi0", "infra_spi0_sel", 11), -+ GATE_INFRA1(CLK_INFRA_SPI1_CK, "infra_spi1", "infra_spi1_sel", 12), -+ GATE_INFRA1(CLK_INFRA_SPI0_HCK_CK, "infra_spi0_hck", "infra_66m_mck", -+ 13), -+ GATE_INFRA1(CLK_INFRA_SPI1_HCK_CK, "infra_spi1_hck", "infra_66m_mck", -+ 14), -+ GATE_INFRA1(CLK_INFRA_FRTC_CK, "infra_frtc", "cb_rtc_32k", 15), -+ GATE_INFRA1(CLK_INFRA_MSDC_CK, "infra_msdc", "emmc_400m", 16), -+ GATE_INFRA1(CLK_INFRA_MSDC_HCK_CK, "infra_msdc_hck", "emmc_208m", 17), -+ GATE_INFRA1(CLK_INFRA_MSDC_133M_CK, "infra_msdc_133m", "sysaxi", 18), -+ GATE_INFRA1(CLK_INFRA_MSDC_66M_CK, "infra_msdc_66m", "sysaxi", 19), -+ GATE_INFRA1(CLK_INFRA_ADC_26M_CK, "infra_adc_26m", "infra_adc_frc", 20), -+ GATE_INFRA1(CLK_INFRA_ADC_FRC_CK, "infra_adc_frc", "csw_f26m", 21), -+ GATE_INFRA1(CLK_INFRA_FBIST2FPC_CK, "infra_fbist2fpc", "nfi1x", 23), -+ GATE_INFRA1(CLK_INFRA_I2C_MCK_CK, "infra_i2c_mck", "sysaxi", 25), -+ GATE_INFRA1(CLK_INFRA_I2C_PCK_CK, "infra_i2c_pck", "infra_66m_mck", 26), -+ /* INFRA2 */ -+ GATE_INFRA2(CLK_INFRA_IUSB_133_CK, "infra_iusb_133", "sysaxi", 0), -+ GATE_INFRA2(CLK_INFRA_IUSB_66M_CK, "infra_iusb_66m", "sysaxi", 1), -+ GATE_INFRA2(CLK_INFRA_IUSB_SYS_CK, "infra_iusb_sys", "u2u3_sys", 2), -+ GATE_INFRA2(CLK_INFRA_IUSB_CK, "infra_iusb", "u2u3_ref", 3), -+ GATE_INFRA2(CLK_INFRA_IPCIE_CK, "infra_ipcie", "pextp_tl", 12), -+ GATE_INFRA2(CLK_INFRA_IPCIE_PIPE_CK, "infra_ipcie_pipe", "cb_cksq_40m", -+ 13), -+ GATE_INFRA2(CLK_INFRA_IPCIER_CK, "infra_ipcier", "csw_f26m", 14), -+ GATE_INFRA2(CLK_INFRA_IPCIEB_CK, "infra_ipcieb", "sysaxi", 15), -+}; -+ -+static const struct mtk_clk_desc infracfg_desc = { -+ .factor_clks = infra_divs, -+ .num_factor_clks = ARRAY_SIZE(infra_divs), -+ .mux_clks = infra_muxes, -+ .num_mux_clks = ARRAY_SIZE(infra_muxes), -+ .clks = infra_clks, -+ .num_clks = ARRAY_SIZE(infra_clks), -+ .clk_lock = &mt7981_clk_lock, -+}; -+ -+static const struct of_device_id of_match_clk_mt7981_infracfg[] = { -+ { .compatible = "mediatek,mt7981-infracfg", .data = &infracfg_desc }, -+ { /* sentinel */ } -+}; -+ -+static struct platform_driver clk_mt7981_infracfg_drv = { -+ .probe = mtk_clk_simple_probe, -+ .remove = mtk_clk_simple_remove, -+ .driver = { -+ .name = "clk-mt7981-infracfg", -+ .of_match_table = of_match_clk_mt7981_infracfg, -+ }, -+}; -+builtin_platform_driver(clk_mt7981_infracfg_drv); ---- /dev/null -+++ b/drivers/clk/mediatek/clk-mt7981-topckgen.c -@@ -0,0 +1,422 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (c) 2021 MediaTek Inc. -+ * Author: Sam Shih -+ * Author: Wenzhen Yu -+ * Author: Jianhui Zhao -+ */ -+ -+ -+#include -+#include -+#include -+#include -+#include -+#include "clk-mtk.h" -+#include "clk-gate.h" -+#include "clk-mux.h" -+ -+#include -+#include -+ -+static DEFINE_SPINLOCK(mt7981_clk_lock); -+ -+static const struct mtk_fixed_factor top_divs[] = { -+ FACTOR(CLK_TOP_CB_CKSQ_40M, "cb_cksq_40m", "clkxtal", 1, 1), -+ FACTOR(CLK_TOP_CB_M_416M, "cb_m_416m", "mpll", 1, 1), -+ FACTOR(CLK_TOP_CB_M_D2, "cb_m_d2", "mpll", 1, 2), -+ FACTOR(CLK_TOP_CB_M_D3, "cb_m_d3", "mpll", 1, 3), -+ FACTOR(CLK_TOP_M_D3_D2, "m_d3_d2", "mpll", 1, 2), -+ FACTOR(CLK_TOP_CB_M_D4, "cb_m_d4", "mpll", 1, 4), -+ FACTOR(CLK_TOP_CB_M_D8, "cb_m_d8", "mpll", 1, 8), -+ FACTOR(CLK_TOP_M_D8_D2, "m_d8_d2", "mpll", 1, 16), -+ FACTOR(CLK_TOP_CB_MM_720M, "cb_mm_720m", "mmpll", 1, 1), -+ FACTOR(CLK_TOP_CB_MM_D2, "cb_mm_d2", "mmpll", 1, 2), -+ FACTOR(CLK_TOP_CB_MM_D3, "cb_mm_d3", "mmpll", 1, 3), -+ FACTOR(CLK_TOP_CB_MM_D3_D5, "cb_mm_d3_d5", "mmpll", 1, 15), -+ FACTOR(CLK_TOP_CB_MM_D4, "cb_mm_d4", "mmpll", 1, 4), -+ FACTOR(CLK_TOP_CB_MM_D6, "cb_mm_d6", "mmpll", 1, 6), -+ FACTOR(CLK_TOP_MM_D6_D2, "mm_d6_d2", "mmpll", 1, 12), -+ FACTOR(CLK_TOP_CB_MM_D8, "cb_mm_d8", "mmpll", 1, 8), -+ FACTOR(CLK_TOP_CB_APLL2_196M, "cb_apll2_196m", "apll2", 1, 1), -+ FACTOR(CLK_TOP_APLL2_D2, "apll2_d2", "apll2", 1, 2), -+ FACTOR(CLK_TOP_APLL2_D4, "apll2_d4", "apll2", 1, 4), -+ FACTOR(CLK_TOP_NET1_2500M, "net1_2500m", "net1pll", 1, 1), -+ FACTOR(CLK_TOP_CB_NET1_D4, "cb_net1_d4", "net1pll", 1, 4), -+ FACTOR(CLK_TOP_CB_NET1_D5, "cb_net1_d5", "net1pll", 1, 5), -+ FACTOR(CLK_TOP_NET1_D5_D2, "net1_d5_d2", "net1pll", 1, 10), -+ FACTOR(CLK_TOP_NET1_D5_D4, "net1_d5_d4", "net1pll", 1, 20), -+ FACTOR(CLK_TOP_CB_NET1_D8, "cb_net1_d8", "net1pll", 1, 8), -+ FACTOR(CLK_TOP_NET1_D8_D2, "net1_d8_d2", "net1pll", 1, 16), -+ FACTOR(CLK_TOP_NET1_D8_D4, "net1_d8_d4", "net1pll", 1, 32), -+ FACTOR(CLK_TOP_CB_NET2_800M, "cb_net2_800m", "net2pll", 1, 1), -+ FACTOR(CLK_TOP_CB_NET2_D2, "cb_net2_d2", "net2pll", 1, 2), -+ FACTOR(CLK_TOP_CB_NET2_D4, "cb_net2_d4", "net2pll", 1, 4), -+ FACTOR(CLK_TOP_NET2_D4_D2, "net2_d4_d2", "net2pll", 1, 8), -+ FACTOR(CLK_TOP_NET2_D4_D4, "net2_d4_d4", "net2pll", 1, 16), -+ FACTOR(CLK_TOP_CB_NET2_D6, "cb_net2_d6", "net2pll", 1, 6), -+ FACTOR(CLK_TOP_CB_WEDMCU_208M, "cb_wedmcu_208m", "wedmcupll", 1, 1), -+ FACTOR(CLK_TOP_CB_SGM_325M, "cb_sgm_325m", "sgmpll", 1, 1), -+ FACTOR(CLK_TOP_CKSQ_40M_D2, "cksq_40m_d2", "cb_cksq_40m", 1, 2), -+ FACTOR(CLK_TOP_CB_RTC_32K, "cb_rtc_32k", "cb_cksq_40m", 1, 1250), -+ FACTOR(CLK_TOP_CB_RTC_32P7K, "cb_rtc_32p7k", "cb_cksq_40m", 1, 1220), -+ FACTOR(CLK_TOP_USB_TX250M, "usb_tx250m", "cb_cksq_40m", 1, 1), -+ FACTOR(CLK_TOP_FAUD, "faud", "aud_sel", 1, 1), -+ FACTOR(CLK_TOP_NFI1X, "nfi1x", "nfi1x_sel", 1, 1), -+ FACTOR(CLK_TOP_USB_EQ_RX250M, "usb_eq_rx250m", "cb_cksq_40m", 1, 1), -+ FACTOR(CLK_TOP_USB_CDR_CK, "usb_cdr", "cb_cksq_40m", 1, 1), -+ FACTOR(CLK_TOP_USB_LN0_CK, "usb_ln0", "cb_cksq_40m", 1, 1), -+ FACTOR(CLK_TOP_SPINFI_BCK, "spinfi_bck", "spinfi_sel", 1, 1), -+ FACTOR(CLK_TOP_SPI, "spi", "spi_sel", 1, 1), -+ FACTOR(CLK_TOP_SPIM_MST, "spim_mst", "spim_mst_sel", 1, 1), -+ FACTOR(CLK_TOP_UART_BCK, "uart_bck", "uart_sel", 1, 1), -+ FACTOR(CLK_TOP_PWM_BCK, "pwm_bck", "pwm_sel", 1, 1), -+ FACTOR(CLK_TOP_I2C_BCK, "i2c_bck", "i2c_sel", 1, 1), -+ FACTOR(CLK_TOP_PEXTP_TL, "pextp_tl", "pextp_tl_ck_sel", 1, 1), -+ FACTOR(CLK_TOP_EMMC_208M, "emmc_208m", "emmc_208m_sel", 1, 1), -+ FACTOR(CLK_TOP_EMMC_400M, "emmc_400m", "emmc_400m_sel", 1, 1), -+ FACTOR(CLK_TOP_DRAMC_REF, "dramc_ref", "dramc_sel", 1, 1), -+ FACTOR(CLK_TOP_DRAMC_MD32, "dramc_md32", "dramc_md32_sel", 1, 1), -+ FACTOR(CLK_TOP_SYSAXI, "sysaxi", "sysaxi_sel", 1, 1), -+ FACTOR(CLK_TOP_SYSAPB, "sysapb", "sysapb_sel", 1, 1), -+ FACTOR(CLK_TOP_ARM_DB_MAIN, "arm_db_main", "arm_db_main_sel", 1, 1), -+ FACTOR(CLK_TOP_AP2CNN_HOST, "ap2cnn_host", "ap2cnn_host_sel", 1, 1), -+ FACTOR(CLK_TOP_NETSYS, "netsys", "netsys_sel", 1, 1), -+ FACTOR(CLK_TOP_NETSYS_500M, "netsys_500m", "netsys_500m_sel", 1, 1), -+ FACTOR(CLK_TOP_NETSYS_WED_MCU, "netsys_wed_mcu", "netsys_mcu_sel", 1, 1), -+ FACTOR(CLK_TOP_NETSYS_2X, "netsys_2x", "netsys_2x_sel", 1, 1), -+ FACTOR(CLK_TOP_SGM_325M, "sgm_325m", "sgm_325m_sel", 1, 1), -+ FACTOR(CLK_TOP_SGM_REG, "sgm_reg", "sgm_reg_sel", 1, 1), -+ FACTOR(CLK_TOP_F26M, "csw_f26m", "csw_f26m_sel", 1, 1), -+ FACTOR(CLK_TOP_EIP97B, "eip97b", "eip97b_sel", 1, 1), -+ FACTOR(CLK_TOP_USB3_PHY, "usb3_phy", "usb3_phy_sel", 1, 1), -+ FACTOR(CLK_TOP_AUD, "aud", "faud", 1, 1), -+ FACTOR(CLK_TOP_A1SYS, "a1sys", "a1sys_sel", 1, 1), -+ FACTOR(CLK_TOP_AUD_L, "aud_l", "aud_l_sel", 1, 1), -+ FACTOR(CLK_TOP_A_TUNER, "a_tuner", "a_tuner_sel", 1, 1), -+ FACTOR(CLK_TOP_U2U3_REF, "u2u3_ref", "u2u3_sel", 1, 1), -+ FACTOR(CLK_TOP_U2U3_SYS, "u2u3_sys", "u2u3_sys_sel", 1, 1), -+ FACTOR(CLK_TOP_U2U3_XHCI, "u2u3_xhci", "u2u3_xhci_sel", 1, 1), -+ FACTOR(CLK_TOP_USB_FRMCNT, "usb_frmcnt", "usb_frmcnt_sel", 1, 1), -+}; -+ -+static const char * const nfi1x_parents[] __initconst = { -+ "cb_cksq_40m", -+ "cb_mm_d4", -+ "net1_d8_d2", -+ "cb_net2_d6", -+ "cb_m_d4", -+ "cb_mm_d8", -+ "net1_d8_d4", -+ "cb_m_d8" -+}; -+ -+static const char * const spinfi_parents[] __initconst = { -+ "cksq_40m_d2", -+ "cb_cksq_40m", -+ "net1_d5_d4", -+ "cb_m_d4", -+ "cb_mm_d8", -+ "net1_d8_d4", -+ "mm_d6_d2", -+ "cb_m_d8" -+}; -+ -+static const char * const spi_parents[] __initconst = { -+ "cb_cksq_40m", -+ "cb_m_d2", -+ "cb_mm_d4", -+ "net1_d8_d2", -+ "cb_net2_d6", -+ "net1_d5_d4", -+ "cb_m_d4", -+ "net1_d8_d4" -+}; -+ -+static const char * const uart_parents[] __initconst = { -+ "cb_cksq_40m", -+ "cb_m_d8", -+ "m_d8_d2" -+}; -+ -+static const char * const pwm_parents[] __initconst = { -+ "cb_cksq_40m", -+ "net1_d8_d2", -+ "net1_d5_d4", -+ "cb_m_d4", -+ "m_d8_d2", -+ "cb_rtc_32k" -+}; -+ -+static const char * const i2c_parents[] __initconst = { -+ "cb_cksq_40m", -+ "net1_d5_d4", -+ "cb_m_d4", -+ "net1_d8_d4" -+}; -+ -+static const char * const pextp_tl_ck_parents[] __initconst = { -+ "cb_cksq_40m", -+ "net1_d5_d4", -+ "cb_m_d4", -+ "cb_rtc_32k" -+}; -+ -+static const char * const emmc_208m_parents[] __initconst = { -+ "cb_cksq_40m", -+ "cb_m_d2", -+ "cb_net2_d4", -+ "cb_apll2_196m", -+ "cb_mm_d4", -+ "net1_d8_d2", -+ "cb_mm_d6" -+}; -+ -+static const char * const emmc_400m_parents[] __initconst = { -+ "cb_cksq_40m", -+ "cb_net2_d2", -+ "cb_mm_d2", -+ "cb_net2_d2" -+}; -+ -+static const char * const csw_f26m_parents[] __initconst = { -+ "cksq_40m_d2", -+ "m_d8_d2" -+}; -+ -+static const char * const dramc_md32_parents[] __initconst = { -+ "cb_cksq_40m", -+ "cb_m_d2", -+ "cb_wedmcu_208m" -+}; -+ -+static const char * const sysaxi_parents[] __initconst = { -+ "cb_cksq_40m", -+ "net1_d8_d2" -+}; -+ -+static const char * const sysapb_parents[] __initconst = { -+ "cb_cksq_40m", -+ "m_d3_d2" -+}; -+ -+static const char * const arm_db_main_parents[] __initconst = { -+ "cb_cksq_40m", -+ "cb_net2_d6" -+}; -+ -+static const char * const ap2cnn_host_parents[] __initconst = { -+ "cb_cksq_40m", -+ "net1_d8_d4" -+}; -+ -+static const char * const netsys_parents[] __initconst = { -+ "cb_cksq_40m", -+ "cb_mm_d2" -+}; -+ -+static const char * const netsys_500m_parents[] __initconst = { -+ "cb_cksq_40m", -+ "cb_net1_d5" -+}; -+ -+static const char * const netsys_mcu_parents[] __initconst = { -+ "cb_cksq_40m", -+ "cb_mm_720m", -+ "cb_net1_d4", -+ "cb_net1_d5", -+ "cb_m_416m" -+}; -+ -+static const char * const netsys_2x_parents[] __initconst = { -+ "cb_cksq_40m", -+ "cb_net2_800m", -+ "cb_mm_720m" -+}; -+ -+static const char * const sgm_325m_parents[] __initconst = { -+ "cb_cksq_40m", -+ "cb_sgm_325m" -+}; -+ -+static const char * const sgm_reg_parents[] __initconst = { -+ "cb_cksq_40m", -+ "cb_net2_d4" -+}; -+ -+static const char * const eip97b_parents[] __initconst = { -+ "cb_cksq_40m", -+ "cb_net1_d5", -+ "cb_m_416m", -+ "cb_mm_d2", -+ "net1_d5_d2" -+}; -+ -+static const char * const aud_parents[] __initconst = { -+ "cb_cksq_40m", -+ "cb_apll2_196m" -+}; -+ -+static const char * const a1sys_parents[] __initconst = { -+ "cb_cksq_40m", -+ "apll2_d4" -+}; -+ -+static const char * const aud_l_parents[] __initconst = { -+ "cb_cksq_40m", -+ "cb_apll2_196m", -+ "m_d8_d2" -+}; -+ -+static const char * const a_tuner_parents[] __initconst = { -+ "cb_cksq_40m", -+ "apll2_d4", -+ "m_d8_d2" -+}; -+ -+static const char * const u2u3_parents[] __initconst = { -+ "cb_cksq_40m", -+ "m_d8_d2" -+}; -+ -+static const char * const u2u3_sys_parents[] __initconst = { -+ "cb_cksq_40m", -+ "net1_d5_d4" -+}; -+ -+static const char * const usb_frmcnt_parents[] __initconst = { -+ "cb_cksq_40m", -+ "cb_mm_d3_d5" -+}; -+ -+static const struct mtk_mux top_muxes[] = { -+ /* CLK_CFG_0 */ -+ MUX_GATE_CLR_SET_UPD(CLK_TOP_NFI1X_SEL, "nfi1x_sel", nfi1x_parents, -+ 0x000, 0x004, 0x008, 0, 3, 7, 0x1C0, 0), -+ MUX_GATE_CLR_SET_UPD(CLK_TOP_SPINFI_SEL, "spinfi_sel", spinfi_parents, -+ 0x000, 0x004, 0x008, 8, 3, 15, 0x1C0, 1), -+ MUX_GATE_CLR_SET_UPD(CLK_TOP_SPI_SEL, "spi_sel", spi_parents, -+ 0x000, 0x004, 0x008, 16, 3, 23, 0x1C0, 2), -+ MUX_GATE_CLR_SET_UPD(CLK_TOP_SPIM_MST_SEL, "spim_mst_sel", spi_parents, -+ 0x000, 0x004, 0x008, 24, 3, 31, 0x1C0, 3), -+ /* CLK_CFG_1 */ -+ MUX_GATE_CLR_SET_UPD(CLK_TOP_UART_SEL, "uart_sel", uart_parents, -+ 0x010, 0x014, 0x018, 0, 2, 7, 0x1C0, 4), -+ MUX_GATE_CLR_SET_UPD(CLK_TOP_PWM_SEL, "pwm_sel", pwm_parents, -+ 0x010, 0x014, 0x018, 8, 3, 15, 0x1C0, 5), -+ MUX_GATE_CLR_SET_UPD(CLK_TOP_I2C_SEL, "i2c_sel", i2c_parents, -+ 0x010, 0x014, 0x018, 16, 2, 23, 0x1C0, 6), -+ MUX_GATE_CLR_SET_UPD(CLK_TOP_PEXTP_TL_SEL, "pextp_tl_ck_sel", -+ pextp_tl_ck_parents, 0x010, 0x014, 0x018, 24, 2, 31, -+ 0x1C0, 7), -+ /* CLK_CFG_2 */ -+ MUX_GATE_CLR_SET_UPD(CLK_TOP_EMMC_208M_SEL, "emmc_208m_sel", -+ emmc_208m_parents, 0x020, 0x024, 0x028, 0, 3, 7, -+ 0x1C0, 8), -+ MUX_GATE_CLR_SET_UPD(CLK_TOP_EMMC_400M_SEL, "emmc_400m_sel", -+ emmc_400m_parents, 0x020, 0x024, 0x028, 8, 2, 15, -+ 0x1C0, 9), -+ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_F26M_SEL, "csw_f26m_sel", -+ csw_f26m_parents, 0x020, 0x024, 0x028, 16, 1, 23, -+ 0x1C0, 10, -+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), -+ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_DRAMC_SEL, "dramc_sel", -+ csw_f26m_parents, 0x020, 0x024, 0x028, 24, 1, -+ 31, 0x1C0, 11, -+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), -+ /* CLK_CFG_3 */ -+ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_DRAMC_MD32_SEL, "dramc_md32_sel", -+ dramc_md32_parents, 0x030, 0x034, 0x038, 0, 2, -+ 7, 0x1C0, 12, -+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), -+ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SYSAXI_SEL, "sysaxi_sel", -+ sysaxi_parents, 0x030, 0x034, 0x038, 8, 1, 15, -+ 0x1C0, 13, -+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), -+ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SYSAPB_SEL, "sysapb_sel", -+ sysapb_parents, 0x030, 0x034, 0x038, 16, 1, -+ 23, 0x1C0, 14, -+ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), -+ MUX_GATE_CLR_SET_UPD(CLK_TOP_ARM_DB_MAIN_SEL, "arm_db_main_sel", -+ arm_db_main_parents, 0x030, 0x034, 0x038, 24, 1, 31, -+ 0x1C0, 15), -+ /* CLK_CFG_4 */ -+ MUX_GATE_CLR_SET_UPD(CLK_TOP_AP2CNN_HOST_SEL, "ap2cnn_host_sel", -+ ap2cnn_host_parents, 0x040, 0x044, 0x048, 0, 1, 7, -+ 0x1C0, 16), -+ MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_SEL, "netsys_sel", netsys_parents, -+ 0x040, 0x044, 0x048, 8, 1, 15, 0x1C0, 17), -+ MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_500M_SEL, "netsys_500m_sel", -+ netsys_500m_parents, 0x040, 0x044, 0x048, 16, 1, 23, -+ 0x1C0, 18), -+ MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_MCU_SEL, "netsys_mcu_sel", -+ netsys_mcu_parents, 0x040, 0x044, 0x048, 24, 3, 31, -+ 0x1C0, 19), -+ /* CLK_CFG_5 */ -+ MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_2X_SEL, "netsys_2x_sel", -+ netsys_2x_parents, 0x050, 0x054, 0x058, 0, 2, 7, -+ 0x1C0, 20), -+ MUX_GATE_CLR_SET_UPD(CLK_TOP_SGM_325M_SEL, "sgm_325m_sel", -+ sgm_325m_parents, 0x050, 0x054, 0x058, 8, 1, 15, -+ 0x1C0, 21), -+ MUX_GATE_CLR_SET_UPD(CLK_TOP_SGM_REG_SEL, "sgm_reg_sel", sgm_reg_parents, -+ 0x050, 0x054, 0x058, 16, 1, 23, 0x1C0, 22), -+ MUX_GATE_CLR_SET_UPD(CLK_TOP_EIP97B_SEL, "eip97b_sel", eip97b_parents, -+ 0x050, 0x054, 0x058, 24, 3, 31, 0x1C0, 23), -+ /* CLK_CFG_6 */ -+ MUX_GATE_CLR_SET_UPD(CLK_TOP_USB3_PHY_SEL, "usb3_phy_sel", -+ csw_f26m_parents, 0x060, 0x064, 0x068, 0, 1, -+ 7, 0x1C0, 24), -+ MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_SEL, "aud_sel", aud_parents, 0x060, -+ 0x064, 0x068, 8, 1, 15, 0x1C0, 25), -+ MUX_GATE_CLR_SET_UPD(CLK_TOP_A1SYS_SEL, "a1sys_sel", a1sys_parents, -+ 0x060, 0x064, 0x068, 16, 1, 23, 0x1C0, 26), -+ MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_L_SEL, "aud_l_sel", aud_l_parents, -+ 0x060, 0x064, 0x068, 24, 2, 31, 0x1C0, 27), -+ /* CLK_CFG_7 */ -+ MUX_GATE_CLR_SET_UPD(CLK_TOP_A_TUNER_SEL, "a_tuner_sel", -+ a_tuner_parents, 0x070, 0x074, 0x078, 0, 2, 7, -+ 0x1C0, 28), -+ MUX_GATE_CLR_SET_UPD(CLK_TOP_U2U3_SEL, "u2u3_sel", u2u3_parents, 0x070, -+ 0x074, 0x078, 8, 1, 15, 0x1C0, 29), -+ MUX_GATE_CLR_SET_UPD(CLK_TOP_U2U3_SYS_SEL, "u2u3_sys_sel", -+ u2u3_sys_parents, 0x070, 0x074, 0x078, 16, 1, 23, -+ 0x1C0, 30), -+ MUX_GATE_CLR_SET_UPD(CLK_TOP_U2U3_XHCI_SEL, "u2u3_xhci_sel", -+ u2u3_sys_parents, 0x070, 0x074, 0x078, 24, 1, 31, -+ 0x1C4, 0), -+ /* CLK_CFG_8 */ -+ MUX_GATE_CLR_SET_UPD(CLK_TOP_USB_FRMCNT_SEL, "usb_frmcnt_sel", -+ usb_frmcnt_parents, 0x080, 0x084, 0x088, 0, 1, 7, -+ 0x1C4, 1), -+}; -+ -+static struct mtk_composite top_aud_divs[] = { -+ DIV_GATE(CLK_TOP_AUD_I2S_M, "aud_i2s_m", "aud", -+ 0x0420, 0, 0x0420, 8, 8), -+}; -+ -+static const struct mtk_clk_desc topck_desc = { -+ .factor_clks = top_divs, -+ .num_factor_clks = ARRAY_SIZE(top_divs), -+ .mux_clks = top_muxes, -+ .num_mux_clks = ARRAY_SIZE(top_muxes), -+ .composite_clks = top_aud_divs, -+ .num_composite_clks = ARRAY_SIZE(top_aud_divs), -+ .clk_lock = &mt7981_clk_lock, -+}; -+ -+static const struct of_device_id of_match_clk_mt7981_topckgen[] = { -+ { .compatible = "mediatek,mt7981-topckgen", .data = &topck_desc }, -+ { /* sentinel */ } -+}; -+ -+static struct platform_driver clk_mt7981_topckgen_drv = { -+ .probe = mtk_clk_simple_probe, -+ .remove = mtk_clk_simple_remove, -+ .driver = { -+ .name = "clk-mt7981-topckgen", -+ .of_match_table = of_match_clk_mt7981_topckgen, -+ }, -+}; -+builtin_platform_driver(clk_mt7981_topckgen_drv); diff --git a/target/linux/mediatek/patches-6.1/240-pinctrl-mediatek-add-support-for-MT7988-SoC.patch b/target/linux/mediatek/patches-6.1/240-pinctrl-mediatek-add-support-for-MT7988-SoC.patch deleted file mode 100644 index a365f0860..000000000 --- a/target/linux/mediatek/patches-6.1/240-pinctrl-mediatek-add-support-for-MT7988-SoC.patch +++ /dev/null @@ -1,26 +0,0 @@ ---- a/drivers/pinctrl/mediatek/Kconfig -+++ b/drivers/pinctrl/mediatek/Kconfig -@@ -141,6 +141,13 @@ config PINCTRL_MT7986 - default ARM64 && ARCH_MEDIATEK - select PINCTRL_MTK_MOORE - -+config PINCTRL_MT7988 -+ bool "Mediatek MT7988 pin control" -+ depends on OF -+ depends on ARM64 || COMPILE_TEST -+ default ARCH_MEDIATEK -+ select PINCTRL_MTK_MOORE -+ - config PINCTRL_MT8167 - bool "Mediatek MT8167 pin control" - depends on OF ---- a/drivers/pinctrl/mediatek/Makefile -+++ b/drivers/pinctrl/mediatek/Makefile -@@ -20,6 +20,7 @@ obj-$(CONFIG_PINCTRL_MT7623) += pinctrl- - obj-$(CONFIG_PINCTRL_MT7629) += pinctrl-mt7629.o - obj-$(CONFIG_PINCTRL_MT7981) += pinctrl-mt7981.o - obj-$(CONFIG_PINCTRL_MT7986) += pinctrl-mt7986.o -+obj-$(CONFIG_PINCTRL_MT7988) += pinctrl-mt7988.o - obj-$(CONFIG_PINCTRL_MT8167) += pinctrl-mt8167.o - obj-$(CONFIG_PINCTRL_MT8173) += pinctrl-mt8173.o - obj-$(CONFIG_PINCTRL_MT8183) += pinctrl-mt8183.o diff --git a/target/linux/mediatek/patches-6.1/241-clk-mediatek-Add-pcw-chg-shift-control.patch b/target/linux/mediatek/patches-6.1/241-clk-mediatek-Add-pcw-chg-shift-control.patch deleted file mode 100644 index 75ca114a5..000000000 --- a/target/linux/mediatek/patches-6.1/241-clk-mediatek-Add-pcw-chg-shift-control.patch +++ /dev/null @@ -1,24 +0,0 @@ ---- a/drivers/clk/mediatek/clk-pll.c -+++ b/drivers/clk/mediatek/clk-pll.c -@@ -141,7 +141,10 @@ static void mtk_pll_set_rate_regs(struct - pll->data->pcw_shift); - val |= pcw << pll->data->pcw_shift; - writel(val, pll->pcw_addr); -- chg = readl(pll->pcw_chg_addr) | PCW_CHG_MASK; -+ if (pll->data->pcw_chg_shift) -+ chg = readl(pll->pcw_chg_addr) | BIT(pll->data->pcw_chg_shift); -+ else -+ chg = readl(pll->pcw_chg_addr) | PCW_CHG_MASK; - writel(chg, pll->pcw_chg_addr); - if (pll->tuner_addr) - writel(val + 1, pll->tuner_addr); ---- a/drivers/clk/mediatek/clk-pll.h -+++ b/drivers/clk/mediatek/clk-pll.h -@@ -42,6 +42,7 @@ struct mtk_pll_data { - u32 pcw_reg; - int pcw_shift; - u32 pcw_chg_reg; -+ int pcw_chg_shift; - const struct mtk_pll_div_table *div_table; - const char *parent_name; - u32 en_reg; diff --git a/target/linux/mediatek/patches-6.1/242-clk-mediatek-add-mt7988-clock-support.patch b/target/linux/mediatek/patches-6.1/242-clk-mediatek-add-mt7988-clock-support.patch deleted file mode 100644 index 3ced01249..000000000 --- a/target/linux/mediatek/patches-6.1/242-clk-mediatek-add-mt7988-clock-support.patch +++ /dev/null @@ -1,31 +0,0 @@ ---- a/drivers/clk/mediatek/Kconfig -+++ b/drivers/clk/mediatek/Kconfig -@@ -415,6 +415,15 @@ config COMMON_CLK_MT7986_ETHSYS - This driver adds support for clocks for Ethernet and SGMII - required on MediaTek MT7986 SoC. - -+config COMMON_CLK_MT7988 -+ bool "Clock driver for MediaTek MT7988" -+ depends on ARCH_MEDIATEK || COMPILE_TEST -+ select COMMON_CLK_MEDIATEK -+ default ARCH_MEDIATEK -+ help -+ This driver supports MediaTek MT7988 basic clocks and clocks -+ required for various periperals found on MediaTek. -+ - config COMMON_CLK_MT8135 - bool "Clock driver for MediaTek MT8135" - depends on (ARCH_MEDIATEK && ARM) || COMPILE_TEST ---- a/drivers/clk/mediatek/Makefile -+++ b/drivers/clk/mediatek/Makefile -@@ -60,6 +60,10 @@ obj-$(CONFIG_COMMON_CLK_MT7986) += clk-m - obj-$(CONFIG_COMMON_CLK_MT7986) += clk-mt7986-topckgen.o - obj-$(CONFIG_COMMON_CLK_MT7986) += clk-mt7986-infracfg.o - obj-$(CONFIG_COMMON_CLK_MT7986_ETHSYS) += clk-mt7986-eth.o -+obj-$(CONFIG_COMMON_CLK_MT7988) += clk-mt7988-apmixed.o -+obj-$(CONFIG_COMMON_CLK_MT7988) += clk-mt7988-topckgen.o -+obj-$(CONFIG_COMMON_CLK_MT7988) += clk-mt7988-infracfg.o -+obj-$(CONFIG_COMMON_CLK_MT7988) += clk-mt7988-eth.o - obj-$(CONFIG_COMMON_CLK_MT8135) += clk-mt8135.o - obj-$(CONFIG_COMMON_CLK_MT8167) += clk-mt8167.o - obj-$(CONFIG_COMMON_CLK_MT8167_AUDSYS) += clk-mt8167-aud.o diff --git a/target/linux/mediatek/patches-6.1/320-v6.2-mmc-mediatek-add-support-for-MT7986-SoC.patch b/target/linux/mediatek/patches-6.1/320-v6.2-mmc-mediatek-add-support-for-MT7986-SoC.patch deleted file mode 100644 index 5e3afd856..000000000 --- a/target/linux/mediatek/patches-6.1/320-v6.2-mmc-mediatek-add-support-for-MT7986-SoC.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 24e961b93d292d0dd6380213d22a071a99ea787d Mon Sep 17 00:00:00 2001 -From: Sam Shih -Date: Tue, 25 Oct 2022 15:29:53 +0200 -Subject: [PATCH 1/6] mmc: mediatek: add support for MT7986 SoC - -Adding mt7986 own characteristics and of_device_id to have support -of MT7986 SoC. - -Signed-off-by: Sam Shih -Signed-off-by: Frank Wunderlich -Reviewed-by: AngeloGioacchino Del Regno -Link: https://lore.kernel.org/r/20221025132953.81286-7-linux@fw-web.de -Signed-off-by: Ulf Hansson ---- - drivers/mmc/host/mtk-sd.c | 14 ++++++++++++++ - 1 file changed, 14 insertions(+) - ---- a/drivers/mmc/host/mtk-sd.c -+++ b/drivers/mmc/host/mtk-sd.c -@@ -552,6 +552,19 @@ static const struct mtk_mmc_compatible m - .support_64g = false, - }; - -+static const struct mtk_mmc_compatible mt7986_compat = { -+ .clk_div_bits = 12, -+ .recheck_sdio_irq = true, -+ .hs400_tune = false, -+ .pad_tune_reg = MSDC_PAD_TUNE0, -+ .async_fifo = true, -+ .data_tune = true, -+ .busy_check = true, -+ .stop_clk_fix = true, -+ .enhance_rx = true, -+ .support_64g = true, -+}; -+ - static const struct mtk_mmc_compatible mt8135_compat = { - .clk_div_bits = 8, - .recheck_sdio_irq = true, -@@ -609,6 +622,7 @@ static const struct of_device_id msdc_of - { .compatible = "mediatek,mt6795-mmc", .data = &mt6795_compat}, - { .compatible = "mediatek,mt7620-mmc", .data = &mt7620_compat}, - { .compatible = "mediatek,mt7622-mmc", .data = &mt7622_compat}, -+ { .compatible = "mediatek,mt7986-mmc", .data = &mt7986_compat}, - { .compatible = "mediatek,mt8135-mmc", .data = &mt8135_compat}, - { .compatible = "mediatek,mt8173-mmc", .data = &mt8173_compat}, - { .compatible = "mediatek,mt8183-mmc", .data = &mt8183_compat}, diff --git a/target/linux/mediatek/patches-6.1/321-v6.2-mmc-mtk-sd-add-Inline-Crypto-Engine-clock-control.patch b/target/linux/mediatek/patches-6.1/321-v6.2-mmc-mtk-sd-add-Inline-Crypto-Engine-clock-control.patch deleted file mode 100644 index db2802bd0..000000000 --- a/target/linux/mediatek/patches-6.1/321-v6.2-mmc-mtk-sd-add-Inline-Crypto-Engine-clock-control.patch +++ /dev/null @@ -1,57 +0,0 @@ -From 7b438d0377fbd520b475a68bdd9de1692393f22d Mon Sep 17 00:00:00 2001 -From: Mengqi Zhang -Date: Sun, 6 Nov 2022 11:39:24 +0800 -Subject: [PATCH 2/6] mmc: mtk-sd: add Inline Crypto Engine clock control - -Add crypto clock control and ungate it before CQHCI init. - -Signed-off-by: Mengqi Zhang -Reviewed-by: AngeloGioacchino Del Regno -Link: https://lore.kernel.org/r/20221106033924.9854-2-mengqi.zhang@mediatek.com -Signed-off-by: Ulf Hansson ---- - drivers/mmc/host/mtk-sd.c | 12 ++++++++++++ - 1 file changed, 12 insertions(+) - ---- a/drivers/mmc/host/mtk-sd.c -+++ b/drivers/mmc/host/mtk-sd.c -@@ -452,6 +452,7 @@ struct msdc_host { - struct clk *bus_clk; /* bus clock which used to access register */ - struct clk *src_clk_cg; /* msdc source clock control gate */ - struct clk *sys_clk_cg; /* msdc subsys clock control gate */ -+ struct clk *crypto_clk; /* msdc crypto clock control gate */ - struct clk_bulk_data bulk_clks[MSDC_NR_CLOCKS]; - u32 mclk; /* mmc subsystem clock frequency */ - u32 src_clk_freq; /* source clock frequency */ -@@ -840,6 +841,7 @@ static void msdc_set_busy_timeout(struct - static void msdc_gate_clock(struct msdc_host *host) - { - clk_bulk_disable_unprepare(MSDC_NR_CLOCKS, host->bulk_clks); -+ clk_disable_unprepare(host->crypto_clk); - clk_disable_unprepare(host->src_clk_cg); - clk_disable_unprepare(host->src_clk); - clk_disable_unprepare(host->bus_clk); -@@ -855,6 +857,7 @@ static int msdc_ungate_clock(struct msdc - clk_prepare_enable(host->bus_clk); - clk_prepare_enable(host->src_clk); - clk_prepare_enable(host->src_clk_cg); -+ clk_prepare_enable(host->crypto_clk); - ret = clk_bulk_prepare_enable(MSDC_NR_CLOCKS, host->bulk_clks); - if (ret) { - dev_err(host->dev, "Cannot enable pclk/axi/ahb clock gates\n"); -@@ -2670,6 +2673,15 @@ static int msdc_drv_probe(struct platfor - goto host_free; - } - -+ /* only eMMC has crypto property */ -+ if (!(mmc->caps2 & MMC_CAP2_NO_MMC)) { -+ host->crypto_clk = devm_clk_get_optional(&pdev->dev, "crypto"); -+ if (IS_ERR(host->crypto_clk)) -+ host->crypto_clk = NULL; -+ else -+ mmc->caps2 |= MMC_CAP2_CRYPTO; -+ } -+ - host->irq = platform_get_irq(pdev, 0); - if (host->irq < 0) { - ret = host->irq; diff --git a/target/linux/mediatek/patches-6.1/322-v6.2-mmc-mtk-sd-fix-two-spelling-mistakes-in-comment.patch b/target/linux/mediatek/patches-6.1/322-v6.2-mmc-mtk-sd-fix-two-spelling-mistakes-in-comment.patch deleted file mode 100644 index 921d249f8..000000000 --- a/target/linux/mediatek/patches-6.1/322-v6.2-mmc-mtk-sd-fix-two-spelling-mistakes-in-comment.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 4b323f02b6e8df1b04292635ef829e7f723bf50e Mon Sep 17 00:00:00 2001 -From: Yu Zhe -Date: Thu, 10 Nov 2022 15:28:19 +0800 -Subject: [PATCH 3/6] mmc: mtk-sd: fix two spelling mistakes in comment - -spelling mistake fix : "alreay" -> "already" - "checksume" -> "checksum" - -Signed-off-by: Yu Zhe -Reviewed-by: AngeloGioacchino Del Regno -Link: https://lore.kernel.org/r/20221110072819.11530-1-yuzhe@nfschina.com -Signed-off-by: Ulf Hansson ---- - drivers/mmc/host/mtk-sd.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/drivers/mmc/host/mtk-sd.c -+++ b/drivers/mmc/host/mtk-sd.c -@@ -750,7 +750,7 @@ static inline void msdc_dma_setup(struct - else - bd[j].bd_info &= ~BDMA_DESC_EOL; - -- /* checksume need to clear first */ -+ /* checksum need to clear first */ - bd[j].bd_info &= ~BDMA_DESC_CHECKSUM; - bd[j].bd_info |= msdc_dma_calcs((u8 *)(&bd[j]), 16) << 8; - } -@@ -1229,7 +1229,7 @@ static bool msdc_cmd_done(struct msdc_ho - !host->hs400_tuning)) - /* - * should not clear fifo/interrupt as the tune data -- * may have alreay come when cmd19/cmd21 gets response -+ * may have already come when cmd19/cmd21 gets response - * CRC error. - */ - msdc_reset_hw(host); diff --git a/target/linux/mediatek/patches-6.1/323-v6.2-mmc-Avoid-open-coding-by-using-mmc_op_tuning.patch b/target/linux/mediatek/patches-6.1/323-v6.2-mmc-Avoid-open-coding-by-using-mmc_op_tuning.patch deleted file mode 100644 index 8e2151e16..000000000 --- a/target/linux/mediatek/patches-6.1/323-v6.2-mmc-Avoid-open-coding-by-using-mmc_op_tuning.patch +++ /dev/null @@ -1,39 +0,0 @@ -From b98e7e8daf0ebab9dcc36812378a71e1be0b5089 Mon Sep 17 00:00:00 2001 -From: ChanWoo Lee -Date: Thu, 24 Nov 2022 17:00:31 +0900 -Subject: [PATCH 4/6] mmc: Avoid open coding by using mmc_op_tuning() - -Replace code with the already defined function. No functional changes. - -Signed-off-by: ChanWoo Lee -Reviewed-by: Adrian Hunter -Link: https://lore.kernel.org/r/20221124080031.14690-1-cw9316.lee@samsung.com -Signed-off-by: Ulf Hansson ---- - drivers/mmc/host/mtk-sd.c | 8 ++------ - 1 file changed, 2 insertions(+), 6 deletions(-) - ---- a/drivers/mmc/host/mtk-sd.c -+++ b/drivers/mmc/host/mtk-sd.c -@@ -1224,9 +1224,7 @@ static bool msdc_cmd_done(struct msdc_ho - - if (!sbc_error && !(events & MSDC_INT_CMDRDY)) { - if (events & MSDC_INT_CMDTMO || -- (cmd->opcode != MMC_SEND_TUNING_BLOCK && -- cmd->opcode != MMC_SEND_TUNING_BLOCK_HS200 && -- !host->hs400_tuning)) -+ (!mmc_op_tuning(cmd->opcode) && !host->hs400_tuning)) - /* - * should not clear fifo/interrupt as the tune data - * may have already come when cmd19/cmd21 gets response -@@ -1320,9 +1318,7 @@ static void msdc_cmd_next(struct msdc_ho - { - if ((cmd->error && - !(cmd->error == -EILSEQ && -- (cmd->opcode == MMC_SEND_TUNING_BLOCK || -- cmd->opcode == MMC_SEND_TUNING_BLOCK_HS200 || -- host->hs400_tuning))) || -+ (mmc_op_tuning(cmd->opcode) || host->hs400_tuning))) || - (mrq->sbc && mrq->sbc->error)) - msdc_request_done(host, mrq); - else if (cmd == mrq->sbc) diff --git a/target/linux/mediatek/patches-6.1/330-snand-mtk-bmt-support.patch b/target/linux/mediatek/patches-6.1/330-snand-mtk-bmt-support.patch deleted file mode 100644 index 55a308e46..000000000 --- a/target/linux/mediatek/patches-6.1/330-snand-mtk-bmt-support.patch +++ /dev/null @@ -1,34 +0,0 @@ ---- a/drivers/mtd/nand/spi/core.c -+++ b/drivers/mtd/nand/spi/core.c -@@ -19,6 +19,7 @@ - #include - #include - #include -+#include - - static int spinand_read_reg_op(struct spinand_device *spinand, u8 reg, u8 *val) - { -@@ -1344,6 +1345,7 @@ static int spinand_probe(struct spi_mem - if (ret) - return ret; - -+ mtk_bmt_attach(mtd); - ret = mtd_device_register(mtd, NULL, 0); - if (ret) - goto err_spinand_cleanup; -@@ -1351,6 +1353,7 @@ static int spinand_probe(struct spi_mem - return 0; - - err_spinand_cleanup: -+ mtk_bmt_detach(mtd); - spinand_cleanup(spinand); - - return ret; -@@ -1369,6 +1372,7 @@ static int spinand_remove(struct spi_mem - if (ret) - return ret; - -+ mtk_bmt_detach(mtd); - spinand_cleanup(spinand); - - return 0; diff --git a/target/linux/mediatek/patches-6.1/331-mt7622-rfb1-enable-bmt.patch b/target/linux/mediatek/patches-6.1/331-mt7622-rfb1-enable-bmt.patch deleted file mode 100644 index 9c1a8f284..000000000 --- a/target/linux/mediatek/patches-6.1/331-mt7622-rfb1-enable-bmt.patch +++ /dev/null @@ -1,10 +0,0 @@ ---- a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts -@@ -553,6 +553,7 @@ - spi-tx-bus-width = <4>; - spi-rx-bus-width = <4>; - nand-ecc-engine = <&snfi>; -+ mediatek,bmt-v2; - - partitions { - compatible = "fixed-partitions"; diff --git a/target/linux/mediatek/patches-6.1/340-mtd-spinand-Add-support-for-the-Fidelix-FM35X1GA.patch b/target/linux/mediatek/patches-6.1/340-mtd-spinand-Add-support-for-the-Fidelix-FM35X1GA.patch deleted file mode 100644 index b00c6fc3f..000000000 --- a/target/linux/mediatek/patches-6.1/340-mtd-spinand-Add-support-for-the-Fidelix-FM35X1GA.patch +++ /dev/null @@ -1,122 +0,0 @@ -From 5f49a5c9b16330e0df8f639310e4715dcad71947 Mon Sep 17 00:00:00 2001 -From: Davide Fioravanti -Date: Fri, 8 Jan 2021 15:35:24 +0100 -Subject: [PATCH] mtd: spinand: Add support for the Fidelix FM35X1GA - -Datasheet: http://www.hobos.com.cn/upload/datasheet/DS35X1GAXXX_100_rev00.pdf - -Signed-off-by: Davide Fioravanti ---- - drivers/mtd/nand/spi/Makefile | 2 +- - drivers/mtd/nand/spi/core.c | 1 + - drivers/mtd/nand/spi/fidelix.c | 76 ++++++++++++++++++++++++++++++++++ - include/linux/mtd/spinand.h | 1 + - 4 files changed, 79 insertions(+), 1 deletion(-) - create mode 100644 drivers/mtd/nand/spi/fidelix.c - ---- a/drivers/mtd/nand/spi/Makefile -+++ b/drivers/mtd/nand/spi/Makefile -@@ -1,3 +1,3 @@ - # SPDX-License-Identifier: GPL-2.0 --spinand-objs := core.o ato.o esmt.o etron.o gigadevice.o macronix.o micron.o paragon.o toshiba.o winbond.o xtx.o -+spinand-objs := core.o ato.o esmt.o etron.o fidelix.o gigadevice.o macronix.o 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 -@@ -940,6 +940,7 @@ static const struct nand_ops spinand_ops - static const struct spinand_manufacturer *spinand_manufacturers[] = { - &ato_spinand_manufacturer, - &esmt_c8_spinand_manufacturer, -+ &fidelix_spinand_manufacturer, - &etron_spinand_manufacturer, - &gigadevice_spinand_manufacturer, - ¯onix_spinand_manufacturer, ---- /dev/null -+++ b/drivers/mtd/nand/spi/fidelix.c -@@ -0,0 +1,76 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (c) 2020 Davide Fioravanti -+ */ -+ -+#include -+#include -+#include -+ -+#define SPINAND_MFR_FIDELIX 0xE5 -+#define FIDELIX_ECCSR_MASK 0x0F -+ -+static SPINAND_OP_VARIANTS(read_cache_variants, -+ SPINAND_PAGE_READ_FROM_CACHE_X4_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(true, 0, NULL, 0), -+ SPINAND_PROG_LOAD(true, 0, NULL, 0)); -+ -+static int fm35x1ga_ooblayout_ecc(struct mtd_info *mtd, int section, -+ struct mtd_oob_region *region) -+{ -+ if (section > 3) -+ return -ERANGE; -+ -+ region->offset = (16 * section) + 8; -+ region->length = 8; -+ -+ return 0; -+} -+ -+static int fm35x1ga_ooblayout_free(struct mtd_info *mtd, int section, -+ struct mtd_oob_region *region) -+{ -+ if (section > 3) -+ return -ERANGE; -+ -+ region->offset = (16 * section) + 2; -+ region->length = 6; -+ -+ return 0; -+} -+ -+static const struct mtd_ooblayout_ops fm35x1ga_ooblayout = { -+ .ecc = fm35x1ga_ooblayout_ecc, -+ .free = fm35x1ga_ooblayout_free, -+}; -+ -+static const struct spinand_info fidelix_spinand_table[] = { -+ SPINAND_INFO("FM35X1GA", -+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x71), -+ NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1), -+ NAND_ECCREQ(4, 512), -+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants, -+ &write_cache_variants, -+ &update_cache_variants), -+ SPINAND_HAS_QE_BIT, -+ SPINAND_ECCINFO(&fm35x1ga_ooblayout, NULL)), -+}; -+ -+static const struct spinand_manufacturer_ops fidelix_spinand_manuf_ops = { -+}; -+ -+const struct spinand_manufacturer fidelix_spinand_manufacturer = { -+ .id = SPINAND_MFR_FIDELIX, -+ .name = "Fidelix", -+ .chips = fidelix_spinand_table, -+ .nchips = ARRAY_SIZE(fidelix_spinand_table), -+ .ops = &fidelix_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 ato_spinand_manufacturer; - extern const struct spinand_manufacturer esmt_c8_spinand_manufacturer; - extern const struct spinand_manufacturer etron_spinand_manufacturer; -+extern const struct spinand_manufacturer fidelix_spinand_manufacturer; - extern const struct spinand_manufacturer gigadevice_spinand_manufacturer; - extern const struct spinand_manufacturer macronix_spinand_manufacturer; - extern const struct spinand_manufacturer micron_spinand_manufacturer; diff --git a/target/linux/mediatek/patches-6.1/350-21-cpufreq-mediatek-Add-support-for-MT7988.patch b/target/linux/mediatek/patches-6.1/350-21-cpufreq-mediatek-Add-support-for-MT7988.patch deleted file mode 100644 index 49cd62d0a..000000000 --- a/target/linux/mediatek/patches-6.1/350-21-cpufreq-mediatek-Add-support-for-MT7988.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 4983a1517e7ddbc6f53fc07607e4ebeb51412843 Mon Sep 17 00:00:00 2001 -From: Sam Shih -Date: Tue, 28 Feb 2023 19:59:22 +0800 -Subject: [PATCH 21/21] cpufreq: mediatek: Add support for MT7988 - -This add cpufreq support for mediatek MT7988 SoC. - -The platform data of MT7988 is different from previous MediaTek SoCs, -so we add a new compatible and platform data for it. - -Signed-off-by: Sam Shih ---- - drivers/cpufreq/mediatek-cpufreq.c | 10 ++++++++++ - 1 file changed, 10 insertions(+) - ---- a/drivers/cpufreq/mediatek-cpufreq.c -+++ b/drivers/cpufreq/mediatek-cpufreq.c -@@ -709,6 +709,15 @@ static const struct mtk_cpufreq_platform - .ccifreq_supported = false, - }; - -+static const struct mtk_cpufreq_platform_data mt7988_platform_data = { -+ .min_volt_shift = 100000, -+ .max_volt_shift = 200000, -+ .proc_max_volt = 900000, -+ .sram_min_volt = 0, -+ .sram_max_volt = 1150000, -+ .ccifreq_supported = true, -+}; -+ - static const struct mtk_cpufreq_platform_data mt8183_platform_data = { - .min_volt_shift = 100000, - .max_volt_shift = 200000, -@@ -742,6 +751,7 @@ static const struct of_device_id mtk_cpu - { .compatible = "mediatek,mt2712", .data = &mt2701_platform_data }, - { .compatible = "mediatek,mt7622", .data = &mt7622_platform_data }, - { .compatible = "mediatek,mt7623", .data = &mt7623_platform_data }, -+ { .compatible = "mediatek,mt7988", .data = &mt7988_platform_data }, - { .compatible = "mediatek,mt8167", .data = &mt8516_platform_data }, - { .compatible = "mediatek,mt817x", .data = &mt2701_platform_data }, - { .compatible = "mediatek,mt8173", .data = &mt2701_platform_data }, diff --git a/target/linux/mediatek/patches-6.1/400-crypto-add-eip97-inside-secure-support.patch b/target/linux/mediatek/patches-6.1/400-crypto-add-eip97-inside-secure-support.patch deleted file mode 100644 index 25ca9485e..000000000 --- a/target/linux/mediatek/patches-6.1/400-crypto-add-eip97-inside-secure-support.patch +++ /dev/null @@ -1,27 +0,0 @@ ---- a/drivers/crypto/inside-secure/safexcel.c -+++ b/drivers/crypto/inside-secure/safexcel.c -@@ -600,6 +600,14 @@ static int safexcel_hw_init(struct safex - val |= EIP197_MST_CTRL_TX_MAX_CMD(5); - writel(val, EIP197_HIA_AIC(priv) + EIP197_HIA_MST_CTRL); - } -+ /* -+ * Set maximum number of TX commands to 2^4 = 16 for EIP97 HW2.1/HW2.3 -+ */ -+ else { -+ val = 0; -+ val |= EIP97_MST_CTRL_TX_MAX_CMD(4); -+ writel(val, EIP197_HIA_AIC(priv) + EIP197_HIA_MST_CTRL); -+ } - - /* Configure wr/rd cache values */ - writel(EIP197_MST_CTRL_RD_CACHE(RD_CACHE_4BITS) | ---- a/drivers/crypto/inside-secure/safexcel.h -+++ b/drivers/crypto/inside-secure/safexcel.h -@@ -315,6 +315,7 @@ - #define EIP197_MST_CTRL_RD_CACHE(n) (((n) & 0xf) << 0) - #define EIP197_MST_CTRL_WD_CACHE(n) (((n) & 0xf) << 4) - #define EIP197_MST_CTRL_TX_MAX_CMD(n) (((n) & 0xf) << 20) -+#define EIP97_MST_CTRL_TX_MAX_CMD(n) (((n) & 0xf) << 4) - #define EIP197_MST_CTRL_BYTE_SWAP BIT(24) - #define EIP197_MST_CTRL_NO_BYTE_SWAP BIT(25) - #define EIP197_MST_CTRL_BYTE_SWAP_BITS GENMASK(25, 24) diff --git a/target/linux/mediatek/patches-6.1/401-crypto-fix-eip97-cache-incoherent.patch b/target/linux/mediatek/patches-6.1/401-crypto-fix-eip97-cache-incoherent.patch deleted file mode 100644 index 186c66f68..000000000 --- a/target/linux/mediatek/patches-6.1/401-crypto-fix-eip97-cache-incoherent.patch +++ /dev/null @@ -1,26 +0,0 @@ ---- a/drivers/crypto/inside-secure/safexcel.h -+++ b/drivers/crypto/inside-secure/safexcel.h -@@ -737,6 +737,9 @@ enum safexcel_eip_version { - /* Priority we use for advertising our algorithms */ - #define SAFEXCEL_CRA_PRIORITY 300 - -+/* System cache line size */ -+#define SYSTEM_CACHELINE_SIZE 64 -+ - /* SM3 digest result for zero length message */ - #define EIP197_SM3_ZEROM_HASH "\x1A\xB2\x1D\x83\x55\xCF\xA1\x7F" \ - "\x8E\x61\x19\x48\x31\xE8\x1A\x8F" \ ---- a/drivers/crypto/inside-secure/safexcel_hash.c -+++ b/drivers/crypto/inside-secure/safexcel_hash.c -@@ -55,9 +55,9 @@ struct safexcel_ahash_req { - u8 block_sz; /* block size, only set once */ - u8 digest_sz; /* output digest size, only set once */ - __le32 state[SHA3_512_BLOCK_SIZE / -- sizeof(__le32)] __aligned(sizeof(__le32)); -+ sizeof(__le32)] __aligned(SYSTEM_CACHELINE_SIZE); - -- u64 len; -+ u64 len __aligned(SYSTEM_CACHELINE_SIZE); - u64 processed; - - u8 cache[HASH_CACHE_SIZE] __aligned(sizeof(u32)); diff --git a/target/linux/mediatek/patches-6.1/405-v6.2-mt7986-trng-add-rng-support.patch b/target/linux/mediatek/patches-6.1/405-v6.2-mt7986-trng-add-rng-support.patch deleted file mode 100644 index 615a1a1d7..000000000 --- a/target/linux/mediatek/patches-6.1/405-v6.2-mt7986-trng-add-rng-support.patch +++ /dev/null @@ -1,43 +0,0 @@ -From f1da27b7c4191f78ed81d3dabf64c769f896296c Mon Sep 17 00:00:00 2001 -From: "Mingming.Su" -Date: Sat, 8 Oct 2022 18:45:53 +0200 -Subject: [PATCH] hwrng: mtk - add mt7986 support - -1. Add trng compatible name for MT7986 -2. Fix mtk_rng_wait_ready() function - -Signed-off-by: Mingming.Su -Signed-off-by: Frank Wunderlich -Signed-off-by: Herbert Xu ---- - drivers/char/hw_random/mtk-rng.c | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - ---- a/drivers/char/hw_random/mtk-rng.c -+++ b/drivers/char/hw_random/mtk-rng.c -@@ -22,7 +22,7 @@ - #define RNG_AUTOSUSPEND_TIMEOUT 100 - - #define USEC_POLL 2 --#define TIMEOUT_POLL 20 -+#define TIMEOUT_POLL 60 - - #define RNG_CTRL 0x00 - #define RNG_EN BIT(0) -@@ -77,7 +77,7 @@ static bool mtk_rng_wait_ready(struct hw - readl_poll_timeout_atomic(priv->base + RNG_CTRL, ready, - ready & RNG_READY, USEC_POLL, - TIMEOUT_POLL); -- return !!ready; -+ return !!(ready & RNG_READY); - } - - static int mtk_rng_read(struct hwrng *rng, void *buf, size_t max, bool wait) -@@ -179,6 +179,7 @@ static const struct dev_pm_ops mtk_rng_p - #endif /* CONFIG_PM */ - - static const struct of_device_id mtk_rng_match[] = { -+ { .compatible = "mediatek,mt7986-rng" }, - { .compatible = "mediatek,mt7623-rng" }, - {}, - }; diff --git a/target/linux/mediatek/patches-6.1/410-bt-mtk-serial-fix.patch b/target/linux/mediatek/patches-6.1/410-bt-mtk-serial-fix.patch deleted file mode 100644 index fa232b5d4..000000000 --- a/target/linux/mediatek/patches-6.1/410-bt-mtk-serial-fix.patch +++ /dev/null @@ -1,33 +0,0 @@ ---- a/drivers/tty/serial/8250/8250.h -+++ b/drivers/tty/serial/8250/8250.h -@@ -86,6 +86,7 @@ struct serial8250_config { - * STOP PARITY EPAR SPAR WLEN5 WLEN6 - */ - #define UART_CAP_NOTEMT BIT(18) /* UART without interrupt on TEMT available */ -+#define UART_CAP_NMOD BIT(19) /* UART doesn't do termios */ - - #define UART_BUG_QUOT BIT(0) /* UART has buggy quot LSB */ - #define UART_BUG_TXEN BIT(1) /* UART has buggy TX IIR status */ ---- a/drivers/tty/serial/8250/8250_port.c -+++ b/drivers/tty/serial/8250/8250_port.c -@@ -287,7 +287,7 @@ static const struct serial8250_config ua - .tx_loadsz = 16, - .fcr = UART_FCR_ENABLE_FIFO | - UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT, -- .flags = UART_CAP_FIFO, -+ .flags = UART_CAP_FIFO | UART_CAP_NMOD, - }, - [PORT_NPCM] = { - .name = "Nuvoton 16550", -@@ -2767,6 +2767,11 @@ serial8250_do_set_termios(struct uart_po - unsigned long flags; - unsigned int baud, quot, frac = 0; - -+ if (up->capabilities & UART_CAP_NMOD) { -+ termios->c_cflag = 0; -+ return; -+ } -+ - if (up->capabilities & UART_CAP_MINI) { - termios->c_cflag &= ~(CSTOPB | PARENB | PARODD | CMSPAR); - if ((termios->c_cflag & CSIZE) == CS5 || diff --git a/target/linux/mediatek/patches-6.1/431-drivers-spi-mt65xx-Move-chip_config-to-driver-s-priv.patch b/target/linux/mediatek/patches-6.1/431-drivers-spi-mt65xx-Move-chip_config-to-driver-s-priv.patch deleted file mode 100644 index 95fc7f466..000000000 --- a/target/linux/mediatek/patches-6.1/431-drivers-spi-mt65xx-Move-chip_config-to-driver-s-priv.patch +++ /dev/null @@ -1,130 +0,0 @@ -From bfd3acc428085742d754a6d328d1a93ebf9451df Mon Sep 17 00:00:00 2001 -From: "SkyLake.Huang" -Date: Thu, 23 Jun 2022 18:29:51 +0800 -Subject: [PATCH 1/6] drivers: spi-mt65xx: Move chip_config to driver's private - data - -Signed-off-by: SkyLake.Huang ---- - drivers/spi/spi-mt65xx.c | 29 +++++++++--------------- - include/linux/platform_data/spi-mt65xx.h | 17 -------------- - 2 files changed, 11 insertions(+), 35 deletions(-) - delete mode 100644 include/linux/platform_data/spi-mt65xx.h - ---- a/drivers/spi/spi-mt65xx.c -+++ b/drivers/spi/spi-mt65xx.c -@@ -14,7 +14,6 @@ - #include - #include - #include --#include - #include - #include - #include -@@ -171,6 +170,8 @@ struct mtk_spi { - struct device *dev; - dma_addr_t tx_dma; - dma_addr_t rx_dma; -+ u32 sample_sel; -+ u32 get_tick_dly; - }; - - static const struct mtk_spi_compatible mtk_common_compat; -@@ -216,15 +217,6 @@ static const struct mtk_spi_compatible m - .no_need_unprepare = true, - }; - --/* -- * A piece of default chip info unless the platform -- * supplies it. -- */ --static const struct mtk_chip_config mtk_default_chip_info = { -- .sample_sel = 0, -- .tick_delay = 0, --}; -- - static const struct of_device_id mtk_spi_of_match[] = { - { .compatible = "mediatek,spi-ipm", - .data = (void *)&mtk_ipm_compat, -@@ -352,7 +344,6 @@ static int mtk_spi_hw_init(struct spi_ma - { - u16 cpha, cpol; - u32 reg_val; -- struct mtk_chip_config *chip_config = spi->controller_data; - struct mtk_spi *mdata = spi_master_get_devdata(master); - - cpha = spi->mode & SPI_CPHA ? 1 : 0; -@@ -402,7 +393,7 @@ static int mtk_spi_hw_init(struct spi_ma - else - reg_val &= ~SPI_CMD_CS_POL; - -- if (chip_config->sample_sel) -+ if (mdata->sample_sel) - reg_val |= SPI_CMD_SAMPLE_SEL; - else - reg_val &= ~SPI_CMD_SAMPLE_SEL; -@@ -429,20 +420,20 @@ static int mtk_spi_hw_init(struct spi_ma - if (mdata->dev_comp->ipm_design) { - reg_val = readl(mdata->base + SPI_CMD_REG); - reg_val &= ~SPI_CMD_IPM_GET_TICKDLY_MASK; -- reg_val |= ((chip_config->tick_delay & 0x7) -+ reg_val |= ((mdata->get_tick_dly & 0x7) - << SPI_CMD_IPM_GET_TICKDLY_OFFSET); - writel(reg_val, mdata->base + SPI_CMD_REG); - } else { - reg_val = readl(mdata->base + SPI_CFG1_REG); - reg_val &= ~SPI_CFG1_GET_TICK_DLY_MASK; -- reg_val |= ((chip_config->tick_delay & 0x7) -+ reg_val |= ((mdata->get_tick_dly & 0x7) - << SPI_CFG1_GET_TICK_DLY_OFFSET); - writel(reg_val, mdata->base + SPI_CFG1_REG); - } - } else { - reg_val = readl(mdata->base + SPI_CFG1_REG); - reg_val &= ~SPI_CFG1_GET_TICK_DLY_MASK_V1; -- reg_val |= ((chip_config->tick_delay & 0x3) -+ reg_val |= ((mdata->get_tick_dly & 0x3) - << SPI_CFG1_GET_TICK_DLY_OFFSET_V1); - writel(reg_val, mdata->base + SPI_CFG1_REG); - } -@@ -732,9 +723,6 @@ static int mtk_spi_setup(struct spi_devi - { - struct mtk_spi *mdata = spi_master_get_devdata(spi->master); - -- if (!spi->controller_data) -- spi->controller_data = (void *)&mtk_default_chip_info; -- - if (mdata->dev_comp->need_pad_sel && spi->cs_gpiod) - /* CS de-asserted, gpiolib will handle inversion */ - gpiod_direction_output(spi->cs_gpiod, 0); -@@ -1140,6 +1128,10 @@ static int mtk_spi_probe(struct platform - mdata = spi_master_get_devdata(master); - mdata->dev_comp = device_get_match_data(dev); - -+ /* Set device configs to default first. Calibrate it later. */ -+ mdata->sample_sel = 0; -+ mdata->get_tick_dly = 2; -+ - if (mdata->dev_comp->enhance_timing) - master->mode_bits |= SPI_CS_HIGH; - ---- a/include/linux/platform_data/spi-mt65xx.h -+++ /dev/null -@@ -1,17 +0,0 @@ --/* SPDX-License-Identifier: GPL-2.0-only */ --/* -- * MTK SPI bus driver definitions -- * -- * Copyright (c) 2015 MediaTek Inc. -- * Author: Leilk Liu -- */ -- --#ifndef ____LINUX_PLATFORM_DATA_SPI_MTK_H --#define ____LINUX_PLATFORM_DATA_SPI_MTK_H -- --/* Board specific platform_data */ --struct mtk_chip_config { -- u32 sample_sel; -- u32 tick_delay; --}; --#endif diff --git a/target/linux/mediatek/patches-6.1/432-drivers-spi-Add-support-for-dynamic-calibration.patch b/target/linux/mediatek/patches-6.1/432-drivers-spi-Add-support-for-dynamic-calibration.patch deleted file mode 100644 index 10e528dba..000000000 --- a/target/linux/mediatek/patches-6.1/432-drivers-spi-Add-support-for-dynamic-calibration.patch +++ /dev/null @@ -1,236 +0,0 @@ -From 2ade0172154e50c8a2bfd8634c6eff943cffea29 Mon Sep 17 00:00:00 2001 -From: "SkyLake.Huang" -Date: Thu, 23 Jun 2022 18:35:52 +0800 -Subject: [PATCH 2/6] drivers: spi: Add support for dynamic calibration - -Signed-off-by: SkyLake.Huang ---- - drivers/spi/spi.c | 137 ++++++++++++++++++++++++++++++++++++++++ - include/linux/spi/spi.h | 42 ++++++++++++ - 2 files changed, 179 insertions(+) - ---- a/drivers/spi/spi.c -+++ b/drivers/spi/spi.c -@@ -1389,6 +1389,70 @@ static int spi_transfer_wait(struct spi_ - return 0; - } - -+int spi_do_calibration(struct spi_controller *ctlr, struct spi_device *spi, -+ int (*cal_read)(void *priv, u32 *addr, int addrlen, u8 *buf, int readlen), void *drv_priv) -+{ -+ int datalen = ctlr->cal_rule->datalen; -+ int addrlen = ctlr->cal_rule->addrlen; -+ u8 *buf; -+ int ret; -+ int i; -+ struct list_head *cal_head, *listptr; -+ struct spi_cal_target *target; -+ -+ /* Calculate calibration result */ -+ int hit_val, total_hit, origin; -+ bool hit; -+ -+ /* Make sure we can start calibration */ -+ if(!ctlr->cal_target || !ctlr->cal_rule || !ctlr->append_caldata) -+ return 0; -+ -+ buf = kzalloc(datalen * sizeof(u8), GFP_KERNEL); -+ if(!buf) -+ return -ENOMEM; -+ -+ ret = ctlr->append_caldata(ctlr); -+ if (ret) -+ goto cal_end; -+ -+ cal_head = ctlr->cal_target; -+ list_for_each(listptr, cal_head) { -+ target = list_entry(listptr, struct spi_cal_target, list); -+ -+ hit = false; -+ hit_val = 0; -+ total_hit = 0; -+ origin = *target->cal_item; -+ -+ for(i=target->cal_min; i<=target->cal_max; i+=target->step) { -+ *target->cal_item = i; -+ ret = (*cal_read)(drv_priv, ctlr->cal_rule->addr, addrlen, buf, datalen); -+ if(ret) -+ break; -+ dev_dbg(&spi->dev, "controller cal item value: 0x%x\n", i); -+ if(memcmp(ctlr->cal_rule->match_data, buf, datalen * sizeof(u8)) == 0) { -+ hit = true; -+ hit_val += i; -+ total_hit++; -+ dev_dbg(&spi->dev, "golden data matches data read!\n"); -+ } -+ } -+ if(hit) { -+ *target->cal_item = DIV_ROUND_CLOSEST(hit_val, total_hit); -+ dev_info(&spi->dev, "calibration result: 0x%x", *target->cal_item); -+ } else { -+ *target->cal_item = origin; -+ dev_warn(&spi->dev, "calibration failed, fallback to default: 0x%x", origin); -+ } -+ } -+ -+cal_end: -+ kfree(buf); -+ return ret? ret: 0; -+} -+EXPORT_SYMBOL_GPL(spi_do_calibration); -+ - static void _spi_transfer_delay_ns(u32 ns) - { - if (!ns) -@@ -2227,6 +2291,75 @@ void spi_flush_queue(struct spi_controll - /*-------------------------------------------------------------------------*/ - - #if defined(CONFIG_OF) -+static inline void alloc_cal_data(struct list_head **cal_target, -+ struct spi_cal_rule **cal_rule, bool enable) -+{ -+ if(enable) { -+ *cal_target = kmalloc(sizeof(struct list_head), GFP_KERNEL); -+ INIT_LIST_HEAD(*cal_target); -+ *cal_rule = kmalloc(sizeof(struct spi_cal_rule), GFP_KERNEL); -+ } else { -+ kfree(*cal_target); -+ kfree(*cal_rule); -+ } -+} -+ -+static int of_spi_parse_cal_dt(struct spi_controller *ctlr, struct spi_device *spi, -+ struct device_node *nc) -+{ -+ u32 value; -+ int rc; -+ const char *cal_mode; -+ -+ rc = of_property_read_bool(nc, "spi-cal-enable"); -+ if (rc) -+ alloc_cal_data(&ctlr->cal_target, &ctlr->cal_rule, true); -+ else -+ return 0; -+ -+ rc = of_property_read_string(nc, "spi-cal-mode", &cal_mode); -+ if(!rc) { -+ if(strcmp("read-data", cal_mode) == 0){ -+ ctlr->cal_rule->mode = SPI_CAL_READ_DATA; -+ } else if(strcmp("read-pp", cal_mode) == 0) { -+ ctlr->cal_rule->mode = SPI_CAL_READ_PP; -+ return 0; -+ } else if(strcmp("read-sfdp", cal_mode) == 0){ -+ ctlr->cal_rule->mode = SPI_CAL_READ_SFDP; -+ return 0; -+ } -+ } else -+ goto err; -+ -+ ctlr->cal_rule->datalen = 0; -+ rc = of_property_read_u32(nc, "spi-cal-datalen", &value); -+ if(!rc && value > 0) { -+ ctlr->cal_rule->datalen = value; -+ -+ ctlr->cal_rule->match_data = kzalloc(value * sizeof(u8), GFP_KERNEL); -+ rc = of_property_read_u8_array(nc, "spi-cal-data", -+ ctlr->cal_rule->match_data, value); -+ if(rc) -+ kfree(ctlr->cal_rule->match_data); -+ } -+ -+ rc = of_property_read_u32(nc, "spi-cal-addrlen", &value); -+ if(!rc && value > 0) { -+ ctlr->cal_rule->addrlen = value; -+ -+ ctlr->cal_rule->addr = kzalloc(value * sizeof(u32), GFP_KERNEL); -+ rc = of_property_read_u32_array(nc, "spi-cal-addr", -+ ctlr->cal_rule->addr, value); -+ if(rc) -+ kfree(ctlr->cal_rule->addr); -+ } -+ return 0; -+ -+err: -+ alloc_cal_data(&ctlr->cal_target, &ctlr->cal_rule, false); -+ return 0; -+} -+ - static int of_spi_parse_dt(struct spi_controller *ctlr, struct spi_device *spi, - struct device_node *nc) - { -@@ -2345,6 +2478,10 @@ of_register_spi_device(struct spi_contro - if (rc) - goto err_out; - -+ rc = of_spi_parse_cal_dt(ctlr, spi, nc); -+ if (rc) -+ goto err_out; -+ - /* Store a pointer to the node in the device structure */ - of_node_get(nc); - spi->dev.of_node = nc; ---- a/include/linux/spi/spi.h -+++ b/include/linux/spi/spi.h -@@ -318,6 +318,40 @@ struct spi_driver { - struct device_driver driver; - }; - -+enum { -+ SPI_CAL_READ_DATA = 0, -+ SPI_CAL_READ_PP = 1, /* only for SPI-NAND */ -+ SPI_CAL_READ_SFDP = 2, /* only for SPI-NOR */ -+}; -+ -+struct nand_addr { -+ unsigned int lun; -+ unsigned int plane; -+ unsigned int eraseblock; -+ unsigned int page; -+ unsigned int dataoffs; -+}; -+ -+/** -+ * Read calibration rule from device dts node. -+ * Once calibration result matches the rule, we regard is as success. -+ */ -+struct spi_cal_rule { -+ int datalen; -+ u8 *match_data; -+ int addrlen; -+ u32 *addr; -+ int mode; -+}; -+ -+struct spi_cal_target { -+ u32 *cal_item; -+ int cal_min; /* min of cal_item */ -+ int cal_max; /* max of cal_item */ -+ int step; /* Increase/decrease cal_item */ -+ struct list_head list; -+}; -+ - static inline struct spi_driver *to_spi_driver(struct device_driver *drv) - { - return drv ? container_of(drv, struct spi_driver, driver) : NULL; -@@ -712,6 +746,11 @@ struct spi_controller { - void *dummy_rx; - void *dummy_tx; - -+ /* For calibration */ -+ int (*append_caldata)(struct spi_controller *ctlr); -+ struct list_head *cal_target; -+ struct spi_cal_rule *cal_rule; -+ - int (*fw_translate_cs)(struct spi_controller *ctlr, unsigned cs); - - /* -@@ -1555,6 +1594,9 @@ spi_register_board_info(struct spi_board - { return 0; } - #endif - -+extern int spi_do_calibration(struct spi_controller *ctlr, -+ struct spi_device *spi, int (*cal_read)(void *, u32 *, int, u8 *, int), void *drv_priv); -+ - /* If you're hotplugging an adapter with devices (parport, usb, etc) - * use spi_new_device() to describe each device. You can also call - * spi_unregister_device() to start making that device vanish, but diff --git a/target/linux/mediatek/patches-6.1/433-drivers-spi-mem-Add-spi-calibration-hook.patch b/target/linux/mediatek/patches-6.1/433-drivers-spi-mem-Add-spi-calibration-hook.patch deleted file mode 100644 index e87d63db6..000000000 --- a/target/linux/mediatek/patches-6.1/433-drivers-spi-mem-Add-spi-calibration-hook.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 06640a5da2973318c06e516da16a5b579622e7c5 Mon Sep 17 00:00:00 2001 -From: "SkyLake.Huang" -Date: Thu, 23 Jun 2022 18:37:55 +0800 -Subject: [PATCH 3/6] drivers: spi-mem: Add spi calibration hook - -Signed-off-by: SkyLake.Huang ---- - drivers/spi/spi-mem.c | 8 ++++++++ - include/linux/spi/spi-mem.h | 4 ++++ - 2 files changed, 12 insertions(+) - ---- a/drivers/spi/spi-mem.c -+++ b/drivers/spi/spi-mem.c -@@ -419,6 +419,14 @@ int spi_mem_exec_op(struct spi_mem *mem, - } - EXPORT_SYMBOL_GPL(spi_mem_exec_op); - -+int spi_mem_do_calibration(struct spi_mem *mem, -+ int (*cal_read)(void *priv, u32 *addr, int addrlen, u8 *buf, int readlen), -+ void *priv) -+{ -+ return spi_do_calibration(mem->spi->controller, mem->spi, cal_read, priv); -+} -+EXPORT_SYMBOL_GPL(spi_mem_do_calibration); -+ - /** - * spi_mem_get_name() - Return the SPI mem device name to be used by the - * upper layer if necessary ---- a/include/linux/spi/spi-mem.h -+++ b/include/linux/spi/spi-mem.h -@@ -366,6 +366,10 @@ bool spi_mem_supports_op(struct spi_mem - int spi_mem_exec_op(struct spi_mem *mem, - const struct spi_mem_op *op); - -+int spi_mem_do_calibration(struct spi_mem *mem, -+ int (*cal_read)(void *, u32 *, int, u8 *, int), -+ void *priv); -+ - const char *spi_mem_get_name(struct spi_mem *mem); - - struct spi_mem_dirmap_desc * diff --git a/target/linux/mediatek/patches-6.1/434-drivers-spi-mt65xx-Add-controller-s-calibration-para.patch b/target/linux/mediatek/patches-6.1/434-drivers-spi-mt65xx-Add-controller-s-calibration-para.patch deleted file mode 100644 index dbdb1947a..000000000 --- a/target/linux/mediatek/patches-6.1/434-drivers-spi-mt65xx-Add-controller-s-calibration-para.patch +++ /dev/null @@ -1,43 +0,0 @@ -From d278c7a0bf730318a7ccf8d0a8b434c813e23fd0 Mon Sep 17 00:00:00 2001 -From: "SkyLake.Huang" -Date: Thu, 23 Jun 2022 18:39:03 +0800 -Subject: [PATCH 4/6] drivers: spi-mt65xx: Add controller's calibration - paramter - -Signed-off-by: SkyLake.Huang ---- - drivers/spi/spi-mt65xx.c | 16 ++++++++++++++++ - 1 file changed, 16 insertions(+) - ---- a/drivers/spi/spi-mt65xx.c -+++ b/drivers/spi/spi-mt65xx.c -@@ -834,6 +834,21 @@ static irqreturn_t mtk_spi_interrupt(int - return IRQ_HANDLED; - } - -+static int mtk_spi_append_caldata(struct spi_controller *ctlr) -+{ -+ struct spi_cal_target *cal_target = kmalloc(sizeof(*cal_target), GFP_KERNEL); -+ struct mtk_spi *mdata = spi_master_get_devdata(ctlr); -+ -+ cal_target->cal_item = &mdata->get_tick_dly; -+ cal_target->cal_min = 0; -+ cal_target->cal_max = 7; -+ cal_target->step = 1; -+ -+ list_add(&cal_target->list, ctlr->cal_target); -+ -+ return 0; -+} -+ - static int mtk_spi_mem_adjust_op_size(struct spi_mem *mem, - struct spi_mem_op *op) - { -@@ -1124,6 +1139,7 @@ static int mtk_spi_probe(struct platform - master->setup = mtk_spi_setup; - master->set_cs_timing = mtk_spi_set_hw_cs_timing; - master->use_gpio_descriptors = true; -+ master->append_caldata = mtk_spi_append_caldata; - - mdata = spi_master_get_devdata(master); - mdata->dev_comp = device_get_match_data(dev); diff --git a/target/linux/mediatek/patches-6.1/435-drivers-mtd-spinand-Add-calibration-support-for-spin.patch b/target/linux/mediatek/patches-6.1/435-drivers-mtd-spinand-Add-calibration-support-for-spin.patch deleted file mode 100644 index 3991d8925..000000000 --- a/target/linux/mediatek/patches-6.1/435-drivers-mtd-spinand-Add-calibration-support-for-spin.patch +++ /dev/null @@ -1,81 +0,0 @@ -From 7670ec4a14891a1a182b98a9c403ffbf6b49e4b1 Mon Sep 17 00:00:00 2001 -From: "SkyLake.Huang" -Date: Thu, 23 Jun 2022 18:39:56 +0800 -Subject: [PATCH 5/6] drivers: mtd: spinand: Add calibration support for - spinand - -Signed-off-by: SkyLake.Huang ---- - drivers/mtd/nand/spi/core.c | 54 +++++++++++++++++++++++++++++++++++++ - 1 file changed, 54 insertions(+) - ---- a/drivers/mtd/nand/spi/core.c -+++ b/drivers/mtd/nand/spi/core.c -@@ -978,6 +978,56 @@ static int spinand_manufacturer_match(st - return -ENOTSUPP; - } - -+int spinand_cal_read(void *priv, u32 *addr, int addrlen, u8 *buf, int readlen) { -+ struct spinand_device *spinand = (struct spinand_device *)priv; -+ struct device *dev = &spinand->spimem->spi->dev; -+ struct spi_mem_op op = SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, buf, readlen); -+ struct nand_pos pos; -+ struct nand_page_io_req req; -+ u8 status; -+ int ret; -+ -+ if(addrlen != sizeof(struct nand_addr)/sizeof(unsigned int)) { -+ dev_err(dev, "Must provide correct addr(length) for spinand calibration\n"); -+ return -EINVAL; -+ } -+ -+ ret = spinand_reset_op(spinand); -+ if (ret) -+ return ret; -+ -+ /* We should store our golden data in first target because -+ * we can't switch target at this moment. -+ */ -+ pos = (struct nand_pos){ -+ .target = 0, -+ .lun = *addr, -+ .plane = *(addr+1), -+ .eraseblock = *(addr+2), -+ .page = *(addr+3), -+ }; -+ -+ req = (struct nand_page_io_req){ -+ .pos = pos, -+ .dataoffs = *(addr+4), -+ .datalen = readlen, -+ .databuf.in = buf, -+ .mode = MTD_OPS_AUTO_OOB, -+ }; -+ -+ ret = spinand_load_page_op(spinand, &req); -+ if (ret) -+ return ret; -+ -+ ret = spinand_wait(spinand, &status); -+ if (ret < 0) -+ return ret; -+ -+ ret = spi_mem_exec_op(spinand->spimem, &op); -+ -+ return 0; -+} -+ - static int spinand_id_detect(struct spinand_device *spinand) - { - u8 *id = spinand->id.data; -@@ -1228,6 +1278,10 @@ static int spinand_init(struct spinand_d - if (!spinand->scratchbuf) - return -ENOMEM; - -+ ret = spi_mem_do_calibration(spinand->spimem, spinand_cal_read, spinand); -+ if (ret) -+ dev_err(dev, "Failed to calibrate SPI-NAND (err = %d)\n", ret); -+ - ret = spinand_detect(spinand); - if (ret) - goto err_free_bufs; diff --git a/target/linux/mediatek/patches-6.1/436-drivers-mtd-spi-nor-Add-calibration-support-for-spi-.patch b/target/linux/mediatek/patches-6.1/436-drivers-mtd-spi-nor-Add-calibration-support-for-spi-.patch deleted file mode 100644 index 1f747d1f4..000000000 --- a/target/linux/mediatek/patches-6.1/436-drivers-mtd-spi-nor-Add-calibration-support-for-spi-.patch +++ /dev/null @@ -1,57 +0,0 @@ -From f3fe3b15eca7908eaac57f9b8387a5dbc45ec5b2 Mon Sep 17 00:00:00 2001 -From: "SkyLake.Huang" -Date: Thu, 23 Jun 2022 18:40:59 +0800 -Subject: [PATCH 6/6] drivers: mtd: spi-nor: Add calibration support for - spi-nor - -Signed-off-by: SkyLake.Huang ---- - drivers/mtd/nand/spi/core.c | 5 ++++- - drivers/mtd/spi-nor/core.c | 15 +++++++++++++++ - 2 files changed, 19 insertions(+), 1 deletion(-) - ---- a/drivers/mtd/nand/spi/core.c -+++ b/drivers/mtd/nand/spi/core.c -@@ -1019,7 +1019,10 @@ int spinand_cal_read(void *priv, u32 *ad - if (ret) - return ret; - -- ret = spinand_wait(spinand, &status); -+ ret = spinand_wait(spinand, -+ SPINAND_READ_INITIAL_DELAY_US, -+ SPINAND_READ_POLL_DELAY_US, -+ &status); - if (ret < 0) - return ret; - ---- a/drivers/mtd/spi-nor/core.c -+++ b/drivers/mtd/spi-nor/core.c -@@ -2900,6 +2900,18 @@ static const struct flash_info *spi_nor_ - return NULL; - } - -+static int spi_nor_cal_read(void *priv, u32 *addr, int addrlen, u8 *buf, int readlen) -+{ -+ struct spi_nor *nor = (struct spi_nor *)priv; -+ -+ nor->reg_proto = SNOR_PROTO_1_1_1; -+ nor->read_proto = SNOR_PROTO_1_1_1; -+ nor->read_opcode = SPINOR_OP_READ; -+ nor->read_dummy = 0; -+ -+ return nor->controller_ops->read(nor, *addr, readlen, buf); -+} -+ - static const struct flash_info *spi_nor_get_flash_info(struct spi_nor *nor, - const char *name) - { -@@ -3003,6 +3015,9 @@ int spi_nor_scan(struct spi_nor *nor, co - if (!nor->bouncebuf) - return -ENOMEM; - -+ if(nor->spimem) -+ spi_mem_do_calibration(nor->spimem, spi_nor_cal_read, nor); -+ - info = spi_nor_get_flash_info(nor, name); - if (IS_ERR(info)) - return PTR_ERR(info); diff --git a/target/linux/mediatek/patches-6.1/500-gsw-rtl8367s-mt7622-support.patch b/target/linux/mediatek/patches-6.1/500-gsw-rtl8367s-mt7622-support.patch deleted file mode 100644 index e37705f38..000000000 --- a/target/linux/mediatek/patches-6.1/500-gsw-rtl8367s-mt7622-support.patch +++ /dev/null @@ -1,25 +0,0 @@ ---- a/drivers/net/phy/Kconfig -+++ b/drivers/net/phy/Kconfig -@@ -389,6 +389,12 @@ config ROCKCHIP_PHY - help - Currently supports the integrated Ethernet PHY. - -+config RTL8367S_GSW -+ tristate "rtl8367 Gigabit Switch support for mt7622" -+ depends on NET_VENDOR_MEDIATEK -+ help -+ This driver supports rtl8367s in mt7622 -+ - config SMSC_PHY - tristate "SMSC PHYs" - help ---- a/drivers/net/phy/Makefile -+++ b/drivers/net/phy/Makefile -@@ -98,6 +98,7 @@ obj-$(CONFIG_QSEMI_PHY) += qsemi.o - obj-$(CONFIG_REALTEK_PHY) += realtek.o - obj-$(CONFIG_RENESAS_PHY) += uPD60620.o - obj-$(CONFIG_ROCKCHIP_PHY) += rockchip.o -+obj-$(CONFIG_RTL8367S_GSW) += rtk/ - obj-$(CONFIG_SMSC_PHY) += smsc.o - obj-$(CONFIG_STE10XP) += ste10Xp.o - obj-$(CONFIG_TERANETICS_PHY) += teranetics.o diff --git a/target/linux/mediatek/patches-6.1/601-PCI-mediatek-Assert-PERST-for-100ms-for-power-and-cl.patch b/target/linux/mediatek/patches-6.1/601-PCI-mediatek-Assert-PERST-for-100ms-for-power-and-cl.patch deleted file mode 100644 index 983fde707..000000000 --- a/target/linux/mediatek/patches-6.1/601-PCI-mediatek-Assert-PERST-for-100ms-for-power-and-cl.patch +++ /dev/null @@ -1,34 +0,0 @@ -From: qizhong cheng -Date: Mon, 27 Dec 2021 21:31:10 +0800 -Subject: [PATCH] PCI: mediatek: Assert PERST# for 100ms for power and clock to - stabilize -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Described in PCIe CEM specification sections 2.2 (PERST# Signal) and -2.2.1 (Initial Power-Up (G3 to S0)). The deassertion of PERST# should -be delayed 100ms (TPVPERL) for the power and clock to become stable. - -Link: https://lore.kernel.org/r/20211227133110.14500-1-qizhong.cheng@mediatek.com -Signed-off-by: qizhong cheng -Signed-off-by: Lorenzo Pieralisi -Acked-by: Pali Rohár ---- - ---- a/drivers/pci/controller/pcie-mediatek.c -+++ b/drivers/pci/controller/pcie-mediatek.c -@@ -708,6 +708,13 @@ static int mtk_pcie_startup_port_v2(stru - */ - msleep(100); - -+ /* -+ * Described in PCIe CEM specification sections 2.2 (PERST# Signal) and -+ * 2.2.1 (Initial Power-Up (G3 to S0)). The deassertion of PERST# should -+ * be delayed 100ms (TPVPERL) for the power and clock to become stable. -+ */ -+ msleep(100); -+ - /* De-assert PHY, PE, PIPE, MAC and configuration reset */ - val = readl(port->base + PCIE_RST_CTRL); - val |= PCIE_PHY_RSTB | PCIE_PERSTB | PCIE_PIPE_SRSTB | diff --git a/target/linux/mediatek/patches-6.1/602-arm64-dts-mediatek-add-mt7622-pcie-slot-node.patch b/target/linux/mediatek/patches-6.1/602-arm64-dts-mediatek-add-mt7622-pcie-slot-node.patch deleted file mode 100644 index d58082aa6..000000000 --- a/target/linux/mediatek/patches-6.1/602-arm64-dts-mediatek-add-mt7622-pcie-slot-node.patch +++ /dev/null @@ -1,28 +0,0 @@ ---- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi -+++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi -@@ -844,6 +844,12 @@ - #address-cells = <0>; - #interrupt-cells = <1>; - }; -+ -+ slot0: pcie@0,0 { -+ reg = <0x0000 0 0 0 0>; -+ #address-cells = <3>; -+ #size-cells = <2>; -+ }; - }; - - pcie1: pcie@1a145000 { -@@ -882,6 +888,12 @@ - #address-cells = <0>; - #interrupt-cells = <1>; - }; -+ -+ slot1: pcie@1,0 { -+ reg = <0x0800 0 0 0 0>; -+ #address-cells = <3>; -+ #size-cells = <2>; -+ }; - }; - - sata: sata@1a200000 { diff --git a/target/linux/mediatek/patches-6.1/610-pcie-mediatek-fix-clearing-interrupt-status.patch b/target/linux/mediatek/patches-6.1/610-pcie-mediatek-fix-clearing-interrupt-status.patch deleted file mode 100644 index 2a49b2275..000000000 --- a/target/linux/mediatek/patches-6.1/610-pcie-mediatek-fix-clearing-interrupt-status.patch +++ /dev/null @@ -1,23 +0,0 @@ -From: Felix Fietkau -Date: Fri, 4 Sep 2020 18:33:27 +0200 -Subject: [PATCH] pcie-mediatek: fix clearing interrupt status - -Clearing the status needs to happen after running the handler, otherwise -we will get an extra spurious interrupt after the cause has been cleared - -Signed-off-by: Felix Fietkau ---- - ---- a/drivers/pci/controller/pcie-mediatek.c -+++ b/drivers/pci/controller/pcie-mediatek.c -@@ -607,9 +607,9 @@ static void mtk_pcie_intr_handler(struct - if (status & INTX_MASK) { - for_each_set_bit_from(bit, &status, PCI_NUM_INTX + INTX_SHIFT) { - /* Clear the INTx */ -- writel(1 << bit, port->base + PCIE_INT_STATUS); - generic_handle_domain_irq(port->irq_domain, - bit - INTX_SHIFT); -+ writel(1 << bit, port->base + PCIE_INT_STATUS); - } - } - diff --git a/target/linux/mediatek/patches-6.1/710-pci-pcie-mediatek-add-support-for-coherent-DMA.patch b/target/linux/mediatek/patches-6.1/710-pci-pcie-mediatek-add-support-for-coherent-DMA.patch deleted file mode 100644 index 917a458d3..000000000 --- a/target/linux/mediatek/patches-6.1/710-pci-pcie-mediatek-add-support-for-coherent-DMA.patch +++ /dev/null @@ -1,91 +0,0 @@ -From: Felix Fietkau -Date: Fri, 4 Sep 2020 18:42:42 +0200 -Subject: [PATCH] pci: pcie-mediatek: add support for coherent DMA - -It improves performance by eliminating the need for a cache flush for DMA on -attached devices - -Signed-off-by: Felix Fietkau ---- - ---- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi -+++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi -@@ -832,6 +832,9 @@ - bus-range = <0x00 0xff>; - ranges = <0x82000000 0 0x20000000 0x0 0x20000000 0 0x8000000>; - status = "disabled"; -+ dma-coherent; -+ mediatek,hifsys = <&hifsys>; -+ mediatek,cci-control = <&cci_control2>; - - #interrupt-cells = <1>; - interrupt-map-mask = <0 0 0 7>; -@@ -876,6 +879,9 @@ - bus-range = <0x00 0xff>; - ranges = <0x82000000 0 0x28000000 0x0 0x28000000 0 0x8000000>; - status = "disabled"; -+ dma-coherent; -+ mediatek,hifsys = <&hifsys>; -+ mediatek,cci-control = <&cci_control2>; - - #interrupt-cells = <1>; - interrupt-map-mask = <0 0 0 7>; -@@ -937,7 +943,7 @@ - }; - - hifsys: clock-controller@1af00000 { -- compatible = "mediatek,mt7622-hifsys"; -+ compatible = "mediatek,mt7622-hifsys", "syscon"; - reg = <0 0x1af00000 0 0x70>; - #clock-cells = <1>; - }; ---- a/drivers/pci/controller/pcie-mediatek.c -+++ b/drivers/pci/controller/pcie-mediatek.c -@@ -20,6 +20,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -139,6 +140,11 @@ - #define PCIE_LINK_STATUS_V2 0x804 - #define PCIE_PORT_LINKUP_V2 BIT(10) - -+/* DMA channel mapping */ -+#define HIFSYS_DMA_AG_MAP 0x008 -+#define HIFSYS_DMA_AG_MAP_PCIE0 BIT(0) -+#define HIFSYS_DMA_AG_MAP_PCIE1 BIT(1) -+ - struct mtk_pcie_port; - - /** -@@ -1060,6 +1066,27 @@ static int mtk_pcie_setup(struct mtk_pci - struct mtk_pcie_port *port, *tmp; - int err, slot; - -+ if (of_dma_is_coherent(node)) { -+ struct regmap *con; -+ u32 mask; -+ -+ con = syscon_regmap_lookup_by_phandle(node, -+ "mediatek,cci-control"); -+ /* enable CPU/bus coherency */ -+ if (!IS_ERR(con)) -+ regmap_write(con, 0, 3); -+ -+ con = syscon_regmap_lookup_by_phandle(node, -+ "mediatek,hifsys"); -+ if (IS_ERR(con)) { -+ dev_err(dev, "missing hifsys node\n"); -+ return PTR_ERR(con); -+ } -+ -+ mask = HIFSYS_DMA_AG_MAP_PCIE0 | HIFSYS_DMA_AG_MAP_PCIE1; -+ regmap_update_bits(con, HIFSYS_DMA_AG_MAP, mask, mask); -+ } -+ - slot = of_get_pci_domain_nr(dev->of_node); - if (slot < 0) { - for_each_available_child_of_node(node, child) { diff --git a/target/linux/mediatek/patches-6.1/721-dts-mt7622-mediatek-fix-300mhz.patch b/target/linux/mediatek/patches-6.1/721-dts-mt7622-mediatek-fix-300mhz.patch deleted file mode 100644 index f9a5fdbd0..000000000 --- a/target/linux/mediatek/patches-6.1/721-dts-mt7622-mediatek-fix-300mhz.patch +++ /dev/null @@ -1,27 +0,0 @@ -From: Jip de Beer -Date: Sun, 9 Jan 2022 13:14:04 +0100 -Subject: [PATCH] mediatek mt7622: fix 300mhz typo in dts - -The lowest frequency should be 300MHz, since that is the label -assigned to the OPP in the mt7622.dtsi device tree, while there is one -missing zero in the actual value. - -To be clear, the lowest frequency should be 300MHz instead of 30MHz. - -As mentioned @dangowrt on the OpenWrt forum there is no benefit in -leaving 30MHz as the lowest frequency. - -Signed-off-by: Jip de Beer -Signed-off-by: Fritz D. Ansel ---- ---- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi -+++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi -@@ -24,7 +24,7 @@ - compatible = "operating-points-v2"; - opp-shared; - opp-300000000 { -- opp-hz = /bits/ 64 <30000000>; -+ opp-hz = /bits/ 64 <300000000>; - opp-microvolt = <950000>; - }; - diff --git a/target/linux/mediatek/patches-6.1/722-remove-300Hz-to-prevent-freeze.patch b/target/linux/mediatek/patches-6.1/722-remove-300Hz-to-prevent-freeze.patch deleted file mode 100644 index 52069496c..000000000 --- a/target/linux/mediatek/patches-6.1/722-remove-300Hz-to-prevent-freeze.patch +++ /dev/null @@ -1,25 +0,0 @@ ---- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi -+++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi -@@ -23,11 +23,17 @@ - cpu_opp_table: opp-table { - compatible = "operating-points-v2"; - opp-shared; -- opp-300000000 { -- opp-hz = /bits/ 64 <300000000>; -- opp-microvolt = <950000>; -- }; -- -+ /* Due to the bug described at the link below, remove the 300 MHz clock to avoid a low -+ * voltage condition that can cause a hang when rebooting the RT3200/E8450. -+ * -+ * https://forum.openwrt.org/t/belkin-rt3200-linksys-e8450-wifi-ax-discussion/94302/1490 -+ * -+ * opp-300000000 { -+ * opp-hz = /bits/ 64 <300000000>; -+ * opp-microvolt = <950000>; -+ * }; -+ * -+ */ - opp-437500000 { - opp-hz = /bits/ 64 <437500000>; - opp-microvolt = <1000000>; diff --git a/target/linux/mediatek/patches-6.1/730-v6.5-net-phy-add-driver-for-MediaTek-SoC-built-in-GE-PHYs.patch b/target/linux/mediatek/patches-6.1/730-v6.5-net-phy-add-driver-for-MediaTek-SoC-built-in-GE-PHYs.patch deleted file mode 100644 index 8d1b89d69..000000000 --- a/target/linux/mediatek/patches-6.1/730-v6.5-net-phy-add-driver-for-MediaTek-SoC-built-in-GE-PHYs.patch +++ /dev/null @@ -1,1204 +0,0 @@ -From 98c485eaf509bc0e2a85f9b58d17cd501f274c4e Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Sun, 11 Jun 2023 00:48:10 +0100 -Subject: [PATCH] net: phy: add driver for MediaTek SoC built-in GE PHYs - -Some of MediaTek's Filogic SoCs come with built-in gigabit Ethernet -PHYs which require calibration data from the SoC's efuse. -Despite the similar design the driver doesn't share any code with the -existing mediatek-ge.c. -Add support for such PHYs by introducing a new driver with basic -support for MediaTek SoCs MT7981 and MT7988 built-in 1GE PHYs. - -Signed-off-by: Daniel Golle -Reviewed-by: Andrew Lunn -Signed-off-by: David S. Miller ---- - MAINTAINERS | 9 + - drivers/net/phy/Kconfig | 12 + - drivers/net/phy/Makefile | 1 + - drivers/net/phy/mediatek-ge-soc.c | 1116 +++++++++++++++++++++++++++++ - drivers/net/phy/mediatek-ge.c | 3 +- - 5 files changed, 1140 insertions(+), 1 deletion(-) - create mode 100644 drivers/net/phy/mediatek-ge-soc.c - ---- a/MAINTAINERS -+++ b/MAINTAINERS -@@ -12943,6 +12943,15 @@ S: Maintained - F: drivers/net/pcs/pcs-mtk-lynxi.c - F: include/linux/pcs/pcs-mtk-lynxi.h - -+MEDIATEK ETHERNET PHY DRIVERS -+M: Daniel Golle -+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 -+ - MEDIATEK I2C CONTROLLER DRIVER - M: Qii Wang - L: linux-i2c@vger.kernel.org ---- a/drivers/net/phy/Kconfig -+++ b/drivers/net/phy/Kconfig -@@ -314,6 +314,18 @@ config MEDIATEK_GE_PHY - help - Supports the MediaTek Gigabit Ethernet PHYs. - -+config MEDIATEK_GE_SOC_PHY -+ tristate "MediaTek SoC Ethernet PHYs" -+ depends on (ARM64 && ARCH_MEDIATEK) || COMPILE_TEST -+ select 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. -+ - config MICREL_PHY - tristate "Micrel PHYs" - depends on PTP_1588_CLOCK_OPTIONAL ---- a/drivers/net/phy/Makefile -+++ b/drivers/net/phy/Makefile -@@ -84,6 +84,7 @@ obj-$(CONFIG_MARVELL_PHY) += marvell.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-$(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-ge-soc.c -@@ -0,0 +1,1116 @@ -+// SPDX-License-Identifier: GPL-2.0+ -+#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_SHIFT (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 -+ -+#define MTK_PHY_RG_BG_RASEL 0x115 -+#define MTK_PHY_RG_BG_RASEL_MASK GENMASK(2, 0) -+ -+/* 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 { -+ GPHY_PORT0, -+ GPHY_PORT1, -+ GPHY_PORT2, -+ GPHY_PORT3, -+}; -+ -+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 -+}; -+ -+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) >> -+ MTK_PHY_AD_CAL_COMP_OUT_SHIFT; -+ 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) -+{ -+ 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 }; -+ 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, (buf[0] + bias[0]) << 10); -+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TXVLD_DA_RG, -+ 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); -+ 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]); -+ -+ 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); -+ 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]); -+ 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); -+ 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]); -+ -+ 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); -+ 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]); -+ 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); -+ 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]); -+ -+ 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); -+ 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]); -+ 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); -+ 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]); -+ -+ 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 = -2; -+ -+ 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); -+ /* 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); -+ -+ /* TrFreeze = 0 */ -+ __phy_write(phydev, 0x11, 0x0); -+ __phy_write(phydev, 0x12, 0x0); -+ __phy_write(phydev, 0x10, 0x9686); -+ -+ /* SSTrKp1000Slv = 5 */ -+ __phy_write(phydev, 0x11, 0xbaef); -+ __phy_write(phydev, 0x12, 0x2e); -+ __phy_write(phydev, 0x10, 0x968c); -+ -+ /* 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 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); -+ /* SlvDSPreadyTime = 24, MasDSPreadyTime = 24 */ -+ __phy_write(phydev, 0x11, 0xc71); -+ __phy_write(phydev, 0x12, 0xc); -+ __phy_write(phydev, 0x10, 0x8fae); -+ -+ /* 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); -+ -+ /* FfeUpdGainForce = 4 */ -+ __phy_write(phydev, 0x11, 0x240); -+ __phy_write(phydev, 0x12, 0x0); -+ __phy_write(phydev, 0x10, 0x9680); -+ -+ phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0); -+} -+ -+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); -+ -+ /* Disable TX power saving */ -+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RXADC_CTRL_RG7, -+ MTK_PHY_DA_AD_BUF_BIAS_LP_MASK, 0x3 << 8); -+ -+ phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5); -+ -+ /* SlvDSPreadyTime = 24, MasDSPreadyTime = 12 */ -+ __phy_write(phydev, 0x11, 0x671); -+ __phy_write(phydev, 0x12, 0xc); -+ __phy_write(phydev, 0x10, 0x8fae); -+ -+ /* ResetSyncOffset = 5 */ -+ __phy_write(phydev, 0x11, 0x500); -+ __phy_write(phydev, 0x12, 0x0); -+ __phy_write(phydev, 0x10, 0x8fc0); -+ -+ /* VgaDecRate is 1 at default on mt7988 */ -+ -+ phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0); -+ -+ phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_2A30); -+ /* TxClkOffset = 2 */ -+ __phy_modify(phydev, MTK_PHY_ANARG_RG, MTK_PHY_TCLKOFFSET_MASK, -+ FIELD_PREP(MTK_PHY_TCLKOFFSET_MASK, 0x2)); -+ phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0); -+} -+ -+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)); -+ -+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG239, -+ MTK_PHY_LPI_SEND_LOC_TIMER_MASK | -+ MTK_PHY_LPI_TXPCS_LOC_RCV, -+ FIELD_PREP(MTK_PHY_LPI_SEND_LOC_TIMER_MASK, 0x117)); -+ -+ 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 = 3 */ -+ __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 = 1 */ -+ __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) -+{ -+ int ret = 0; -+ u32 *buf; -+ size_t len; -+ struct nvmem_cell *cell; -+ -+ 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 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 = mt798x_phy_calibration, -+ .suspend = genphy_suspend, -+ .resume = genphy_resume, -+ .read_page = mtk_socphy_read_page, -+ .write_page = mtk_socphy_write_page, -+ }, -+ { -+ 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 = mt798x_phy_calibration, -+ .suspend = genphy_suspend, -+ .resume = genphy_resume, -+ .read_page = mtk_socphy_read_page, -+ .write_page = mtk_socphy_write_page, -+ }, -+}; -+ -+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 -+++ b/drivers/net/phy/mediatek-ge.c -@@ -136,7 +136,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_VENDOR(0x03a29400) }, -+ { PHY_ID_MATCH_EXACT(0x03a29441) }, -+ { PHY_ID_MATCH_EXACT(0x03a29412) }, - { } - }; - diff --git a/target/linux/mediatek/patches-6.1/731-v6.5-net-phy-mediatek-ge-soc-support-PHY-LEDs.patch b/target/linux/mediatek/patches-6.1/731-v6.5-net-phy-mediatek-ge-soc-support-PHY-LEDs.patch deleted file mode 100644 index 286ce96a7..000000000 --- a/target/linux/mediatek/patches-6.1/731-v6.5-net-phy-mediatek-ge-soc-support-PHY-LEDs.patch +++ /dev/null @@ -1,524 +0,0 @@ -From c66937b0f8dbb4c6c043663c702b1053fb47fab2 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Mon, 14 Aug 2023 02:58:14 +0100 -Subject: [PATCH] net: phy: mediatek-ge-soc: support PHY LEDs - -Implement netdev trigger and primitive bliking offloading as well as -simple set_brigthness function for both PHY LEDs of the in-SoC PHYs -found in MT7981 and MT7988. - -For MT7988, read boottrap register and apply LED polarities accordingly -to get uniform behavior from all LEDs on MT7988. -This requires syscon phandle 'mediatek,pio' present in parenting MDIO bus -which should point to the syscon holding the boottrap register. - -Signed-off-by: Daniel Golle -Reviewed-by: Andrew Lunn -Link: https://lore.kernel.org/r/dc324d48c00cd7350f3a506eaa785324cae97372.1691977904.git.daniel@makrotopia.org -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/mediatek-ge-soc.c | 435 +++++++++++++++++++++++++++++- - 1 file changed, 426 insertions(+), 9 deletions(-) - ---- a/drivers/net/phy/mediatek-ge-soc.c -+++ b/drivers/net/phy/mediatek-ge-soc.c -@@ -1,11 +1,14 @@ - // SPDX-License-Identifier: GPL-2.0+ - #include -+#include -+#include - #include - #include - #include - #include - #include - #include -+#include - - #define MTK_GPHY_ID_MT7981 0x03a29461 - #define MTK_GPHY_ID_MT7988 0x03a29481 -@@ -208,9 +211,42 @@ - #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_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_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)) -@@ -238,13 +274,6 @@ enum { - PAIR_D, - }; - --enum { -- GPHY_PORT0, -- GPHY_PORT1, -- GPHY_PORT2, -- GPHY_PORT3, --}; -- - enum calibration_mode { - EFUSE_K, - SW_K -@@ -263,6 +292,19 @@ enum CAL_MODE { - SW_M - }; - -+#define MTK_PHY_LED_STATE_FORCE_ON 0 -+#define MTK_PHY_LED_STATE_FORCE_BLINK 1 -+#define MTK_PHY_LED_STATE_NETDEV 2 -+ -+struct mtk_socphy_priv { -+ unsigned long led_state; -+}; -+ -+struct mtk_socphy_shared { -+ u32 boottrap; -+ struct mtk_socphy_priv priv[4]; -+}; -+ - static int mtk_socphy_read_page(struct phy_device *phydev) - { - return __phy_read(phydev, MTK_EXT_PAGE_ACCESS); -@@ -1073,6 +1115,371 @@ 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; -+ -+ 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_LINK1000 | MTK_PHY_LED_ON_LINK100 | -+ MTK_PHY_LED_ON_LINK10)) || -+ (blink & (MTK_PHY_LED_BLINK_1000RX | MTK_PHY_LED_BLINK_100RX | -+ MTK_PHY_LED_BLINK_10RX | MTK_PHY_LED_BLINK_1000TX | -+ MTK_PHY_LED_BLINK_100TX | MTK_PHY_LED_BLINK_10TX))) -+ 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_LINK1000 | MTK_PHY_LED_ON_LINK100 | MTK_PHY_LED_ON_LINK10)) -+ *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_1000RX | MTK_PHY_LED_BLINK_100RX | MTK_PHY_LED_BLINK_10RX)) -+ *rules |= BIT(TRIGGER_NETDEV_RX); -+ -+ if (blink & (MTK_PHY_LED_BLINK_1000TX | MTK_PHY_LED_BLINK_100TX | MTK_PHY_LED_BLINK_10TX)) -+ *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 |= MTK_PHY_LED_BLINK_10RX | -+ MTK_PHY_LED_BLINK_100RX | -+ MTK_PHY_LED_BLINK_1000RX; -+ } -+ -+ if (rules & BIT(TRIGGER_NETDEV_TX)) { -+ blink |= MTK_PHY_LED_BLINK_10TX | -+ MTK_PHY_LED_BLINK_100TX | -+ MTK_PHY_LED_BLINK_1000TX; -+ } -+ -+ 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_LINK10 | -+ MTK_PHY_LED_ON_LINK100 | -+ MTK_PHY_LED_ON_LINK1000, -+ 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 practise 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; -+ -+ 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), -@@ -1080,11 +1487,16 @@ static struct phy_driver mtk_socphy_driv - .config_init = mt798x_phy_config_init, - .config_intr = genphy_no_config_intr, - .handle_interrupt = genphy_handle_interrupt_no_ack, -- .probe = mt798x_phy_calibration, -+ .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), -@@ -1092,11 +1504,16 @@ static struct phy_driver mtk_socphy_driv - .config_init = mt798x_phy_config_init, - .config_intr = genphy_no_config_intr, - .handle_interrupt = genphy_handle_interrupt_no_ack, -- .probe = mt798x_phy_calibration, -+ .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, - }, - }; - diff --git a/target/linux/mediatek/patches-6.1/732-net-phy-mxl-gpy-don-t-use-SGMII-AN-if-using-phylink.patch b/target/linux/mediatek/patches-6.1/732-net-phy-mxl-gpy-don-t-use-SGMII-AN-if-using-phylink.patch deleted file mode 100644 index d74572737..000000000 --- a/target/linux/mediatek/patches-6.1/732-net-phy-mxl-gpy-don-t-use-SGMII-AN-if-using-phylink.patch +++ /dev/null @@ -1,63 +0,0 @@ -From a969b663c866129ed9eb217785a6574fbe826f1d Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Thu, 6 Apr 2023 23:36:50 +0100 -Subject: [PATCH] net: phy: mxl-gpy: don't use SGMII AN if using phylink - -MAC drivers using phylink expect SGMII in-band-status to be switched off -when attached to a PHY. Make sure this is the case also for mxl-gpy which -keeps SGMII in-band-status in case of SGMII interface mode is used. - -Signed-off-by: Daniel Golle ---- - drivers/net/phy/mxl-gpy.c | 19 ++++++++++++++++--- - 1 file changed, 16 insertions(+), 3 deletions(-) - ---- a/drivers/net/phy/mxl-gpy.c -+++ b/drivers/net/phy/mxl-gpy.c -@@ -367,8 +367,11 @@ static bool gpy_2500basex_chk(struct phy - - phydev->speed = SPEED_2500; - phydev->interface = PHY_INTERFACE_MODE_2500BASEX; -- phy_modify_mmd(phydev, MDIO_MMD_VEND1, VSPEC1_SGMII_CTRL, -- VSPEC1_SGMII_CTRL_ANEN, 0); -+ -+ if (!phydev->phylink) -+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, VSPEC1_SGMII_CTRL, -+ VSPEC1_SGMII_CTRL_ANEN, 0); -+ - return true; - } - -@@ -392,6 +395,14 @@ static int gpy_config_aneg(struct phy_de - u32 adv; - int ret; - -+ /* Disable SGMII auto-negotiation if using phylink */ -+ if (phydev->phylink) { -+ ret = phy_modify_mmd(phydev, MDIO_MMD_VEND1, VSPEC1_SGMII_CTRL, -+ VSPEC1_SGMII_CTRL_ANEN, 0); -+ if (ret < 0) -+ return ret; -+ } -+ - if (phydev->autoneg == AUTONEG_DISABLE) { - /* Configure half duplex with genphy_setup_forced, - * because genphy_c45_pma_setup_forced does not support. -@@ -482,6 +493,8 @@ static void gpy_update_interface(struct - switch (phydev->speed) { - case SPEED_2500: - phydev->interface = PHY_INTERFACE_MODE_2500BASEX; -+ if (phydev->phylink) -+ break; - ret = phy_modify_mmd(phydev, MDIO_MMD_VEND1, VSPEC1_SGMII_CTRL, - VSPEC1_SGMII_CTRL_ANEN, 0); - if (ret < 0) -@@ -493,7 +506,7 @@ static void gpy_update_interface(struct - case SPEED_100: - case SPEED_10: - phydev->interface = PHY_INTERFACE_MODE_SGMII; -- if (gpy_sgmii_aneg_en(phydev)) -+ if (phydev->phylink || gpy_sgmii_aneg_en(phydev)) - break; - /* Enable and restart SGMII ANEG for 10/100/1000Mbps link speed - * if ANEG is disabled (in 2500-BaseX mode). diff --git a/target/linux/mediatek/patches-6.1/733-net-phy-add-driver-for-MediaTek-2.5G-PHY.patch b/target/linux/mediatek/patches-6.1/733-net-phy-add-driver-for-MediaTek-2.5G-PHY.patch deleted file mode 100644 index 125bd9b0b..000000000 --- a/target/linux/mediatek/patches-6.1/733-net-phy-add-driver-for-MediaTek-2.5G-PHY.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 128dc09b0af36772062142ce9e85b19c84ac789a Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Tue, 28 Feb 2023 17:53:37 +0000 -Subject: [PATCH] net: phy: add driver for MediaTek 2.5G PHY - -Signed-off-by: Daniel Golle ---- - drivers/net/phy/Kconfig | 7 ++ - drivers/net/phy/Makefile | 1 + - drivers/net/phy/mediatek-2p5ge.c | 220 +++++++++++++++++++++++++++++++ - 3 files changed, 226 insertions(+) - create mode 100644 drivers/net/phy/mediatek-2p5ge.c - ---- a/drivers/net/phy/Kconfig -+++ b/drivers/net/phy/Kconfig -@@ -326,6 +326,13 @@ config MEDIATEK_GE_SOC_PHY - present in the SoCs efuse and will dynamically calibrate VCM - (common-mode voltage) during startup. - -+config MEDIATEK_2P5G_PHY -+ tristate "MediaTek 2.5G Ethernet PHY" -+ depends on (ARCH_MEDIATEK && ARM64) || COMPILE_TEST -+ default NET_MEDIATEK_SOC -+ help -+ Supports the MediaTek 2.5G Ethernet PHY. -+ - config MICREL_PHY - tristate "Micrel PHYs" - depends on PTP_1588_CLOCK_OPTIONAL ---- a/drivers/net/phy/Makefile -+++ b/drivers/net/phy/Makefile -@@ -83,6 +83,7 @@ obj-$(CONFIG_MARVELL_10G_PHY) += marvell - obj-$(CONFIG_MARVELL_PHY) += marvell.o - obj-$(CONFIG_MARVELL_88X2222_PHY) += marvell-88x2222.o - obj-$(CONFIG_MAXLINEAR_GPHY) += mxl-gpy.o -+obj-$(CONFIG_MEDIATEK_2P5G_PHY) += mediatek-2p5ge.o - obj-$(CONFIG_MEDIATEK_GE_PHY) += mediatek-ge.o - obj-$(CONFIG_MEDIATEK_GE_SOC_PHY) += mediatek-ge-soc.o - obj-$(CONFIG_MESON_GXL_PHY) += meson-gxl.o diff --git a/target/linux/mediatek/patches-6.1/804-pwm-add-mt7986-support.patch b/target/linux/mediatek/patches-6.1/804-pwm-add-mt7986-support.patch deleted file mode 100644 index 0c73d520b..000000000 --- a/target/linux/mediatek/patches-6.1/804-pwm-add-mt7986-support.patch +++ /dev/null @@ -1,23 +0,0 @@ ---- a/drivers/pwm/pwm-mediatek.c -+++ b/drivers/pwm/pwm-mediatek.c -@@ -329,6 +329,12 @@ static const struct pwm_mediatek_of_data - .has_ck_26m_sel = true, - }; - -+static const struct pwm_mediatek_of_data mt7986_pwm_data = { -+ .num_pwms = 2, -+ .pwm45_fixup = false, -+ .has_ck_26m_sel = true, -+}; -+ - static const struct pwm_mediatek_of_data mt8516_pwm_data = { - .num_pwms = 5, - .pwm45_fixup = false, -@@ -342,6 +348,7 @@ static const struct of_device_id pwm_med - { .compatible = "mediatek,mt7623-pwm", .data = &mt7623_pwm_data }, - { .compatible = "mediatek,mt7628-pwm", .data = &mt7628_pwm_data }, - { .compatible = "mediatek,mt7629-pwm", .data = &mt7629_pwm_data }, -+ { .compatible = "mediatek,mt7986-pwm", .data = &mt7986_pwm_data }, - { .compatible = "mediatek,mt8183-pwm", .data = &mt8183_pwm_data }, - { .compatible = "mediatek,mt8365-pwm", .data = &mt8365_pwm_data }, - { .compatible = "mediatek,mt8516-pwm", .data = &mt8516_pwm_data }, diff --git a/target/linux/mediatek/patches-6.1/805-v6.2-thermal-drivers-mtk-use-function-pointer-for-raw_to_.patch b/target/linux/mediatek/patches-6.1/805-v6.2-thermal-drivers-mtk-use-function-pointer-for-raw_to_.patch deleted file mode 100644 index c58ae9640..000000000 --- a/target/linux/mediatek/patches-6.1/805-v6.2-thermal-drivers-mtk-use-function-pointer-for-raw_to_.patch +++ /dev/null @@ -1,56 +0,0 @@ -From 69c17529e8418da3eec703dde31e1b01e5b0f7e8 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Wed, 18 Jan 2023 02:48:41 +0000 -Subject: [PATCH 1/2] thermal/drivers/mtk: use function pointer for - raw_to_mcelsius - -Instead of having if-else logic selecting either raw_to_mcelsius_v1 or -raw_to_mcelsius_v2 in mtk_thermal_bank_temperature introduce a function -pointer raw_to_mcelsius to struct mtk_thermal which is initialized in the -probe function. - -Signed-off-by: Daniel Golle ---- - drivers/thermal/mtk_thermal.c | 17 ++++++++++------- - 1 file changed, 10 insertions(+), 7 deletions(-) - ---- a/drivers/thermal/mtk_thermal.c -+++ b/drivers/thermal/mtk_thermal.c -@@ -292,6 +292,8 @@ struct mtk_thermal { - - const struct mtk_thermal_data *conf; - struct mtk_thermal_bank banks[MAX_NUM_ZONES]; -+ -+ int (*raw_to_mcelsius)(struct mtk_thermal *mt, int sensno, s32 raw); - }; - - /* MT8183 thermal sensor data */ -@@ -656,13 +658,9 @@ static int mtk_thermal_bank_temperature( - for (i = 0; i < conf->bank_data[bank->id].num_sensors; i++) { - raw = readl(mt->thermal_base + conf->msr[i]); - -- if (mt->conf->version == MTK_THERMAL_V1) { -- temp = raw_to_mcelsius_v1( -- mt, conf->bank_data[bank->id].sensors[i], raw); -- } else { -- temp = raw_to_mcelsius_v2( -- mt, conf->bank_data[bank->id].sensors[i], raw); -- } -+ temp = mt->raw_to_mcelsius( -+ mt, conf->bank_data[bank->id].sensors[i], raw); -+ - - /* - * The first read of a sensor often contains very high bogus -@@ -1075,6 +1073,11 @@ static int mtk_thermal_probe(struct plat - mtk_thermal_release_periodic_ts(mt, auxadc_base); - } - -+ if (mt->conf->version == MTK_THERMAL_V1) -+ mt->raw_to_mcelsius = raw_to_mcelsius_v1; -+ else -+ mt->raw_to_mcelsius = raw_to_mcelsius_v2; -+ - for (ctrl_id = 0; ctrl_id < mt->conf->num_controller ; ctrl_id++) - for (i = 0; i < mt->conf->num_banks; i++) - mtk_thermal_init_bank(mt, i, apmixed_phys_base, diff --git a/target/linux/mediatek/patches-6.1/806-v6.2-thermal-mediatek-add-support-for-MT7986-and-MT7981.patch b/target/linux/mediatek/patches-6.1/806-v6.2-thermal-mediatek-add-support-for-MT7986-and-MT7981.patch deleted file mode 100644 index 65311d571..000000000 --- a/target/linux/mediatek/patches-6.1/806-v6.2-thermal-mediatek-add-support-for-MT7986-and-MT7981.patch +++ /dev/null @@ -1,240 +0,0 @@ -From aa957c759b1182aee00cc35178667f849f941b42 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Wed, 30 Nov 2022 13:19:39 +0000 -Subject: [PATCH 2/2] thermal: mediatek: add support for MT7986 and MT7981 - -Add support for V3 generation thermal found in MT7986 and MT7981 SoCs. -Brings code to assign values from efuse as well as new function to -convert raw temperature to millidegree celsius, as found in MediaTek's -SDK sources (but cleaned up and de-duplicated) - -[1]: https://git01.mediatek.com/plugins/gitiles/openwrt/feeds/mtk-openwrt-feeds/+/baf36c7eef477aae1f8f2653b6c29e2caf48475b -Signed-off-by: Daniel Golle ---- - drivers/thermal/mtk_thermal.c | 137 ++++++++++++++++++++++++++++++++-- - 1 file changed, 132 insertions(+), 5 deletions(-) - ---- a/drivers/thermal/mtk_thermal.c -+++ b/drivers/thermal/mtk_thermal.c -@@ -150,6 +150,20 @@ - #define CALIB_BUF1_VALID_V2(x) (((x) >> 4) & 0x1) - #define CALIB_BUF1_O_SLOPE_SIGN_V2(x) (((x) >> 3) & 0x1) - -+/* -+ * Layout of the fuses providing the calibration data -+ * These macros can be used for MT7981 and MT7986. -+ */ -+#define CALIB_BUF0_ADC_GE_V3(x) (((x) >> 0) & 0x3ff) -+#define CALIB_BUF0_DEGC_CALI_V3(x) (((x) >> 20) & 0x3f) -+#define CALIB_BUF0_O_SLOPE_V3(x) (((x) >> 26) & 0x3f) -+#define CALIB_BUF1_VTS_TS1_V3(x) (((x) >> 0) & 0x1ff) -+#define CALIB_BUF1_VTS_TS2_V3(x) (((x) >> 21) & 0x1ff) -+#define CALIB_BUF1_VTS_TSABB_V3(x) (((x) >> 9) & 0x1ff) -+#define CALIB_BUF1_VALID_V3(x) (((x) >> 18) & 0x1) -+#define CALIB_BUF1_O_SLOPE_SIGN_V3(x) (((x) >> 19) & 0x1) -+#define CALIB_BUF1_ID_V3(x) (((x) >> 20) & 0x1) -+ - enum { - VTS1, - VTS2, -@@ -163,6 +177,7 @@ enum { - enum mtk_thermal_version { - MTK_THERMAL_V1 = 1, - MTK_THERMAL_V2, -+ MTK_THERMAL_V3, - }; - - /* MT2701 thermal sensors */ -@@ -245,6 +260,27 @@ enum mtk_thermal_version { - /* The calibration coefficient of sensor */ - #define MT8183_CALIBRATION 153 - -+/* AUXADC channel 11 is used for the temperature sensors */ -+#define MT7986_TEMP_AUXADC_CHANNEL 11 -+ -+/* The total number of temperature sensors in the MT7986 */ -+#define MT7986_NUM_SENSORS 1 -+ -+/* The number of banks in the MT7986 */ -+#define MT7986_NUM_ZONES 1 -+ -+/* The number of sensing points per bank */ -+#define MT7986_NUM_SENSORS_PER_ZONE 1 -+ -+/* MT7986 thermal sensors */ -+#define MT7986_TS1 0 -+ -+/* The number of controller in the MT7986 */ -+#define MT7986_NUM_CONTROLLER 1 -+ -+/* The calibration coefficient of sensor */ -+#define MT7986_CALIBRATION 165 -+ - struct mtk_thermal; - - struct thermal_bank_cfg { -@@ -388,6 +424,14 @@ static const int mt7622_mux_values[MT762 - static const int mt7622_vts_index[MT7622_NUM_SENSORS] = { VTS1 }; - static const int mt7622_tc_offset[MT7622_NUM_CONTROLLER] = { 0x0, }; - -+/* MT7986 thermal sensor data */ -+static const int mt7986_bank_data[MT7986_NUM_SENSORS] = { MT7986_TS1, }; -+static const int mt7986_msr[MT7986_NUM_SENSORS_PER_ZONE] = { TEMP_MSR0, }; -+static const int mt7986_adcpnp[MT7986_NUM_SENSORS_PER_ZONE] = { TEMP_ADCPNP0, }; -+static const int mt7986_mux_values[MT7986_NUM_SENSORS] = { 0, }; -+static const int mt7986_vts_index[MT7986_NUM_SENSORS] = { VTS1 }; -+static const int mt7986_tc_offset[MT7986_NUM_CONTROLLER] = { 0x0, }; -+ - /* - * The MT8173 thermal controller has four banks. Each bank can read up to - * four temperature sensors simultaneously. The MT8173 has a total of 5 -@@ -551,6 +595,30 @@ static const struct mtk_thermal_data mt8 - .version = MTK_THERMAL_V1, - }; - -+/* -+ * MT7986 uses AUXADC Channel 11 for raw data access. -+ */ -+static const struct mtk_thermal_data mt7986_thermal_data = { -+ .auxadc_channel = MT7986_TEMP_AUXADC_CHANNEL, -+ .num_banks = MT7986_NUM_ZONES, -+ .num_sensors = MT7986_NUM_SENSORS, -+ .vts_index = mt7986_vts_index, -+ .cali_val = MT7986_CALIBRATION, -+ .num_controller = MT7986_NUM_CONTROLLER, -+ .controller_offset = mt7986_tc_offset, -+ .need_switch_bank = true, -+ .bank_data = { -+ { -+ .num_sensors = 1, -+ .sensors = mt7986_bank_data, -+ }, -+ }, -+ .msr = mt7986_msr, -+ .adcpnp = mt7986_adcpnp, -+ .sensor_mux_values = mt7986_mux_values, -+ .version = MTK_THERMAL_V3, -+}; -+ - /** - * raw_to_mcelsius - convert a raw ADC value to mcelsius - * @mt: The thermal controller -@@ -605,6 +673,22 @@ static int raw_to_mcelsius_v2(struct mtk - return (format_2 - tmp) * 100; - } - -+static int raw_to_mcelsius_v3(struct mtk_thermal *mt, int sensno, s32 raw) -+{ -+ s32 tmp; -+ -+ if (raw == 0) -+ return 0; -+ -+ raw &= 0xfff; -+ tmp = 100000 * 15 / 16 * 10000; -+ tmp /= 4096 - 512 + mt->adc_ge; -+ tmp /= 1490; -+ tmp *= raw - mt->vts[sensno] - 2900; -+ -+ return mt->degc_cali * 500 - tmp; -+} -+ - /** - * mtk_thermal_get_bank - get bank - * @bank: The bank -@@ -885,6 +969,25 @@ static int mtk_thermal_extract_efuse_v2( - return 0; - } - -+static int mtk_thermal_extract_efuse_v3(struct mtk_thermal *mt, u32 *buf) -+{ -+ if (!CALIB_BUF1_VALID_V3(buf[1])) -+ return -EINVAL; -+ -+ mt->adc_ge = CALIB_BUF0_ADC_GE_V3(buf[0]); -+ mt->degc_cali = CALIB_BUF0_DEGC_CALI_V3(buf[0]); -+ mt->o_slope = CALIB_BUF0_O_SLOPE_V3(buf[0]); -+ mt->vts[VTS1] = CALIB_BUF1_VTS_TS1_V3(buf[1]); -+ mt->vts[VTS2] = CALIB_BUF1_VTS_TS2_V3(buf[1]); -+ mt->vts[VTSABB] = CALIB_BUF1_VTS_TSABB_V3(buf[1]); -+ mt->o_slope_sign = CALIB_BUF1_O_SLOPE_SIGN_V3(buf[1]); -+ -+ if (CALIB_BUF1_ID_V3(buf[1]) == 0) -+ mt->o_slope = 0; -+ -+ return 0; -+} -+ - static int mtk_thermal_get_calibration_data(struct device *dev, - struct mtk_thermal *mt) - { -@@ -895,6 +998,7 @@ static int mtk_thermal_get_calibration_d - - /* Start with default values */ - mt->adc_ge = 512; -+ mt->adc_oe = 512; - for (i = 0; i < mt->conf->num_sensors; i++) - mt->vts[i] = 260; - mt->degc_cali = 40; -@@ -920,10 +1024,20 @@ static int mtk_thermal_get_calibration_d - goto out; - } - -- if (mt->conf->version == MTK_THERMAL_V1) -+ switch (mt->conf->version) { -+ case MTK_THERMAL_V1: - ret = mtk_thermal_extract_efuse_v1(mt, buf); -- else -+ break; -+ case MTK_THERMAL_V2: - ret = mtk_thermal_extract_efuse_v2(mt, buf); -+ break; -+ case MTK_THERMAL_V3: -+ ret = mtk_thermal_extract_efuse_v3(mt, buf); -+ break; -+ default: -+ ret = -EINVAL; -+ break; -+ } - - if (ret) { - dev_info(dev, "Device not calibrated, using default calibration values\n"); -@@ -954,6 +1068,10 @@ static const struct of_device_id mtk_the - .data = (void *)&mt7622_thermal_data, - }, - { -+ .compatible = "mediatek,mt7986-thermal", -+ .data = (void *)&mt7986_thermal_data, -+ }, -+ { - .compatible = "mediatek,mt8183-thermal", - .data = (void *)&mt8183_thermal_data, - }, { -@@ -1068,15 +1186,24 @@ static int mtk_thermal_probe(struct plat - goto err_disable_clk_auxadc; - } - -- if (mt->conf->version == MTK_THERMAL_V2) { -+ if (mt->conf->version != MTK_THERMAL_V1) { - mtk_thermal_turn_on_buffer(apmixed_base); - mtk_thermal_release_periodic_ts(mt, auxadc_base); - } - -- if (mt->conf->version == MTK_THERMAL_V1) -+ switch (mt->conf->version) { -+ case MTK_THERMAL_V1: - mt->raw_to_mcelsius = raw_to_mcelsius_v1; -- else -+ break; -+ case MTK_THERMAL_V2: - mt->raw_to_mcelsius = raw_to_mcelsius_v2; -+ break; -+ case MTK_THERMAL_V3: -+ mt->raw_to_mcelsius = raw_to_mcelsius_v3; -+ break; -+ default: -+ break; -+ } - - for (ctrl_id = 0; ctrl_id < mt->conf->num_controller ; ctrl_id++) - for (i = 0; i < mt->conf->num_banks; i++) diff --git a/target/linux/mediatek/patches-6.1/826-v6.2-pinctrl-mediatek-extend-pinctrl-moore-to-support-new.patch b/target/linux/mediatek/patches-6.1/826-v6.2-pinctrl-mediatek-extend-pinctrl-moore-to-support-new.patch deleted file mode 100644 index f130fdbc5..000000000 --- a/target/linux/mediatek/patches-6.1/826-v6.2-pinctrl-mediatek-extend-pinctrl-moore-to-support-new.patch +++ /dev/null @@ -1,129 +0,0 @@ -From fae82621ac33e2a4a96220c56e90d1ec6237d394 Mon Sep 17 00:00:00 2001 -From: Sam Shih -Date: Sun, 6 Nov 2022 09:01:12 +0100 -Subject: [PATCH] pinctrl: mediatek: extend pinctrl-moore to support new bias - functions - -Commit fb34a9ae383a ("pinctrl: mediatek: support rsel feature") -introduced SoC specify 'pull_type' attribute to mtk_pinconf_bias_set_combo -and mtk_pinconf_bias_get_combo, and make the functions able to support -almost all Mediatek SoCs that use pinctrl-mtk-common-v2.c. - -This patch enables pinctrl_moore to support these functions. - -Signed-off-by: Sam Shih -Signed-off-by: Frank Wunderlich -Reviewed-by: AngeloGioacchino Del Regno -Link: https://lore.kernel.org/r/20221106080114.7426-6-linux@fw-web.de -Signed-off-by: Linus Walleij ---- - drivers/pinctrl/mediatek/pinctrl-moore.c | 49 ++++++++++++++++++++---- - 1 file changed, 42 insertions(+), 7 deletions(-) - ---- a/drivers/pinctrl/mediatek/pinctrl-moore.c -+++ b/drivers/pinctrl/mediatek/pinctrl-moore.c -@@ -8,6 +8,7 @@ - * - */ - -+#include - #include - #include "pinctrl-moore.h" - -@@ -105,7 +106,7 @@ static int mtk_pinconf_get(struct pinctr - { - struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev); - u32 param = pinconf_to_config_param(*config); -- int val, val2, err, reg, ret = 1; -+ int val, val2, err, pullup, reg, ret = 1; - const struct mtk_pin_desc *desc; - - desc = (const struct mtk_pin_desc *)&hw->soc->pins[pin]; -@@ -114,7 +115,13 @@ static int mtk_pinconf_get(struct pinctr - - switch (param) { - case PIN_CONFIG_BIAS_DISABLE: -- if (hw->soc->bias_disable_get) { -+ if (hw->soc->bias_get_combo) { -+ err = hw->soc->bias_get_combo(hw, desc, &pullup, &ret); -+ if (err) -+ return err; -+ if (ret != MTK_PUPD_SET_R1R0_00 && ret != MTK_DISABLE) -+ return -EINVAL; -+ } else if (hw->soc->bias_disable_get) { - err = hw->soc->bias_disable_get(hw, desc, &ret); - if (err) - return err; -@@ -123,7 +130,15 @@ static int mtk_pinconf_get(struct pinctr - } - break; - case PIN_CONFIG_BIAS_PULL_UP: -- if (hw->soc->bias_get) { -+ if (hw->soc->bias_get_combo) { -+ err = hw->soc->bias_get_combo(hw, desc, &pullup, &ret); -+ if (err) -+ return err; -+ if (ret == MTK_PUPD_SET_R1R0_00 || ret == MTK_DISABLE) -+ return -EINVAL; -+ if (!pullup) -+ return -EINVAL; -+ } else if (hw->soc->bias_get) { - err = hw->soc->bias_get(hw, desc, 1, &ret); - if (err) - return err; -@@ -132,7 +147,15 @@ static int mtk_pinconf_get(struct pinctr - } - break; - case PIN_CONFIG_BIAS_PULL_DOWN: -- if (hw->soc->bias_get) { -+ if (hw->soc->bias_get_combo) { -+ err = hw->soc->bias_get_combo(hw, desc, &pullup, &ret); -+ if (err) -+ return err; -+ if (ret == MTK_PUPD_SET_R1R0_00 || ret == MTK_DISABLE) -+ return -EINVAL; -+ if (pullup) -+ return -EINVAL; -+ } else if (hw->soc->bias_get) { - err = hw->soc->bias_get(hw, desc, 0, &ret); - if (err) - return err; -@@ -235,7 +258,11 @@ static int mtk_pinconf_set(struct pinctr - - switch (param) { - case PIN_CONFIG_BIAS_DISABLE: -- if (hw->soc->bias_disable_set) { -+ if (hw->soc->bias_set_combo) { -+ err = hw->soc->bias_set_combo(hw, desc, 0, MTK_DISABLE); -+ if (err) -+ return err; -+ } else if (hw->soc->bias_disable_set) { - err = hw->soc->bias_disable_set(hw, desc); - if (err) - return err; -@@ -244,7 +271,11 @@ static int mtk_pinconf_set(struct pinctr - } - break; - case PIN_CONFIG_BIAS_PULL_UP: -- if (hw->soc->bias_set) { -+ if (hw->soc->bias_set_combo) { -+ err = hw->soc->bias_set_combo(hw, desc, 1, arg); -+ if (err) -+ return err; -+ } else if (hw->soc->bias_set) { - err = hw->soc->bias_set(hw, desc, 1); - if (err) - return err; -@@ -253,7 +284,11 @@ static int mtk_pinconf_set(struct pinctr - } - break; - case PIN_CONFIG_BIAS_PULL_DOWN: -- if (hw->soc->bias_set) { -+ if (hw->soc->bias_set_combo) { -+ err = hw->soc->bias_set_combo(hw, desc, 0, arg); -+ if (err) -+ return err; -+ } else if (hw->soc->bias_set) { - err = hw->soc->bias_set(hw, desc, 0); - if (err) - return err; diff --git a/target/linux/mediatek/patches-6.1/851-v6.2-i2c-mediatek-add-mt7986-support.patch b/target/linux/mediatek/patches-6.1/851-v6.2-i2c-mediatek-add-mt7986-support.patch deleted file mode 100644 index 4c398c59f..000000000 --- a/target/linux/mediatek/patches-6.1/851-v6.2-i2c-mediatek-add-mt7986-support.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 11f9a0f4e51887ad7b4a2898a368fcd0c2984e89 Mon Sep 17 00:00:00 2001 -From: Frank Wunderlich -Date: Sun, 9 Oct 2022 12:16:31 +0200 -Subject: [PATCH 12/16] i2c: mediatek: add mt7986 support - -Add i2c support for MT7986 SoC. - -Signed-off-by: Frank Wunderlich -Reviewed-by: AngeloGioacchino Del Regno -Signed-off-by: Wolfram Sang ---- - drivers/i2c/busses/i2c-mt65xx.c | 14 ++++++++++++++ - 1 file changed, 14 insertions(+) - ---- a/drivers/i2c/busses/i2c-mt65xx.c -+++ b/drivers/i2c/busses/i2c-mt65xx.c -@@ -431,6 +431,19 @@ static const struct mtk_i2c_compatible m - .max_dma_support = 33, - }; - -+static const struct mtk_i2c_compatible mt7986_compat = { -+ .quirks = &mt7622_i2c_quirks, -+ .regs = mt_i2c_regs_v1, -+ .pmic_i2c = 0, -+ .dcm = 1, -+ .auto_restart = 1, -+ .aux_len_reg = 1, -+ .timing_adjust = 0, -+ .dma_sync = 1, -+ .ltiming_adjust = 0, -+ .max_dma_support = 32, -+}; -+ - static const struct mtk_i2c_compatible mt8173_compat = { - .regs = mt_i2c_regs_v1, - .pmic_i2c = 0, -@@ -503,6 +516,7 @@ static const struct of_device_id mtk_i2c - { .compatible = "mediatek,mt6577-i2c", .data = &mt6577_compat }, - { .compatible = "mediatek,mt6589-i2c", .data = &mt6589_compat }, - { .compatible = "mediatek,mt7622-i2c", .data = &mt7622_compat }, -+ { .compatible = "mediatek,mt7986-i2c", .data = &mt7986_compat }, - { .compatible = "mediatek,mt8168-i2c", .data = &mt8168_compat }, - { .compatible = "mediatek,mt8173-i2c", .data = &mt8173_compat }, - { .compatible = "mediatek,mt8183-i2c", .data = &mt8183_compat }, diff --git a/target/linux/mediatek/patches-6.1/852-v6.3-i2c-mt65xx-Use-devm_platform_get_and_ioremap_resourc.patch b/target/linux/mediatek/patches-6.1/852-v6.3-i2c-mt65xx-Use-devm_platform_get_and_ioremap_resourc.patch deleted file mode 100644 index 18c66cdac..000000000 --- a/target/linux/mediatek/patches-6.1/852-v6.3-i2c-mt65xx-Use-devm_platform_get_and_ioremap_resourc.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 98204ccafd45a8a6109ff2d60e2c179b95d92578 Mon Sep 17 00:00:00 2001 -From: ye xingchen -Date: Thu, 19 Jan 2023 17:19:58 +0800 -Subject: [PATCH 13/16] i2c: mt65xx: Use - devm_platform_get_and_ioremap_resource() - -Convert platform_get_resource(), devm_ioremap_resource() to a single -call to devm_platform_get_and_ioremap_resource(), as this is exactly -what this function does. - -Signed-off-by: ye xingchen -Reviewed-by: AngeloGioacchino Del Regno -Signed-off-by: Wolfram Sang ---- - drivers/i2c/busses/i2c-mt65xx.c | 7 ++----- - 1 file changed, 2 insertions(+), 5 deletions(-) - ---- a/drivers/i2c/busses/i2c-mt65xx.c -+++ b/drivers/i2c/busses/i2c-mt65xx.c -@@ -1366,20 +1366,17 @@ static int mtk_i2c_probe(struct platform - { - int ret = 0; - struct mtk_i2c *i2c; -- struct resource *res; - int i, irq, speed_clk; - - i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL); - if (!i2c) - return -ENOMEM; - -- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -- i2c->base = devm_ioremap_resource(&pdev->dev, res); -+ i2c->base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL); - if (IS_ERR(i2c->base)) - return PTR_ERR(i2c->base); - -- res = platform_get_resource(pdev, IORESOURCE_MEM, 1); -- i2c->pdmabase = devm_ioremap_resource(&pdev->dev, res); -+ i2c->pdmabase = devm_platform_get_and_ioremap_resource(pdev, 1, NULL); - if (IS_ERR(i2c->pdmabase)) - return PTR_ERR(i2c->pdmabase); - diff --git a/target/linux/mediatek/patches-6.1/853-v6.3-i2c-mt65xx-drop-of_match_ptr-for-ID-table.patch b/target/linux/mediatek/patches-6.1/853-v6.3-i2c-mt65xx-drop-of_match_ptr-for-ID-table.patch deleted file mode 100644 index d000d5352..000000000 --- a/target/linux/mediatek/patches-6.1/853-v6.3-i2c-mt65xx-drop-of_match_ptr-for-ID-table.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 8106fa2e0ae6082833fe1df97829c46c0183eaea Mon Sep 17 00:00:00 2001 -From: Krzysztof Kozlowski -Date: Sat, 11 Mar 2023 12:16:54 +0100 -Subject: [PATCH 14/16] i2c: mt65xx: drop of_match_ptr for ID table -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The driver can match only via the DT table so the table should be always -used and the of_match_ptr does not have any sense (this also allows ACPI -matching via PRP0001, even though it might not be relevant here). - - drivers/i2c/busses/i2c-mt65xx.c:514:34: error: ‘mtk_i2c_of_match’ defined but not used [-Werror=unused-const-variable=] - -Signed-off-by: Krzysztof Kozlowski -Reviewed-by: Guenter Roeck -Reviewed-by: AngeloGioacchino Del Regno -Signed-off-by: Wolfram Sang ---- - drivers/i2c/busses/i2c-mt65xx.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/i2c/busses/i2c-mt65xx.c -+++ b/drivers/i2c/busses/i2c-mt65xx.c -@@ -1546,7 +1546,7 @@ static struct platform_driver mtk_i2c_dr - .driver = { - .name = I2C_DRV_NAME, - .pm = &mtk_i2c_pm, -- .of_match_table = of_match_ptr(mtk_i2c_of_match), -+ .of_match_table = mtk_i2c_of_match, - }, - }; - diff --git a/target/linux/mediatek/patches-6.1/854-v6.4-i2c-mediatek-add-support-for-MT7981-SoC.patch b/target/linux/mediatek/patches-6.1/854-v6.4-i2c-mediatek-add-support-for-MT7981-SoC.patch deleted file mode 100644 index e0973741e..000000000 --- a/target/linux/mediatek/patches-6.1/854-v6.4-i2c-mediatek-add-support-for-MT7981-SoC.patch +++ /dev/null @@ -1,47 +0,0 @@ -From f69f3d662ba3bf999c36d9ac1e684540c4487bc3 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Mon, 10 Apr 2023 17:19:38 +0100 -Subject: [PATCH 15/16] i2c: mediatek: add support for MT7981 SoC - -Add support for the I2C units found in the MediaTek MT7981 and MT7988 -SoCs. Just like other recent MediaTek I2C units that also uses v3 -register offsets (which differ from v2 only by OFFSET_SLAVE_ADDR being -0x94 instead of 0x4). - -Signed-off-by: Daniel Golle -Reviewed-by: AngeloGioacchino Del Regno -Reviewed-by: Alexandre Mergnat -Signed-off-by: Wolfram Sang ---- - drivers/i2c/busses/i2c-mt65xx.c | 13 +++++++++++++ - 1 file changed, 13 insertions(+) - ---- a/drivers/i2c/busses/i2c-mt65xx.c -+++ b/drivers/i2c/busses/i2c-mt65xx.c -@@ -431,6 +431,18 @@ static const struct mtk_i2c_compatible m - .max_dma_support = 33, - }; - -+static const struct mtk_i2c_compatible mt7981_compat = { -+ .regs = mt_i2c_regs_v3, -+ .pmic_i2c = 0, -+ .dcm = 0, -+ .auto_restart = 1, -+ .aux_len_reg = 1, -+ .timing_adjust = 1, -+ .dma_sync = 1, -+ .ltiming_adjust = 1, -+ .max_dma_support = 33 -+}; -+ - static const struct mtk_i2c_compatible mt7986_compat = { - .quirks = &mt7622_i2c_quirks, - .regs = mt_i2c_regs_v1, -@@ -516,6 +528,7 @@ static const struct of_device_id mtk_i2c - { .compatible = "mediatek,mt6577-i2c", .data = &mt6577_compat }, - { .compatible = "mediatek,mt6589-i2c", .data = &mt6589_compat }, - { .compatible = "mediatek,mt7622-i2c", .data = &mt7622_compat }, -+ { .compatible = "mediatek,mt7981-i2c", .data = &mt7981_compat }, - { .compatible = "mediatek,mt7986-i2c", .data = &mt7986_compat }, - { .compatible = "mediatek,mt8168-i2c", .data = &mt8168_compat }, - { .compatible = "mediatek,mt8173-i2c", .data = &mt8173_compat }, diff --git a/target/linux/mediatek/patches-6.1/900-dts-mt7622-bpi-r64-aliases-for-dtoverlay.patch b/target/linux/mediatek/patches-6.1/900-dts-mt7622-bpi-r64-aliases-for-dtoverlay.patch deleted file mode 100644 index 2ee9c6299..000000000 --- a/target/linux/mediatek/patches-6.1/900-dts-mt7622-bpi-r64-aliases-for-dtoverlay.patch +++ /dev/null @@ -1,65 +0,0 @@ ---- a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts -@@ -315,7 +315,7 @@ - /* Attention: GPIO 90 is used to switch between PCIe@1,0 and - * SATA functions. i.e. output-high: PCIe, output-low: SATA - */ -- asm_sel { -+ asmsel: asm_sel { - gpio-hog; - gpios = <90 GPIO_ACTIVE_HIGH>; - output-high; ---- /dev/null -+++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64-sata.dtso -@@ -0,0 +1,31 @@ -+/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */ -+ -+#include -+ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "bananapi,bpi-r64", "mediatek,mt7622"; -+ -+ fragment@0 { -+ target = <&asmsel>; -+ __overlay__ { -+ gpios = <90 GPIO_ACTIVE_LOW>; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&sata>; -+ __overlay__ { -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@2 { -+ target = <&sata_phy>; -+ __overlay__ { -+ status = "okay"; -+ }; -+ }; -+}; ---- /dev/null -+++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64-pcie1.dtso -@@ -0,0 +1,17 @@ -+/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */ -+ -+#include -+ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "bananapi,bpi-r64", "mediatek,mt7622"; -+ -+ fragment@0 { -+ target = <&asmsel>; -+ __overlay__ { -+ gpios = <90 GPIO_ACTIVE_HIGH>; -+ }; -+ }; -+}; diff --git a/target/linux/mediatek/patches-6.1/901-arm-add-cmdline-override.patch b/target/linux/mediatek/patches-6.1/901-arm-add-cmdline-override.patch deleted file mode 100644 index f8857bdf7..000000000 --- a/target/linux/mediatek/patches-6.1/901-arm-add-cmdline-override.patch +++ /dev/null @@ -1,54 +0,0 @@ ---- a/arch/arm/Kconfig -+++ b/arch/arm/Kconfig -@@ -1589,6 +1589,14 @@ config ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEN - - endchoice - -+config CMDLINE_OVERRIDE -+ bool "Use alternative cmdline from device tree" -+ help -+ Some bootloaders may have uneditable bootargs. While CMDLINE_FORCE can -+ be used, this is not a good option for kernels that are shared across -+ devices. This setting enables using "chosen/cmdline-override" as the -+ cmdline if it exists in the device tree. -+ - config CMDLINE - string "Default kernel command string" - default "" ---- a/drivers/of/fdt.c -+++ b/drivers/of/fdt.c -@@ -1187,6 +1187,17 @@ int __init early_init_dt_scan_chosen(cha - if (p != NULL && l > 0) - strlcat(cmdline, p, min_t(int, strlen(cmdline) + (int)l, COMMAND_LINE_SIZE)); - -+ /* CONFIG_CMDLINE_OVERRIDE is used to fallback to a different -+ * device tree option of chosen/bootargs-override. This is -+ * helpful on boards where u-boot sets bootargs, and is unable -+ * to be modified. -+ */ -+#ifdef CONFIG_CMDLINE_OVERRIDE -+ p = of_get_flat_dt_prop(node, "bootargs-override", &l); -+ if (p != NULL && l > 0) -+ strlcpy(cmdline, p, min((int)l, COMMAND_LINE_SIZE)); -+#endif -+ - handle_cmdline: - /* - * CONFIG_CMDLINE is meant to be a default in case nothing else ---- a/arch/arm64/Kconfig -+++ b/arch/arm64/Kconfig -@@ -2239,6 +2239,14 @@ config CMDLINE_FORCE - - endchoice - -+config CMDLINE_OVERRIDE -+ bool "Use alternative cmdline from device tree" -+ help -+ Some bootloaders may have uneditable bootargs. While CMDLINE_FORCE can -+ be used, this is not a good option for kernels that are shared across -+ devices. This setting enables using "chosen/cmdline-override" as the -+ cmdline if it exists in the device tree. -+ - config EFI_STUB - bool - diff --git a/target/linux/mediatek/patches-6.1/910-dts-mt7622-bpi-r64-wifi-eeprom.patch b/target/linux/mediatek/patches-6.1/910-dts-mt7622-bpi-r64-wifi-eeprom.patch deleted file mode 100644 index 0c7e64a5e..000000000 --- a/target/linux/mediatek/patches-6.1/910-dts-mt7622-bpi-r64-wifi-eeprom.patch +++ /dev/null @@ -1,31 +0,0 @@ ---- a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts -+++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts -@@ -642,5 +642,28 @@ - }; - - &wmac { -+ mediatek,eeprom-data = <0x22760500 0x0 0x0 0x0 -+ 0x0 0x0 0x0 0x0 -+ 0x0 0x0 0x0 0x0 -+ 0x0 0x44000020 0x0 0x10002000 -+ 0x4400 0x4000000 0x0 0x0 -+ 0x200000b3 0x40b6c3c3 0x26000000 0x41c42600 -+ 0x41c4 0x26000000 0xc0c52600 0x0 -+ 0x0 0x0 0x0 0x0 -+ 0x0 0x0 0x0 0x0 -+ 0x0 0x0 0x0 0x0 -+ 0x0 0x0 0x0 0x0 -+ 0x0 0x0 0x0 0xc6c6 -+ 0xc3c3c2c1 0xc300c3 0x818181 0x83c1c182 -+ 0x83838382 0x0 0x0 0x0 -+ 0x0 0x0 0x0 0x0 -+ 0x84002e00 0x90000087 0x8a000000 0x0 -+ 0x0 0x0 0x0 0x0 -+ 0x0 0x0 0x0 0x0 -+ 0xb000009 0x0 0x0 0x0 -+ 0x0 0x0 0x0 0x0 -+ 0x0 0x0 0x0 0x0 -+ 0x0 0x0 0x0 0x7707>; -+ - status = "okay"; - }; diff --git a/target/linux/mediatek/patches-6.1/930-spi-mt65xx-enable-sel-clk.patch b/target/linux/mediatek/patches-6.1/930-spi-mt65xx-enable-sel-clk.patch deleted file mode 100644 index 3d05bf767..000000000 --- a/target/linux/mediatek/patches-6.1/930-spi-mt65xx-enable-sel-clk.patch +++ /dev/null @@ -1,18 +0,0 @@ ---- a/drivers/spi/spi-mt65xx.c -+++ b/drivers/spi/spi-mt65xx.c -@@ -1227,8 +1227,15 @@ static int mtk_spi_probe(struct platform - if (ret < 0) - return dev_err_probe(dev, ret, "failed to enable hclk\n"); - -+ ret = clk_prepare_enable(mdata->sel_clk); -+ if (ret < 0) { -+ clk_disable_unprepare(mdata->spi_hclk); -+ return dev_err_probe(dev, ret, "failed to enable sel_clk\n"); -+ } -+ - ret = clk_prepare_enable(mdata->spi_clk); - if (ret < 0) { -+ clk_disable_unprepare(mdata->sel_clk); - clk_disable_unprepare(mdata->spi_hclk); - return dev_err_probe(dev, ret, "failed to enable spi_clk\n"); - } diff --git a/target/linux/mediatek/patches-6.1/940-net-ethernet-mtk_wed-rename-mtk_wed_get_memory_regio.patch b/target/linux/mediatek/patches-6.1/940-net-ethernet-mtk_wed-rename-mtk_wed_get_memory_regio.patch deleted file mode 100644 index 2fe565f3b..000000000 --- a/target/linux/mediatek/patches-6.1/940-net-ethernet-mtk_wed-rename-mtk_wed_get_memory_regio.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 3cf212c4ce6cd72c09bc47f35f539ba0afd4d106 Mon Sep 17 00:00:00 2001 -Message-Id: <3cf212c4ce6cd72c09bc47f35f539ba0afd4d106.1678716918.git.lorenzo@kernel.org> -From: Lorenzo Bianconi -Date: Sun, 12 Mar 2023 16:40:31 +0100 -Subject: [PATCH net-next 1/2] net: ethernet: mtk_wed: rename - mtk_wed_get_memory_region in mtk_wed_get_reserved_memory_region - -This is a preliminary patch to move wed ilm/dlm and cpuboot properties in -dedicated dts nodes. - -Signed-off-by: Lorenzo Bianconi ---- - drivers/net/ethernet/mediatek/mtk_wed_mcu.c | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_wed_mcu.c -+++ b/drivers/net/ethernet/mediatek/mtk_wed_mcu.c -@@ -215,8 +215,8 @@ int mtk_wed_mcu_msg_update(struct mtk_we - } - - static int --mtk_wed_get_memory_region(struct mtk_wed_wo *wo, -- struct mtk_wed_wo_memory_region *region) -+mtk_wed_get_reserved_memory_region(struct mtk_wed_wo *wo, -+ struct mtk_wed_wo_memory_region *region) - { - struct reserved_mem *rmem; - struct device_node *np; -@@ -311,13 +311,13 @@ mtk_wed_mcu_load_firmware(struct mtk_wed - - /* load firmware region metadata */ - for (i = 0; i < ARRAY_SIZE(mem_region); i++) { -- ret = mtk_wed_get_memory_region(wo, &mem_region[i]); -+ ret = mtk_wed_get_reserved_memory_region(wo, &mem_region[i]); - if (ret) - return ret; - } - - wo->boot.name = "wo-boot"; -- ret = mtk_wed_get_memory_region(wo, &wo->boot); -+ ret = mtk_wed_get_reserved_memory_region(wo, &wo->boot); - if (ret) - return ret; - diff --git a/target/linux/mediatek/patches-6.1/941-arm64-dts-mt7986-move-cpuboot-in-a-dedicated-node.patch b/target/linux/mediatek/patches-6.1/941-arm64-dts-mt7986-move-cpuboot-in-a-dedicated-node.patch deleted file mode 100644 index 7b791b88d..000000000 --- a/target/linux/mediatek/patches-6.1/941-arm64-dts-mt7986-move-cpuboot-in-a-dedicated-node.patch +++ /dev/null @@ -1,66 +0,0 @@ -From 247e566e3459481f1fa98733534bfed767e18b42 Mon Sep 17 00:00:00 2001 -Message-Id: <247e566e3459481f1fa98733534bfed767e18b42.1678620342.git.lorenzo@kernel.org> -From: Lorenzo Bianconi -Date: Sat, 11 Mar 2023 16:32:41 +0100 -Subject: [PATCH net-next] arm64: dts: mt7986: move cpuboot in a dedicated node - -Signed-off-by: Lorenzo Bianconi ---- - arch/arm64/boot/dts/mediatek/mt7986a.dtsi | 21 +++++++++++---------- - 1 file changed, 11 insertions(+), 10 deletions(-) - ---- a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi -+++ b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi -@@ -121,12 +121,6 @@ - reg = <0 0x151f8000 0 0x2000>; - no-map; - }; -- -- wo_boot: wo-boot@15194000 { -- reg = <0 0x15194000 0 0x1000>; -- no-map; -- }; -- - }; - - timer { -@@ -519,10 +513,11 @@ - interrupt-parent = <&gic>; - interrupts = ; - memory-region = <&wo_emi0>, <&wo_ilm0>, <&wo_dlm0>, -- <&wo_data>, <&wo_boot>; -+ <&wo_data>; - memory-region-names = "wo-emi", "wo-ilm", "wo-dlm", -- "wo-data", "wo-boot"; -+ "wo-data"; - mediatek,wo-ccif = <&wo_ccif0>; -+ mediatek,wo-cpuboot = <&wo_cpuboot>; - }; - - wed1: wed@15011000 { -@@ -532,10 +527,11 @@ - interrupt-parent = <&gic>; - interrupts = ; - memory-region = <&wo_emi1>, <&wo_ilm1>, <&wo_dlm1>, -- <&wo_data>, <&wo_boot>; -+ <&wo_data>; - memory-region-names = "wo-emi", "wo-ilm", "wo-dlm", -- "wo-data", "wo-boot"; -+ "wo-data"; - mediatek,wo-ccif = <&wo_ccif1>; -+ mediatek,wo-cpuboot = <&wo_cpuboot>; - }; - - wo_ccif0: syscon@151a5000 { -@@ -552,6 +548,11 @@ - interrupts = ; - }; - -+ wo_cpuboot: syscon@15194000 { -+ compatible = "mediatek,mt7986-wo-cpuboot", "syscon"; -+ reg = <0 0x15194000 0 0x1000>; -+ }; -+ - eth: ethernet@15100000 { - compatible = "mediatek,mt7986-eth"; - reg = <0 0x15100000 0 0x80000>; diff --git a/target/linux/mediatek/patches-6.1/942-net-ethernet-mtk_wed-move-cpuboot-in-a-dedicated-dts.patch b/target/linux/mediatek/patches-6.1/942-net-ethernet-mtk_wed-move-cpuboot-in-a-dedicated-dts.patch deleted file mode 100644 index 9de4ffa43..000000000 --- a/target/linux/mediatek/patches-6.1/942-net-ethernet-mtk_wed-move-cpuboot-in-a-dedicated-dts.patch +++ /dev/null @@ -1,89 +0,0 @@ -From f292d1bf83ec160bef2532b58aa08f5b71041923 Mon Sep 17 00:00:00 2001 -Message-Id: -In-Reply-To: <3cf212c4ce6cd72c09bc47f35f539ba0afd4d106.1678716918.git.lorenzo@kernel.org> -References: <3cf212c4ce6cd72c09bc47f35f539ba0afd4d106.1678716918.git.lorenzo@kernel.org> -From: Lorenzo Bianconi -Date: Sat, 11 Mar 2023 18:13:04 +0100 -Subject: [PATCH net-next 2/2] net: ethernet: mtk_wed: move cpuboot in a - dedicated dts node - -Since the cpuboot memory region is not part of the RAM SoC, move cpuboot -in a deidicated syscon node. -This patch helps to keep backward-compatibility with older version of -uboot codebase where we have a limit of 8 reserved-memory dts child -nodes. -Keep backward-compatibility with older dts version where cpuboot was -defined as reserved-memory child node. - -Signed-off-by: Lorenzo Bianconi ---- - drivers/net/ethernet/mediatek/mtk_wed_mcu.c | 34 +++++++++++++++++---- - drivers/net/ethernet/mediatek/mtk_wed_wo.h | 3 +- - 2 files changed, 30 insertions(+), 7 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_wed_mcu.c -+++ b/drivers/net/ethernet/mediatek/mtk_wed_mcu.c -@@ -18,12 +18,23 @@ - - static u32 wo_r32(struct mtk_wed_wo *wo, u32 reg) - { -- return readl(wo->boot.addr + reg); -+ u32 val; -+ -+ if (!wo->boot_regmap) -+ return readl(wo->boot.addr + reg); -+ -+ if (regmap_read(wo->boot_regmap, reg, &val)) -+ val = ~0; -+ -+ return val; - } - - static void wo_w32(struct mtk_wed_wo *wo, u32 reg, u32 val) - { -- writel(val, wo->boot.addr + reg); -+ if (wo->boot_regmap) -+ regmap_write(wo->boot_regmap, reg, val); -+ else -+ writel(val, wo->boot.addr + reg); - } - - static struct sk_buff * -@@ -316,10 +327,21 @@ mtk_wed_mcu_load_firmware(struct mtk_wed - return ret; - } - -- wo->boot.name = "wo-boot"; -- ret = mtk_wed_get_reserved_memory_region(wo, &wo->boot); -- if (ret) -- return ret; -+ wo->boot_regmap = syscon_regmap_lookup_by_phandle(wo->hw->node, -+ "mediatek,wo-cpuboot"); -+ if (IS_ERR(wo->boot_regmap)) { -+ if (wo->boot_regmap != ERR_PTR(-ENODEV)) -+ return PTR_ERR(wo->boot_regmap); -+ -+ /* For backward compatibility, we need to check if cpu_boot -+ * is defined through reserved memory property. -+ */ -+ wo->boot_regmap = NULL; -+ wo->boot.name = "wo-boot"; -+ ret = mtk_wed_get_reserved_memory_region(wo, &wo->boot); -+ if (ret) -+ return ret; -+ } - - /* set dummy cr */ - wed_w32(wo->hw->wed_dev, MTK_WED_SCR0 + 4 * MTK_WED_DUMMY_CR_FWDL, ---- a/drivers/net/ethernet/mediatek/mtk_wed_wo.h -+++ b/drivers/net/ethernet/mediatek/mtk_wed_wo.h -@@ -228,7 +228,8 @@ struct mtk_wed_wo_queue { - - struct mtk_wed_wo { - struct mtk_wed_hw *hw; -- struct mtk_wed_wo_memory_region boot; -+ struct mtk_wed_wo_memory_region boot; /* backward compatibility */ -+ struct regmap *boot_regmap; - - struct mtk_wed_wo_queue q_tx; - struct mtk_wed_wo_queue q_rx; diff --git a/target/linux/mediatek/patches-6.1/943-net-ethernet-mtk_wed-move-ilm-a-dedicated-dts-node.patch b/target/linux/mediatek/patches-6.1/943-net-ethernet-mtk_wed-move-ilm-a-dedicated-dts-node.patch deleted file mode 100644 index 7b6c5d1e2..000000000 --- a/target/linux/mediatek/patches-6.1/943-net-ethernet-mtk_wed-move-ilm-a-dedicated-dts-node.patch +++ /dev/null @@ -1,91 +0,0 @@ -From f3565e6c2276411275e707a5442d3f69cc111273 Mon Sep 17 00:00:00 2001 -Message-Id: -From: Lorenzo Bianconi -Date: Sun, 12 Mar 2023 18:51:47 +0100 -Subject: [PATCH net-next 1/3] net: ethernet: mtk_wed: move ilm a dedicated dts - node - -Since the ilm memory region is not part of the RAM SoC, move ilm in a -deidicated syscon node. -This patch helps to keep backward-compatibility with older version of -uboot codebase where we have a limit of 8 reserved-memory dts child -nodes. -Keep backward-compatibility with older dts version where ilm was defined -as reserved-memory child node. - -Signed-off-by: Lorenzo Bianconi ---- - drivers/net/ethernet/mediatek/mtk_wed_mcu.c | 55 ++++++++++++++++++--- - 1 file changed, 49 insertions(+), 6 deletions(-) - ---- a/drivers/net/ethernet/mediatek/mtk_wed_mcu.c -+++ b/drivers/net/ethernet/mediatek/mtk_wed_mcu.c -@@ -300,6 +300,52 @@ next: - } - - static int -+mtk_wed_mcu_load_memory_regions(struct mtk_wed_wo *wo, -+ struct mtk_wed_wo_memory_region *region) -+{ -+ struct device_node *np; -+ int ret; -+ -+ /* firmware EMI memory region */ -+ ret = mtk_wed_get_reserved_memory_region(wo, -+ ®ion[MTK_WED_WO_REGION_EMI]); -+ if (ret) -+ return ret; -+ -+ /* firmware DATA memory region */ -+ ret = mtk_wed_get_reserved_memory_region(wo, -+ ®ion[MTK_WED_WO_REGION_DATA]); -+ if (ret) -+ return ret; -+ -+ np = of_parse_phandle(wo->hw->node, "mediatek,wo-ilm", 0); -+ if (np) { -+ struct mtk_wed_wo_memory_region *ilm_region; -+ struct resource res; -+ -+ ret = of_address_to_resource(np, 0, &res); -+ of_node_put(np); -+ -+ if (ret < 0) -+ return ret; -+ -+ ilm_region = ®ion[MTK_WED_WO_REGION_ILM]; -+ ilm_region->phy_addr = res.start; -+ ilm_region->size = resource_size(&res); -+ ilm_region->addr = devm_ioremap(wo->hw->dev, res.start, -+ resource_size(&res)); -+ -+ return IS_ERR(ilm_region->addr) ? PTR_ERR(ilm_region->addr) : 0; -+ } -+ -+ /* For backward compatibility, we need to check if ILM -+ * node is defined through reserved memory property. -+ */ -+ return mtk_wed_get_reserved_memory_region(wo, -+ ®ion[MTK_WED_WO_REGION_ILM]); -+} -+ -+static int - mtk_wed_mcu_load_firmware(struct mtk_wed_wo *wo) - { - static struct mtk_wed_wo_memory_region mem_region[] = { -@@ -320,12 +366,9 @@ mtk_wed_mcu_load_firmware(struct mtk_wed - u32 val, boot_cr; - int ret, i; - -- /* load firmware region metadata */ -- for (i = 0; i < ARRAY_SIZE(mem_region); i++) { -- ret = mtk_wed_get_reserved_memory_region(wo, &mem_region[i]); -- if (ret) -- return ret; -- } -+ ret = mtk_wed_mcu_load_memory_regions(wo, mem_region); -+ if (ret) -+ return ret; - - wo->boot_regmap = syscon_regmap_lookup_by_phandle(wo->hw->node, - "mediatek,wo-cpuboot"); diff --git a/target/linux/mediatek/patches-6.1/944-net-ethernet-mtk_wed-move-dlm-a-dedicated-dts-node.patch b/target/linux/mediatek/patches-6.1/944-net-ethernet-mtk_wed-move-dlm-a-dedicated-dts-node.patch deleted file mode 100644 index 209580d64..000000000 --- a/target/linux/mediatek/patches-6.1/944-net-ethernet-mtk_wed-move-dlm-a-dedicated-dts-node.patch +++ /dev/null @@ -1,57 +0,0 @@ -From b74ba226be2c45091b93bd49192bdd6d2178729e Mon Sep 17 00:00:00 2001 -Message-Id: -In-Reply-To: -References: -From: Lorenzo Bianconi -Date: Mon, 13 Mar 2023 15:45:16 +0100 -Subject: [PATCH net-next 3/3] net: ethernet: mtk_wed: move dlm a dedicated dts - node - -Since the dlm memory region is not part of the RAM SoC, move dlm in a -deidicated syscon node. -This patch helps to keep backward-compatibility with older version of -uboot codebase where we have a limit of 8 reserved-memory dts child -nodes. -Keep backward-compatibility with older dts version where dlm was defined -as reserved-memory child node. - -Signed-off-by: Lorenzo Bianconi ---- - drivers/net/ethernet/mediatek/mtk_wed.c | 19 +++++++++++++++++++ - 1 file changed, 19 insertions(+) - ---- a/drivers/net/ethernet/mediatek/mtk_wed.c -+++ b/drivers/net/ethernet/mediatek/mtk_wed.c -@@ -814,6 +814,24 @@ mtk_wed_rro_alloc(struct mtk_wed_device - struct device_node *np; - int index; - -+ np = of_parse_phandle(dev->hw->node, "mediatek,wo-dlm", 0); -+ if (np) { -+ struct resource res; -+ int ret; -+ -+ ret = of_address_to_resource(np, 0, &res); -+ of_node_put(np); -+ -+ if (ret < 0) -+ return ret; -+ -+ dev->rro.miod_phys = res.start; -+ goto out; -+ } -+ -+ /* For backward compatibility, we need to check if DLM -+ * node is defined through reserved memory property. -+ */ - index = of_property_match_string(dev->hw->node, "memory-region-names", - "wo-dlm"); - if (index < 0) -@@ -830,6 +848,7 @@ mtk_wed_rro_alloc(struct mtk_wed_device - return -ENODEV; - - dev->rro.miod_phys = rmem->base; -+out: - dev->rro.fdbk_phys = MTK_WED_MIOD_COUNT + dev->rro.miod_phys; - - return mtk_wed_rro_ring_alloc(dev, &dev->rro.ring, diff --git a/target/linux/mediatek/patches-6.1/945-arm64-dts-mt7986-move-ilm-in-a-dedicated-node.patch b/target/linux/mediatek/patches-6.1/945-arm64-dts-mt7986-move-ilm-in-a-dedicated-node.patch deleted file mode 100644 index 8accda584..000000000 --- a/target/linux/mediatek/patches-6.1/945-arm64-dts-mt7986-move-ilm-in-a-dedicated-node.patch +++ /dev/null @@ -1,83 +0,0 @@ -From 01561065af5bf1d2a4244896d897e3a1eafbcd46 Mon Sep 17 00:00:00 2001 -Message-Id: <01561065af5bf1d2a4244896d897e3a1eafbcd46.1678717704.git.lorenzo@kernel.org> -From: Lorenzo Bianconi -Date: Mon, 13 Mar 2023 15:10:56 +0100 -Subject: [PATCH net-next] arm64: dts: mt7986: move ilm in a dedicated node - -Since the ilm memory region is not part of the RAM SoC, move ilm in a -deidicated syscon node. -This patch helps to keep backward-compatibility with older version of -uboot codebase where we have a limit of 8 reserved-memory dts child -nodes. - -Signed-off-by: Lorenzo Bianconi ---- - arch/arm64/boot/dts/mediatek/mt7986a.dtsi | 34 +++++++++++------------ - 1 file changed, 16 insertions(+), 18 deletions(-) - ---- a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi -+++ b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi -@@ -97,16 +97,6 @@ - no-map; - }; - -- wo_ilm0: wo-ilm@151e0000 { -- reg = <0 0x151e0000 0 0x8000>; -- no-map; -- }; -- -- wo_ilm1: wo-ilm@151f0000 { -- reg = <0 0x151f0000 0 0x8000>; -- no-map; -- }; -- - wo_data: wo-data@4fd80000 { - reg = <0 0x4fd80000 0 0x240000>; - no-map; -@@ -512,11 +502,10 @@ - reg = <0 0x15010000 0 0x1000>; - interrupt-parent = <&gic>; - interrupts = ; -- memory-region = <&wo_emi0>, <&wo_ilm0>, <&wo_dlm0>, -- <&wo_data>; -- memory-region-names = "wo-emi", "wo-ilm", "wo-dlm", -- "wo-data"; -+ memory-region = <&wo_emi0>, <&wo_dlm0>, <&wo_data>; -+ memory-region-names = "wo-emi", "wo-dlm", "wo-data"; - mediatek,wo-ccif = <&wo_ccif0>; -+ mediatek,wo-ilm = <&wo_ilm0>; - mediatek,wo-cpuboot = <&wo_cpuboot>; - }; - -@@ -526,11 +515,10 @@ - reg = <0 0x15011000 0 0x1000>; - interrupt-parent = <&gic>; - interrupts = ; -- memory-region = <&wo_emi1>, <&wo_ilm1>, <&wo_dlm1>, -- <&wo_data>; -- memory-region-names = "wo-emi", "wo-ilm", "wo-dlm", -- "wo-data"; -+ memory-region = <&wo_emi1>, <&wo_dlm1>, <&wo_data>; -+ memory-region-names = "wo-emi", "wo-dlm", "wo-data"; - mediatek,wo-ccif = <&wo_ccif1>; -+ mediatek,wo-ilm = <&wo_ilm1>; - mediatek,wo-cpuboot = <&wo_cpuboot>; - }; - -@@ -548,6 +536,16 @@ - interrupts = ; - }; - -+ wo_ilm0: syscon@151e0000 { -+ compatible = "mediatek,mt7986-wo-ilm", "syscon"; -+ reg = <0 0x151e0000 0 0x8000>; -+ }; -+ -+ wo_ilm1: syscon@151f0000 { -+ compatible = "mediatek,mt7986-wo-ilm", "syscon"; -+ reg = <0 0x151f0000 0 0x8000>; -+ }; -+ - wo_cpuboot: syscon@15194000 { - compatible = "mediatek,mt7986-wo-cpuboot", "syscon"; - reg = <0 0x15194000 0 0x1000>; diff --git a/target/linux/mediatek/patches-6.1/946-arm64-dts-mt7986-move-dlm-in-a-dedicated-node.patch b/target/linux/mediatek/patches-6.1/946-arm64-dts-mt7986-move-dlm-in-a-dedicated-node.patch deleted file mode 100644 index 6bf751591..000000000 --- a/target/linux/mediatek/patches-6.1/946-arm64-dts-mt7986-move-dlm-in-a-dedicated-node.patch +++ /dev/null @@ -1,81 +0,0 @@ -From 9f76be683a8ec498563c294bc1cc279468058302 Mon Sep 17 00:00:00 2001 -Message-Id: <9f76be683a8ec498563c294bc1cc279468058302.1678719283.git.lorenzo@kernel.org> -From: Lorenzo Bianconi -Date: Mon, 13 Mar 2023 15:53:30 +0100 -Subject: [PATCH net-next] arm64: dts: mt7986: move dlm in a dedicated node - -Since the dlm memory region is not part of the RAM SoC, move dlm in a -deidicated syscon node. -This patch helps to keep backward-compatibility with older version of -uboot codebase where we have a limit of 8 reserved-memory dts child -nodes. - -Signed-off-by: Lorenzo Bianconi ---- - arch/arm64/boot/dts/mediatek/mt7986a.dtsi | 30 ++++++++++++----------- - 1 file changed, 16 insertions(+), 14 deletions(-) - ---- a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi -+++ b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi -@@ -101,16 +101,6 @@ - reg = <0 0x4fd80000 0 0x240000>; - no-map; - }; -- -- wo_dlm0: wo-dlm@151e8000 { -- reg = <0 0x151e8000 0 0x2000>; -- no-map; -- }; -- -- wo_dlm1: wo-dlm@151f8000 { -- reg = <0 0x151f8000 0 0x2000>; -- no-map; -- }; - }; - - timer { -@@ -502,10 +492,11 @@ - reg = <0 0x15010000 0 0x1000>; - interrupt-parent = <&gic>; - interrupts = ; -- memory-region = <&wo_emi0>, <&wo_dlm0>, <&wo_data>; -- memory-region-names = "wo-emi", "wo-dlm", "wo-data"; -+ memory-region = <&wo_emi0>, <&wo_data>; -+ memory-region-names = "wo-emi", "wo-data"; - mediatek,wo-ccif = <&wo_ccif0>; - mediatek,wo-ilm = <&wo_ilm0>; -+ mediatek,wo-dlm = <&wo_dlm0>; - mediatek,wo-cpuboot = <&wo_cpuboot>; - }; - -@@ -515,10 +506,11 @@ - reg = <0 0x15011000 0 0x1000>; - interrupt-parent = <&gic>; - interrupts = ; -- memory-region = <&wo_emi1>, <&wo_dlm1>, <&wo_data>; -- memory-region-names = "wo-emi", "wo-dlm", "wo-data"; -+ memory-region = <&wo_emi1>, <&wo_data>; -+ memory-region-names = "wo-emi", "wo-data"; - mediatek,wo-ccif = <&wo_ccif1>; - mediatek,wo-ilm = <&wo_ilm1>; -+ mediatek,wo-dlm = <&wo_dlm1>; - mediatek,wo-cpuboot = <&wo_cpuboot>; - }; - -@@ -546,6 +538,16 @@ - reg = <0 0x151f0000 0 0x8000>; - }; - -+ wo_dlm0: syscon@151e8000 { -+ compatible = "mediatek,mt7986-wo-dlm", "syscon"; -+ reg = <0 0x151e8000 0 0x2000>; -+ }; -+ -+ wo_dlm1: syscon@151f8000 { -+ compatible = "mediatek,mt7986-wo-dlm", "syscon"; -+ reg = <0 0x151f8000 0 0x2000>; -+ }; -+ - wo_cpuboot: syscon@15194000 { - compatible = "mediatek,mt7986-wo-cpuboot", "syscon"; - reg = <0 0x15194000 0 0x1000>;

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 y1@XYZfd2h@WcSMM6}UQY;bZ>6RDuA8i`b+ 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 D=&jCpwqxhMk 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