From 8801e8909098861e8bf94bec15ce95a6f2223de0 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Mon, 4 Sep 2023 12:33:11 +0200 Subject: [PATCH] ipq40xx: add target feed Signed-off-by: John Crispin --- feeds/ipq40xx/ath10k-ct-firmware/Makefile | 701 ++++++ feeds/ipq40xx/ath10k-ct/Makefile | 122 + ...64-ath10k-commit-rates-from-mac80211.patch | 37 + ...rolling-support-for-various-chipsets.patch | 598 +++++ ...02-ath10k-use-tpt-trigger-by-default.patch | 53 + ...10k-Add-NL80211_EXT_FEATURE_AQL-flag.patch | 10 + ...0-0010-ath10k-limit-htt-rx-ring-size.patch | 14 + ...60-0011-ath10k-limit-pci-buffer-size.patch | 50 + ...cmd_processing_time_for_scan_timeout.patch | 22 + .../patches/970-accumulate-survey-info-data | 11 + .../970-add-survey-local-bss-receive-time | 31 + .../patches/999-ath10k-threading.patch | 14 + feeds/ipq40xx/ath10k-firmware/Makefile | 182 ++ feeds/ipq40xx/batctl/Makefile | 231 ++ feeds/ipq40xx/batman-adv/Config.in | 110 + feeds/ipq40xx/batman-adv/Makefile | 91 + .../etc/uci-defaults/99-migrate-batadv_hardif | 97 + .../files/lib/netifd/proto/batadv.sh | 123 + .../files/lib/netifd/proto/batadv_hardif.sh | 49 + .../files/lib/netifd/proto/batadv_vlan.sh | 25 + feeds/ipq40xx/batman-adv/src/compat-hacks.h | 181 ++ feeds/ipq40xx/ipq-wifi/Makefile | 151 ++ .../ipq-wifi/board-8dev_habanero-dvk.qca4019 | Bin 0 -> 24324 bytes .../ipq-wifi/board-aruba_ap-303.qca4019 | Bin 0 -> 24316 bytes .../board-avm_fritzrepeater-1200.qca4019 | Bin 0 -> 24332 bytes .../board-buffalo_wtr-m2133hp.qca4019 | Bin 0 -> 24332 bytes .../board-buffalo_wtr-m2133hp.qca9984 | Bin 0 -> 12172 bytes .../ipq-wifi/board-cellc_rtl30vw.qca4019 | Bin 0 -> 24316 bytes .../ipq40xx/ipq-wifi/board-cig_wf610d.qca4019 | Bin 0 -> 24316 bytes .../board-devolo_magic-2-wifi-next.qca4019 | Bin 0 -> 24340 bytes .../ipq-wifi/board-dlink_dap2610.qca4019 | Bin 0 -> 24316 bytes .../ipq-wifi/board-edgecore_ecw5410.qca9984 | Bin 0 -> 24324 bytes .../ipq-wifi/board-edgecore_oap100.qca4019 | Bin 0 -> 24324 bytes .../board-edgecore_ssw2ac2600.qca9984 | Bin 0 -> 24324 bytes .../ipq-wifi/board-engenius_eap2200.qca4019 | Bin 0 -> 24324 bytes .../ipq-wifi/board-engenius_eap2200.qca9888 | Bin 0 -> 12172 bytes .../ipq-wifi/board-engenius_emd1.qca4019 | Bin 0 -> 24316 bytes .../ipq-wifi/board-engenius_emr3500.qca4019 | Bin 0 -> 24324 bytes .../board-ezviz_cs-w3-wd1200g-eup.qca4019 | Bin 0 -> 24340 bytes .../ipq-wifi/board-glinet_gl-ap1300.qca4019 | Bin 0 -> 48596 bytes .../ipq-wifi/board-glinet_gl-s1300.qca4019 | Bin 0 -> 24276 bytes .../ipq-wifi/board-linksys_ea8300.qca4019 | Bin 0 -> 97236 bytes .../ipq-wifi/board-linksys_ea8300.qca9888 | Bin 0 -> 48628 bytes .../ipq-wifi/board-linksys_mr8300-v0.qca4019 | Bin 0 -> 97268 bytes .../ipq-wifi/board-linksys_mr8300-v0.qca9888 | Bin 0 -> 48644 bytes .../ipq-wifi/board-luma_wrtq-329acn.qca4019 | Bin 0 -> 24324 bytes .../ipq-wifi/board-mikrotik_hap-ac2.qca4019 | Bin 0 -> 24324 bytes .../board-mikrotik_sxtsq-5-ac.qca4019 | Bin 0 -> 12176 bytes .../board-mobipromo_cm520-79f.qca4019 | Bin 0 -> 24308 bytes .../ipq-wifi/board-nec_wg2600hp3.qca9984 | Bin 0 -> 24332 bytes .../ipq-wifi/board-plasmacloud_pa1200.qca4019 | Bin 0 -> 24324 bytes .../ipq-wifi/board-plasmacloud_pa2200.qca4019 | Bin 0 -> 24324 bytes .../ipq-wifi/board-plasmacloud_pa2200.qca9888 | Bin 0 -> 12172 bytes .../ipq-wifi/board-qxwlan_e2600ac.qca4019 | Bin 0 -> 36464 bytes .../ipq-wifi/board-tp-link_ec420-g1.qca4019 | Bin 0 -> 607304 bytes .../ipq-wifi/board-tp-link_ec420-g1.qca9984 | Bin 0 -> 171916 bytes .../ipq-wifi/board-udaya-a5-id2.qca4019 | Bin 0 -> 607304 bytes .../ipq-wifi/board-wallys_dr40x9.qca4019 | Bin 0 -> 24316 bytes feeds/ipq40xx/ipq40xx/Makefile | 25 + .../ipq40xx/base-files/etc/board.d/01_leds | 91 + .../ipq40xx/base-files/etc/board.d/02_network | 211 ++ .../base-files/etc/board.d/03_gpio_switches | 29 + .../etc/hotplug.d/firmware/11-ath10k-caldata | 315 +++ .../etc/hotplug.d/firmware/40-ct-fw-cfg | 32 + .../base-files/etc/hotplug.d/net/20-smp-tune | 67 + .../ipq40xx/base-files/etc/init.d/bootcount | 36 + feeds/ipq40xx/ipq40xx/base-files/etc/inittab | 5 + .../etc/uci-defaults/04_led_migration | 19 + .../lib/firmware/ath10k/fwcfg-ipq4019.txt | 15 + .../lib/firmware/ath10k/fwcfg-qca9888.txt | 16 + .../lib/firmware/ath10k/fwcfg-qca9984.txt | 16 + .../lib/preinit/05_set_iface_mac_ipq40xx.sh | 39 + .../lib/preinit/05_set_threading.sh | 7 + .../preinit/06_set_preinit_iface_ipq40xx.sh | 22 + .../lib/upgrade/dualboot_datachk.sh | 108 + .../ipq40xx/base-files/lib/upgrade/linksys.sh | 122 + .../base-files/lib/upgrade/platform.sh | 160 ++ feeds/ipq40xx/ipq40xx/config-5.4 | 470 ++++ .../arch/arm/boot/dts/qcom-ipq4018-a42.dts | 205 ++ .../arm/boot/dts/qcom-ipq4018-ap120c-ac.dts | 350 +++ .../dts/qcom-ipq4018-cs-w3-wd1200g-eup.dts | 242 ++ .../arm/boot/dts/qcom-ipq4018-dap-2610.dts | 241 ++ .../arm/boot/dts/qcom-ipq4018-ea6350v3.dts | 277 +++ .../arm/boot/dts/qcom-ipq4018-eap1300.dts | 235 ++ .../arm/boot/dts/qcom-ipq4018-ecw5211.dts | 333 +++ .../arch/arm/boot/dts/qcom-ipq4018-emd1.dts | 233 ++ .../arm/boot/dts/qcom-ipq4018-emr3500.dts | 235 ++ .../arm/boot/dts/qcom-ipq4018-ens620ext.dts | 265 ++ .../arm/boot/dts/qcom-ipq4018-ex6100v2.dts | 31 + .../arm/boot/dts/qcom-ipq4018-ex6150v2.dts | 31 + .../arm/boot/dts/qcom-ipq4018-ex61x0v2.dtsi | 312 +++ .../boot/dts/qcom-ipq4018-fritzbox-4040.dts | 309 +++ .../arm/boot/dts/qcom-ipq4018-gl-ap1300.dts | 269 ++ .../arm/boot/dts/qcom-ipq4018-hap-ac2.dts | 273 +++ .../arm/boot/dts/qcom-ipq4018-jalapeno.dts | 9 + .../arm/boot/dts/qcom-ipq4018-jalapeno.dtsi | 269 ++ .../dts/qcom-ipq4018-magic-2-wifi-next.dts | 268 ++ .../boot/dts/qcom-ipq4018-meshpoint-one.dts | 81 + .../arm/boot/dts/qcom-ipq4018-nbg6617.dts | 337 +++ .../arch/arm/boot/dts/qcom-ipq4018-pa1200.dts | 197 ++ .../arm/boot/dts/qcom-ipq4018-rt-ac58u.dts | 309 +++ .../dts/qcom-ipq4018-spw2ac1200-lan-poe.dts | 6 + .../arm/boot/dts/qcom-ipq4018-spw2ac1200.dts | 332 +++ .../arm/boot/dts/qcom-ipq4018-sxtsq-5-ac.dts | 242 ++ .../boot/dts/qcom-ipq4018-udaya-a5-id2.dts | 114 + .../arm/boot/dts/qcom-ipq4018-wre6606.dts | 265 ++ .../arm/boot/dts/qcom-ipq4018-wrtq-329acn.dts | 275 +++ .../arch/arm/boot/dts/qcom-ipq4019-a62.dts | 229 ++ .../arm/boot/dts/qcom-ipq4019-cm520-79f.dts | 354 +++ .../arm/boot/dts/qcom-ipq4019-e2600ac-c1.dts | 80 + .../arm/boot/dts/qcom-ipq4019-e2600ac-c2.dts | 115 + .../arm/boot/dts/qcom-ipq4019-e2600ac.dtsi | 266 ++ .../arch/arm/boot/dts/qcom-ipq4019-ea8300.dts | 95 + .../arm/boot/dts/qcom-ipq4019-eap2200.dts | 282 +++ .../boot/dts/qcom-ipq4019-fritzbox-7530.dts | 303 +++ .../dts/qcom-ipq4019-fritzrepeater-1200.dts | 273 +++ .../dts/qcom-ipq4019-fritzrepeater-3000.dts | 269 ++ .../boot/dts/qcom-ipq4019-habanero-dvk.dts | 357 +++ .../arm/boot/dts/qcom-ipq4019-hfcl-ion4.dts | 236 ++ .../arm/boot/dts/qcom-ipq4019-map-ac2200.dts | 326 +++ .../arch/arm/boot/dts/qcom-ipq4019-mr8300.dts | 80 + .../arch/arm/boot/dts/qcom-ipq4019-oap100.dts | 339 +++ .../arm/boot/dts/qcom-ipq4019-oap100e.dts | 351 +++ .../arch/arm/boot/dts/qcom-ipq4019-pa2200.dts | 210 ++ .../arm/boot/dts/qcom-ipq4019-rtl30vw.dts | 385 +++ .../dts/qcom-ipq4019-tp-link-ec420-g1.dts | 275 +++ .../arm/boot/dts/qcom-ipq4019-u4019-32m.dts | 77 + .../arch/arm/boot/dts/qcom-ipq4019-u4019.dtsi | 224 ++ .../arm/boot/dts/qcom-ipq4019-um-325ac.dts | 94 + .../arm/boot/dts/qcom-ipq4019-um-325ac.dtsi | 168 ++ .../arm/boot/dts/qcom-ipq4019-um-510ac-v3.dts | 94 + .../boot/dts/qcom-ipq4019-um-510ac-v3.dtsi | 168 ++ .../arm/boot/dts/qcom-ipq4019-um-550ac.dts | 94 + .../arm/boot/dts/qcom-ipq4019-um-550ac.dtsi | 168 ++ .../arch/arm/boot/dts/qcom-ipq4019-wpj419.dts | 385 +++ .../arm/boot/dts/qcom-ipq4019-wtr-m2133hp.dts | 419 ++++ .../arm/boot/dts/qcom-ipq4019-xx8300.dtsi | 299 +++ .../arch/arm/boot/dts/qcom-ipq4028-wpj428.dts | 288 +++ .../arch/arm/boot/dts/qcom-ipq4029-ap-303.dts | 178 ++ .../arm/boot/dts/qcom-ipq4029-ap-303h.dts | 421 ++++ .../arch/arm/boot/dts/qcom-ipq4029-ap-365.dts | 192 ++ .../boot/dts/qcom-ipq4029-ap-cig-wf610d.dts | 414 ++++ .../dts/qcom-ipq4029-aruba-glenmorangie.dtsi | 251 ++ .../arm/boot/dts/qcom-ipq4029-gl-b1300.dts | 280 +++ .../arm/boot/dts/qcom-ipq4029-gl-s1300.dts | 356 +++ .../arch/arm/boot/dts/qcom-ipq4029-mr33.dts | 400 +++ .../arch/arm/boot/dts/qcom-ipq40x9-dr40x9.dts | 387 +++ .../net/ethernet/qualcomm/essedma/Makefile | 9 + .../net/ethernet/qualcomm/essedma/edma.c | 2177 +++++++++++++++++ .../net/ethernet/qualcomm/essedma/edma.h | 455 ++++ .../net/ethernet/qualcomm/essedma/edma_axi.c | 1351 ++++++++++ .../ethernet/qualcomm/essedma/edma_ethtool.c | 334 +++ .../net/ethernet/qualcomm/essedma/ess_edma.h | 389 +++ .../ipq40xx/files/drivers/net/phy/ar40xx.c | 1909 +++++++++++++++ .../ipq40xx/files/drivers/net/phy/ar40xx.h | 342 +++ .../ipq40xx/files/drivers/net/phy/qca807x.c | 829 +++++++ feeds/ipq40xx/ipq40xx/generic/target.mk | 1 + feeds/ipq40xx/ipq40xx/image/Makefile | 19 + feeds/ipq40xx/ipq40xx/image/generic.mk | 963 ++++++++ feeds/ipq40xx/ipq40xx/image/mikrotik.mk | 28 + feeds/ipq40xx/ipq40xx/mikrotik/config-default | 4 + feeds/ipq40xx/ipq40xx/mikrotik/target.mk | 4 + ...5.7-ARM-qcom-Add-support-for-IPQ40xx.patch | 42 + ...r-add-IPQ4019-SDHCI-VQMMC-LDO-driver.patch | 153 ++ ...om-ipq4019-Add-SDHCI-controller-node.patch | 36 + ...om-Add-nodes-for-SMP-boot-in-IPQ40xx.patch | 71 + ...RM-dts-qcom-add-gpio-ranges-property.patch | 119 + ...om-ipq4019-fix-high-resolution-timer.patch | 33 + ...net-phy-mdio-add-IPQ4019-MDIO-driver.patch | 210 ++ ...2-ARM-dts-qcom-ipq4019-add-MDIO-node.patch | 57 + ...add-CRYPTO_ALG_KERN_DRIVER_ONLY-flag.patch | 31 + ....5-crypto-qce-switch-to-skcipher-API.patch | 993 ++++++++ ...ce-fix-ctr-aes-qce-block-chunk-sizes.patch | 43 + ...crypto-qce-fix-xts-aes-qce-key-sizes.patch | 60 + ...-save-a-sg-table-slot-for-result-buf.patch | 85 + ....6-crypto-qce-update-the-skcipher-IV.patch | 31 + ...qce-initialize-fallback-only-for-AES.patch | 54 + ...e-allow-building-only-hashes-ciphers.patch | 419 ++++ ...e-use-cryptlen-when-adding-extra-sgl.patch | 89 + ...-use-AES-fallback-for-small-requests.patch | 113 + ...-handle-AES-XTS-cases-that-qce-fails.patch | 59 + ...-driver-for-Qualcomm-IPQ40xx-USB-PHY.patch | 197 ++ .../0018-v5.9-pinctrl-msm-open-drain.patch | 81 + ...d-spi-nor-Add-support-for-mx25r3235f.patch | 29 + .../100-GPIO-add-named-gpio-exports.patch | 165 ++ ...dts-IPQ4019-add-SDHCI-VQMMC-LDO-node.patch | 32 + ...com-ipq4019-add-USB-devicetree-nodes.patch | 97 + ...arm-dts-qcom-ipq4019-add-more-labels.patch | 42 + .../104-clk-fix-apss-cpu-overclocking.patch | 115 + .../300-clk-qcom-ipq4019-add-ess-reset.patch | 52 + ...-compressed-add-appended-DTB-section.patch | 48 + ...d-set-ipq40xx-watchdog-to-allow-boot.patch | 66 + ...msm-use-sdhci_set_clock-instead-of-s.patch | 25 + ...702-dts-ipq4019-add-PHY-switch-nodes.patch | 46 + ...4019-needs-rfs-vlan_tag-callbacks-in.patch | 53 + .../705-net-add-qualcomm-ar40xx-phy.patch | 26 + .../706-dt-bindings-net-add-QCA807x-PHY.patch | 61 + ...7-net-phy-Add-Qualcom-QCA807x-driver.patch | 50 + ...8-arm-dts-ipq4019-QCA807x-properties.patch | 62 + ...add-qualcomm-essedma-ethernet-driver.patch | 37 + ...ts-ipq4019-add-ethernet-essedma-node.patch | 92 + .../850-soc-add-qualcomm-syscon.patch | 180 ++ .../900-dts-ipq4019-ap-dk01.1.patch | 176 ++ .../901-arm-boot-add-dts-files.patch | 77 + .../902-dts-ipq4019-ap-dk04.1.patch | 167 ++ .../ipq40xx/patches-5.4/903-pstore.patch | 17 + .../911-dts-ipq4019-indio-um-325ac.patch | 13 + .../912-dts-ipq4019-indio-um-550ac.patch | 13 + .../913-dts-ipq4019-indio-um-510ac-v3.patch | 11 + .../patches-5.4/997-device_tree_cmdline.patch | 12 + .../patches-5.4/998-tp-link-ec420-g1.patch | 12 + .../ipq40xx/patches-5.4/999-hfcl_ion.patch | 20 + .../9991-arm-boot-add-oap100e-dts-files.patch | 10 + feeds/ipq40xx/mac80211/Makefile | 528 ++++ feeds/ipq40xx/mac80211/ath.mk | 310 +++ feeds/ipq40xx/mac80211/broadcom.mk | 510 ++++ .../files/lib/netifd/wireless/mac80211.sh | 1170 +++++++++ .../mac80211/files/lib/wifi/mac80211.sh | 190 ++ feeds/ipq40xx/mac80211/files/mac80211.hotplug | 5 + feeds/ipq40xx/mac80211/intel.mk | 200 ++ feeds/ipq40xx/mac80211/marvell.mk | 90 + .../patches/ath/070-ath_common_config.patch | 10 + .../ath/080-ath10k_thermal_config.patch | 47 + .../patches/ath/120-owl-loader-compat.patch | 53 + .../201-ath5k-WAR-for-AR71xx-PCI-bug.patch | 38 + ...w-reset-AHB-WMAC-interface-on-AR91xx.patch | 25 + ..._hw-issue-external-reset-for-QCA955x.patch | 129 + ...h9k-force-rx_clear-when-disabling-rx.patch | 35 + ...erpret-requested-txpower-in-EIRP-dom.patch | 36 + ...power-reduction-for-US-regulatory-do.patch | 24 + .../patches/ath/400-ath_move_debug_code.patch | 31 + .../patches/ath/401-ath9k_blink_default.patch | 11 + .../patches/ath/402-ath_regd_optional.patch | 92 + .../patches/ath/403-world_regd_fixup.patch | 84 + .../patches/ath/404-regd_no_assoc_hints.patch | 19 + .../patches/ath/405-ath_regd_us.patch | 26 + .../ath/406-ath_relax_default_regd.patch | 51 + .../ath/410-ath9k_allow_adhoc_and_ap.patch | 10 + .../ath/411-ath5k_allow_adhoc_and_ap.patch | 46 + .../ath/420-ath5k_disable_fast_cc.patch | 18 + .../patches/ath/430-add_ath5k_platform.patch | 33 + ...add_platform_eeprom_support_to_ath5k.patch | 56 + .../patches/ath/432-ath5k_add_pciids.patch | 11 + .../ath/440-ath5k_channel_bw_debugfs.patch | 142 ++ ...abled-MFP-capability-unconditionally.patch | 34 + .../ath/500-ath9k_eeprom_debugfs.patch | 65 + .../patches/ath/501-ath9k_ahb_init.patch | 34 + .../ath/510-ath9k_intr_mitigation_tweak.patch | 18 + .../patches/ath/511-ath9k_reduce_rxbuf.patch | 11 + .../ath/512-ath9k_channelbw_debugfs.patch | 125 + .../patches/ath/513-ath9k_add_pci_ids.patch | 30 + .../patches/ath/530-ath9k_extra_leds.patch | 267 ++ .../ath/531-ath9k_extra_platform_leds.patch | 76 + .../ath/540-ath9k_reduce_ani_interval.patch | 11 + .../patches/ath/542-ath9k_debugfs_diag.patch | 139 ++ .../ath/543-ath9k_entropy_from_adc.patch | 186 ++ ...544-ath9k-ar933x-usb-hang-workaround.patch | 79 + .../patches/ath/545-ath9k_ani_ws_detect.patch | 155 ++ .../ath/547-ath9k_led_defstate_fix.patch | 29 + .../ath/548-ath9k_enable_gpio_chip.patch | 251 ++ .../ath/549-ath9k_enable_gpio_buttons.patch | 143 ++ .../ath/550-ath9k-disable-bands-via-dt.patch | 15 + .../ath/551-ath9k_ubnt_uap_plus_hsr.patch | 418 ++++ .../mac80211/patches/ath/552-ahb_of.patch | 337 +++ .../patches/ath/553-ath9k_of_gpio_mask.patch | 25 + ...21-ath10k_init_devices_synchronously.patch | 33 + ...h10k-increase-rx-buffer-size-to-2048.patch | 37 + .../ath/930-ath10k_add_tpt_led_trigger.patch | 37 + ...rolling-support-for-various-chipsets.patch | 609 +++++ ...75-ath10k-use-tpt-trigger-by-default.patch | 53 + ...980-ath10k-fix-max-antenna-gain-unit.patch | 49 + ...-power-reduction-for-US-regulatory-d.patch | 101 + .../patches/brcm/040-brcmutil_option.patch | 10 + .../810-b43-gpio-mask-module-option.patch | 37 + .../patches/brcm/811-b43_no_pio.patch | 86 + .../brcm/812-b43-add-antenna-control.patch | 131 + .../813-b43-reduce-number-of-RX-slots.patch | 11 + .../814-b43-only-use-gpio-0-1-for-led.patch | 17 + ...815-b43-always-take-overlapping-devs.patch | 11 + ...-remove-extra-regulation-restriction.patch | 27 + ...-register-wiphy-s-during-module_init.patch | 74 + ...und-bug-with-some-inconsistent-BSSes.patch | 49 + ...62-brcmfmac-Disable-power-management.patch | 27 + ...-in-driver-tables-with-country-codes.patch | 60 + ...e-internal-roaming-engine-by-default.patch | 23 + .../mac80211/patches/brcm/998-survey.patch | 148 ++ .../patches/build/000-fix_kconfig.patch | 14 + .../patches/build/001-fix_build.patch | 169 ++ .../patches/build/002-change_allconfig.patch | 64 + .../build/003-remove_bogus_modparams.patch | 34 + .../build/004-kconfig_backport_fix.patch | 28 + .../patches/build/010-disable_rfkill.patch | 15 + .../build/012-kernel_build_check.patch | 11 + .../patches/build/015-ipw200-mtu.patch | 34 + .../patches/build/050-lib80211_option.patch | 33 + .../patches/build/060-no_local_ssb_bcma.patch | 335 +++ ...700-mwl8k-missing-pci-id-for-WNR854T.patch | 10 + .../801-libertas-configure-sysfs-links.patch | 21 + .../802-libertas-set-wireless-macaddr.patch | 11 + ...940-mwl8k_init_devices_synchronously.patch | 20 + ...define-RF5592-in-init_eeprom-routine.patch | 51 + .../patches/rt2x00/100-rt2x00_options.patch | 47 + ...to-build-rt2800soc-module-for-RT3883.patch | 30 + ...1-rt2x00-introduce-rt2x00_platform_h.patch | 32 + .../602-rt2x00-introduce-rt2x00eeprom.patch | 296 +++ .../603-rt2x00-of_load_eeprom_filename.patch | 33 + ...om-on-SoC-from-a-mtd-device-defines-.patch | 113 + ...isabling_bands_through_platform_data.patch | 47 + ...07-rt2x00-add_platform_data_mac_addr.patch | 26 + ...00-allow_disabling_bands_through_dts.patch | 19 + ...c-loadable-via-OF-on-rt288x-305x-SoC.patch | 33 + ...0-rt2x00-change-led-polarity-from-OF.patch | 40 + .../611-rt2x00-add-AP+STA-support.patch | 11 + .../612-rt2x00-led-tpt-trigger-support.patch | 44 + ...dd-support-for-external-PA-on-MT7620.patch | 107 + ...-rt2x00-add-rf-self-txdc-calibration.patch | 67 + .../rt2x00/983-rt2x00-add-r-calibration.patch | 166 ++ .../984-rt2x00-add-rxdcoc-calibration.patch | 81 + .../985-rt2x00-add-rxiq-calibration.patch | 395 +++ .../986-rt2x00-add-TX-LOFT-calibration.patch | 973 ++++++++ ...backports-add-netif_receive_skb_list.patch | 30 + .../071-backports-add-skb_list_del_init.patch | 24 + .../100-remove-cryptoapi-dependencies.patch | 698 ++++++ .../110-mac80211_keep_keys_on_stop_ap.patch | 12 + .../120-cfg80211_allow_perm_addr_change.patch | 43 + ...aes-cmac-switch-to-shash-CMAC-driver.patch | 230 ++ .../132-mac80211-remove-cmac-dependency.patch | 10 + .../subsys/150-disable_addr_notifier.patch | 67 + .../mac80211/patches/subsys/210-ap_scan.patch | 11 + .../300-mac80211-optimize-skb-resizing.patch | 201 ++ ...domize-BA-session-dialog-token-alloc.patch | 38 + ...11-improve-AQL-tx-airtime-estimation.patch | 81 + ...unction-for-running-rx-without-passi.patch | 186 ++ ...skb_get_hash-instead-of-skb_get_hash.patch | 55 + ...lcate-skb-hash-early-when-using-itxq.patch | 19 + ...ce-packet-loss-event-false-positives.patch | 116 + ...e-provided-via-status-rate-on-ieee80.patch | 151 ++ ...out-code-to-look-up-the-average-pack.patch | 187 ++ ...-AQL-aggregation-estimation-for-low-.patch | 67 + ...sing-queue-hash-initialization-to-80.patch | 25 + ...nd-refresh-aggregation-session-in-en.patch | 45 + ...cap-offload-for-tx-multicast-control.patch | 136 + ...o-control.hw_key-for-encap-offload-p.patch | 31 + ...-rework-tx-encapsulation-offload-API.patch | 613 +++++ ...e-duplication-in-tx-status-functions.patch | 197 ++ ...tx-status-call-to-ieee80211_sta_regi.patch | 26 + ...-optimize-station-connection-monitor.patch | 174 ++ ...ED_TXPROCESSING-and-HW_80211_ENCAP-t.patch | 227 ++ ...02.3-offload-and-802.11-tx-status-co.patch | 159 ++ ...-using-ieee80211_tx_status_ext-to-fr.patch | 63 + ...ieee80211_tx_status_ext-to-support-b.patch | 53 + ...the-driver-when-a-sta-uses-4-address.patch | 109 + ...ize-code-to-remove-a-forward-declara.patch | 1110 +++++++++ ...AQL-aggregation-estimation-to-HE-and.patch | 49 + ...-add-AQL-support-for-VHT160-tx-rates.patch | 23 + ...11-fix-misplaced-while-instead-of-if.patch | 31 + .../patches/subsys/400-allow-ibss-mixed.patch | 29 + .../500-mac80211_configure_antenna_gain.patch | 160 ++ .../mac80211/patches/subsys/800-oom.patch | 71 + feeds/ipq40xx/mac80211/ralink.mk | 172 ++ feeds/ipq40xx/mac80211/realtek.mk | 206 ++ .../mac80211/scripts/import-backports.sh | 109 + feeds/ipq40xx/wireguard/Makefile | 55 + .../wireguard/patches/100-compat.patch | 20 + patches/0057-ipq40xx-add-v5.4-backport.patch | 179 +- 365 files changed, 52689 insertions(+), 158 deletions(-) create mode 100644 feeds/ipq40xx/ath10k-ct-firmware/Makefile create mode 100644 feeds/ipq40xx/ath10k-ct/Makefile create mode 100644 feeds/ipq40xx/ath10k-ct/patches/164-ath10k-commit-rates-from-mac80211.patch create mode 100644 feeds/ipq40xx/ath10k-ct/patches/201-ath10k-add-LED-and-GPIO-controlling-support-for-various-chipsets.patch create mode 100644 feeds/ipq40xx/ath10k-ct/patches/202-ath10k-use-tpt-trigger-by-default.patch create mode 100644 feeds/ipq40xx/ath10k-ct/patches/205-ath10k-Add-NL80211_EXT_FEATURE_AQL-flag.patch create mode 100644 feeds/ipq40xx/ath10k-ct/patches/960-0010-ath10k-limit-htt-rx-ring-size.patch create mode 100644 feeds/ipq40xx/ath10k-ct/patches/960-0011-ath10k-limit-pci-buffer-size.patch create mode 100644 feeds/ipq40xx/ath10k-ct/patches/960-0012-ath10k-add_cmd_processing_time_for_scan_timeout.patch create mode 100644 feeds/ipq40xx/ath10k-ct/patches/970-accumulate-survey-info-data create mode 100644 feeds/ipq40xx/ath10k-ct/patches/970-add-survey-local-bss-receive-time create mode 100644 feeds/ipq40xx/ath10k-ct/patches/999-ath10k-threading.patch create mode 100644 feeds/ipq40xx/ath10k-firmware/Makefile create mode 100644 feeds/ipq40xx/batctl/Makefile create mode 100644 feeds/ipq40xx/batman-adv/Config.in create mode 100644 feeds/ipq40xx/batman-adv/Makefile create mode 100755 feeds/ipq40xx/batman-adv/files/etc/uci-defaults/99-migrate-batadv_hardif create mode 100755 feeds/ipq40xx/batman-adv/files/lib/netifd/proto/batadv.sh create mode 100755 feeds/ipq40xx/batman-adv/files/lib/netifd/proto/batadv_hardif.sh create mode 100755 feeds/ipq40xx/batman-adv/files/lib/netifd/proto/batadv_vlan.sh create mode 100644 feeds/ipq40xx/batman-adv/src/compat-hacks.h create mode 100644 feeds/ipq40xx/ipq-wifi/Makefile create mode 100644 feeds/ipq40xx/ipq-wifi/board-8dev_habanero-dvk.qca4019 create mode 100644 feeds/ipq40xx/ipq-wifi/board-aruba_ap-303.qca4019 create mode 100644 feeds/ipq40xx/ipq-wifi/board-avm_fritzrepeater-1200.qca4019 create mode 100644 feeds/ipq40xx/ipq-wifi/board-buffalo_wtr-m2133hp.qca4019 create mode 100644 feeds/ipq40xx/ipq-wifi/board-buffalo_wtr-m2133hp.qca9984 create mode 100644 feeds/ipq40xx/ipq-wifi/board-cellc_rtl30vw.qca4019 create mode 100644 feeds/ipq40xx/ipq-wifi/board-cig_wf610d.qca4019 create mode 100644 feeds/ipq40xx/ipq-wifi/board-devolo_magic-2-wifi-next.qca4019 create mode 100644 feeds/ipq40xx/ipq-wifi/board-dlink_dap2610.qca4019 create mode 100644 feeds/ipq40xx/ipq-wifi/board-edgecore_ecw5410.qca9984 create mode 100644 feeds/ipq40xx/ipq-wifi/board-edgecore_oap100.qca4019 create mode 100644 feeds/ipq40xx/ipq-wifi/board-edgecore_ssw2ac2600.qca9984 create mode 100644 feeds/ipq40xx/ipq-wifi/board-engenius_eap2200.qca4019 create mode 100644 feeds/ipq40xx/ipq-wifi/board-engenius_eap2200.qca9888 create mode 100644 feeds/ipq40xx/ipq-wifi/board-engenius_emd1.qca4019 create mode 100644 feeds/ipq40xx/ipq-wifi/board-engenius_emr3500.qca4019 create mode 100644 feeds/ipq40xx/ipq-wifi/board-ezviz_cs-w3-wd1200g-eup.qca4019 create mode 100644 feeds/ipq40xx/ipq-wifi/board-glinet_gl-ap1300.qca4019 create mode 100644 feeds/ipq40xx/ipq-wifi/board-glinet_gl-s1300.qca4019 create mode 100644 feeds/ipq40xx/ipq-wifi/board-linksys_ea8300.qca4019 create mode 100644 feeds/ipq40xx/ipq-wifi/board-linksys_ea8300.qca9888 create mode 100644 feeds/ipq40xx/ipq-wifi/board-linksys_mr8300-v0.qca4019 create mode 100644 feeds/ipq40xx/ipq-wifi/board-linksys_mr8300-v0.qca9888 create mode 100644 feeds/ipq40xx/ipq-wifi/board-luma_wrtq-329acn.qca4019 create mode 100644 feeds/ipq40xx/ipq-wifi/board-mikrotik_hap-ac2.qca4019 create mode 100644 feeds/ipq40xx/ipq-wifi/board-mikrotik_sxtsq-5-ac.qca4019 create mode 100644 feeds/ipq40xx/ipq-wifi/board-mobipromo_cm520-79f.qca4019 create mode 100644 feeds/ipq40xx/ipq-wifi/board-nec_wg2600hp3.qca9984 create mode 100644 feeds/ipq40xx/ipq-wifi/board-plasmacloud_pa1200.qca4019 create mode 100644 feeds/ipq40xx/ipq-wifi/board-plasmacloud_pa2200.qca4019 create mode 100644 feeds/ipq40xx/ipq-wifi/board-plasmacloud_pa2200.qca9888 create mode 100644 feeds/ipq40xx/ipq-wifi/board-qxwlan_e2600ac.qca4019 create mode 100644 feeds/ipq40xx/ipq-wifi/board-tp-link_ec420-g1.qca4019 create mode 100644 feeds/ipq40xx/ipq-wifi/board-tp-link_ec420-g1.qca9984 create mode 100644 feeds/ipq40xx/ipq-wifi/board-udaya-a5-id2.qca4019 create mode 100644 feeds/ipq40xx/ipq-wifi/board-wallys_dr40x9.qca4019 create mode 100644 feeds/ipq40xx/ipq40xx/Makefile create mode 100755 feeds/ipq40xx/ipq40xx/base-files/etc/board.d/01_leds create mode 100755 feeds/ipq40xx/ipq40xx/base-files/etc/board.d/02_network create mode 100755 feeds/ipq40xx/ipq40xx/base-files/etc/board.d/03_gpio_switches create mode 100644 feeds/ipq40xx/ipq40xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata create mode 100644 feeds/ipq40xx/ipq40xx/base-files/etc/hotplug.d/firmware/40-ct-fw-cfg create mode 100644 feeds/ipq40xx/ipq40xx/base-files/etc/hotplug.d/net/20-smp-tune create mode 100755 feeds/ipq40xx/ipq40xx/base-files/etc/init.d/bootcount create mode 100644 feeds/ipq40xx/ipq40xx/base-files/etc/inittab create mode 100644 feeds/ipq40xx/ipq40xx/base-files/etc/uci-defaults/04_led_migration create mode 100644 feeds/ipq40xx/ipq40xx/base-files/lib/firmware/ath10k/fwcfg-ipq4019.txt create mode 100644 feeds/ipq40xx/ipq40xx/base-files/lib/firmware/ath10k/fwcfg-qca9888.txt create mode 100644 feeds/ipq40xx/ipq40xx/base-files/lib/firmware/ath10k/fwcfg-qca9984.txt create mode 100644 feeds/ipq40xx/ipq40xx/base-files/lib/preinit/05_set_iface_mac_ipq40xx.sh create mode 100644 feeds/ipq40xx/ipq40xx/base-files/lib/preinit/05_set_threading.sh create mode 100644 feeds/ipq40xx/ipq40xx/base-files/lib/preinit/06_set_preinit_iface_ipq40xx.sh create mode 100644 feeds/ipq40xx/ipq40xx/base-files/lib/upgrade/dualboot_datachk.sh create mode 100755 feeds/ipq40xx/ipq40xx/base-files/lib/upgrade/linksys.sh create mode 100644 feeds/ipq40xx/ipq40xx/base-files/lib/upgrade/platform.sh create mode 100644 feeds/ipq40xx/ipq40xx/config-5.4 create mode 100644 feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-a42.dts create mode 100644 feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-ap120c-ac.dts create mode 100644 feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-cs-w3-wd1200g-eup.dts create mode 100644 feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-dap-2610.dts create mode 100644 feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-ea6350v3.dts create mode 100644 feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-eap1300.dts create mode 100644 feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-ecw5211.dts create mode 100644 feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-emd1.dts create mode 100644 feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-emr3500.dts create mode 100644 feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-ens620ext.dts create mode 100644 feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-ex6100v2.dts create mode 100644 feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-ex6150v2.dts create mode 100644 feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-ex61x0v2.dtsi create mode 100644 feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-fritzbox-4040.dts create mode 100644 feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-gl-ap1300.dts create mode 100644 feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-hap-ac2.dts create mode 100644 feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-jalapeno.dts create mode 100644 feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-jalapeno.dtsi create mode 100644 feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-magic-2-wifi-next.dts create mode 100644 feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-meshpoint-one.dts create mode 100644 feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-nbg6617.dts create mode 100644 feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-pa1200.dts create mode 100644 feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-rt-ac58u.dts create mode 100644 feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-spw2ac1200-lan-poe.dts create mode 100644 feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-spw2ac1200.dts create mode 100644 feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-sxtsq-5-ac.dts create mode 100644 feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-udaya-a5-id2.dts create mode 100644 feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-wre6606.dts create mode 100644 feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-wrtq-329acn.dts create mode 100644 feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-a62.dts create mode 100644 feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-cm520-79f.dts create mode 100644 feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-e2600ac-c1.dts create mode 100644 feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-e2600ac-c2.dts create mode 100644 feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-e2600ac.dtsi create mode 100644 feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-ea8300.dts create mode 100644 feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-eap2200.dts create mode 100644 feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-fritzbox-7530.dts create mode 100644 feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-fritzrepeater-1200.dts create mode 100644 feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-fritzrepeater-3000.dts create mode 100644 feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-habanero-dvk.dts create mode 100644 feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-hfcl-ion4.dts create mode 100644 feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-map-ac2200.dts create mode 100644 feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-mr8300.dts create mode 100644 feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-oap100.dts create mode 100644 feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-oap100e.dts create mode 100644 feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-pa2200.dts create mode 100644 feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-rtl30vw.dts create mode 100755 feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-tp-link-ec420-g1.dts create mode 100644 feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-u4019-32m.dts create mode 100644 feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-u4019.dtsi create mode 100644 feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-um-325ac.dts create mode 100644 feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-um-325ac.dtsi create mode 100644 feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-um-510ac-v3.dts create mode 100644 feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-um-510ac-v3.dtsi create mode 100644 feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-um-550ac.dts create mode 100644 feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-um-550ac.dtsi create mode 100644 feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-wpj419.dts create mode 100644 feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-wtr-m2133hp.dts create mode 100644 feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-xx8300.dtsi create mode 100644 feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4028-wpj428.dts create mode 100644 feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4029-ap-303.dts create mode 100644 feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4029-ap-303h.dts create mode 100644 feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4029-ap-365.dts create mode 100755 feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4029-ap-cig-wf610d.dts create mode 100644 feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4029-aruba-glenmorangie.dtsi create mode 100644 feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4029-gl-b1300.dts create mode 100644 feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4029-gl-s1300.dts create mode 100644 feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4029-mr33.dts create mode 100644 feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq40x9-dr40x9.dts create mode 100644 feeds/ipq40xx/ipq40xx/files/drivers/net/ethernet/qualcomm/essedma/Makefile create mode 100644 feeds/ipq40xx/ipq40xx/files/drivers/net/ethernet/qualcomm/essedma/edma.c create mode 100644 feeds/ipq40xx/ipq40xx/files/drivers/net/ethernet/qualcomm/essedma/edma.h create mode 100644 feeds/ipq40xx/ipq40xx/files/drivers/net/ethernet/qualcomm/essedma/edma_axi.c create mode 100644 feeds/ipq40xx/ipq40xx/files/drivers/net/ethernet/qualcomm/essedma/edma_ethtool.c create mode 100644 feeds/ipq40xx/ipq40xx/files/drivers/net/ethernet/qualcomm/essedma/ess_edma.h create mode 100644 feeds/ipq40xx/ipq40xx/files/drivers/net/phy/ar40xx.c create mode 100644 feeds/ipq40xx/ipq40xx/files/drivers/net/phy/ar40xx.h create mode 100644 feeds/ipq40xx/ipq40xx/files/drivers/net/phy/qca807x.c create mode 100644 feeds/ipq40xx/ipq40xx/generic/target.mk create mode 100644 feeds/ipq40xx/ipq40xx/image/Makefile create mode 100644 feeds/ipq40xx/ipq40xx/image/generic.mk create mode 100644 feeds/ipq40xx/ipq40xx/image/mikrotik.mk create mode 100644 feeds/ipq40xx/ipq40xx/mikrotik/config-default create mode 100644 feeds/ipq40xx/ipq40xx/mikrotik/target.mk create mode 100644 feeds/ipq40xx/ipq40xx/patches-5.4/0001-v5.7-ARM-qcom-Add-support-for-IPQ40xx.patch create mode 100644 feeds/ipq40xx/ipq40xx/patches-5.4/0002-01-v5.6-regulator-add-IPQ4019-SDHCI-VQMMC-LDO-driver.patch create mode 100644 feeds/ipq40xx/ipq40xx/patches-5.4/0002-02-v5.5-ARM-dts-qcom-ipq4019-Add-SDHCI-controller-node.patch create mode 100644 feeds/ipq40xx/ipq40xx/patches-5.4/0003-v5.6-ARM-dts-qcom-Add-nodes-for-SMP-boot-in-IPQ40xx.patch create mode 100644 feeds/ipq40xx/ipq40xx/patches-5.4/0003-v5.7-ARM-dts-qcom-add-gpio-ranges-property.patch create mode 100644 feeds/ipq40xx/ipq40xx/patches-5.4/0004-v5.8-ARM-dts-qcom-ipq4019-fix-high-resolution-timer.patch create mode 100644 feeds/ipq40xx/ipq40xx/patches-5.4/0005-01-v5.8-net-phy-mdio-add-IPQ4019-MDIO-driver.patch create mode 100644 feeds/ipq40xx/ipq40xx/patches-5.4/0005-02-v5.8-02-ARM-dts-qcom-ipq4019-add-MDIO-node.patch create mode 100644 feeds/ipq40xx/ipq40xx/patches-5.4/0006-v5.5-crypto-qce-add-CRYPTO_ALG_KERN_DRIVER_ONLY-flag.patch create mode 100644 feeds/ipq40xx/ipq40xx/patches-5.4/0007-v5.5-crypto-qce-switch-to-skcipher-API.patch create mode 100644 feeds/ipq40xx/ipq40xx/patches-5.4/0008-v5.6-crypto-qce-fix-ctr-aes-qce-block-chunk-sizes.patch create mode 100644 feeds/ipq40xx/ipq40xx/patches-5.4/0009-v5.6-crypto-qce-fix-xts-aes-qce-key-sizes.patch create mode 100644 feeds/ipq40xx/ipq40xx/patches-5.4/0010-v5.6-crypto-qce-save-a-sg-table-slot-for-result-buf.patch create mode 100644 feeds/ipq40xx/ipq40xx/patches-5.4/0011-v5.6-crypto-qce-update-the-skcipher-IV.patch create mode 100644 feeds/ipq40xx/ipq40xx/patches-5.4/0012-v5.6-crypto-qce-initialize-fallback-only-for-AES.patch create mode 100644 feeds/ipq40xx/ipq40xx/patches-5.4/0013-v5.6-crypto-qce-allow-building-only-hashes-ciphers.patch create mode 100644 feeds/ipq40xx/ipq40xx/patches-5.4/0014-v5.7-crypto-qce-use-cryptlen-when-adding-extra-sgl.patch create mode 100644 feeds/ipq40xx/ipq40xx/patches-5.4/0015-v5.7-crypto-qce-use-AES-fallback-for-small-requests.patch create mode 100644 feeds/ipq40xx/ipq40xx/patches-5.4/0016-v5.7-crypto-qce-handle-AES-XTS-cases-that-qce-fails.patch create mode 100644 feeds/ipq40xx/ipq40xx/patches-5.4/0017-v5.8-phy-add-driver-for-Qualcomm-IPQ40xx-USB-PHY.patch create mode 100644 feeds/ipq40xx/ipq40xx/patches-5.4/0018-v5.9-pinctrl-msm-open-drain.patch create mode 100644 feeds/ipq40xx/ipq40xx/patches-5.4/0019-v5.6-mtd-spi-nor-Add-support-for-mx25r3235f.patch create mode 100644 feeds/ipq40xx/ipq40xx/patches-5.4/100-GPIO-add-named-gpio-exports.patch create mode 100644 feeds/ipq40xx/ipq40xx/patches-5.4/101-arm-dts-IPQ4019-add-SDHCI-VQMMC-LDO-node.patch create mode 100644 feeds/ipq40xx/ipq40xx/patches-5.4/102-ARM-dts-qcom-ipq4019-add-USB-devicetree-nodes.patch create mode 100644 feeds/ipq40xx/ipq40xx/patches-5.4/103-arm-dts-qcom-ipq4019-add-more-labels.patch create mode 100644 feeds/ipq40xx/ipq40xx/patches-5.4/104-clk-fix-apss-cpu-overclocking.patch create mode 100644 feeds/ipq40xx/ipq40xx/patches-5.4/300-clk-qcom-ipq4019-add-ess-reset.patch create mode 100644 feeds/ipq40xx/ipq40xx/patches-5.4/301-arm-compressed-add-appended-DTB-section.patch create mode 100644 feeds/ipq40xx/ipq40xx/patches-5.4/302-arm-compressed-set-ipq40xx-watchdog-to-allow-boot.patch create mode 100644 feeds/ipq40xx/ipq40xx/patches-5.4/400-mmc-sdhci-sdhci-msm-use-sdhci_set_clock-instead-of-s.patch create mode 100644 feeds/ipq40xx/ipq40xx/patches-5.4/702-dts-ipq4019-add-PHY-switch-nodes.patch create mode 100644 feeds/ipq40xx/ipq40xx/patches-5.4/703-net-IPQ4019-needs-rfs-vlan_tag-callbacks-in.patch create mode 100644 feeds/ipq40xx/ipq40xx/patches-5.4/705-net-add-qualcomm-ar40xx-phy.patch create mode 100644 feeds/ipq40xx/ipq40xx/patches-5.4/706-dt-bindings-net-add-QCA807x-PHY.patch create mode 100644 feeds/ipq40xx/ipq40xx/patches-5.4/707-net-phy-Add-Qualcom-QCA807x-driver.patch create mode 100644 feeds/ipq40xx/ipq40xx/patches-5.4/708-arm-dts-ipq4019-QCA807x-properties.patch create mode 100644 feeds/ipq40xx/ipq40xx/patches-5.4/710-net-add-qualcomm-essedma-ethernet-driver.patch create mode 100644 feeds/ipq40xx/ipq40xx/patches-5.4/711-dts-ipq4019-add-ethernet-essedma-node.patch create mode 100644 feeds/ipq40xx/ipq40xx/patches-5.4/850-soc-add-qualcomm-syscon.patch create mode 100644 feeds/ipq40xx/ipq40xx/patches-5.4/900-dts-ipq4019-ap-dk01.1.patch create mode 100644 feeds/ipq40xx/ipq40xx/patches-5.4/901-arm-boot-add-dts-files.patch create mode 100644 feeds/ipq40xx/ipq40xx/patches-5.4/902-dts-ipq4019-ap-dk04.1.patch create mode 100644 feeds/ipq40xx/ipq40xx/patches-5.4/903-pstore.patch create mode 100644 feeds/ipq40xx/ipq40xx/patches-5.4/911-dts-ipq4019-indio-um-325ac.patch create mode 100644 feeds/ipq40xx/ipq40xx/patches-5.4/912-dts-ipq4019-indio-um-550ac.patch create mode 100644 feeds/ipq40xx/ipq40xx/patches-5.4/913-dts-ipq4019-indio-um-510ac-v3.patch create mode 100644 feeds/ipq40xx/ipq40xx/patches-5.4/997-device_tree_cmdline.patch create mode 100644 feeds/ipq40xx/ipq40xx/patches-5.4/998-tp-link-ec420-g1.patch create mode 100644 feeds/ipq40xx/ipq40xx/patches-5.4/999-hfcl_ion.patch create mode 100644 feeds/ipq40xx/ipq40xx/patches-5.4/9991-arm-boot-add-oap100e-dts-files.patch create mode 100644 feeds/ipq40xx/mac80211/Makefile create mode 100644 feeds/ipq40xx/mac80211/ath.mk create mode 100644 feeds/ipq40xx/mac80211/broadcom.mk create mode 100644 feeds/ipq40xx/mac80211/files/lib/netifd/wireless/mac80211.sh create mode 100644 feeds/ipq40xx/mac80211/files/lib/wifi/mac80211.sh create mode 100644 feeds/ipq40xx/mac80211/files/mac80211.hotplug create mode 100644 feeds/ipq40xx/mac80211/intel.mk create mode 100644 feeds/ipq40xx/mac80211/marvell.mk create mode 100644 feeds/ipq40xx/mac80211/patches/ath/070-ath_common_config.patch create mode 100644 feeds/ipq40xx/mac80211/patches/ath/080-ath10k_thermal_config.patch create mode 100644 feeds/ipq40xx/mac80211/patches/ath/120-owl-loader-compat.patch create mode 100644 feeds/ipq40xx/mac80211/patches/ath/201-ath5k-WAR-for-AR71xx-PCI-bug.patch create mode 100644 feeds/ipq40xx/mac80211/patches/ath/350-ath9k_hw-reset-AHB-WMAC-interface-on-AR91xx.patch create mode 100644 feeds/ipq40xx/mac80211/patches/ath/351-ath9k_hw-issue-external-reset-for-QCA955x.patch create mode 100644 feeds/ipq40xx/mac80211/patches/ath/354-ath9k-force-rx_clear-when-disabling-rx.patch create mode 100644 feeds/ipq40xx/mac80211/patches/ath/356-Revert-ath9k-interpret-requested-txpower-in-EIRP-dom.patch create mode 100644 feeds/ipq40xx/mac80211/patches/ath/365-ath9k-adjust-tx-power-reduction-for-US-regulatory-do.patch create mode 100644 feeds/ipq40xx/mac80211/patches/ath/400-ath_move_debug_code.patch create mode 100644 feeds/ipq40xx/mac80211/patches/ath/401-ath9k_blink_default.patch create mode 100644 feeds/ipq40xx/mac80211/patches/ath/402-ath_regd_optional.patch create mode 100644 feeds/ipq40xx/mac80211/patches/ath/403-world_regd_fixup.patch create mode 100644 feeds/ipq40xx/mac80211/patches/ath/404-regd_no_assoc_hints.patch create mode 100644 feeds/ipq40xx/mac80211/patches/ath/405-ath_regd_us.patch create mode 100644 feeds/ipq40xx/mac80211/patches/ath/406-ath_relax_default_regd.patch create mode 100644 feeds/ipq40xx/mac80211/patches/ath/410-ath9k_allow_adhoc_and_ap.patch create mode 100644 feeds/ipq40xx/mac80211/patches/ath/411-ath5k_allow_adhoc_and_ap.patch create mode 100644 feeds/ipq40xx/mac80211/patches/ath/420-ath5k_disable_fast_cc.patch create mode 100644 feeds/ipq40xx/mac80211/patches/ath/430-add_ath5k_platform.patch create mode 100644 feeds/ipq40xx/mac80211/patches/ath/431-add_platform_eeprom_support_to_ath5k.patch create mode 100644 feeds/ipq40xx/mac80211/patches/ath/432-ath5k_add_pciids.patch create mode 100644 feeds/ipq40xx/mac80211/patches/ath/440-ath5k_channel_bw_debugfs.patch create mode 100644 feeds/ipq40xx/mac80211/patches/ath/450-ath9k-enabled-MFP-capability-unconditionally.patch create mode 100644 feeds/ipq40xx/mac80211/patches/ath/500-ath9k_eeprom_debugfs.patch create mode 100644 feeds/ipq40xx/mac80211/patches/ath/501-ath9k_ahb_init.patch create mode 100644 feeds/ipq40xx/mac80211/patches/ath/510-ath9k_intr_mitigation_tweak.patch create mode 100644 feeds/ipq40xx/mac80211/patches/ath/511-ath9k_reduce_rxbuf.patch create mode 100644 feeds/ipq40xx/mac80211/patches/ath/512-ath9k_channelbw_debugfs.patch create mode 100644 feeds/ipq40xx/mac80211/patches/ath/513-ath9k_add_pci_ids.patch create mode 100644 feeds/ipq40xx/mac80211/patches/ath/530-ath9k_extra_leds.patch create mode 100644 feeds/ipq40xx/mac80211/patches/ath/531-ath9k_extra_platform_leds.patch create mode 100644 feeds/ipq40xx/mac80211/patches/ath/540-ath9k_reduce_ani_interval.patch create mode 100644 feeds/ipq40xx/mac80211/patches/ath/542-ath9k_debugfs_diag.patch create mode 100644 feeds/ipq40xx/mac80211/patches/ath/543-ath9k_entropy_from_adc.patch create mode 100644 feeds/ipq40xx/mac80211/patches/ath/544-ath9k-ar933x-usb-hang-workaround.patch create mode 100644 feeds/ipq40xx/mac80211/patches/ath/545-ath9k_ani_ws_detect.patch create mode 100644 feeds/ipq40xx/mac80211/patches/ath/547-ath9k_led_defstate_fix.patch create mode 100644 feeds/ipq40xx/mac80211/patches/ath/548-ath9k_enable_gpio_chip.patch create mode 100644 feeds/ipq40xx/mac80211/patches/ath/549-ath9k_enable_gpio_buttons.patch create mode 100644 feeds/ipq40xx/mac80211/patches/ath/550-ath9k-disable-bands-via-dt.patch create mode 100644 feeds/ipq40xx/mac80211/patches/ath/551-ath9k_ubnt_uap_plus_hsr.patch create mode 100644 feeds/ipq40xx/mac80211/patches/ath/552-ahb_of.patch create mode 100644 feeds/ipq40xx/mac80211/patches/ath/553-ath9k_of_gpio_mask.patch create mode 100644 feeds/ipq40xx/mac80211/patches/ath/921-ath10k_init_devices_synchronously.patch create mode 100644 feeds/ipq40xx/mac80211/patches/ath/922-ath10k-increase-rx-buffer-size-to-2048.patch create mode 100644 feeds/ipq40xx/mac80211/patches/ath/930-ath10k_add_tpt_led_trigger.patch create mode 100644 feeds/ipq40xx/mac80211/patches/ath/974-ath10k_add-LED-and-GPIO-controlling-support-for-various-chipsets.patch create mode 100644 feeds/ipq40xx/mac80211/patches/ath/975-ath10k-use-tpt-trigger-by-default.patch create mode 100644 feeds/ipq40xx/mac80211/patches/ath/980-ath10k-fix-max-antenna-gain-unit.patch create mode 100644 feeds/ipq40xx/mac80211/patches/ath/981-ath10k-adjust-tx-power-reduction-for-US-regulatory-d.patch create mode 100644 feeds/ipq40xx/mac80211/patches/brcm/040-brcmutil_option.patch create mode 100644 feeds/ipq40xx/mac80211/patches/brcm/810-b43-gpio-mask-module-option.patch create mode 100644 feeds/ipq40xx/mac80211/patches/brcm/811-b43_no_pio.patch create mode 100644 feeds/ipq40xx/mac80211/patches/brcm/812-b43-add-antenna-control.patch create mode 100644 feeds/ipq40xx/mac80211/patches/brcm/813-b43-reduce-number-of-RX-slots.patch create mode 100644 feeds/ipq40xx/mac80211/patches/brcm/814-b43-only-use-gpio-0-1-for-led.patch create mode 100644 feeds/ipq40xx/mac80211/patches/brcm/815-b43-always-take-overlapping-devs.patch create mode 100644 feeds/ipq40xx/mac80211/patches/brcm/850-brcmsmac-remove-extra-regulation-restriction.patch create mode 100644 feeds/ipq40xx/mac80211/patches/brcm/860-brcmfmac-register-wiphy-s-during-module_init.patch create mode 100644 feeds/ipq40xx/mac80211/patches/brcm/861-brcmfmac-workaround-bug-with-some-inconsistent-BSSes.patch create mode 100644 feeds/ipq40xx/mac80211/patches/brcm/862-brcmfmac-Disable-power-management.patch create mode 100644 feeds/ipq40xx/mac80211/patches/brcm/863-brcmfmac-add-in-driver-tables-with-country-codes.patch create mode 100644 feeds/ipq40xx/mac80211/patches/brcm/864-brcmfmac-do-not-use-internal-roaming-engine-by-default.patch create mode 100644 feeds/ipq40xx/mac80211/patches/brcm/998-survey.patch create mode 100644 feeds/ipq40xx/mac80211/patches/build/000-fix_kconfig.patch create mode 100644 feeds/ipq40xx/mac80211/patches/build/001-fix_build.patch create mode 100644 feeds/ipq40xx/mac80211/patches/build/002-change_allconfig.patch create mode 100644 feeds/ipq40xx/mac80211/patches/build/003-remove_bogus_modparams.patch create mode 100644 feeds/ipq40xx/mac80211/patches/build/004-kconfig_backport_fix.patch create mode 100644 feeds/ipq40xx/mac80211/patches/build/010-disable_rfkill.patch create mode 100644 feeds/ipq40xx/mac80211/patches/build/012-kernel_build_check.patch create mode 100644 feeds/ipq40xx/mac80211/patches/build/015-ipw200-mtu.patch create mode 100644 feeds/ipq40xx/mac80211/patches/build/050-lib80211_option.patch create mode 100644 feeds/ipq40xx/mac80211/patches/build/060-no_local_ssb_bcma.patch create mode 100644 feeds/ipq40xx/mac80211/patches/mwl/700-mwl8k-missing-pci-id-for-WNR854T.patch create mode 100644 feeds/ipq40xx/mac80211/patches/mwl/801-libertas-configure-sysfs-links.patch create mode 100644 feeds/ipq40xx/mac80211/patches/mwl/802-libertas-set-wireless-macaddr.patch create mode 100644 feeds/ipq40xx/mac80211/patches/mwl/940-mwl8k_init_devices_synchronously.patch create mode 100644 feeds/ipq40xx/mac80211/patches/rt2x00/002-rt2x00-define-RF5592-in-init_eeprom-routine.patch create mode 100644 feeds/ipq40xx/mac80211/patches/rt2x00/100-rt2x00_options.patch create mode 100644 feeds/ipq40xx/mac80211/patches/rt2x00/501-rt2x00-allow-to-build-rt2800soc-module-for-RT3883.patch create mode 100644 feeds/ipq40xx/mac80211/patches/rt2x00/601-rt2x00-introduce-rt2x00_platform_h.patch create mode 100644 feeds/ipq40xx/mac80211/patches/rt2x00/602-rt2x00-introduce-rt2x00eeprom.patch create mode 100644 feeds/ipq40xx/mac80211/patches/rt2x00/603-rt2x00-of_load_eeprom_filename.patch create mode 100644 feeds/ipq40xx/mac80211/patches/rt2x00/604-rt2x00-load-eeprom-on-SoC-from-a-mtd-device-defines-.patch create mode 100644 feeds/ipq40xx/mac80211/patches/rt2x00/606-rt2x00-allow_disabling_bands_through_platform_data.patch create mode 100644 feeds/ipq40xx/mac80211/patches/rt2x00/607-rt2x00-add_platform_data_mac_addr.patch create mode 100644 feeds/ipq40xx/mac80211/patches/rt2x00/608-rt2x00-allow_disabling_bands_through_dts.patch create mode 100644 feeds/ipq40xx/mac80211/patches/rt2x00/609-rt2x00-make-wmac-loadable-via-OF-on-rt288x-305x-SoC.patch create mode 100644 feeds/ipq40xx/mac80211/patches/rt2x00/610-rt2x00-change-led-polarity-from-OF.patch create mode 100644 feeds/ipq40xx/mac80211/patches/rt2x00/611-rt2x00-add-AP+STA-support.patch create mode 100644 feeds/ipq40xx/mac80211/patches/rt2x00/612-rt2x00-led-tpt-trigger-support.patch create mode 100644 feeds/ipq40xx/mac80211/patches/rt2x00/650-rt2x00-add-support-for-external-PA-on-MT7620.patch create mode 100644 feeds/ipq40xx/mac80211/patches/rt2x00/982-rt2x00-add-rf-self-txdc-calibration.patch create mode 100644 feeds/ipq40xx/mac80211/patches/rt2x00/983-rt2x00-add-r-calibration.patch create mode 100644 feeds/ipq40xx/mac80211/patches/rt2x00/984-rt2x00-add-rxdcoc-calibration.patch create mode 100644 feeds/ipq40xx/mac80211/patches/rt2x00/985-rt2x00-add-rxiq-calibration.patch create mode 100644 feeds/ipq40xx/mac80211/patches/rt2x00/986-rt2x00-add-TX-LOFT-calibration.patch create mode 100644 feeds/ipq40xx/mac80211/patches/subsys/070-backports-add-netif_receive_skb_list.patch create mode 100644 feeds/ipq40xx/mac80211/patches/subsys/071-backports-add-skb_list_del_init.patch create mode 100644 feeds/ipq40xx/mac80211/patches/subsys/100-remove-cryptoapi-dependencies.patch create mode 100644 feeds/ipq40xx/mac80211/patches/subsys/110-mac80211_keep_keys_on_stop_ap.patch create mode 100644 feeds/ipq40xx/mac80211/patches/subsys/120-cfg80211_allow_perm_addr_change.patch create mode 100644 feeds/ipq40xx/mac80211/patches/subsys/131-Revert-mac80211-aes-cmac-switch-to-shash-CMAC-driver.patch create mode 100644 feeds/ipq40xx/mac80211/patches/subsys/132-mac80211-remove-cmac-dependency.patch create mode 100644 feeds/ipq40xx/mac80211/patches/subsys/150-disable_addr_notifier.patch create mode 100644 feeds/ipq40xx/mac80211/patches/subsys/210-ap_scan.patch create mode 100644 feeds/ipq40xx/mac80211/patches/subsys/300-mac80211-optimize-skb-resizing.patch create mode 100644 feeds/ipq40xx/mac80211/patches/subsys/304-mac80211-sta-randomize-BA-session-dialog-token-alloc.patch create mode 100644 feeds/ipq40xx/mac80211/patches/subsys/305-mac80211-improve-AQL-tx-airtime-estimation.patch create mode 100644 feeds/ipq40xx/mac80211/patches/subsys/307-mac80211-add-a-function-for-running-rx-without-passi.patch create mode 100644 feeds/ipq40xx/mac80211/patches/subsys/308-net-fq_impl-use-skb_get_hash-instead-of-skb_get_hash.patch create mode 100644 feeds/ipq40xx/mac80211/patches/subsys/309-mac80211-calculcate-skb-hash-early-when-using-itxq.patch create mode 100644 feeds/ipq40xx/mac80211/patches/subsys/310-mac80211-reduce-packet-loss-event-false-positives.patch create mode 100644 feeds/ipq40xx/mac80211/patches/subsys/311-mac80211-use-rate-provided-via-status-rate-on-ieee80.patch create mode 100644 feeds/ipq40xx/mac80211/patches/subsys/312-mac80211-factor-out-code-to-look-up-the-average-pack.patch create mode 100644 feeds/ipq40xx/mac80211/patches/subsys/313-mac80211-improve-AQL-aggregation-estimation-for-low-.patch create mode 100644 feeds/ipq40xx/mac80211/patches/subsys/314-mac80211-add-missing-queue-hash-initialization-to-80.patch create mode 100644 feeds/ipq40xx/mac80211/patches/subsys/315-mac80211-check-and-refresh-aggregation-session-in-en.patch create mode 100644 feeds/ipq40xx/mac80211/patches/subsys/316-mac80211-skip-encap-offload-for-tx-multicast-control.patch create mode 100644 feeds/ipq40xx/mac80211/patches/subsys/317-mac80211-set-info-control.hw_key-for-encap-offload-p.patch create mode 100644 feeds/ipq40xx/mac80211/patches/subsys/318-mac80211-rework-tx-encapsulation-offload-API.patch create mode 100644 feeds/ipq40xx/mac80211/patches/subsys/319-mac80211-reduce-duplication-in-tx-status-functions.patch create mode 100644 feeds/ipq40xx/mac80211/patches/subsys/320-mac80211-remove-tx-status-call-to-ieee80211_sta_regi.patch create mode 100644 feeds/ipq40xx/mac80211/patches/subsys/321-mac80211-optimize-station-connection-monitor.patch create mode 100644 feeds/ipq40xx/mac80211/patches/subsys/322-mac80211-swap-NEED_TXPROCESSING-and-HW_80211_ENCAP-t.patch create mode 100644 feeds/ipq40xx/mac80211/patches/subsys/323-mac80211-unify-802.3-offload-and-802.11-tx-status-co.patch create mode 100644 feeds/ipq40xx/mac80211/patches/subsys/324-mac80211-support-using-ieee80211_tx_status_ext-to-fr.patch create mode 100644 feeds/ipq40xx/mac80211/patches/subsys/325-mac80211-extend-ieee80211_tx_status_ext-to-support-b.patch create mode 100644 feeds/ipq40xx/mac80211/patches/subsys/326-mac80211-notify-the-driver-when-a-sta-uses-4-address.patch create mode 100644 feeds/ipq40xx/mac80211/patches/subsys/327-mac80211-reorganize-code-to-remove-a-forward-declara.patch create mode 100644 feeds/ipq40xx/mac80211/patches/subsys/328-mac80211-extend-AQL-aggregation-estimation-to-HE-and.patch create mode 100644 feeds/ipq40xx/mac80211/patches/subsys/329-mac80211-add-AQL-support-for-VHT160-tx-rates.patch create mode 100644 feeds/ipq40xx/mac80211/patches/subsys/370-mac80211-fix-misplaced-while-instead-of-if.patch create mode 100644 feeds/ipq40xx/mac80211/patches/subsys/400-allow-ibss-mixed.patch create mode 100644 feeds/ipq40xx/mac80211/patches/subsys/500-mac80211_configure_antenna_gain.patch create mode 100644 feeds/ipq40xx/mac80211/patches/subsys/800-oom.patch create mode 100644 feeds/ipq40xx/mac80211/ralink.mk create mode 100644 feeds/ipq40xx/mac80211/realtek.mk create mode 100755 feeds/ipq40xx/mac80211/scripts/import-backports.sh create mode 100644 feeds/ipq40xx/wireguard/Makefile create mode 100644 feeds/ipq40xx/wireguard/patches/100-compat.patch diff --git a/feeds/ipq40xx/ath10k-ct-firmware/Makefile b/feeds/ipq40xx/ath10k-ct-firmware/Makefile new file mode 100644 index 000000000..ce92567b5 --- /dev/null +++ b/feeds/ipq40xx/ath10k-ct-firmware/Makefile @@ -0,0 +1,701 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=ath10k-ct-firmware +PKG_VERSION:=2020-10-07 +PKG_RELEASE:=2 +CTVER1=021 +CTVER2=021 + +# From fw_lede.bash, or can do it manually as well. +H988XFC=a4c3d1e2fb80f6b8b9738c7189795ab9505e6c09efc12ba5f08ee7f49e934239 +H988XFCH=93108bd0870652860cdb57749f5a12205ecb15bb1f129d916ad73b6f06406c82 +H9887FC=459692deb186a63ab8eeddb7ad5d54779266e68ca686e7c46062554db6dca12b +H9887FCH=fd126a457d0927d0c8ea10d66ef5b67d5e1e0741f8692bb3016bb602d0af3098 +H9980FC=52300e9d128c3d506e0b133d7a7964df3115f9511f1b574ef2a0767972c063bd +H9980FCH=9c20c3a44b701f8fef0fe02f156e382b36b717fb56c76d540f6eac2077ec189b +H9980CH=55f27045e7cf87a6a5656a050771d6d7a6197153a0737288a702c0836d5c6572 +H9980FHQ=add509b2a15ba90869f403c2e4440dbb91bd7037188d8468249cf1263adfd44e +H9984FC=e6354a1547a308b4b0fe4cbc29693848c234acedd9e7a483a1b4fb5f9bbf0dc0 +H9984FCH=6e19ecd0b001ffb594a8b033deb2007595b8c0402402789b7de55b208639ebec +H9984CH=7b6fdf3d970f3eff7c34df476c934a9bebb4f289b7968067950d31b82c71bb07 +H9984FHQ=f6a5d5a3a7b2c9267dc31673a19ee3b5312a2f84f26123cb5e8c000428ed76d2 +H4019FC=cde992cb328680e81cf85e195554699bcceef065c0c696ce4ef90c3311ab11fb +H4019FCH=818afeb1226389357dfde754d641f936fb82ebe78607f10e15efd5c952a54f48 +H4019CH=30ba10f0d82116c6617cb58c3df5cc81e5ed8f29dbc8f95c0ca9c5013ce4f702 +H4019FHQ=8e4161f7bed5bd56513ca5caab582a6eee64e9e14a69f4de67587563b7b4d735 +H9888FC=d24e66bdb2f1098a2e06ff20fe037e31937e1a483e87c68827830513b4233b5d +H9888FCH=5891e1c184da433ecc12ca0176ca89a77f7bc2b675576698b69bc93d46b77042 +H9888CH=b94f46cdda6171e5f566b1cdd6aafd68ff1a4f7e8a27762b90eb5d4f03839d99 +H9888FHQ=3cc81f8707bf5ba63bc9ffc14578c77637cae0e15766ae146af02eefb9ab7bfd + +include $(INCLUDE_DIR)/package.mk + +ATH10K_FIRMWARE_REV:=d622d160e9f552ead68d9ae81b715422892dc2ef +ATH10K_FIRMWARE_URL:=@GITHUB/kvalo/ath10k-firmware/$(ATH10K_FIRMWARE_REV) + +QCA9887_BOARD_FILE:=ath10k-firmware-$(ATH10K_FIRMWARE_REV)-qca9887-board.bin +define Download/qca9887-board + FILE:=$(QCA9887_BOARD_FILE) + URL:=$(ATH10K_FIRMWARE_URL)/QCA9887/hw1.0 + URL_FILE:=board.bin + HASH:=cf4df099f6ee05c181f55ce17297a1d32c61d725eb96246fd315ad5587c42426 +endef +$(eval $(call Download,qca9887-board)) + +QCA988X_BOARD_FILE:=ath10k-firmware-$(ATH10K_FIRMWARE_REV)-qca988x-board.bin +define Download/qca988x-board + FILE:=$(QCA988X_BOARD_FILE) + URL:=$(ATH10K_FIRMWARE_URL)/QCA988X/hw2.0 + URL_FILE:=board.bin + HASH:=5b5b380333c2dd3b6ce67f30e2f7008f4020bf594970d3b464fd8d4a80fcd880 +endef +$(eval $(call Download,qca988x-board)) + +QCA99X0_BOARD_FILE:=ath10k-firmware-$(ATH10K_FIRMWARE_REV)-qca99x0-board.bin +define Download/qca99x0-board + FILE:=$(QCA99X0_BOARD_FILE) + URL:=$(ATH10K_FIRMWARE_URL)/QCA99X0/hw2.0 + URL_FILE:=boardData_AR900B_CUS239_5G_v2_001.bin + HASH:=3bf7561ee373b369025dcd366d276d038a97d3397ccae41ce841d98a58b30aff +endef +$(eval $(call Download,qca99x0-board)) + +QCA99X0_BOARD2_REV:=ddcec9efd245da9365c474f513a855a55f3ac7fe +QCA99X0_BOARD2_FILE:=ath10k-firmware-$(QCA99X0_BOARD2_REV)-qca99x0-board-2.bin +define Download/qca99x0-board2 + FILE:=$(QCA99X0_BOARD2_FILE) + URL:=https://source.codeaurora.org/quic/qsdk/oss/firmware/ath10k-firmware/plain/ath10k/QCA99X0/hw2.0 + URL_FILE:=board-2.bin?id=$(QCA99X0_BOARD2_REV) + HASH:=03711ac21e60ef59d3815e235eb721c0c22851b5410299411085aa6f2af45401 +endef +$(eval $(call Download,qca99x0-board2)) + +QCA9984_BOARD2_FILE:=ath10k-firmware-$(ATH10K_FIRMWARE_REV)-qca9984-board-2.bin +define Download/qca9984-board2 + FILE:=$(QCA9984_BOARD2_FILE) + URL:=$(ATH10K_FIRMWARE_URL)/QCA9984/hw1.0 + URL_FILE:=board-2.bin + HASH:=0d6d46cf0467185e3959ce3cb69e2415be6e48ab8a4bee3eb400edbe48cb9c25 +endef +$(eval $(call Download,qca9984-board2)) + +QCA4019_BOARD2_FILE:=ath10k-firmware-$(ATH10K_FIRMWARE_REV)-qca4019-board-2.bin +define Download/qca4019-board2 + FILE:=$(QCA4019_BOARD2_FILE) + URL:=$(ATH10K_FIRMWARE_URL)/QCA4019/hw1.0 + URL_FILE:=board-2.bin + HASH:=94b66aa4ddbed5110a96364d3c7b4ebcb320e3ac4e8697660b277e76077bc338 +endef +$(eval $(call Download,qca4019-board2)) + +QCA9888_BOARD2_FILE:=ath10k-firmware-$(ATH10K_FIRMWARE_REV)-qca9888-board-2.bin +define Download/qca9888-board2 + FILE:=$(QCA9888_BOARD2_FILE) + URL:=$(ATH10K_FIRMWARE_URL)/QCA9888/hw2.0 + URL_FILE:=board-2.bin + HASH:=5b871bb567f64525ca45adb88063211de472015d09e0f9aa3fa61ab71c8fdfd3 +endef +$(eval $(call Download,qca9888-board2)) + +CT_FIRMWARE_FILE = $(1)-$($(1)_FIRMWARE_FILE_CT) +CT_FIRMWARE_FILE_FULL_HTT = $(1)-$($(1)_FIRMWARE_FILE_CT_FULL_HTT) +CT_FIRMWARE_FILE_HTT = $(1)-$($(1)_FIRMWARE_FILE_CT_HTT) + +define Download/ct-firmware + URL:=https://www.candelatech.com/downloads/$(2) + FILE:=$(call CT_FIRMWARE_FILE,$(1)) + URL_FILE:=$($(1)_FIRMWARE_FILE_CT) +endef + +define Download/ct-firmware-full-htt + URL:=https://www.candelatech.com/downloads/$(2) + FILE:=$(call CT_FIRMWARE_FILE_FULL_HTT,$(1)) + URL_FILE:=$($(1)_FIRMWARE_FILE_CT_FULL_HTT) +endef + +define Download/ct-firmware-htt + URL:=https://www.candelatech.com/downloads/$(2) + FILE:=$(call CT_FIRMWARE_FILE_HTT,$(1)) + URL_FILE:=$($(1)_FIRMWARE_FILE_CT_HTT) +endef + +QCA988X_FIRMWARE_FILE_CT:=firmware-2-ct-full-community-22.bin.lede.$(CTVER1) +define Download/ath10k-firmware-qca988x-ct + $(call Download/ct-firmware,QCA988X,) + HASH:=$(H988XFC) +endef +$(eval $(call Download,ath10k-firmware-qca988x-ct)) + +QCA988X_FIRMWARE_FILE_CT_FULL_HTT:=firmware-2-ct-full-htt-mgt-community-22.bin.lede.$(CTVER1) +define Download/ath10k-firmware-qca988x-ct-full-htt + $(call Download/ct-firmware-full-htt,QCA988X,) + HASH:=$(H988XFCH) +endef +$(eval $(call Download,ath10k-firmware-qca988x-ct-full-htt)) + + +QCA9887_FIRMWARE_FILE_CT:=firmware-2-ct-full-community-22.bin.lede.$(CTVER1) +define Download/ath10k-firmware-qca9887-ct + $(call Download/ct-firmware,QCA9887,ath10k-9887) + HASH:=$(H9887FC) +endef +$(eval $(call Download,ath10k-firmware-qca9887-ct)) + +QCA9887_FIRMWARE_FILE_CT_FULL_HTT:=firmware-2-ct-full-htt-mgt-community-22.bin.lede.$(CTVER1) +define Download/ath10k-firmware-qca9887-ct-full-htt + $(call Download/ct-firmware-full-htt,QCA9887,ath10k-9887) + HASH:=$(H9887FCH) +endef +$(eval $(call Download,ath10k-firmware-qca9887-ct-full-htt)) + + +QCA99X0_FIRMWARE_FILE_CT:=firmware-5-ct-full-community-12.bin-lede.$(CTVER2) +define Download/ath10k-firmware-qca99x0-ct + $(call Download/ct-firmware,QCA99X0,ath10k-10-4b) + HASH:=$(H9980FC) +endef +$(eval $(call Download,ath10k-firmware-qca99x0-ct)) + +QCA99X0_FIRMWARE_FILE_CT_FULL_HTT:=firmware-5-ct-full-htt-mgt-community-12.bin-lede.$(CTVER2) +define Download/ath10k-firmware-qca99x0-ct-full-htt + $(call Download/ct-firmware-full-htt,QCA99X0,ath10k-10-4b) + HASH:=$(H9980FCH) +endef +$(eval $(call Download,ath10k-firmware-qca99x0-ct-full-htt)) + +QCA99X0_FIRMWARE_FILE_CT_HTT:=firmware-5-ct-htt-mgt-community-12.bin-lede.$(CTVER2) +define Download/ath10k-firmware-qca99x0-ct-htt + $(call Download/ct-firmware-htt,QCA99X0,ath10k-10-4b) + HASH:=$(H9980CH) +endef +$(eval $(call Download,ath10k-firmware-qca99x0-ct-htt)) + + +QCA9984_FIRMWARE_FILE_CT:=firmware-5-ct-full-community-12.bin-lede.$(CTVER2) +define Download/ath10k-firmware-qca9984-ct + $(call Download/ct-firmware,QCA9984,ath10k-9984-10-4b) + HASH:=$(H9984FC) +endef +$(eval $(call Download,ath10k-firmware-qca9984-ct)) + +QCA9984_FIRMWARE_FILE_CT_FULL_HTT:=firmware-5-ct-full-htt-mgt-community-12.bin-lede.$(CTVER2) +define Download/ath10k-firmware-qca9984-ct-full-htt + $(call Download/ct-firmware-full-htt,QCA9984,ath10k-9984-10-4b) + HASH:=$(H9984FCH) +endef +$(eval $(call Download,ath10k-firmware-qca9984-ct-full-htt)) + +QCA9984_FIRMWARE_FILE_CT_HTT:=firmware-5-ct-htt-mgt-community-12.bin-lede.$(CTVER2) +define Download/ath10k-firmware-qca9984-ct-htt + $(call Download/ct-firmware-htt,QCA9984,ath10k-9984-10-4b) + HASH:=$(H9984CH) +endef +$(eval $(call Download,ath10k-firmware-qca9984-ct-htt)) + + +QCA4019_FIRMWARE_FILE_CT:=firmware-5-ct-full-community-12.bin-lede.$(CTVER2) +define Download/ath10k-firmware-qca4019-ct + $(call Download/ct-firmware,QCA4019,ath10k-4019-10-4b) + HASH:=$(H4019FC) +endef +$(eval $(call Download,ath10k-firmware-qca4019-ct)) + +QCA4019_FIRMWARE_FILE_CT_FULL_HTT:=firmware-5-ct-full-htt-mgt-community-12.bin-lede.$(CTVER2) +define Download/ath10k-firmware-qca4019-ct-full-htt + $(call Download/ct-firmware-full-htt,QCA4019,ath10k-4019-10-4b) + HASH:=$(H4019FCH) +endef +$(eval $(call Download,ath10k-firmware-qca4019-ct-full-htt)) + +QCA4019_FIRMWARE_FILE_CT_HTT:=firmware-5-ct-htt-mgt-community-12.bin-lede.$(CTVER2) +define Download/ath10k-firmware-qca4019-ct-htt + $(call Download/ct-firmware-htt,QCA4019,ath10k-4019-10-4b) + HASH:=$(H4019CH) +endef +$(eval $(call Download,ath10k-firmware-qca4019-ct-htt)) + + +QCA9888_FIRMWARE_FILE_CT:=firmware-5-ct-full-community-12.bin-lede.$(CTVER2) +define Download/ath10k-firmware-qca9888-ct + $(call Download/ct-firmware,QCA9888,ath10k-9888-10-4b) + HASH:=$(H9888FC) +endef +$(eval $(call Download,ath10k-firmware-qca9888-ct)) + +QCA9888_FIRMWARE_FILE_CT_FULL_HTT:=firmware-5-ct-full-htt-mgt-community-12.bin-lede.$(CTVER2) +define Download/ath10k-firmware-qca9888-ct-full-htt + $(call Download/ct-firmware-full-htt,QCA9888,ath10k-9888-10-4b) + HASH:=$(H9888FCH) +endef +$(eval $(call Download,ath10k-firmware-qca9888-ct-full-htt)) + +QCA9888_FIRMWARE_FILE_CT_HTT:=firmware-5-ct-htt-mgt-community-12.bin-lede.$(CTVER2) +define Download/ath10k-firmware-qca9888-ct-htt + $(call Download/ct-firmware-htt,QCA9888,ath10k-9888-10-4b) + HASH:=$(H9888CH) +endef +$(eval $(call Download,ath10k-firmware-qca9888-ct-htt)) + + +define Package/ath10k-ct-firmware-default + SECTION:=firmware + CATEGORY:=Firmware + URL:=https://www.candelatech.com/ath10k.php + DEPENDS:= +endef + +define Package/ath10k-firmware-qca988x-ct +$(Package/ath10k-ct-firmware-default) + TITLE:=ath10k CT 10.1 firmware for QCA988x devices + SECTION:=firmware + CATEGORY:=Firmware + PROVIDES:=ath10k-firmware-qca988x +endef +define Package/ath10k-firmware-qca988x-ct-full-htt +$(Package/ath10k-ct-firmware-default) + TITLE:=ath10k CT 10.1 full-htt-mgt fw for QCA988x + SECTION:=firmware + CATEGORY:=Firmware + PROVIDES:=ath10k-firmware-qca988x + DEPENDS:=+!PACKAGE_kmod-ath10k-ct-smallbuffers:kmod-ath10k-ct +endef + +define Package/ath10k-firmware-qca9887-ct +$(Package/ath10k-ct-firmware-default) + TITLE:=ath10k CT 10.1 firmware for QCA9887 devices + SECTION:=firmware + CATEGORY:=Firmware + PROVIDES:=ath10k-firmware-qca9887 +endef +define Package/ath10k-firmware-qca9887-ct-full-htt +$(Package/ath10k-ct-firmware-default) + TITLE:=ath10k CT 10.1 full-htt-mgt fw for QCA9887 + SECTION:=firmware + CATEGORY:=Firmware + PROVIDES:=ath10k-firmware-qca9887 + DEPENDS:=+!PACKAGE_kmod-ath10k-ct-smallbuffers:kmod-ath10k-ct +endef + +define Package/ath10k-firmware-qca99x0-ct +$(Package/ath10k-ct-firmware-default) + TITLE:=ath10k CT 10.4 firmware for QCA99x0 devices + SECTION:=firmware + CATEGORY:=Firmware + PROVIDES:=ath10k-firmware-qca99x0 +endef +define Package/ath10k-firmware-qca99x0-ct-full-htt +$(Package/ath10k-ct-firmware-default) + TITLE:=ath10k CT 10.4 full-htt-mgt fw for QCA99x0 + SECTION:=firmware + CATEGORY:=Firmware + PROVIDES:=ath10k-firmware-qca99x0 + DEPENDS:=+!PACKAGE_kmod-ath10k-ct-smallbuffers:kmod-ath10k-ct +endef +define Package/ath10k-firmware-qca99x0-ct-htt +$(Package/ath10k-firmware-default) + TITLE:=ath10k CT 10.4 htt-mgt fw for QCA99x0 + SECTION:=firmware + CATEGORY:=Firmware + PROVIDES:=ath10k-firmware-qca99x0 + DEPENDS:=+!PACKAGE_kmod-ath10k-ct-smallbuffers:kmod-ath10k-ct +endef + +define Package/ath10k-firmware-qca9984-ct +$(Package/ath10k-ct-firmware-default) + TITLE:=ath10k CT 10.4 firmware for QCA9984 devices + SECTION:=firmware + CATEGORY:=Firmware + PROVIDES:=ath10k-firmware-qca9984 +endef +define Package/ath10k-firmware-qca9984-ct-full-htt +$(Package/ath10k-ct-firmware-default) + TITLE:=ath10k CT 10.4 full-htt-mgt fw for QCA9984 + SECTION:=firmware + CATEGORY:=Firmware + PROVIDES:=ath10k-firmware-qca9984 + DEPENDS:=+!PACKAGE_kmod-ath10k-ct-smallbuffers:kmod-ath10k-ct +endef +define Package/ath10k-firmware-qca9984-ct-htt +$(Package/ath10k-firmware-default) + TITLE:=ath10k CT 10.4 htt-mgt fw for QCA9984 + SECTION:=firmware + CATEGORY:=Firmware + PROVIDES:=ath10k-firmware-qca9984 + DEPENDS:=+!PACKAGE_kmod-ath10k-ct-smallbuffers:kmod-ath10k-ct +endef + +define Package/ath10k-firmware-qca4019-ct +$(Package/ath10k-ct-firmware-default) + TITLE:=ath10k CT 10.4 firmware for QCA4018/9 + SECTION:=firmware + CATEGORY:=Firmware + PROVIDES:=ath10k-firmware-qca4019 +endef +define Package/ath10k-firmware-qca4019-ct-full-htt +$(Package/ath10k-ct-firmware-default) + TITLE:=ath10k CT 10.4 full-htt-mgt for QCA4018/9 + SECTION:=firmware + CATEGORY:=Firmware + PROVIDES:=ath10k-firmware-qca4019 + DEPENDS:=+!PACKAGE_kmod-ath10k-ct-smallbuffers:kmod-ath10k-ct +endef +define Package/ath10k-firmware-qca4019-ct-htt +$(Package/ath10k-firmware-default) + TITLE:=ath10k CT 10.4 htt-mgt for QCA4018/9 + SECTION:=firmware + CATEGORY:=Firmware + PROVIDES:=ath10k-firmware-qca4019 + DEPENDS:=+!PACKAGE_kmod-ath10k-ct-smallbuffers:kmod-ath10k-ct +endef + +define Package/ath10k-firmware-qca9888-ct +$(Package/ath10k-ct-firmware-default) + TITLE:=ath10k CT 10.4 fw for QCA9886/8 devices + SECTION:=firmware + CATEGORY:=Firmware + PROVIDES:=ath10k-firmware-qca9888 +endef +define Package/ath10k-firmware-qca9888-ct-full-htt +$(Package/ath10k-ct-firmware-default) + TITLE:=ath10k CT 10.4 full-htt-mgt fw for QCA9886/8 + SECTION:=firmware + CATEGORY:=Firmware + PROVIDES:=ath10k-firmware-qca9888 + DEPENDS:=+!PACKAGE_kmod-ath10k-ct-smallbuffers:kmod-ath10k-ct +endef +define Package/ath10k-firmware-qca9888-ct-htt +$(Package/ath10k-firmware-default) + TITLE:=ath10k CT 10.4 htt-mgt fw for QCA9886/8 + SECTION:=firmware + CATEGORY:=Firmware + PROVIDES:=ath10k-firmware-qca9888 + DEPENDS:=+!PACKAGE_kmod-ath10k-ct-smallbuffers:kmod-ath10k-ct +endef + + +define Package/ath10k-firmware-qca9887-ct/description +Alternative ath10k firmware for QCA9887 from Candela Technologies. +Enables IBSS and other features. See: +http://www.candelatech.com/ath10k-10.1.php +This firmware conflicts with the standard 9887 firmware, so select only +one. +endef +define Package/ath10k-firmware-qca9887-ct-full-htt/description +Alternative ath10k firmware for QCA9887 from Candela Technologies. +Uses normal HTT TX data path for management frames, which improves +stability in busy networks and fixes .11r authentication. +Enables IBSS and other features. See: +http://www.candelatech.com/ath10k-10.1.php +This firmware selects and requires the ath10k-ct driver. +endef + +define Package/ath10k-firmware-qca988x-ct/description +Alternative ath10k firmware for QCA988X from Candela Technologies. +Enables IBSS and other features. See: +http://www.candelatech.com/ath10k-10.1.php +This firmware will NOT be used unless the standard ath10k-firmware-qca988x +is un-selected since the driver will try to load firmware-5.bin before +firmware-2.bin +endef +define Package/ath10k-firmware-qca988x-ct-full-htt/description +Alternative ath10k firmware for QCA988X from Candela Technologies. +Uses normal HTT TX data path for management frames, which improves +stability in busy networks and fixes .11r authentication. +Enables IBSS and other features. See: +http://www.candelatech.com/ath10k-10.1.php +This firmware selects and requires the ath10k-ct driver. +endef + +define Package/ath10k-firmware-qca99x0-ct/description +Alternative ath10k firmware for QCA99x0 from Candela Technologies. +Enables IBSS and other features. See: +http://www.candelatech.com/ath10k-10.4.php +This firmware conflicts with the standard 99x0 firmware, so select only +one. +endef +define Package/ath10k-firmware-qca99x0-ct-full-htt/description +Alternative ath10k firmware for QCA99x0 from Candela Technologies. +Uses normal HTT TX data path for management frames, which improves +stability in busy networks and may be required for .11r authentication. +Enables IBSS and other features. See: +http://www.candelatech.com/ath10k-10.4.php +This firmware selects and requires the ath10k-ct driver. +endef +define Package/ath10k-firmware-qca99x0-ct-htt/description +Alternative ath10k firmware for QCA99x0 from Candela Technologies. +Uses normal HTT TX data path for management frames, which improves +stability in busy networks and may be required for .11r authentication. +This firmware lacks a lot of features that ath10k does not use, saving +a lot of resources. +Enables IBSS and other features. See: +http://www.candelatech.com/ath10k-10.4.php +This firmware selects and requires the ath10k-ct driver. +endef + +define Package/ath10k-firmware-qca9984-ct/description +Alternative ath10k firmware for QCA9984 from Candela Technologies. +Enables IBSS and other features. See: +http://www.candelatech.com/ath10k-10.4.php +This firmware conflicts with the standard 9984 firmware, so select only +one. +endef +define Package/ath10k-firmware-qca9984-ct-full-htt/description +Alternative ath10k firmware for QCA9984 from Candela Technologies. +Uses normal HTT TX data path for management frames, which improves +stability in busy networks and may be required for .11r authentication. +Enables IBSS and other features. See: +http://www.candelatech.com/ath10k-10.4.php +This firmware selects and requires the ath10k-ct driver. +endef +define Package/ath10k-firmware-qca9984-ct-htt/description +Alternative ath10k firmware for QCA9984 from Candela Technologies. +Uses normal HTT TX data path for management frames, which improves +stability in busy networks and may be required for .11r authentication. +This firmware lacks a lot of features that ath10k does not use, saving +a lot of resources. +Enables IBSS and other features. See: +http://www.candelatech.com/ath10k-10.4.php +This firmware selects and requires the ath10k-ct driver. +endef + +define Package/ath10k-firmware-qca4019-ct/description +Alternative ath10k firmware for IPQ4019 radio from Candela Technologies. +Enables IBSS and other features. Works with standard or ath10k-ct driver. +See: http://www.candelatech.com/ath10k-10.4.php +endef +define Package/ath10k-firmware-qca4019-ct-full-htt/description +Alternative ath10k firmware for IPQ4019 radio from Candela Technologies. +Uses normal HTT TX data path for management frames, which improves +stability in busy networks and may be required for .11r authentication. +Enables IBSS and other features. +See: http://www.candelatech.com/ath10k-10.4.php +This firmware selects and requires the ath10k-ct driver. +endef +define Package/ath10k-firmware-qca4019-ct-htt/description +Alternative ath10k firmware for IPQ4019 radio from Candela Technologies. +Uses normal HTT TX data path for management frames, which improves +stability in busy networks and may be required for .11r authentication. +This firmware lacks a lot of features that ath10k does not use, saving +a lot of resources. +Enables IBSS and other features. +See: http://www.candelatech.com/ath10k-10.4.php +This firmware selects and requires the ath10k-ct driver. +endef + +define Package/ath10k-firmware-qca9888-ct/description +Alternative ath10k firmware for QCA9886 and QCA9888 from Candela Technologies. +Enables IBSS and other features. See: +http://www.candelatech.com/ath10k-10.4.php +This firmware conflicts with the standard 9886 and 9888 firmware, so select only +one. +endef +define Package/ath10k-firmware-qca9888-ct-full-htt/description +Alternative ath10k firmware for QCA9886 and QCA9888 from Candela Technologies. +Uses normal HTT TX data path for management frames, which improves +stability in busy networks and may be required for .11r authentication. +Enables IBSS and other features. See: +http://www.candelatech.com/ath10k-10.4.php +This firmware selects and requires the ath10k-ct driver. +endef +define Package/ath10k-firmware-qca9888-ct-htt/description +Alternative ath10k firmware for QCA9886 and QCA9888 from Candela Technologies. +Uses normal HTT TX data path for management frames, which improves +stability in busy networks and may be required for .11r authentication. +This firmware lacks a lot of features that ath10k does not use, saving +a lot of resources. +Enables IBSS and other features. See: +http://www.candelatech.com/ath10k-10.4.php +This firmware selects and requires the ath10k-ct driver. +endef + + +define Build/Compile + +endef + + +define Package/ath10k-firmware-qca9887-ct/install + $(INSTALL_DIR) $(1)/lib/firmware/ath10k/QCA9887/hw1.0 + $(INSTALL_DATA) \ + $(DL_DIR)/$(call CT_FIRMWARE_FILE,QCA9887) \ + $(1)/lib/firmware/ath10k/QCA9887/hw1.0/firmware-2.bin + $(INSTALL_DATA) \ + $(DL_DIR)/$(QCA9887_BOARD_FILE) \ + $(1)/lib/firmware/ath10k/QCA9887/hw1.0/board.bin +endef +define Package/ath10k-firmware-qca9887-ct-full-htt/install + $(INSTALL_DIR) $(1)/lib/firmware/ath10k/QCA9887/hw1.0 + $(INSTALL_DATA) \ + $(DL_DIR)/$(call CT_FIRMWARE_FILE_FULL_HTT,QCA9887) \ + $(1)/lib/firmware/ath10k/QCA9887/hw1.0/ct-firmware-2.bin + $(INSTALL_DATA) \ + $(DL_DIR)/$(QCA9887_BOARD_FILE) \ + $(1)/lib/firmware/ath10k/QCA9887/hw1.0/board.bin +endef + +define Package/ath10k-firmware-qca988x-ct/install + $(INSTALL_DIR) $(1)/lib/firmware/ath10k/QCA988X/hw2.0 + $(INSTALL_DATA) \ + $(DL_DIR)/$(QCA988X_BOARD_FILE) \ + $(1)/lib/firmware/ath10k/QCA988X/hw2.0/board.bin + $(INSTALL_DATA) \ + $(DL_DIR)/$(call CT_FIRMWARE_FILE,QCA988X) \ + $(1)/lib/firmware/ath10k/QCA988X/hw2.0/firmware-2.bin +endef +define Package/ath10k-firmware-qca988x-ct-full-htt/install + $(INSTALL_DIR) $(1)/lib/firmware/ath10k/QCA988X/hw2.0 + $(INSTALL_DATA) \ + $(DL_DIR)/$(QCA988X_BOARD_FILE) \ + $(1)/lib/firmware/ath10k/QCA988X/hw2.0/board.bin + $(INSTALL_DATA) \ + $(DL_DIR)/$(call CT_FIRMWARE_FILE_FULL_HTT,QCA988X) \ + $(1)/lib/firmware/ath10k/QCA988X/hw2.0/ct-firmware-2.bin +endef + +define Package/ath10k-firmware-qca99x0-ct/install + $(INSTALL_DIR) $(1)/lib/firmware/ath10k/QCA99X0/hw2.0 + $(INSTALL_DATA) \ + $(DL_DIR)/$(QCA99X0_BOARD2_FILE) \ + $(1)/lib/firmware/ath10k/QCA99X0/hw2.0/board-2.bin + $(INSTALL_DATA) \ + $(DL_DIR)/$(QCA99X0_BOARD_FILE) \ + $(1)/lib/firmware/ath10k/QCA99X0/hw2.0/board.bin + $(INSTALL_DATA) \ + $(DL_DIR)/$(call CT_FIRMWARE_FILE,QCA99X0) \ + $(1)/lib/firmware/ath10k/QCA99X0/hw2.0/firmware-5.bin +endef +define Package/ath10k-firmware-qca99x0-ct-full-htt/install + $(INSTALL_DIR) $(1)/lib/firmware/ath10k/QCA99X0/hw2.0 + $(INSTALL_DATA) \ + $(DL_DIR)/$(QCA99X0_BOARD2_FILE) \ + $(1)/lib/firmware/ath10k/QCA99X0/hw2.0/board-2.bin + $(INSTALL_DATA) \ + $(DL_DIR)/$(QCA99X0_BOARD_FILE) \ + $(1)/lib/firmware/ath10k/QCA99X0/hw2.0/board.bin + $(INSTALL_DATA) \ + $(DL_DIR)/$(call CT_FIRMWARE_FILE_FULL_HTT,QCA99X0) \ + $(1)/lib/firmware/ath10k/QCA99X0/hw2.0/ct-firmware-5.bin +endef +define Package/ath10k-firmware-qca99x0-ct-htt/install + $(INSTALL_DIR) $(1)/lib/firmware/ath10k/QCA99X0/hw2.0 + $(INSTALL_DATA) \ + $(DL_DIR)/$(QCA99X0_BOARD2_FILE) \ + $(1)/lib/firmware/ath10k/QCA99X0/hw2.0/board-2.bin + $(INSTALL_DATA) \ + $(DL_DIR)/$(QCA99X0_BOARD_FILE) \ + $(1)/lib/firmware/ath10k/QCA99X0/hw2.0/board.bin + $(INSTALL_DATA) \ + $(DL_DIR)/$(call CT_FIRMWARE_FILE_HTT,QCA99X0) \ + $(1)/lib/firmware/ath10k/QCA99X0/hw2.0/ct-firmware-5.bin +endef + +define Package/ath10k-firmware-qca9984-ct/install + $(INSTALL_DIR) $(1)/lib/firmware/ath10k/QCA9984/hw1.0 + $(INSTALL_DATA) \ + $(DL_DIR)/$(QCA9984_BOARD2_FILE) \ + $(1)/lib/firmware/ath10k/QCA9984/hw1.0/board-2.bin + $(INSTALL_DATA) \ + $(DL_DIR)/$(call CT_FIRMWARE_FILE,QCA9984) \ + $(1)/lib/firmware/ath10k/QCA9984/hw1.0/firmware-5.bin +endef +define Package/ath10k-firmware-qca9984-ct-full-htt/install + $(INSTALL_DIR) $(1)/lib/firmware/ath10k/QCA9984/hw1.0 + $(INSTALL_DATA) \ + $(DL_DIR)/$(QCA9984_BOARD2_FILE) \ + $(1)/lib/firmware/ath10k/QCA9984/hw1.0/board-2.bin + $(INSTALL_DATA) \ + $(DL_DIR)/$(call CT_FIRMWARE_FILE_FULL_HTT,QCA9984) \ + $(1)/lib/firmware/ath10k/QCA9984/hw1.0/ct-firmware-5.bin +endef +define Package/ath10k-firmware-qca9984-ct-htt/install + $(INSTALL_DIR) $(1)/lib/firmware/ath10k/QCA9984/hw1.0 + $(INSTALL_DATA) \ + $(DL_DIR)/$(QCA9984_BOARD2_FILE) \ + $(1)/lib/firmware/ath10k/QCA9984/hw1.0/board-2.bin + $(INSTALL_DATA) \ + $(DL_DIR)/$(call CT_FIRMWARE_FILE_HTT,QCA9984) \ + $(1)/lib/firmware/ath10k/QCA9984/hw1.0/ct-firmware-5.bin +endef + +define Package/ath10k-firmware-qca4019-ct/install + $(INSTALL_DIR) $(1)/lib/firmware/ath10k/QCA4019/hw1.0 + $(INSTALL_DATA) \ + $(DL_DIR)/$(QCA4019_BOARD2_FILE) \ + $(1)/lib/firmware/ath10k/QCA4019/hw1.0/board-2.bin + $(INSTALL_DATA) \ + $(DL_DIR)/$(call CT_FIRMWARE_FILE,QCA4019) \ + $(1)/lib/firmware/ath10k/QCA4019/hw1.0/firmware-5.bin +endef +define Package/ath10k-firmware-qca4019-ct-full-htt/install + $(INSTALL_DIR) $(1)/lib/firmware/ath10k/QCA4019/hw1.0 + $(INSTALL_DATA) \ + $(DL_DIR)/$(QCA4019_BOARD2_FILE) \ + $(1)/lib/firmware/ath10k/QCA4019/hw1.0/board-2.bin + $(INSTALL_DATA) \ + $(DL_DIR)/$(call CT_FIRMWARE_FILE_FULL_HTT,QCA4019) \ + $(1)/lib/firmware/ath10k/QCA4019/hw1.0/ct-firmware-5.bin +endef +define Package/ath10k-firmware-qca4019-ct-htt/install + $(INSTALL_DIR) $(1)/lib/firmware/ath10k/QCA4019/hw1.0 + $(INSTALL_DATA) \ + $(DL_DIR)/$(QCA4019_BOARD2_FILE) \ + $(1)/lib/firmware/ath10k/QCA4019/hw1.0/board-2.bin + $(INSTALL_DATA) \ + $(DL_DIR)/$(call CT_FIRMWARE_FILE_HTT,QCA4019) \ + $(1)/lib/firmware/ath10k/QCA4019/hw1.0/ct-firmware-5.bin +endef + +define Package/ath10k-firmware-qca9888-ct/install + $(INSTALL_DIR) $(1)/lib/firmware/ath10k/QCA9888/hw2.0 + ln -s \ + ../../cal-pci-0000:01:00.0.bin \ + $(1)/lib/firmware/ath10k/QCA9888/hw2.0/board.bin + $(INSTALL_DATA) \ + $(DL_DIR)/$(QCA9888_BOARD2_FILE) \ + $(1)/lib/firmware/ath10k/QCA9888/hw2.0/board-2.bin + $(INSTALL_DATA) \ + $(DL_DIR)/$(call CT_FIRMWARE_FILE,QCA9888) \ + $(1)/lib/firmware/ath10k/QCA9888/hw2.0/firmware-5.bin +endef +define Package/ath10k-firmware-qca9888-ct-full-htt/install + $(INSTALL_DIR) $(1)/lib/firmware/ath10k/QCA9888/hw2.0 + ln -s \ + ../../cal-pci-0000:01:00.0.bin \ + $(1)/lib/firmware/ath10k/QCA9888/hw2.0/board.bin + $(INSTALL_DATA) \ + $(DL_DIR)/$(QCA9888_BOARD2_FILE) \ + $(1)/lib/firmware/ath10k/QCA9888/hw2.0/board-2.bin + $(INSTALL_DATA) \ + $(DL_DIR)/$(call CT_FIRMWARE_FILE_FULL_HTT,QCA9888) \ + $(1)/lib/firmware/ath10k/QCA9888/hw2.0/ct-firmware-5.bin +endef +define Package/ath10k-firmware-qca9888-ct-htt/install + $(INSTALL_DIR) $(1)/lib/firmware/ath10k/QCA9888/hw2.0 + ln -s \ + ../../cal-pci-0000:01:00.0.bin \ + $(1)/lib/firmware/ath10k/QCA9888/hw2.0/board.bin + $(INSTALL_DATA) \ + $(DL_DIR)/$(QCA9888_BOARD2_FILE) \ + $(1)/lib/firmware/ath10k/QCA9888/hw2.0/board-2.bin + $(INSTALL_DATA) \ + $(DL_DIR)/$(call CT_FIRMWARE_FILE_HTT,QCA9888) \ + $(1)/lib/firmware/ath10k/QCA9888/hw2.0/ct-firmware-5.bin +endef + + +$(eval $(call BuildPackage,ath10k-firmware-qca9887-ct)) +$(eval $(call BuildPackage,ath10k-firmware-qca9887-ct-full-htt)) +$(eval $(call BuildPackage,ath10k-firmware-qca988x-ct)) +$(eval $(call BuildPackage,ath10k-firmware-qca988x-ct-full-htt)) +$(eval $(call BuildPackage,ath10k-firmware-qca99x0-ct)) +$(eval $(call BuildPackage,ath10k-firmware-qca99x0-ct-full-htt)) +$(eval $(call BuildPackage,ath10k-firmware-qca99x0-ct-htt)) +$(eval $(call BuildPackage,ath10k-firmware-qca9984-ct)) +$(eval $(call BuildPackage,ath10k-firmware-qca9984-ct-full-htt)) +$(eval $(call BuildPackage,ath10k-firmware-qca9984-ct-htt)) +$(eval $(call BuildPackage,ath10k-firmware-qca4019-ct)) +$(eval $(call BuildPackage,ath10k-firmware-qca4019-ct-full-htt)) +$(eval $(call BuildPackage,ath10k-firmware-qca4019-ct-htt)) +$(eval $(call BuildPackage,ath10k-firmware-qca9888-ct)) +$(eval $(call BuildPackage,ath10k-firmware-qca9888-ct-full-htt)) +$(eval $(call BuildPackage,ath10k-firmware-qca9888-ct-htt)) diff --git a/feeds/ipq40xx/ath10k-ct/Makefile b/feeds/ipq40xx/ath10k-ct/Makefile new file mode 100644 index 000000000..578082457 --- /dev/null +++ b/feeds/ipq40xx/ath10k-ct/Makefile @@ -0,0 +1,122 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=ath10k-ct +PKG_RELEASE=1 + +PKG_LICENSE:=GPLv2 +PKG_LICENSE_FILES:= + +PKG_SOURCE_URL:=https://github.com/greearb/ath10k-ct.git +PKG_MIRROR_HASH:=37b4f00231cb0ae00f63da1c94ae53c940c76d047ce0fb081c08a35fffbfd2c0 +PKG_SOURCE_PROTO:=git +PKG_SOURCE_DATE:=2021-05-22b +PKG_SOURCE_VERSION:=54a9ac02f1139596ea4361ebbc3e444955d86cfd +#PKG_MIRROR_HASH:=97cf22a4a57381c7eb7a9b8a8b1e347e9711ce51c89db971b4ab9a35af476ece + +# Build the 5.4 ath10k-ct driver version. Other option is "-4.19". +# Probably this should match as closely as +# possible to whatever mac80211 backports version is being used. +CT_KVER="-5.7" + +PKG_MAINTAINER:=Ben Greear +PKG_BUILD_PARALLEL:=1 +PKG_EXTMOD_SUBDIRS:=ath10k$(CT_KVER) + +STAMP_CONFIGURED_DEPENDS := $(STAGING_DIR)/usr/include/mac80211-backport/backport/autoconf.h + +include $(INCLUDE_DIR)/kernel.mk +include $(INCLUDE_DIR)/package.mk + +define KernelPackage/ath10k-ct + SUBMENU:=Wireless Drivers + TITLE:=ath10k-ct driver optimized for CT ath10k firmware + DEPENDS:=+kmod-mac80211 +kmod-ath +@DRIVER_11N_SUPPORT +@DRIVER_11AC_SUPPORT +@DRIVER_11W_SUPPORT @PCI_SUPPORT +kmod-hwmon-core + FILES:=\ + $(PKG_BUILD_DIR)/ath10k$(CT_KVER)/ath10k_pci.ko \ + $(PKG_BUILD_DIR)/ath10k$(CT_KVER)/ath10k_core.ko + AUTOLOAD:=$(call AutoProbe,ath10k_pci) + PROVIDES:=kmod-ath10k + VARIANT:=regular +endef + +define KernelPackage/ath10k-ct/config + + config ATH10K-CT_LEDS + bool "Enable LED support" + default y + depends on PACKAGE_kmod-ath10k-ct || PACKAGE_kmod-ath10k-ct-smallbuffers +endef + +define KernelPackage/ath10k-ct-smallbuffers +$(call KernelPackage/ath10k-ct) + TITLE+= (small buffers for low-RAM devices) + VARIANT:=smallbuffers +endef + +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 + +ifdef CONFIG_PACKAGE_MAC80211_MESH + NOSTDINC_FLAGS += -DCONFIG_MAC80211_MESH +endif + +CT_MAKEDEFS += CONFIG_ATH10K=m CONFIG_ATH10K_PCI=m CONFIG_ATH10K_CE=y + +# This AHB logic is needed for IPQ4019 radios +CT_MAKEDEFS += CONFIG_ATH10K_AHB=m +NOSTDINC_FLAGS += -DCONFIG_ATH10K_AHB + +NOSTDINC_FLAGS += -DSTANDALONE_CT + +ifdef CONFIG_PACKAGE_MAC80211_DEBUGFS + CT_MAKEDEFS += CONFIG_ATH10K_DEBUGFS=y CONFIG_MAC80211_DEBUGFS=y + NOSTDINC_FLAGS += -DCONFIG_MAC80211_DEBUGFS + NOSTDINC_FLAGS += -DCONFIG_ATH10K_DEBUGFS +endif + +ifdef CONFIG_PACKAGE_ATH_DEBUG + NOSTDINC_FLAGS += -DCONFIG_ATH10K_DEBUG +endif + +ifdef CONFIG_PACKAGE_ATH_DFS + NOSTDINC_FLAGS += -DCONFIG_ATH10K_DFS_CERTIFIED +endif + +ifdef CONFIG_PACKAGE_ATH_SPECTRAL + CT_MAKEDEFS += CONFIG_ATH10K_SPECTRAL=y + NOSTDINC_FLAGS += -DCONFIG_ATH10K_SPECTRAL +endif + +ifeq ($(CONFIG_ATH10K-CT_LEDS),y) + CT_MAKEDEFS += CONFIG_ATH10K_LEDS=y + NOSTDINC_FLAGS += -DCONFIG_ATH10K_LEDS +endif + +ifeq ($(BUILD_VARIANT),smallbuffers) + NOSTDINC_FLAGS += -DCONFIG_ATH10K_SMALLBUFFERS +endif + +define Build/Configure + cp $(STAGING_DIR)/usr/include/mac80211/ath/*.h $(PKG_BUILD_DIR) +endef + +ifneq ($(findstring c,$(OPENWRT_VERBOSE)),) + CT_MAKEDEFS += V=1 +endif + +define Build/Compile + +$(MAKE) $(CT_MAKEDEFS) $(PKG_JOBS) -C "$(LINUX_DIR)" \ + $(KERNEL_MAKE_FLAGS) \ + M="$(PKG_BUILD_DIR)/ath10k$(CT_KVER)" \ + NOSTDINC_FLAGS="$(NOSTDINC_FLAGS)" \ + modules +endef + +$(eval $(call KernelPackage,ath10k-ct)) +$(eval $(call KernelPackage,ath10k-ct-smallbuffers)) diff --git a/feeds/ipq40xx/ath10k-ct/patches/164-ath10k-commit-rates-from-mac80211.patch b/feeds/ipq40xx/ath10k-ct/patches/164-ath10k-commit-rates-from-mac80211.patch new file mode 100644 index 000000000..4e88c8a19 --- /dev/null +++ b/feeds/ipq40xx/ath10k-ct/patches/164-ath10k-commit-rates-from-mac80211.patch @@ -0,0 +1,37 @@ +From: Sven Eckelmann +Date: Tue, 26 Feb 2019 08:06:35 +0100 +Subject: ath10k-ct: apply mac80211 rates to ath10k-ct rate state + +The rates from mac80211 have to be copied to the state of ath10k-ct or +otherwise the ath10k_check_apply_special_rates function overwrites +them again with some default values. This breaks for example the +mcast_rate set for a wifi-iface. + +Signed-off-by: Sven Eckelmann + +--- a/ath10k-5.4/mac.c ++++ b/ath10k-5.4/mac.c +@@ -6793,6 +6793,7 @@ static void ath10k_bss_info_changed(stru + "mac vdev %d mcast_rate %x\n", + arvif->vdev_id, rate); + ++ arvif->mcast_rate[band] = rate; + vdev_param = ar->wmi.vdev_param->mcast_data_rate; + ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, + vdev_param, rate); +@@ -6801,6 +6802,7 @@ static void ath10k_bss_info_changed(stru + "failed to set mcast rate on vdev %i: %d\n", + arvif->vdev_id, ret); + ++ arvif->bcast_rate[band] = rate; + vdev_param = ar->wmi.vdev_param->bcast_data_rate; + ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, + vdev_param, rate); +@@ -6827,6 +6829,7 @@ static void ath10k_bss_info_changed(stru + return; + } + ++ arvif->mgt_rate[def.chan->band] = hw_rate_code; + vdev_param = ar->wmi.vdev_param->mgmt_rate; + ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param, + hw_rate_code); diff --git a/feeds/ipq40xx/ath10k-ct/patches/201-ath10k-add-LED-and-GPIO-controlling-support-for-various-chipsets.patch b/feeds/ipq40xx/ath10k-ct/patches/201-ath10k-add-LED-and-GPIO-controlling-support-for-various-chipsets.patch new file mode 100644 index 000000000..c20800209 --- /dev/null +++ b/feeds/ipq40xx/ath10k-ct/patches/201-ath10k-add-LED-and-GPIO-controlling-support-for-various-chipsets.patch @@ -0,0 +1,598 @@ +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. +Reworked to use ath10k-ct custom source + + +Signed-off-by: Sebastian Gottschall +Reviewed-by: Steve deRosier +[kvalo: major reorg and cleanup] +Signed-off-by: Kalle Valo +Signed-off-by: Ansuel Smith +--- + +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 + + ath10k-5.4/Kconfig | 10 +++ + ath10k-5.4/Makefile | 1 + + ath10k-5.4/core.c | 22 +++++++ + ath10k-5.4/core.h | 9 ++- + ath10k-5.4/hw.h | 1 + + ath10k-5.4/leds.c | 103 ++++++++++++++++++++++++++++++ + ath10k-5.4/leds.h | 45 +++++++++++++ + ath10k-5.4/mac.c | 1 + + ath10k-5.4/wmi-ops.h | 32 ++++++++++ + ath10k-5.4/wmi-tlv.c | 2 + + ath10k-5.4/wmi.c | 54 ++++++++++++++++ + ath10k-5.4/wmi.h | 35 ++++++++++ + 12 files changed, 314 insertions(+), 1 deletion(-) + create mode 100644 ath10k-5.4/leds.c + create mode 100644 ath10k-5.4/leds.h + +--- a/ath10k-5.4/Kconfig ++++ b/ath10k-5.4/Kconfig +@@ -66,6 +66,16 @@ config ATH10K_DEBUGFS + + If unsure, say Y to make it easier to debug problems. + ++config ATH10K_LEDS ++ bool "Atheros ath10k LED support" ++ depends on ATH10K ++ 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" + depends on ATH10K_DEBUGFS +--- a/ath10k-5.4/Makefile ++++ b/ath10k-5.4/Makefile +@@ -19,6 +19,7 @@ ath10k_core-$(CONFIG_ATH10K_SPECTRAL) += + ath10k_core-$(CONFIG_NL80211_TESTMODE) += testmode.o + ath10k_core-$(CONFIG_ATH10K_TRACING) += trace.o + ath10k_core-$(CONFIG_THERMAL) += thermal.o ++ath10k_core-$(CONFIG_ATH10K_LEDS) += leds.o + ath10k_core-$(CONFIG_MAC80211_DEBUGFS) += debugfs_sta.o + ath10k_core-$(CONFIG_PM) += wow.o + ath10k_core-$(CONFIG_DEV_COREDUMP) += coredump.o +--- a/ath10k-5.4/core.c ++++ b/ath10k-5.4/core.c +@@ -25,6 +25,7 @@ + #include "testmode.h" + #include "wmi-ops.h" + #include "coredump.h" ++#include "leds.h" + + /* Disable ath10k-ct DBGLOG output by default */ + unsigned int ath10k_debug_mask = ATH10K_DBG_NO_DBGLOG; +@@ -67,6 +68,7 @@ static const struct ath10k_hw_params ath + .dev_id = QCA988X_2_0_DEVICE_ID, + .bus = ATH10K_BUS_PCI, + .name = "qca988x hw2.0", ++ .led_pin = 1, + .patch_load_addr = QCA988X_HW_2_0_PATCH_LOAD_ADDR, + .uart_pin = 7, + .cc_wraparound_type = ATH10K_HW_CC_WRAP_SHIFTED_ALL, +@@ -137,6 +139,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, + .cc_wraparound_type = ATH10K_HW_CC_WRAP_SHIFTED_ALL, +@@ -344,6 +347,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, + .otp_exe_param = 0x00000700, +@@ -385,6 +389,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, + .cc_wraparound_type = ATH10K_HW_CC_WRAP_SHIFTED_EACH, +@@ -433,6 +438,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, + .cc_wraparound_type = ATH10K_HW_CC_WRAP_SHIFTED_EACH, +@@ -3573,6 +3579,10 @@ int ath10k_core_start(struct ath10k *ar, + ath10k_wmi_check_apply_board_power_ctl_table(ar); + } + ++ status = ath10k_leds_start(ar); ++ if (status) ++ goto err_hif_stop; ++ + return 0; + + err_hif_stop: +@@ -3829,9 +3839,18 @@ static void ath10k_core_register_work(st + goto err_spectral_destroy; + } + ++ status = ath10k_leds_register(ar); ++ if (status) { ++ ath10k_err(ar, "could not register leds: %d\n", ++ status); ++ goto err_thermal_unregister; ++ } ++ + set_bit(ATH10K_FLAG_CORE_REGISTERED, &ar->dev_flags); + return; + ++err_thermal_unregister: ++ ath10k_thermal_unregister(ar); + err_spectral_destroy: + ath10k_spectral_destroy(ar); + err_debug_destroy: +@@ -3891,6 +3910,8 @@ void ath10k_core_unregister(struct ath10 + if (!test_bit(ATH10K_FLAG_CORE_REGISTERED, &ar->dev_flags)) + return; + ++ ath10k_leds_unregister(ar); ++ + ath10k_thermal_unregister(ar); + /* Stop spectral before unregistering from mac80211 to remove the + * relayfs debugfs file cleanly. Otherwise the parent debugfs tree +--- a/ath10k-5.4/core.h ++++ b/ath10k-5.4/core.h +@@ -14,6 +14,7 @@ + #include + #include + #include ++#include + + #include "htt.h" + #include "htc.h" +@@ -1469,6 +1470,13 @@ struct ath10k { + } testmode; + + struct { ++ struct gpio_led wifi_led; ++ struct led_classdev cdev; ++ char label[48]; ++ u32 gpio_state_pin; ++ } leds; ++ ++ struct { + /* protected by data_lock */ + u32 fw_crash_counter; + u32 fw_warm_reset_counter; +--- a/ath10k-5.4/hw.h ++++ b/ath10k-5.4/hw.h +@@ -518,6 +518,7 @@ struct ath10k_hw_params { + const char *name; + u32 patch_load_addr; + int uart_pin; ++ int led_pin; + u32 otp_exe_param; + + /* Type of hw cycle counter wraparound logic, for more info +--- /dev/null ++++ b/ath10k-5.4/leds.c +@@ -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. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ++ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ++ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++ ++#include "core.h" ++#include "wmi.h" ++#include "wmi-ops.h" ++ ++#include "leds.h" ++ ++static int ath10k_leds_set_brightness_blocking(struct led_classdev *led_cdev, ++ enum led_brightness brightness) ++{ ++ struct ath10k *ar = container_of(led_cdev, struct ath10k, ++ leds.cdev); ++ struct gpio_led *led = &ar->leds.wifi_led; ++ ++ mutex_lock(&ar->conf_mutex); ++ ++ if (ar->state != ATH10K_STATE_ON) ++ goto out; ++ ++ ar->leds.gpio_state_pin = (brightness != LED_OFF) ^ led->active_low; ++ ath10k_wmi_gpio_output(ar, led->gpio, ar->leds.gpio_state_pin); ++ ++out: ++ mutex_unlock(&ar->conf_mutex); ++ ++ return 0; ++} ++ ++int ath10k_leds_start(struct ath10k *ar) ++{ ++ if (ar->hw_params.led_pin == 0) ++ /* leds not supported */ ++ return 0; ++ ++ /* under some circumstances, the gpio pin gets reconfigured ++ * to default state by the firmware, so we need to ++ * reconfigure it this behaviour has only ben seen on ++ * QCA9984 and QCA99XX devices so far ++ */ ++ ath10k_wmi_gpio_config(ar, ar->hw_params.led_pin, 0, ++ WMI_GPIO_PULL_NONE, WMI_GPIO_INTTYPE_DISABLE); ++ ath10k_wmi_gpio_output(ar, ar->hw_params.led_pin, 1); ++ ++ return 0; ++} ++ ++int ath10k_leds_register(struct ath10k *ar) ++{ ++ int ret; ++ ++ if (ar->hw_params.led_pin == 0) ++ /* leds not supported */ ++ return 0; ++ ++ snprintf(ar->leds.label, sizeof(ar->leds.label), "ath10k-%s", ++ wiphy_name(ar->hw->wiphy)); ++ ar->leds.wifi_led.active_low = 1; ++ ar->leds.wifi_led.gpio = ar->hw_params.led_pin; ++ ar->leds.wifi_led.name = ar->leds.label; ++ ar->leds.wifi_led.default_state = LEDS_GPIO_DEFSTATE_KEEP; ++ ++ 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); ++ if (ret) ++ return ret; ++ ++ return 0; ++} ++ ++void ath10k_leds_unregister(struct ath10k *ar) ++{ ++ if (ar->hw_params.led_pin == 0) ++ /* leds not supported */ ++ return; ++ ++ led_classdev_unregister(&ar->leds.cdev); ++} ++ +--- /dev/null ++++ b/ath10k-5.4/leds.h +@@ -0,0 +1,41 @@ ++/* ++ * 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_ ++ ++#include "core.h" ++ ++#ifdef CONFIG_ATH10K_LEDS ++void ath10k_leds_unregister(struct ath10k *ar); ++int ath10k_leds_start(struct ath10k *ar); ++int ath10k_leds_register(struct ath10k *ar); ++#else ++static inline void ath10k_leds_unregister(struct ath10k *ar) ++{ ++} ++ ++static inline int ath10k_leds_start(struct ath10k *ar) ++{ ++ return 0; ++} ++ ++static inline int ath10k_leds_register(struct ath10k *ar) ++{ ++ return 0; ++} ++ ++#endif ++#endif /* _LEDS_H_ */ +--- a/ath10k-5.4/mac.c ++++ b/ath10k-5.4/mac.c +@@ -24,6 +24,7 @@ + #include "wmi-tlv.h" + #include "wmi-ops.h" + #include "wow.h" ++#include "leds.h" + + /*********/ + /* Rates */ +--- a/ath10k-5.4/wmi-ops.h ++++ b/ath10k-5.4/wmi-ops.h +@@ -218,7 +218,10 @@ struct wmi_ops { + struct sk_buff *(*gen_bb_timing) + (struct ath10k *ar, + const struct wmi_bb_timing_cfg_arg *arg); ++ struct sk_buff *(*gen_gpio_config)(struct ath10k *ar, u32 gpio_num, ++ u32 input, u32 pull_type, u32 intr_mode); + ++ struct sk_buff *(*gen_gpio_output)(struct ath10k *ar, u32 gpio_num, u32 set); + }; + + int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id); +@@ -1105,6 +1108,35 @@ ath10k_wmi_force_fw_hang(struct ath10k * + return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->force_fw_hang_cmdid); + } + ++static inline int ath10k_wmi_gpio_config(struct ath10k *ar, u32 gpio_num, ++ u32 input, u32 pull_type, u32 intr_mode) ++{ ++ struct sk_buff *skb; ++ ++ if (!ar->wmi.ops->gen_gpio_config) ++ return -EOPNOTSUPP; ++ ++ skb = ar->wmi.ops->gen_gpio_config(ar, gpio_num, input, pull_type, intr_mode); ++ if (IS_ERR(skb)) ++ return PTR_ERR(skb); ++ ++ return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->gpio_config_cmdid); ++} ++ ++static inline int ath10k_wmi_gpio_output(struct ath10k *ar, u32 gpio_num, u32 set) ++{ ++ struct sk_buff *skb; ++ ++ if (!ar->wmi.ops->gen_gpio_config) ++ return -EOPNOTSUPP; ++ ++ skb = ar->wmi.ops->gen_gpio_output(ar, gpio_num, set); ++ if (IS_ERR(skb)) ++ return PTR_ERR(skb); ++ ++ return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->gpio_output_cmdid); ++} ++ + static inline int + ath10k_wmi_dbglog_cfg(struct ath10k *ar, u64 module_enable, u32 log_level) + { +--- a/ath10k-5.4/wmi-tlv.c ++++ b/ath10k-5.4/wmi-tlv.c +@@ -4364,6 +4364,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, ++ /* .gen_gpio_config not implemented */ ++ /* .gen_gpio_output not implemented */ + }; + + static const struct wmi_peer_flags_map wmi_tlv_peer_flags_map = { +--- a/ath10k-5.4/wmi.c ++++ b/ath10k-5.4/wmi.c +@@ -8295,6 +8295,49 @@ ath10k_wmi_op_gen_peer_set_param(struct + return skb; + } + ++static struct sk_buff *ath10k_wmi_op_gen_gpio_config(struct ath10k *ar, ++ u32 gpio_num, u32 input, ++ u32 pull_type, u32 intr_mode) ++{ ++ struct wmi_gpio_config_cmd *cmd; ++ struct sk_buff *skb; ++ ++ skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd)); ++ if (!skb) ++ return ERR_PTR(-ENOMEM); ++ ++ cmd = (struct wmi_gpio_config_cmd *)skb->data; ++ cmd->pull_type = __cpu_to_le32(pull_type); ++ cmd->gpio_num = __cpu_to_le32(gpio_num); ++ cmd->input = __cpu_to_le32(input); ++ cmd->intr_mode = __cpu_to_le32(intr_mode); ++ ++ ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi gpio_config gpio_num 0x%08x input 0x%08x pull_type 0x%08x intr_mode 0x%08x\n", ++ gpio_num, input, pull_type, intr_mode); ++ ++ return skb; ++} ++ ++static struct sk_buff *ath10k_wmi_op_gen_gpio_output(struct ath10k *ar, ++ u32 gpio_num, u32 set) ++{ ++ struct wmi_gpio_output_cmd *cmd; ++ struct sk_buff *skb; ++ ++ skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd)); ++ if (!skb) ++ return ERR_PTR(-ENOMEM); ++ ++ cmd = (struct wmi_gpio_output_cmd *)skb->data; ++ cmd->gpio_num = __cpu_to_le32(gpio_num); ++ cmd->set = __cpu_to_le32(set); ++ ++ ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi gpio_output gpio_num 0x%08x set 0x%08x\n", ++ gpio_num, set); ++ ++ return skb; ++} ++ + static struct sk_buff * + ath10k_wmi_op_gen_set_psmode(struct ath10k *ar, u32 vdev_id, + enum wmi_sta_ps_mode psmode) +@@ -10094,6 +10137,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, ++ .gen_gpio_config = ath10k_wmi_op_gen_gpio_config, ++ .gen_gpio_output = ath10k_wmi_op_gen_gpio_output, ++ + /* .gen_bcn_tmpl not implemented */ + /* .gen_prb_tmpl not implemented */ + /* .gen_p2p_go_bcn_ie not implemented */ +@@ -10164,6 +10210,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, ++ .gen_gpio_config = ath10k_wmi_op_gen_gpio_config, ++ .gen_gpio_output = ath10k_wmi_op_gen_gpio_output, + /* .gen_bcn_tmpl not implemented */ + /* .gen_prb_tmpl not implemented */ + /* .gen_p2p_go_bcn_ie not implemented */ +@@ -10243,6 +10291,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, ++ .gen_gpio_config = ath10k_wmi_op_gen_gpio_config, ++ .gen_gpio_output = ath10k_wmi_op_gen_gpio_output, + /* .gen_pdev_enable_adaptive_cca not implemented */ + }; + +@@ -10314,6 +10364,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, ++ .gen_gpio_config = ath10k_wmi_op_gen_gpio_config, ++ .gen_gpio_output = ath10k_wmi_op_gen_gpio_output, + /* .gen_bcn_tmpl not implemented */ + /* .gen_prb_tmpl not implemented */ + /* .gen_p2p_go_bcn_ie not implemented */ +@@ -10395,6 +10447,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, ++ .gen_gpio_config = ath10k_wmi_op_gen_gpio_config, ++ .gen_gpio_output = ath10k_wmi_op_gen_gpio_output, + }; + + int ath10k_wmi_attach(struct ath10k *ar) +--- a/ath10k-5.4/wmi.h ++++ b/ath10k-5.4/wmi.h +@@ -3110,6 +3110,41 @@ enum wmi_10_4_feature_mask { + + }; + ++/* WMI_GPIO_CONFIG_CMDID */ ++enum { ++ WMI_GPIO_PULL_NONE, ++ WMI_GPIO_PULL_UP, ++ WMI_GPIO_PULL_DOWN, ++}; ++ ++enum { ++ WMI_GPIO_INTTYPE_DISABLE, ++ WMI_GPIO_INTTYPE_RISING_EDGE, ++ WMI_GPIO_INTTYPE_FALLING_EDGE, ++ WMI_GPIO_INTTYPE_BOTH_EDGE, ++ WMI_GPIO_INTTYPE_LEVEL_LOW, ++ WMI_GPIO_INTTYPE_LEVEL_HIGH ++}; ++ ++/* WMI_GPIO_CONFIG_CMDID */ ++struct wmi_gpio_config_cmd { ++ __le32 gpio_num; /* GPIO number to be setup */ ++ __le32 input; /* 0 - Output/ 1 - Input */ ++ __le32 pull_type; /* Pull type defined above */ ++ __le32 intr_mode; /* Interrupt mode defined above (Input) */ ++} __packed; ++ ++/* WMI_GPIO_OUTPUT_CMDID */ ++struct wmi_gpio_output_cmd { ++ __le32 gpio_num; /* GPIO number to be setup */ ++ __le32 set; /* Set the GPIO pin*/ ++} __packed; ++ ++/* WMI_GPIO_INPUT_EVENTID */ ++struct wmi_gpio_input_event { ++ __le32 gpio_num; /* GPIO number which changed state */ ++} __packed; ++ + struct wmi_ext_resource_config_10_4_cmd { + /* contains enum wmi_host_platform_type */ + __le32 host_platform_config; diff --git a/feeds/ipq40xx/ath10k-ct/patches/202-ath10k-use-tpt-trigger-by-default.patch b/feeds/ipq40xx/ath10k-ct/patches/202-ath10k-use-tpt-trigger-by-default.patch new file mode 100644 index 000000000..b1c7bae19 --- /dev/null +++ b/feeds/ipq40xx/ath10k-ct/patches/202-ath10k-use-tpt-trigger-by-default.patch @@ -0,0 +1,53 @@ +From 79c9d7aabae1d1da9eea97d83b61e1517a8a2221 Mon Sep 17 00:00:00 2001 +From: Mathias Kresin +Date: Fri, 22 Jun 2018 18:59:44 +0200 +Subject: [PATCH] ath10k: use tpt LED trigger by default + +Use the tpt LED trigger for each created phy led. Ths way LEDs attached +to the ath10k GPIO pins are indicating the phy status and blink on +traffic. + +Signed-off-by: Mathias Kresin +--- + ath10k-5.4/core.h | 4 ++++ + ath10k-5.4/leds.c | 4 +--- + ath10k-5.4/mac.c | 2 +- + 3 files changed, 6 insertions(+), 4 deletions(-) + +--- a/ath10k-5.4/core.h ++++ b/ath10k-5.4/core.h +@@ -1573,6 +1573,10 @@ struct ath10k { + u8 csi_data[4096]; + u16 csi_data_len; + ++#ifdef CPTCFG_MAC80211_LEDS ++ const char *led_default_trigger; ++#endif ++ + /* must be last */ + u8 drv_priv[0] __aligned(sizeof(void *)); + }; +--- a/ath10k-5.4/leds.c ++++ b/ath10k-5.4/leds.c +@@ -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; + + ret = led_classdev_register(wiphy_dev(ar->hw->wiphy), &ar->leds.cdev); + if (ret) +--- a/ath10k-5.4/mac.c ++++ b/ath10k-5.4/mac.c +@@ -10367,7 +10367,7 @@ int ath10k_mac_register(struct ath10k *a + ar->hw->weight_multiplier = ATH10K_AIRTIME_WEIGHT_MULTIPLIER; + + #ifdef CPTCFG_MAC80211_LEDS +- ieee80211_create_tpt_led_trigger(ar->hw, ++ ar->led_default_trigger = ieee80211_create_tpt_led_trigger(ar->hw, + IEEE80211_TPT_LEDTRIG_FL_RADIO, ath10k_tpt_blink, + ARRAY_SIZE(ath10k_tpt_blink)); + #endif diff --git a/feeds/ipq40xx/ath10k-ct/patches/205-ath10k-Add-NL80211_EXT_FEATURE_AQL-flag.patch b/feeds/ipq40xx/ath10k-ct/patches/205-ath10k-Add-NL80211_EXT_FEATURE_AQL-flag.patch new file mode 100644 index 000000000..41b917089 --- /dev/null +++ b/feeds/ipq40xx/ath10k-ct/patches/205-ath10k-Add-NL80211_EXT_FEATURE_AQL-flag.patch @@ -0,0 +1,10 @@ +--- a/ath10k-5.4/mac.c ++++ b/ath10k-5.4/mac.c +@@ -10180,6 +10180,7 @@ int ath10k_mac_register(struct ath10k *a + wiphy_ext_feature_set(ar->hw->wiphy, NL80211_EXT_FEATURE_VHT_IBSS); + wiphy_ext_feature_set(ar->hw->wiphy, + NL80211_EXT_FEATURE_SET_SCAN_DWELL); ++ wiphy_ext_feature_set(ar->hw->wiphy, NL80211_EXT_FEATURE_AQL); + + if (test_bit(WMI_SERVICE_TX_DATA_ACK_RSSI, ar->wmi.svc_map) || + test_bit(WMI_SERVICE_HTT_MGMT_TX_COMP_VALID_FLAGS, ar->wmi.svc_map)) diff --git a/feeds/ipq40xx/ath10k-ct/patches/960-0010-ath10k-limit-htt-rx-ring-size.patch b/feeds/ipq40xx/ath10k-ct/patches/960-0010-ath10k-limit-htt-rx-ring-size.patch new file mode 100644 index 000000000..c52743089 --- /dev/null +++ b/feeds/ipq40xx/ath10k-ct/patches/960-0010-ath10k-limit-htt-rx-ring-size.patch @@ -0,0 +1,14 @@ +--- a/ath10k-5.4/htt.h ++++ b/ath10k-5.4/htt.h +@@ -225,7 +225,11 @@ enum htt_rx_ring_flags { + }; + + #define HTT_RX_RING_SIZE_MIN 128 ++#ifndef CONFIG_ATH10K_SMALLBUFFERS + #define HTT_RX_RING_SIZE_MAX 2048 ++#else ++#define HTT_RX_RING_SIZE_MAX 512 ++#endif + #define HTT_RX_RING_SIZE HTT_RX_RING_SIZE_MAX + #define HTT_RX_RING_FILL_LEVEL (((HTT_RX_RING_SIZE) / 2) - 1) + #define HTT_RX_RING_FILL_LEVEL_DUAL_MAC (HTT_RX_RING_SIZE - 1) diff --git a/feeds/ipq40xx/ath10k-ct/patches/960-0011-ath10k-limit-pci-buffer-size.patch b/feeds/ipq40xx/ath10k-ct/patches/960-0011-ath10k-limit-pci-buffer-size.patch new file mode 100644 index 000000000..f559a78f2 --- /dev/null +++ b/feeds/ipq40xx/ath10k-ct/patches/960-0011-ath10k-limit-pci-buffer-size.patch @@ -0,0 +1,50 @@ +--- a/ath10k-5.4/pci.c ++++ b/ath10k-5.4/pci.c +@@ -131,7 +131,11 @@ static struct ce_attr host_ce_config_wla + .flags = CE_ATTR_FLAGS, + .src_nentries = 0, + .src_sz_max = 2048, ++#ifndef CONFIG_ATH10K_SMALLBUFFERS + .dest_nentries = 512, ++#else ++ .dest_nentries = 128, ++#endif + .recv_cb = ath10k_pci_htt_htc_rx_cb, + }, + +@@ -140,7 +144,11 @@ static struct ce_attr host_ce_config_wla + .flags = CE_ATTR_FLAGS, + .src_nentries = 0, + .src_sz_max = 2048, ++#ifndef CONFIG_ATH10K_SMALLBUFFERS + .dest_nentries = 128, ++#else ++ .dest_nentries = 64, ++#endif + .recv_cb = ath10k_pci_htc_rx_cb, + }, + +@@ -167,7 +175,11 @@ static struct ce_attr host_ce_config_wla + .flags = CE_ATTR_FLAGS, + .src_nentries = 0, + .src_sz_max = 512, ++#ifndef CONFIG_ATH10K_SMALLBUFFERS + .dest_nentries = 512, ++#else ++ .dest_nentries = 128, ++#endif + .recv_cb = ath10k_pci_htt_rx_cb, + }, + +@@ -192,7 +204,11 @@ static struct ce_attr host_ce_config_wla + .flags = CE_ATTR_FLAGS, + .src_nentries = 0, + .src_sz_max = 2048, ++#ifndef CONFIG_ATH10K_SMALLBUFFERS + .dest_nentries = 128, ++#else ++ .dest_nentries = 96, ++#endif + .recv_cb = ath10k_pci_pktlog_rx_cb, + }, + diff --git a/feeds/ipq40xx/ath10k-ct/patches/960-0012-ath10k-add_cmd_processing_time_for_scan_timeout.patch b/feeds/ipq40xx/ath10k-ct/patches/960-0012-ath10k-add_cmd_processing_time_for_scan_timeout.patch new file mode 100644 index 000000000..9a2118167 --- /dev/null +++ b/feeds/ipq40xx/ath10k-ct/patches/960-0012-ath10k-add_cmd_processing_time_for_scan_timeout.patch @@ -0,0 +1,22 @@ +diff -Naur a/ath10k-5.7/mac.c b/ath10k-5.7/mac.c +--- a/ath10k-5.7/mac.c 2021-06-09 16:30:17.793556032 -0400 ++++ b/ath10k-5.7/mac.c 2021-06-09 17:38:08.587733979 -0400 +@@ -7103,13 +7103,15 @@ + scan_timeout = min_t(u32, arg.max_rest_time * + (arg.n_channels - 1) + (req->duration + + ATH10K_SCAN_CHANNEL_SWITCH_WMI_EVT_OVERHEAD) * +- arg.n_channels, arg.max_scan_time + 200); ++ arg.n_channels, arg.max_scan_time); + + } else { +- /* Add a 200ms margin to account for event/command processing */ +- scan_timeout = arg.max_scan_time + 200; ++ scan_timeout = arg.max_scan_time; + } + ++ /* Add a 200ms margin to account for event/command processing */ ++ scan_timeout += 200; ++ + ret = ath10k_start_scan(ar, &arg); + if (ret) { + ath10k_warn(ar, "failed to start hw scan: %d\n", ret); diff --git a/feeds/ipq40xx/ath10k-ct/patches/970-accumulate-survey-info-data b/feeds/ipq40xx/ath10k-ct/patches/970-accumulate-survey-info-data new file mode 100644 index 000000000..615d3e126 --- /dev/null +++ b/feeds/ipq40xx/ath10k-ct/patches/970-accumulate-survey-info-data @@ -0,0 +1,11 @@ +--- a/ath10k-5.7/mac.c 2021-07-06 11:12:56.022146449 -0700 ++++ b/ath10k-5.7/mac.c 2021-07-06 19:37:52.352753693 -0700 +@@ -8286,7 +8286,7 @@ + struct ieee80211_channel *channel) + { + int ret; +- enum wmi_bss_survey_req_type type = WMI_BSS_SURVEY_REQ_TYPE_READ_CLEAR; ++ enum wmi_bss_survey_req_type type = WMI_BSS_SURVEY_REQ_TYPE_READ; + + lockdep_assert_held(&ar->conf_mutex); + diff --git a/feeds/ipq40xx/ath10k-ct/patches/970-add-survey-local-bss-receive-time b/feeds/ipq40xx/ath10k-ct/patches/970-add-survey-local-bss-receive-time new file mode 100644 index 000000000..c400445fd --- /dev/null +++ b/feeds/ipq40xx/ath10k-ct/patches/970-add-survey-local-bss-receive-time @@ -0,0 +1,31 @@ +--- a/ath10k-5.7/wmi.c ++++ b/ath10k-5.7/wmi.c +@@ -6347,16 +6347,18 @@ + + survey = &ar->survey[idx]; + +- survey->noise = noise_floor; +- survey->time = div_u64(total, cc_freq_hz); +- survey->time_busy = div_u64(busy, cc_freq_hz); +- survey->time_rx = div_u64(rx_bss, cc_freq_hz); +- survey->time_tx = div_u64(tx, cc_freq_hz); +- survey->filled |= (SURVEY_INFO_NOISE_DBM | +- SURVEY_INFO_TIME | +- SURVEY_INFO_TIME_BUSY | +- SURVEY_INFO_TIME_RX | +- SURVEY_INFO_TIME_TX); ++ survey->noise = noise_floor; ++ survey->time = div_u64(total, cc_freq_hz); ++ survey->time_busy = div_u64(busy, cc_freq_hz); ++ survey->time_rx = div_u64(rx, cc_freq_hz); ++ survey->time_bss_rx = div_u64(rx_bss, cc_freq_hz); ++ survey->time_tx = div_u64(tx, cc_freq_hz); ++ survey->filled |= (SURVEY_INFO_NOISE_DBM | ++ SURVEY_INFO_TIME | ++ SURVEY_INFO_TIME_BUSY | ++ SURVEY_INFO_TIME_RX | ++ SURVEY_INFO_TIME_TX | ++ SURVEY_INFO_TIME_BSS_RX); + exit: + spin_unlock_bh(&ar->data_lock); + complete(&ar->bss_survey_done); diff --git a/feeds/ipq40xx/ath10k-ct/patches/999-ath10k-threading.patch b/feeds/ipq40xx/ath10k-ct/patches/999-ath10k-threading.patch new file mode 100644 index 000000000..4bcb84cf5 --- /dev/null +++ b/feeds/ipq40xx/ath10k-ct/patches/999-ath10k-threading.patch @@ -0,0 +1,14 @@ +Index: ath10k-ct-2021-05-22b-54a9ac02/ath10k-5.7/core.c +=================================================================== +--- ath10k-ct-2021-05-22b-54a9ac02.orig/ath10k-5.7/core.c ++++ ath10k-ct-2021-05-22b-54a9ac02/ath10k-5.7/core.c +@@ -4146,6 +4146,9 @@ struct ath10k *ath10k_core_create(size_t + INIT_WORK(&ar->stop_scan_work, ath10k_wmi_stop_scan_work); + + init_dummy_netdev(&ar->napi_dev); ++ snprintf(ar->napi_dev.name, sizeof(ar->napi_dev.name), "%s", ++ wiphy_name(ar->hw->wiphy)); ++ ar->napi_dev.threaded = 1; + + ret = ath10k_coredump_create(ar); + if (ret) diff --git a/feeds/ipq40xx/ath10k-firmware/Makefile b/feeds/ipq40xx/ath10k-firmware/Makefile new file mode 100644 index 000000000..c427f0884 --- /dev/null +++ b/feeds/ipq40xx/ath10k-firmware/Makefile @@ -0,0 +1,182 @@ +# +# Copyright (C) 2015 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:=ath10k-firmware +PKG_SOURCE_DATE:=2019-10-03 +PKG_SOURCE_VERSION:=d622d160e9f552ead68d9ae81b715422892dc2ef +PKG_MIRROR_HASH:=2e504e071c3f896d629c4cfffe7ff4b5f1acdb4fecd3f01e8ff8c73e87a67cc7 +PKG_RELEASE:=1 + +PKG_SOURCE_PROTO:=git +PKG_SOURCE_URL:=https://github.com/kvalo/ath10k-firmware.git + +PKG_MAINTAINER:=Felix Fietkau + +include $(INCLUDE_DIR)/package.mk + +define Package/ath10k-firmware-default + SECTION:=firmware + CATEGORY:=Firmware + URL:=$(PKG_SOURCE_URL) + DEPENDS:= +endef + +define Package/ath10k-firmware-qca9887 +$(Package/ath10k-firmware-default) + TITLE:=ath10k firmware for QCA9887 devices +endef + +define Package/ath10k-firmware-qca9888 +$(Package/ath10k-firmware-default) + TITLE:=ath10k firmware for QCA9888 devices +endef + +define Package/ath10k-firmware-qca988x +$(Package/ath10k-firmware-default) + TITLE:=ath10k firmware for QCA988x devices + SECTION:=firmware + CATEGORY:=Firmware +endef + +define Package/ath10k-firmware-qca99x0 +$(Package/ath10k-firmware-default) + TITLE:=ath10k firmware for QCA99x0 devices + SECTION:=firmware + CATEGORY:=Firmware +endef + +define Package/ath10k-firmware-qca99x0/description +Standard ath10k firmware for QCA99x0 from QCA +This firmware conflicts with the CT 99x0 firmware, so select only +one. +endef + +define Package/ath10k-firmware-qca9984 +$(Package/ath10k-firmware-default) + TITLE:=ath10k firmware for QCA9984 devices + SECTION:=firmware + CATEGORY:=Firmware +endef + +define Package/ath10k-firmware-qca4019 +$(Package/ath10k-firmware-default) + TITLE:=ath10k firmware for IPQ/QCA4019 devices + SECTION:=firmware + CATEGORY:=Firmware +endef + +define Package/ath10k-firmware-qca6174 +$(Package/ath10k-firmware-default) + TITLE:=ath10k firmware for QCA6174 devices + SECTION:=firmware + CATEGORY:=Firmware +endef + +QCA99X0_BOARD_REV:=ddcec9efd245da9365c474f513a855a55f3ac7fe +QCA99X0_BOARD_FILE:=board-2.bin.$(QCA99X0_BOARD_REV) + +define Download/qca99x0-board + URL:=https://source.codeaurora.org/quic/qsdk/oss/firmware/ath10k-firmware/plain/ath10k/QCA99X0/hw2.0 + URL_FILE:=board-2.bin?id=$(QCA99X0_BOARD_REV) + FILE:=$(QCA99X0_BOARD_FILE) + HASH:=03711ac21e60ef59d3815e235eb721c0c22851b5410299411085aa6f2af45401 +endef +$(eval $(call Download,qca99x0-board)) + +define Build/Compile + +endef + +define Package/ath10k-firmware-qca4019/install + $(INSTALL_DIR) $(1)/lib/firmware/ath10k/QCA4019/hw1.0 + $(INSTALL_DATA) \ + $(PKG_BUILD_DIR)/QCA4019/hw1.0/board-2.bin \ + $(1)/lib/firmware/ath10k/QCA4019/hw1.0/ + $(INSTALL_DATA) \ + $(PKG_BUILD_DIR)/QCA4019/hw1.0/3.5.3/firmware-5.bin_10.4-3.5.3-00057 \ + $(1)/lib/firmware/ath10k/QCA4019/hw1.0/firmware-5.bin +endef + +define Package/ath10k-firmware-qca9887/install + $(INSTALL_DIR) $(1)/lib/firmware/ath10k/QCA9887/hw1.0 + $(INSTALL_DATA) \ + $(PKG_BUILD_DIR)/QCA9887/hw1.0/10.2.4-1.0/firmware-5.bin_10.2.4-1.0-00047 \ + $(1)/lib/firmware/ath10k/QCA9887/hw1.0/firmware-5.bin + $(INSTALL_DATA) \ + $(PKG_BUILD_DIR)/QCA9887/hw1.0/board.bin \ + $(1)/lib/firmware/ath10k/QCA9887/hw1.0/board.bin +endef + +define Package/ath10k-firmware-qca9888/install + $(INSTALL_DIR) $(1)/lib/firmware/ath10k/QCA9888/hw2.0 + $(INSTALL_DATA) \ + $(PKG_BUILD_DIR)/QCA9888/hw2.0/board-2.bin \ + $(1)/lib/firmware/ath10k/QCA9888/hw2.0/board-2.bin + $(INSTALL_DATA) \ + $(PKG_BUILD_DIR)/QCA9888/hw2.0/3.5.3/firmware-5.bin_10.4-3.5.3-00053 \ + $(1)/lib/firmware/ath10k/QCA9888/hw2.0/firmware-5.bin +endef + +define Package/ath10k-firmware-qca988x/install + $(INSTALL_DIR) $(1)/lib/firmware/ath10k/QCA988X/hw2.0 + $(INSTALL_DATA) \ + $(PKG_BUILD_DIR)/QCA988X/hw2.0/board.bin \ + $(1)/lib/firmware/ath10k/QCA988X/hw2.0/ + $(INSTALL_DATA) \ + $(PKG_BUILD_DIR)/QCA988X/hw2.0/10.2.4-1.0/firmware-5.bin_10.2.4-1.0-00047 \ + $(1)/lib/firmware/ath10k/QCA988X/hw2.0/firmware-5.bin +endef + +define Package/ath10k-firmware-qca6174/install + $(INSTALL_DIR) $(1)/lib/firmware/ath10k/QCA6174/hw2.1 + $(INSTALL_DATA) \ + $(PKG_BUILD_DIR)/QCA6174/hw2.1/board-2.bin \ + $(1)/lib/firmware/ath10k/QCA6174/hw2.1/ + $(INSTALL_DATA) \ + $(PKG_BUILD_DIR)/QCA6174/hw2.1/firmware-5.bin_SW_RM.1.1.1-00157-QCARMSWPZ-1 \ + $(1)/lib/firmware/ath10k/QCA6174/hw2.1/firmware-5.bin + $(INSTALL_DIR) $(1)/lib/firmware/ath10k/QCA6174/hw3.0 + $(INSTALL_DATA) \ + $(PKG_BUILD_DIR)/QCA6174/hw3.0/board-2.bin \ + $(1)/lib/firmware/ath10k/QCA6174/hw3.0/ + $(INSTALL_DATA) \ + $(PKG_BUILD_DIR)/QCA6174/hw3.0/4.4.1.c1/firmware-6.bin_RM.4.4.1.c1-00042-QCARMSWP-1 \ + $(1)/lib/firmware/ath10k/QCA6174/hw3.0/firmware-6.bin +endef + +define Package/ath10k-firmware-qca99x0/install + $(INSTALL_DIR) $(1)/lib/firmware/ath10k/QCA99X0/hw2.0 + $(INSTALL_DATA) \ + $(DL_DIR)/$(QCA99X0_BOARD_FILE) \ + $(1)/lib/firmware/ath10k/QCA99X0/hw2.0/board-2.bin + $(INSTALL_DATA) \ + $(PKG_BUILD_DIR)/QCA99X0/hw2.0/boardData_AR900B_CUS239_5G_v2_001.bin \ + $(1)/lib/firmware/ath10k/QCA99X0/hw2.0/board.bin + $(INSTALL_DATA) \ + $(PKG_BUILD_DIR)/QCA99X0/hw2.0/firmware-5.bin_10.4.1.00030-1 \ + $(1)/lib/firmware/ath10k/QCA99X0/hw2.0/firmware-5.bin +endef + +define Package/ath10k-firmware-qca9984/install + $(INSTALL_DIR) $(1)/lib/firmware/ath10k/QCA9984/hw1.0 + $(INSTALL_DATA) \ + $(PKG_BUILD_DIR)/QCA9984/hw1.0/board-2.bin \ + $(1)/lib/firmware/ath10k/QCA9984/hw1.0/board-2.bin + $(INSTALL_DATA) \ + $(PKG_BUILD_DIR)/QCA9984/hw1.0/3.5.3/firmware-5.bin_10.4-3.5.3-00053 \ + $(1)/lib/firmware/ath10k/QCA9984/hw1.0/firmware-5.bin +endef + +$(eval $(call BuildPackage,ath10k-firmware-qca9887)) +#$(eval $(call BuildPackage,ath10k-firmware-qca9888)) +$(eval $(call BuildPackage,ath10k-firmware-qca988x)) +#$(eval $(call BuildPackage,ath10k-firmware-qca99x0)) +#$(eval $(call BuildPackage,ath10k-firmware-qca6174)) +#$(eval $(call BuildPackage,ath10k-firmware-qca9984)) +#$(eval $(call BuildPackage,ath10k-firmware-qca4019)) diff --git a/feeds/ipq40xx/batctl/Makefile b/feeds/ipq40xx/batctl/Makefile new file mode 100644 index 000000000..895e9ea67 --- /dev/null +++ b/feeds/ipq40xx/batctl/Makefile @@ -0,0 +1,231 @@ +# SPDX-License-Identifier: GPL-2.0-only + +include $(TOPDIR)/rules.mk + +PKG_NAME:=batctl +PKG_VERSION:=2020.2 +PKG_RELEASE:=1 + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz +PKG_SOURCE_URL:=https://downloads.open-mesh.org/batman/releases/batman-adv-$(PKG_VERSION) +PKG_HASH:=d29cdb53ee68abd5027eae07d9fd645b3f154e0d577efa2666c1334bb6d60efd +PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(BUILD_VARIANT)/$(PKG_NAME)-$(PKG_VERSION) + +PKG_MAINTAINER:=Simon Wunderlich +PKG_LICENSE:=GPL-2.0-only ISC MIT +PKG_LICENSE_FILES:=LICENSES/preferred/GPL-2.0 LICENSES/preferred/MIT LICENSES/deprecated/ISC + +include $(INCLUDE_DIR)/package.mk + +define Package/batctl/Default + SECTION:=net + CATEGORY:=Network + URL:=https://www.open-mesh.org/ + DEPENDS:=+libnl-tiny +libc +librt + PROVIDES:=batctl +endef + +define Package/batctl/description + batctl is a more intuitive managment utility for B.A.T.M.A.N.-Advanced. + It is an easier method for configuring batman-adv and provides some + additional tools for debugging as well. This package builds + version $(PKG_VERSION) of the user space utility. +endef + +define Package/batctl-tiny +$(call Package/batctl/Default) + TITLE:=B.A.T.M.A.N. Advanced user space configuration tool (Minimal) + VARIANT:=tiny + ALTERNATIVES:=100:/usr/sbin/batctl:/usr/libexec/batctl-tiny +endef + +define Package/batctl-tiny/description +$(Package/batctl/description) + Only configuration relevant subcommands are enabled. +endef + +define Package/batctl-default +$(call Package/batctl/Default) + TITLE:=B.A.T.M.A.N. Advanced user space configuration tool (Default) + VARIANT:=default + ALTERNATIVES:=200:/usr/sbin/batctl:/usr/libexec/batctl-default +endef + +define Package/batctl-default/description +$(Package/batctl/description) + Standard subcommands for configuration and online debugging are enabled. +endef + +define Package/batctl-full +$(call Package/batctl/Default) + TITLE:=B.A.T.M.A.N. Advanced user space configuration tool (Full) + VARIANT:=full + ALTERNATIVES:=300:/usr/sbin/batctl:/usr/libexec/batctl-full +endef + +define Package/batctl-full/description +$(Package/batctl/description) + Subcommands for configuration, online and offline debugging are enabled. +endef + +# The linker can identify unused sections of a binary when each symbol is stored +# in a separate section. This mostly removes unused linker sections and reduces +# the size by ~3% on mipsel. + +TARGET_CFLAGS += -ffunction-sections -fdata-sections +TARGET_LDFLAGS += -Wl,--gc-sections + +# Link-time optimization allows to move parts of the optimization from the single +# source file to the global source view. This is done by emitting the GIMPLE +# representation in each object file and analyzing it again during the link step. + +TARGET_CFLAGS += -flto +TARGET_LDFLAGS += -fuse-linker-plugin + +MAKE_VARS += \ + LIBNL_NAME="libnl-tiny" \ + LIBNL_GENL_NAME="libnl-tiny" + +MAKE_FLAGS += \ + REVISION="$(PKG_VERSION)-openwrt-$(PKG_RELEASE)" + +config-n := \ + aggregation \ + ap_isolation \ + backbonetable \ + bisect_iv \ + bonding \ + bridge_loop_avoidance \ + claimtable \ + dat_cache \ + distributed_arp_table \ + elp_interval \ + event \ + fragmentation \ + gateways \ + gw_mode \ + hop_penalty \ + interface \ + isolation_mark \ + loglevel \ + mcast_flags \ + multicast_fanout \ + multicast_forceflood \ + multicast_mode \ + nc_nodes \ + neighbors \ + network_coding \ + orig_interval \ + originators \ + ping \ + routing_algo \ + statistics \ + tcpdump \ + throughput_override \ + throughputmeter \ + traceroute \ + transglobal \ + translate \ + translocal \ + +config-settings := \ + aggregation \ + ap_isolation \ + bonding \ + bridge_loop_avoidance \ + distributed_arp_table \ + elp_interval \ + fragmentation \ + gw_mode \ + hop_penalty \ + interface \ + isolation_mark \ + loglevel \ + multicast_fanout \ + multicast_forceflood \ + multicast_mode \ + network_coding \ + orig_interval \ + routing_algo \ + throughput_override \ + +config-tables := \ + backbonetable \ + claimtable \ + dat_cache \ + gateways \ + loglevel \ + nc_nodes \ + neighbors \ + originators \ + statistics \ + transglobal \ + translocal \ + +config-tools := \ + event \ + ping \ + tcpdump \ + throughputmeter \ + traceroute \ + translate \ + +config-extratools := \ + bisect_iv \ + +ifeq ($(BUILD_VARIANT),tiny) + +config-y := \ + $(config-settings) \ + +endif + +ifeq ($(BUILD_VARIANT),default) + +config-y := \ + $(config-settings) \ + $(config-tables) \ + $(config-tools) \ + +endif + +ifeq ($(BUILD_VARIANT),full) + +config-y := \ + $(config-settings) \ + $(config-tables) \ + $(config-tools) \ + $(config-extratools) \ + +endif + +define ConfigVars +$(subst $(space),,$(foreach opt,$(config-$(1)),CONFIG_$(opt)=$(1) +)) +endef + +define batctl_config +$(call ConfigVars,n)$(call ConfigVars,y) +endef +$(eval $(call shexport,batctl_config)) + +MAKE_FLAGS += $$$$$(call shvar,batctl_config) + +define Package/batctl-tiny/install + $(INSTALL_DIR) $(1)/usr/libexec + $(INSTALL_BIN) $(PKG_BUILD_DIR)/batctl $(1)/usr/libexec/batctl-tiny +endef + +define Package/batctl-default/install + $(INSTALL_DIR) $(1)/usr/libexec + $(INSTALL_BIN) $(PKG_BUILD_DIR)/batctl $(1)/usr/libexec/batctl-default +endef + +define Package/batctl-full/install + $(INSTALL_DIR) $(1)/usr/libexec + $(INSTALL_BIN) $(PKG_BUILD_DIR)/batctl $(1)/usr/libexec/batctl-full +endef + +$(eval $(call BuildPackage,batctl-default)) +$(eval $(call BuildPackage,batctl-tiny)) +$(eval $(call BuildPackage,batctl-full)) diff --git a/feeds/ipq40xx/batman-adv/Config.in b/feeds/ipq40xx/batman-adv/Config.in new file mode 100644 index 000000000..70cc48ffe --- /dev/null +++ b/feeds/ipq40xx/batman-adv/Config.in @@ -0,0 +1,110 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (C) 2007-2019 B.A.T.M.A.N. contributors: +# +# Marek Lindner, Simon Wunderlich + +# +# B.A.T.M.A.N meshing protocol +# + +config BATMAN_ADV_BATMAN_V + bool "B.A.T.M.A.N. V protocol" + depends on PACKAGE_kmod-batman-adv + default y + help + This option enables the B.A.T.M.A.N. V protocol, the successor + of the currently used B.A.T.M.A.N. IV protocol. The main + changes include splitting of the OGM protocol into a neighbor + discovery protocol (Echo Location Protocol, ELP) and a new OGM + Protocol OGMv2 for flooding protocol information through the + network, as well as a throughput based metric. + B.A.T.M.A.N. V is currently considered experimental and not + compatible to B.A.T.M.A.N. IV networks. + +config BATMAN_ADV_BLA + bool "Bridge Loop Avoidance" + depends on PACKAGE_kmod-batman-adv + select PACKAGE_kmod-lib-crc16 + default y + help + This option enables BLA (Bridge Loop Avoidance), a mechanism + to avoid Ethernet frames looping when mesh nodes are connected + to both the same LAN and the same mesh. If you will never use + more than one mesh node in the same LAN, you can safely remove + this feature and save some space. + +config BATMAN_ADV_DAT + bool "Distributed ARP Table" + depends on PACKAGE_kmod-batman-adv + default y + help + This option enables DAT (Distributed ARP Table), a DHT based + mechanism that increases ARP reliability on sparse wireless + mesh networks. If you think that your network does not need + this option you can safely remove it and save some space. + +config BATMAN_ADV_NC + bool "Network Coding" + depends on PACKAGE_kmod-batman-adv + help + This option enables network coding, a mechanism that aims to + increase the overall network throughput by fusing multiple + packets in one transmission. + Note that interfaces controlled by batman-adv must be manually + configured to have promiscuous mode enabled in order to make + network coding work. + If you think that your network does not need this feature you + can safely disable it and save some space. + +config BATMAN_ADV_MCAST + bool "Multicast optimisation" + depends on PACKAGE_kmod-batman-adv + default y + help + This option enables the multicast optimisation which aims to + reduce the air overhead while improving the reliability of + multicast messages. + +config BATMAN_ADV_DEBUGFS + bool "batman-adv debugfs entries" + depends on PACKAGE_kmod-batman-adv + select KERNEL_DEBUG_FS + help + Enable this to export routing related debug tables via debugfs. + The information for each soft-interface and used hard-interface can be + found under batman_adv/ + + If unsure, say N. + +config BATMAN_ADV_DEBUG + bool "B.A.T.M.A.N. debugging" + depends on PACKAGE_kmod-batman-adv + help + This is an option for use by developers; most people should + say N here. This enables compilation of support for + outputting debugging information to the debugfs log or tracing + buffer. The output is controlled via the batadv netdev specific + log_level setting. + +config BATMAN_ADV_SYSFS + bool "batman-adv sysfs entries" + depends on PACKAGE_kmod-batman-adv + help + Say Y here if you want to enable batman-adv device configuration and + status interface through sysfs attributes. It is replaced by the + batadv generic netlink family but still used by various userspace + tools and scripts. + + If unsure, say Y. + +config BATMAN_ADV_TRACING + bool "B.A.T.M.A.N. tracing support" + depends on PACKAGE_kmod-batman-adv + select KERNEL_FTRACE + select KERNEL_ENABLE_DEFAULT_TRACERS + help + This is an option for use by developers; most people should + say N here. Select this option to gather traces like the debug + messages using the generic tracing infrastructure of the kernel. + BATMAN_ADV_DEBUG must also be selected to get trace events for + batadv_dbg. diff --git a/feeds/ipq40xx/batman-adv/Makefile b/feeds/ipq40xx/batman-adv/Makefile new file mode 100644 index 000000000..5813b0585 --- /dev/null +++ b/feeds/ipq40xx/batman-adv/Makefile @@ -0,0 +1,91 @@ +# SPDX-License-Identifier: GPL-2.0-only + +include $(TOPDIR)/rules.mk + +PKG_NAME:=batman-adv +PKG_VERSION:=2020.2 +PKG_RELEASE:=1 + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz +PKG_SOURCE_URL:=https://downloads.open-mesh.org/batman/releases/batman-adv-$(PKG_VERSION) +PKG_HASH:=a73f5ce72c6efa9dd7bd7cc8daa667d0982e12e40811c978bb652607bb5666a3 +PKG_EXTMOD_SUBDIRS:=net/batman-adv + +PKG_MAINTAINER:=Simon Wunderlich +PKG_LICENSE:=GPL-2.0-only MIT +PKG_LICENSE_FILES:=LICENSES/preferred/GPL-2.0 LICENSES/preferred/MIT + +STAMP_CONFIGURED_DEPENDS := $(STAGING_DIR)/usr/include/mac80211-backport/backport/autoconf.h + +include $(INCLUDE_DIR)/kernel.mk +include $(INCLUDE_DIR)/package.mk + +define KernelPackage/batman-adv + SUBMENU:=Network Support + TITLE:=B.A.T.M.A.N. Adv + URL:=https://www.open-mesh.org/ + DEPENDS:=+BATMAN_ADV_BLA:kmod-lib-crc16 +kmod-lib-crc32c +kmod-cfg80211 +batctl + FILES:=$(PKG_BUILD_DIR)/net/batman-adv/batman-adv.$(LINUX_KMOD_SUFFIX) + AUTOLOAD:=$(call AutoProbe,batman-adv) +endef + +define KernelPackage/batman-adv/description + B.A.T.M.A.N. (better approach to mobile ad-hoc networking) is + a routing protocol for multi-hop ad-hoc mesh networks. The + networks may be wired or wireless. See + https://www.open-mesh.org/ for more information and user space + tools. This package builds version $(PKG_VERSION) of the kernel + module. +endef + +define KernelPackage/batman-adv/config + source "$(SOURCE)/Config.in" +endef + +define Package/kmod-batman-adv/conffiles +/etc/config/batman-adv +endef + +PKG_EXTRA_KCONFIG:= \ + CONFIG_BATMAN_ADV=m \ + CONFIG_BATMAN_ADV_DEBUG=$(if $(CONFIG_BATMAN_ADV_DEBUG),y,n) \ + CONFIG_BATMAN_ADV_DEBUGFS=$(if $(CONFIG_BATMAN_ADV_DEBUGFS),y,n) \ + CONFIG_BATMAN_ADV_BLA=$(if $(CONFIG_BATMAN_ADV_BLA),y,n) \ + CONFIG_BATMAN_ADV_DAT=$(if $(CONFIG_BATMAN_ADV_DAT),y,n) \ + CONFIG_BATMAN_ADV_MCAST=$(if $(CONFIG_BATMAN_ADV_MCAST),y,n) \ + CONFIG_BATMAN_ADV_NC=$(if $(CONFIG_BATMAN_ADV_NC),y,n) \ + CONFIG_BATMAN_ADV_BATMAN_V=$(if $(CONFIG_BATMAN_ADV_BATMAN_V),y,n) \ + CONFIG_BATMAN_ADV_SYSFS=$(if $(CONFIG_BATMAN_ADV_SYSFS),y,n) \ + CONFIG_BATMAN_ADV_TRACING=$(if $(CONFIG_BATMAN_ADV_TRACING),y,n) \ + +PKG_EXTRA_CFLAGS:= \ + $(patsubst CONFIG_%, -DCONFIG_%=1, $(patsubst %=m,%,$(filter %=m,$(PKG_EXTRA_KCONFIG)))) \ + $(patsubst CONFIG_%, -DCONFIG_%=1, $(patsubst %=y,%,$(filter %=y,$(PKG_EXTRA_KCONFIG)))) \ + +NOSTDINC_FLAGS = \ + -I$(PKG_BUILD_DIR)/net/batman-adv \ + -I$(STAGING_DIR)/usr/include/mac80211-backport \ + -I$(STAGING_DIR)/usr/include/mac80211-backport/uapi \ + -I$(STAGING_DIR)/usr/include/mac80211 \ + -I$(STAGING_DIR)/usr/include/mac80211/uapi \ + -I$(PKG_BUILD_DIR)/include/ \ + -include backport/autoconf.h \ + -include backport/backport.h \ + -include $(PKG_BUILD_DIR)/compat-hacks.h \ + -DBATADV_SOURCE_VERSION=\\\"$(PKG_VERSION)-openwrt-$(PKG_RELEASE)\\\" + +define Build/Compile + $(MAKE) $(PKG_JOBS) -C "$(LINUX_DIR)" \ + $(KERNEL_MAKE_FLAGS) \ + M="$(PKG_BUILD_DIR)/net/batman-adv" \ + $(PKG_EXTRA_KCONFIG) \ + EXTRA_CFLAGS="$(PKG_EXTRA_CFLAGS)" \ + NOSTDINC_FLAGS="$(NOSTDINC_FLAGS)" \ + modules +endef + +define KernelPackage/batman-adv/install + $(CP) ./files/. $(1)/ +endef + +$(eval $(call KernelPackage,batman-adv)) diff --git a/feeds/ipq40xx/batman-adv/files/etc/uci-defaults/99-migrate-batadv_hardif b/feeds/ipq40xx/batman-adv/files/etc/uci-defaults/99-migrate-batadv_hardif new file mode 100755 index 000000000..258b7bd6a --- /dev/null +++ b/feeds/ipq40xx/batman-adv/files/etc/uci-defaults/99-migrate-batadv_hardif @@ -0,0 +1,97 @@ +#!/bin/sh + +# This UCI-Defaults script will split the batadv proto network interfaces +# in batadv_hardif and batadv proto. The configuration options from +# /etc/config/batman-adv will be moved to the latter. + +. /lib/functions.sh + +proto_batadv_to_batadv_hardif() { + local section="$1" + local proto + local mesh + local routing_algo + + config_get proto "${section}" proto + config_get mesh "${section}" mesh + config_get routing_algo "${section}" routing_algo + + if [ -z "$mesh" -o "${proto}" != "batadv" ]; then + continue + fi + + uci set network."${section}".proto="batadv_hardif" + uci rename network."${section}".mesh="master" + uci delete network."${section}".routing_algo + + # create new section or adjust existing one + uci set network."${mesh}"=interface + uci set network."${mesh}".proto=batadv + [ -n "${routing_algo}" ] && uci set network."${mesh}".routing_algo="${routing_algo}" +} + +mv_batadv_config_section() { + local section="$1" + local aggregated_ogms + local ap_isolation + local bonding + local bridge_loop_avoidance + local distributed_arp_table + local fragmentation + local gw_bandwidth + local gw_mode + local gw_sel_class + local hop_penalty + local isolation_mark + local log_level + local multicast_mode + local network_coding + local orig_interval + + config_get aggregated_ogms "${section}" aggregated_ogms + config_get ap_isolation "${section}" ap_isolation + config_get bonding "${section}" bonding + config_get bridge_loop_avoidance "${section}" bridge_loop_avoidance + config_get distributed_arp_table "${section}" distributed_arp_table + config_get fragmentation "${section}" fragmentation + config_get gw_bandwidth "${section}" gw_bandwidth + config_get gw_mode "${section}" gw_mode + config_get gw_sel_class "${section}" gw_sel_class + config_get hop_penalty "${section}" hop_penalty + config_get isolation_mark "${section}" isolation_mark + config_get log_level "${section}" log_level + config_get multicast_mode "${section}" multicast_mode + config_get network_coding "${section}" network_coding + config_get orig_interval "${section}" orig_interval + + # update section in case it exists + [ -n "${aggregated_ogms}" ] && uci set network."${section}".aggregated_ogms="${aggregated_ogms}" + [ -n "${ap_isolation}" ] && uci set network."${section}".ap_isolation="${ap_isolation}" + [ -n "${bonding}" ] && uci set network."${section}".bonding="${bonding}" + [ -n "${bridge_loop_avoidance}" ] && uci set network."${section}".bridge_loop_avoidance="${bridge_loop_avoidance}" + [ -n "${distributed_arp_table}" ] && uci set network."${section}".distributed_arp_table="${distributed_arp_table}" + [ -n "${fragmentation}" ] && uci set network."${section}".fragmentation="${fragmentation}" + [ -n "${gw_bandwidth}" ] && uci set network."${section}".gw_bandwidth="${gw_bandwidth}" + [ -n "${gw_mode}" ] && uci set network."${section}".gw_mode="${gw_mode}" + [ -n "${gw_sel_class}" ] && uci set network."${section}".gw_sel_class="${gw_sel_class}" + [ -n "${hop_penalty}" ] && uci set network."${section}".hop_penalty="${hop_penalty}" + [ -n "${isolation_mark}" ] && uci set network."${section}".isolation_mark="${isolation_mark}" + [ -n "${log_level}" ] && uci set network."${section}".log_level="${log_level}" + [ -n "${multicast_mode}" ] && uci set network."${section}".multicast_mode="${multicast_mode}" + [ -n "${network_coding}" ] && uci set network."${section}".network_coding="${network_coding}" + [ -n "${orig_interval}" ] && uci set network."${section}".orig_interval="${orig_interval}" +} + +if [ -f /etc/config/batman-adv ]; then + config_load network + config_foreach proto_batadv_to_batadv_hardif 'interface' + uci commit network + + config_load batman-adv + config_foreach mv_batadv_config_section 'mesh' + uci commit network + + rm -f /etc/config/batman-adv +fi + +exit 0 diff --git a/feeds/ipq40xx/batman-adv/files/lib/netifd/proto/batadv.sh b/feeds/ipq40xx/batman-adv/files/lib/netifd/proto/batadv.sh new file mode 100755 index 000000000..edc14f4cb --- /dev/null +++ b/feeds/ipq40xx/batman-adv/files/lib/netifd/proto/batadv.sh @@ -0,0 +1,123 @@ +#!/bin/sh + +[ -n "$INCLUDE_ONLY" ] || { + . /lib/functions.sh + . ../netifd-proto.sh + init_proto "$@" +} + +proto_batadv_init_config() { + no_device=1 + available=1 + + proto_config_add_boolean 'aggregated_ogms:bool' + proto_config_add_boolean 'ap_isolation:bool' + proto_config_add_boolean 'bonding:bool' + proto_config_add_boolean 'bridge_loop_avoidance:bool' + proto_config_add_boolean 'distributed_arp_table:bool' + proto_config_add_boolean 'fragmentation:bool' + proto_config_add_string 'gw_bandwidth' + proto_config_add_string 'gw_mode' + proto_config_add_int 'gw_sel_class' + proto_config_add_int 'hop_penalty' + proto_config_add_string 'isolation_mark' + proto_config_add_string 'log_level' + proto_config_add_int 'multicast_fanout' + proto_config_add_boolean 'multicast_mode:bool' + proto_config_add_boolean 'network_coding:bool' + proto_config_add_int 'orig_interval' + proto_config_add_string 'routing_algo' +} + +proto_batadv_setup() { + local config="$1" + local iface="$config" + + local aggregated_ogms + local ap_isolation + local bonding + local bridge_loop_avoidance + local distributed_arp_table + local fragmentation + local gw_bandwidth + local gw_mode + local gw_sel_class + local hop_penalty + local isolation_mark + local log_level + local multicast_fanout + local multicast_mode + local network_coding + local orig_interval + local routing_algo + + json_get_vars aggregated_ogms + json_get_vars ap_isolation + json_get_vars bonding + json_get_vars bridge_loop_avoidance + json_get_vars distributed_arp_table + json_get_vars fragmentation + json_get_vars gw_bandwidth + json_get_vars gw_mode + json_get_vars gw_sel_class + json_get_vars hop_penalty + json_get_vars isolation_mark + json_get_vars log_level + json_get_vars multicast_fanout + json_get_vars multicast_mode + json_get_vars network_coding + json_get_vars orig_interval + json_get_vars routing_algo + + set_default routing_algo 'BATMAN_IV' + + batctl routing_algo "$routing_algo" + batctl meshif "$iface" interface create + + [ -n "$aggregated_ogms" ] && batctl meshif "$iface" aggregation "$aggregated_ogms" + [ -n "$ap_isolation" ] && batctl meshif "$iface" ap_isolation "$ap_isolation" + [ -n "$bonding" ] && batctl meshif "$iface" bonding "$bonding" + [ -n "$bridge_loop_avoidance" ] && batctl meshif "$iface" bridge_loop_avoidance "$bridge_loop_avoidance" 2>&- + [ -n "$distributed_arp_table" ] && batctl meshif "$iface" distributed_arp_table "$distributed_arp_table" 2>&- + [ -n "$fragmentation" ] && batctl meshif "$iface" fragmentation "$fragmentation" + + case "$gw_mode" in + server) + if [ -n "$gw_bandwidth" ]; then + batctl meshif "$iface" gw_mode "server" "$gw_bandwidth" + else + batctl meshif "$iface" gw_mode "server" + fi + ;; + client) + if [ -n "$gw_sel_class" ]; then + batctl meshif "$iface" gw_mode "client" "$gw_sel_class" + else + batctl meshif "$iface" gw_mode "client" + fi + ;; + *) + batctl meshif "$iface" gw_mode "off" + ;; + esac + + [ -n "$hop_penalty" ] && batctl meshif "$iface" hop_penalty "$hop_penalty" + [ -n "$isolation_mark" ] && batctl meshif "$iface" isolation_mark "$isolation_mark" + [ -n "$multicast_fanout" ] && batctl meshif "$iface" multicast_fanout "$multicast_fanout" + [ -n "$multicast_mode" ] && batctl meshif "$iface" multicast_mode "$multicast_mode" 2>&- + [ -n "$network_coding" ] && batctl meshif "$iface" network_coding "$network_coding" 2>&- + [ -n "$log_level" ] && batctl meshif "$iface" loglevel "$log_level" 2>&- + [ -n "$orig_interval" ] && batctl meshif "$iface" orig_interval "$orig_interval" + + proto_init_update "$iface" 1 + proto_send_update "$config" +} + +proto_batadv_teardown() { + local config="$1" + local iface="$config" + + batctl meshif "$iface" interface destroy +} + +add_protocol batadv diff --git a/feeds/ipq40xx/batman-adv/files/lib/netifd/proto/batadv_hardif.sh b/feeds/ipq40xx/batman-adv/files/lib/netifd/proto/batadv_hardif.sh new file mode 100755 index 000000000..6eb597ff6 --- /dev/null +++ b/feeds/ipq40xx/batman-adv/files/lib/netifd/proto/batadv_hardif.sh @@ -0,0 +1,49 @@ +#!/bin/sh + +[ -n "$INCLUDE_ONLY" ] || { + . /lib/functions.sh + . ../netifd-proto.sh + init_proto "$@" +} + +proto_batadv_hardif_init_config() { + proto_config_add_int 'elp_interval' + proto_config_add_string "master" + proto_config_add_string 'throughput_override' +} + +proto_batadv_hardif_setup() { + local config="$1" + local iface="$2" + + local elp_interval + local master + local throughput_override + + json_get_vars elp_interval + json_get_vars master + json_get_vars throughput_override + + ( proto_add_host_dependency "$config" '' "$master" ) + + batctl meshif "$master" interface -M add "$iface" + + [ -n "$elp_interval" ] && batctl hardif "$iface" elp_interval "$elp_interval" + [ -n "$throughput_override" ] && batctl hardif "$iface" throughput_override "$throughput_override" + + proto_init_update "$iface" 1 + proto_send_update "$config" +} + +proto_batadv_hardif_teardown() { + local config="$1" + local iface="$2" + + local master + + json_get_vars master + + batctl meshif "$master" interface -M del "$iface" || true +} + +add_protocol batadv_hardif diff --git a/feeds/ipq40xx/batman-adv/files/lib/netifd/proto/batadv_vlan.sh b/feeds/ipq40xx/batman-adv/files/lib/netifd/proto/batadv_vlan.sh new file mode 100755 index 000000000..115e61cde --- /dev/null +++ b/feeds/ipq40xx/batman-adv/files/lib/netifd/proto/batadv_vlan.sh @@ -0,0 +1,25 @@ +#!/bin/sh + +. /lib/functions.sh +. ../netifd-proto.sh +init_proto "$@" + +proto_batadv_vlan_init_config() { + proto_config_add_boolean 'ap_isolation:bool' +} + +proto_batadv_vlan_setup() { + local config="$1" + local iface="$2" + + # batadv_vlan options + local ap_isolation + + json_get_vars ap_isolation + + [ -n "$ap_isolation" ] && batctl vlan "$iface" ap_isolation "$ap_isolation" + proto_init_update "$iface" 1 + proto_send_update "$config" +} + +add_protocol batadv_vlan diff --git a/feeds/ipq40xx/batman-adv/src/compat-hacks.h b/feeds/ipq40xx/batman-adv/src/compat-hacks.h new file mode 100644 index 000000000..b57f7b6e0 --- /dev/null +++ b/feeds/ipq40xx/batman-adv/src/compat-hacks.h @@ -0,0 +1,181 @@ +/* Please avoid adding hacks here - instead add it to mac80211/backports.git */ + +#undef CONFIG_MODULE_STRIPPED + +#include /* LINUX_VERSION_CODE */ +#include + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0) + +#include + +#define netdev_master_upper_dev_link(dev, upper_dev, upper_priv, upper_info, extack) ({\ + BUILD_BUG_ON(extack != NULL); \ + netdev_master_upper_dev_link(dev, upper_dev, upper_priv, upper_info); \ +}) + +#endif /* < KERNEL_VERSION(4, 15, 0) */ + + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 16, 0) + +#ifndef sizeof_field +#define sizeof_field(TYPE, MEMBER) sizeof((((TYPE *)0)->MEMBER)) +#endif + +#endif /* < KERNEL_VERSION(4, 16, 0) */ + + +#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 1, 0) + +#include_next +#include_next + +static inline int batadv_ipv6_mc_check_mld1(struct sk_buff *skb) +{ + return ipv6_mc_check_mld(skb, NULL); +} + +static inline int batadv_ipv6_mc_check_mld2(struct sk_buff *skb, + struct sk_buff **skb_trimmed) +{ + return ipv6_mc_check_mld(skb, skb_trimmed); +} + +#define ipv6_mc_check_mld_get(_1, _2, ipv6_mc_check_mld_name, ...) ipv6_mc_check_mld_name +#define ipv6_mc_check_mld(...) \ + ipv6_mc_check_mld_get(__VA_ARGS__, batadv_ipv6_mc_check_mld2, batadv_ipv6_mc_check_mld1)(__VA_ARGS__) + +static inline int batadv_ip_mc_check_igmp1(struct sk_buff *skb) +{ + return ip_mc_check_igmp(skb, NULL); +} + +static inline int batadv_ip_mc_check_igmp2(struct sk_buff *skb, + struct sk_buff **skb_trimmed) +{ + return ip_mc_check_igmp(skb, skb_trimmed); +} + +#define ip_mc_check_igmp_get(_1, _2, ip_mc_check_igmp_name, ...) ip_mc_check_igmp_name +#define ip_mc_check_igmp(...) \ + ip_mc_check_igmp_get(__VA_ARGS__, batadv_ip_mc_check_igmp2, batadv_ip_mc_check_igmp1)(__VA_ARGS__) + +#endif /* < KERNEL_VERSION(5, 1, 0) */ + + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0) + +#define batadv_softif_slave_add(__dev, __slave_dev, __extack) \ + batadv_softif_slave_add(__dev, __slave_dev) + +#endif /* < KERNEL_VERSION(4, 15, 0) */ + + +#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 0, 0) + +static inline int batadv_access_ok(int type, const void __user *p, + unsigned long size) +{ + return access_ok(type, p, size); +} + +#ifdef access_ok +#undef access_ok +#endif + +#define access_ok_get(_1, _2, _3 , access_ok_name, ...) access_ok_name +#define access_ok(...) \ + access_ok_get(__VA_ARGS__, access_ok3, access_ok2)(__VA_ARGS__) + +#define access_ok2(addr, size) batadv_access_ok(VERIFY_WRITE, (addr), (size)) +#define access_ok3(type, addr, size) batadv_access_ok((type), (addr), (size)) + +#endif /* < KERNEL_VERSION(5, 0, 0) */ + +#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 4, 0) + +#ifndef fallthrough +#if __GNUC__ > 7 && !defined(__CHECKER__) +# define fallthrough __attribute__((__fallthrough__)) +#else +# define fallthrough do {} while (0) /* fallthrough */ +#endif +#endif + +#endif /* < KERNEL_VERSION(5, 4, 0) */ + +/* */ + +#include +#include_next + +#include + +#ifdef DECLARE_EWMA +#undef DECLARE_EWMA +#endif /* DECLARE_EWMA */ + +/* + * Exponentially weighted moving average (EWMA) + * + * This implements a fixed-precision EWMA algorithm, with both the + * precision and fall-off coefficient determined at compile-time + * and built into the generated helper funtions. + * + * The first argument to the macro is the name that will be used + * for the struct and helper functions. + * + * The second argument, the precision, expresses how many bits are + * used for the fractional part of the fixed-precision values. + * + * The third argument, the weight reciprocal, determines how the + * new values will be weighed vs. the old state, new values will + * get weight 1/weight_rcp and old values 1-1/weight_rcp. Note + * that this parameter must be a power of two for efficiency. + */ + +#define DECLARE_EWMA(name, _precision, _weight_rcp) \ + struct ewma_##name { \ + unsigned long internal; \ + }; \ + static inline void ewma_##name##_init(struct ewma_##name *e) \ + { \ + BUILD_BUG_ON(!__builtin_constant_p(_precision)); \ + BUILD_BUG_ON(!__builtin_constant_p(_weight_rcp)); \ + /* \ + * Even if you want to feed it just 0/1 you should have \ + * some bits for the non-fractional part... \ + */ \ + BUILD_BUG_ON((_precision) > 30); \ + BUILD_BUG_ON_NOT_POWER_OF_2(_weight_rcp); \ + e->internal = 0; \ + } \ + static inline unsigned long \ + ewma_##name##_read(struct ewma_##name *e) \ + { \ + BUILD_BUG_ON(!__builtin_constant_p(_precision)); \ + BUILD_BUG_ON(!__builtin_constant_p(_weight_rcp)); \ + BUILD_BUG_ON((_precision) > 30); \ + BUILD_BUG_ON_NOT_POWER_OF_2(_weight_rcp); \ + return e->internal >> (_precision); \ + } \ + static inline void ewma_##name##_add(struct ewma_##name *e, \ + unsigned long val) \ + { \ + unsigned long internal = READ_ONCE(e->internal); \ + unsigned long weight_rcp = ilog2(_weight_rcp); \ + unsigned long precision = _precision; \ + \ + BUILD_BUG_ON(!__builtin_constant_p(_precision)); \ + BUILD_BUG_ON(!__builtin_constant_p(_weight_rcp)); \ + BUILD_BUG_ON((_precision) > 30); \ + BUILD_BUG_ON_NOT_POWER_OF_2(_weight_rcp); \ + \ + WRITE_ONCE(e->internal, internal ? \ + (((internal << weight_rcp) - internal) + \ + (val << precision)) >> weight_rcp : \ + (val << precision)); \ + } + +/* */ diff --git a/feeds/ipq40xx/ipq-wifi/Makefile b/feeds/ipq40xx/ipq-wifi/Makefile new file mode 100644 index 000000000..20d08e981 --- /dev/null +++ b/feeds/ipq40xx/ipq-wifi/Makefile @@ -0,0 +1,151 @@ +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/version.mk + +PKG_NAME:=ipq-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:= \ + 8dev_habanero-dvk \ + aruba_ap-303 \ + avm_fritzrepeater-1200 \ + buffalo_wtr-m2133hp \ + cellc_rtl30vw \ + devolo_magic-2-wifi-next \ + dlink_dap2610 \ + edgecore_ecw5410 \ + edgecore_ssw2ac2600 \ + edgecore_oap100 \ + engenius_eap2200 \ + engenius_emd1 \ + engenius_emr3500 \ + ezviz_cs-w3-wd1200g-eup \ + glinet_gl-ap1300 \ + glinet_gl-s1300 \ + linksys_ea8300 \ + linksys_mr8300-v0 \ + luma_wrtq-329acn \ + mikrotik_hap-ac2 \ + mikrotik_sxtsq-5-ac \ + mobipromo_cm520-79f \ + nec_wg2600hp3 \ + plasmacloud_pa1200 \ + plasmacloud_pa2200 \ + qxwlan_e2600ac \ + cig_wf610d \ + wallys_dr40x9 \ + tp-link_ec420-g1 \ + udaya-a5-id2 \ + hfcl_ion4 + +ALLWIFIPACKAGES:=$(foreach BOARD,$(ALLWIFIBOARDS),ipq-wifi-$(BOARD)) + +define Package/ipq-wifi-default + SUBMENU:=ath10k Board-Specific Overrides + SECTION:=firmware + CATEGORY:=Firmware + DEPENDS:=@(TARGET_ipq40xx||TARGET_ipq806x) + TITLE:=Custom Board +endef + +define ipq-wifi-install-one-to + $(INSTALL_DIR) $(2)/lib/firmware/ath10k/$(3)/ + $(INSTALL_DATA) $(1) $(2)/lib/firmware/ath10k/$(3)/board-2.bin +endef + +define ipq-wifi-install-one + $(if $(filter $(suffix $(1)),.QCA4019 .qca4019),\ + $(call ipq-wifi-install-one-to,$(1),$(2),QCA4019/hw1.0),\ + $(if $(filter $(suffix $(1)),.QCA9888 .qca9888),\ + $(call ipq-wifi-install-one-to,$(1),$(2),QCA9888/hw2.0),\ + $(if $(filter $(suffix $(1)),.QCA9984 .qca9984),\ + $(call ipq-wifi-install-one-to,$(1),$(2),QCA9984/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-ipq-wifi-package + define Package/ipq-wifi-$(1) + $(call Package/ipq-wifi-default) + TITLE:=board-2.bin Overrides for $(2) + CONFLICTS:=$(PREV_BOARD) + endef + + define Package/ipq-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/ipq-wifi-$(1)/install-overlay + $$$$(foreach IPQ_WIFI_BOARD_FILE,$$$$(wildcard board-$(1).*),\ + $$$$(call ipq-wifi-install-one,$$$$(IPQ_WIFI_BOARD_FILE),$$(1))) + endef + + PREV_BOARD+=ipq-wifi-$(1) +endef + +# Add board name to ALLWIFIBOARDS +# Place files in this directory as board-. +# Add $(eval $(call generate-ipq-wifi-package,,)) + +$(eval $(call generate-ipq-wifi-package,8dev_habanero-dvk,8devices Habanero DVK)) +$(eval $(call generate-ipq-wifi-package,aruba_ap-303,Aruba AP-303)) +$(eval $(call generate-ipq-wifi-package,avm_fritzrepeater-1200,AVM FRITZRepeater 1200)) +$(eval $(call generate-ipq-wifi-package,buffalo_wtr-m2133hp,Buffalo WTR-M2133HP)) +$(eval $(call generate-ipq-wifi-package,cellc_rtl30vw, Cell C RTL30VW)) +$(eval $(call generate-ipq-wifi-package,devolo_magic-2-wifi-next,devolo Magic 2 WiFi next)) +$(eval $(call generate-ipq-wifi-package,dlink_dap2610,D-Link DAP-2610)) +$(eval $(call generate-ipq-wifi-package,edgecore_ecw5410,Edgecore ECW5410)) +$(eval $(call generate-ipq-wifi-package,edgecore_ssw2ac2600,Edgecore SSW2AC2600)) +$(eval $(call generate-ipq-wifi-package,edgecore_oap100,Edgecore OAP100)) +$(eval $(call generate-ipq-wifi-package,engenius_eap2200,EnGenius EAP2200)) +$(eval $(call generate-ipq-wifi-package,engenius_emd1,EnGenius EMD1)) +$(eval $(call generate-ipq-wifi-package,engenius_emr3500,EnGenius EMR3500)) +$(eval $(call generate-ipq-wifi-package,ezviz_cs-w3-wd1200g-eup,EZVIZ CS-W3-WD1200G EUP)) +$(eval $(call generate-ipq-wifi-package,glinet_gl-ap1300,GL.iNet GL-AP1300)) +$(eval $(call generate-ipq-wifi-package,glinet_gl-s1300,GL.iNet GL-S1300)) +$(eval $(call generate-ipq-wifi-package,linksys_ea8300,Linksys EA8300)) +$(eval $(call generate-ipq-wifi-package,linksys_mr8300-v0,Linksys MR8300)) +$(eval $(call generate-ipq-wifi-package,luma_wrtq-329acn,Luma WRTQ-329ACN)) +$(eval $(call generate-ipq-wifi-package,mikrotik_hap-ac2,Mikrotik hAP ac2)) +$(eval $(call generate-ipq-wifi-package,mikrotik_sxtsq-5-ac,MikroTik SXTsq 5 ac)) +$(eval $(call generate-ipq-wifi-package,mobipromo_cm520-79f,MobiPromo CM520-79F)) +$(eval $(call generate-ipq-wifi-package,nec_wg2600hp3,NEC Platforms WG2600HP3)) +$(eval $(call generate-ipq-wifi-package,plasmacloud_pa1200,Plasma Cloud PA1200)) +$(eval $(call generate-ipq-wifi-package,plasmacloud_pa2200,Plasma Cloud PA2200)) +$(eval $(call generate-ipq-wifi-package,qxwlan_e2600ac,Qxwlan E2600AC)) +$(eval $(call generate-ipq-wifi-package,cig_wf610d,CIG WF_610D)) +$(eval $(call generate-ipq-wifi-package,tp-link_ec420-g1,tp-link EC420-G1)) +$(eval $(call generate-ipq-wifi-package,wallys_dr40x9,Wallys DR40X9)) +$(eval $(call generate-ipq-wifi-package,hfcl_ion4,HFCL ION4)) +$(eval $(call generate-ipq-wifi-package,udaya-a5-id2,udaya A5 ID2)) + +$(foreach PACKAGE,$(ALLWIFIPACKAGES),$(eval $(call BuildPackage,$(PACKAGE)))) diff --git a/feeds/ipq40xx/ipq-wifi/board-8dev_habanero-dvk.qca4019 b/feeds/ipq40xx/ipq-wifi/board-8dev_habanero-dvk.qca4019 new file mode 100644 index 0000000000000000000000000000000000000000..9048239cf9f59bbc4df70251b73adfe93382ae62 GIT binary patch literal 24324 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 literal 0 HcmV?d00001 diff --git a/feeds/ipq40xx/ipq-wifi/board-aruba_ap-303.qca4019 b/feeds/ipq40xx/ipq-wifi/board-aruba_ap-303.qca4019 new file mode 100644 index 0000000000000000000000000000000000000000..4848115cfbe3a4a0ed6b17cac929731ecbd7968c GIT binary patch literal 24316 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 NIrrxNmNc!u{{!hMI2Hf^ literal 0 HcmV?d00001 diff --git a/feeds/ipq40xx/ipq-wifi/board-avm_fritzrepeater-1200.qca4019 b/feeds/ipq40xx/ipq-wifi/board-avm_fritzrepeater-1200.qca4019 new file mode 100644 index 0000000000000000000000000000000000000000..d78a49d4dbf3fc22c40a83d052fc7c55542ff8e3 GIT binary patch literal 24332 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 F{|7QKi|GIW literal 0 HcmV?d00001 diff --git a/feeds/ipq40xx/ipq-wifi/board-buffalo_wtr-m2133hp.qca4019 b/feeds/ipq40xx/ipq-wifi/board-buffalo_wtr-m2133hp.qca4019 new file mode 100644 index 0000000000000000000000000000000000000000..8305ba0166a2c07054d0789f1abaf3119c7c31bf GIT binary patch literal 24332 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 S+N+$ubtLzGvG1Cu$NxVG<{kV1 literal 0 HcmV?d00001 diff --git a/feeds/ipq40xx/ipq-wifi/board-buffalo_wtr-m2133hp.qca9984 b/feeds/ipq40xx/ipq-wifi/board-buffalo_wtr-m2133hp.qca9984 new file mode 100644 index 0000000000000000000000000000000000000000..656cb99cbb2b6de86639ae8dc8eee73c5c7cb490 GIT binary patch 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 literal 0 HcmV?d00001 diff --git a/feeds/ipq40xx/ipq-wifi/board-cellc_rtl30vw.qca4019 b/feeds/ipq40xx/ipq-wifi/board-cellc_rtl30vw.qca4019 new file mode 100644 index 0000000000000000000000000000000000000000..2fff2bf5fc7ce41c624ef14f5ed5d5f2df2015b3 GIT binary patch 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 literal 0 HcmV?d00001 diff --git a/feeds/ipq40xx/ipq-wifi/board-cig_wf610d.qca4019 b/feeds/ipq40xx/ipq-wifi/board-cig_wf610d.qca4019 new file mode 100644 index 0000000000000000000000000000000000000000..3ba97ff0b9dc46519dc3767cac3931872a8cc5f1 GIT binary patch literal 24316 zcmeHPdr(tX8b9G7>e|8$2_oPngg}Ue0D)?d2mvDUNWoG?0xSYmB)3L+7!X4j?D(J% z5rJATM$j@SkEV!>i!WkvZS9Qm_s;&&cJ|SoS$AzmyVK6>F7COx+$4}h6CNYN{la;D z_k8Dk-|wCz_vZY#?Q^4;EGI!JC4J(5j*edC`GGTar?@v34cz-WVAnfn(92JqwP-3NQaB zjRu_S=+W8uxEs1*RtUgqHxF0=fC0dpQHGlJjK^c+Lje#K74`Ger!)~`1^D$Zr{l@w z3gwUX=u{u|p8f!3kz}*1Gu4+!f8Qw{a8T$enU2`D93icVXv1UT4fnR;6cAZ)1@%ra1V$^{Ka84%BXyhvqTk zzUr&_H1j0Ca{c=^2dX>YX$q_MD;YUedN^(`FB^%u1^Y=bex7IC>&Xv%vl9P|eUZR%-~|z$IXOAe@Z8xM zel4$<61OY$IT79uKHM%qIh;WF7sL(-2xJGa+1V~D?Y$-;eWl8|BaoAmmBD8F!-0PJ z<>`-;llT>okQWq4=>GfTpMEgc;T_knadUEU`5)}(4o{fL{@Jr9kBPo>_v*zXlnuh` z5!j`yu6Ynoc<&8U5P2$Fy%AdzS!Ql>mockJWlwhqe*5KYN#hbnZG z&Zj@5BR;4P-$&|!dLZ6tBAUoge3*!&p=taysTdU_DX0Jy@C6SA$Yyjif3q|KjX;E` z(FyG(>s6yqB9YN6s%mk5?197+^?c%q_@cgiUuhDW^dt#MN7MP~(kL|QNfZ)`#`0sO z#7QvE4O0=&FL;ix-Lj9hgXSq{j$-!JVzp}R{W4qKQn)6iVzB4zQz%g=*+76=8a9BL zre2mPO+$ccPzX>6PzX>6PzX>6EMo-L3f3b2^lgG|NG5%gU=tEgUr7qcDsH_re9t^5 zZ~YxBE$3K8%Dm07j87pIx`PNjvk(UdSg7uHvKE%=PJ%SQR6X(t09YPYcaJ=pSrR{j zhXivtuoePKHj72+mJS9B^|qR?am4@uo_ke?F_*+3jfg<`{mmo4;2z-IgT zv1dp-)LUxV?EE$k5D97E=Ys&WyCF1jGyowh5g-C0m%G&WELkhhfukzQUl! zS%e5YA6mn3a@qrTAmHw@lgr9ap;^dH-XP%_eU5o!NbQn_s{?J z_dh>={5Pnx#km)Wq9X{-{^aDpf0}h4b?sSIxhz>2q#xGxs8yIu=!gHG*zLRA5C9F@v`W=Z z8Gm9(cSd~>%aRFoBie2ZlVu1)^}pA)suZ$BAqzLSGtT7#LpMy7t;(LbsXMP$V(-Z| z>29jeVihS8p#U1RsrHiwW8+*Nn7FOGpss@BzO5h9eWtF(WHOOXuhw9PQnrS88)o$N{Fw1RQrj+C4bzdyZ1tP0EXJ7 zJFQi!3!zI|?QwOvN~XK2?ZOl(3BvG+Te?f?8f=%)hcMs;<1w^qkElyj8Svl*^sas)Tdms=LAwHQ7G9!U@0sO8=+C^Ws5+^@PW(m?O_eRRTp)? z)kscrYu6n(bT;`IuiU42P4eBIy{ERQ0{5+zT^v4iIk7Fg!B;svRH98g^VaWt51#JM zZjL;{!rU{y>f7Hct`AbID^L&Z>=K^wucc!ReFf(QCr~B5c=Ss7S@B1_3i{4_{qnZ> z`oR6(1+@b^FN8JtRJ~c$KUDphxH+VDZK+z5aXj)6bJrVNZ}b(nZmwf}z|8x@4OM@p zhI`aYp}VTQ6x+zIqVI0(%sdfYvf zF`RM_mq_4NznVoP7g!Q$@yEY>J;XWjE|3$S({bhgLU7_28d+Ohds6=@`S$qS6zATs p*EQRW;@r;`Im&L)B4E#+u`Qmxxqi_GI7i1Q&iz7vYrc5={{xZF3n~Br literal 0 HcmV?d00001 diff --git a/feeds/ipq40xx/ipq-wifi/board-devolo_magic-2-wifi-next.qca4019 b/feeds/ipq40xx/ipq-wifi/board-devolo_magic-2-wifi-next.qca4019 new file mode 100644 index 0000000000000000000000000000000000000000..cf86721feabb1cbceb2ffe470dccd6628355062a GIT binary patch literal 24340 zcmeHPYfuwe7QP@a6-GJPSt|AytV;B5G8Xt3-#(n(8$g z2RIiW&dZNF8}Hx%)*WZX<)avz2Z19f1Ym=!C)x#YD~N@?8+_1-P#BA*0w6Xv_CK#) zfh3L#c>V8l$)>iBL+AB=8y`44nLnzViUi(5nSadk{-)VOp0FD9FbT@hq`&KvX)~U% zGUB^&8)m2E1L`qrm{B+^a|?akhcIsWJ@avvbyS&oW5a#acry)lHp#|~pM7SN1I=Io zjqPKYy3k28D|0h=F+AScsa9nwlV6PYcQltOvop6&j`W}EtW|xHxn*(`YIUl-%-_C- za_62f9K0MEKhasK+Nn%=G1`B!xk9PPOq#rfhAA^MrO@F_XCt&FQV!vp!OLsoEzSFs z37L`5wY|ASnGT2D=R}7WgZk+-m-2*C}ybK*_hGjryHuM2)=i$5(1vGRg#* z?1V?xs@t=w!}fTm-@Kvfm3RK8(ZAxsc*8){@xU5(;nK2ZygwEK&K{dEwwI5ee?Xww z8T(E}@3AvNpCY=-aBy&RbaX)5b?cm+on2dHc5D!LPCP!U#K7`C|D3A z5ac_#ftf25`iU9qN+8hP-O#Xmw<1FdHg0rrp(03yp}_({Al%`&{`d8pH(pSqY{(ek z?&|2|^gnW_1EBM#W?8vy%~(y>7@WT5c-I(eC{o0XgdqtL@Npic@n^Ng*+NJ`zOxFY zkuhwy(V>Fj7?z5sVlj9OR&(^&@%GbQ7kU>ez!!;+k53PdBp@K*GJKhl(l*mOwk;gP z!dYV0Qx?X>xni!u6Zgb?aTzWX%bv=xEIdn`rAWb3FgY&4C1S}_36_8-h!Ygicr+%( zXOl1t(W`)m#GlLM`svM7Q#y{0Z2}}gd_F&Lz|2aonv(bSo-L8bn=KMfM(?&#ROsY}i^e4?1^iP8-I|Tj&zy-6spZM)!JItj!*-Ntqg~dG;BU7?dm^z?>Qu zfSF@nlPJwWfZ1UXU=UysU=UysU=Uct2>3{Rut3)5lFzYStawR0mdtW93CJrxKXm7j z`8H`$vM|PalPp_|HT)DZrP~Vv)~*m(JMI(1MRA})H}MPr*f;40C!WpkKe2L{bnOg* zi>??*i332#!W_JzbkFn`XZi>?3?zXhrxbvJzdsVT0uTd&F#!0Gcq4#(9#cz#cA2yA zxy)7g57=%Kzx7|68j-_w~0xmE+I=OuV zYO5X_r3##r4_pFi@lczuMLmg zp1A+;FF*YB%=QD|-Kv(IYJgk^Rj@itE1~2Xs6y6ZS_LK7KNXS=(+a5VAX@aWe{}8i zq*?7{S+i!GlYg+htLMrM;@;HXEa|Jg&c)`(dBeeYI8V$|a6tN-bWDLO#0o_^h4S2_MykZe9O>MFKdl=^X zd7;2^^Y2lPCY&ILvHAqcCG$Y{d?ruw4zkVh8 z_bHq~&U4z|I#^fl=;)|*1IbbFxi%9U9On&PlgqkH(eus%+TB%%5^bK0kwJh#fI+}c z5GX8E=2QH87R%FvD#}LweIe!V;o#TFbvTeZOn7 zNm*I`y(yIsPL8*`z}EaPh58YM`IdyC?Za%*OTwIckMt$d??V-ELDB51#RBzxFT?56 z#wtQ#h|%$;JB*b?wn3r`n7U`^(H<$tkcLj(A+G7P>H;Yb{buZPZ+HZlzF=%7l!g?Y zX!?>-OYAqubWy~FVNk6u$dN`){mF1%t0|C4`N+Yb4-W^^eZ~{SAw#Zi+w_3(G*M;P zqZJX~>Uz|*@^q;LI$Y3JnH;X@!-W72J4@8)^3+?VuNyBAO}c&RBw|X}udbKxi0~yN zRI2w=DH-}uN(N&mQK?NY2$>!-o+D~?d(_*B?{s=~gIpfrKXu=5iA*UFrF5k)0!HXH zenpgMx68TEwS!P;WpaPwkA?xYMxH8-GJZ!4>6+DhrCj7N&?gK7(>=ykqEMS4_nX!m z+lf+blH3m_qSqcR$d(F?_lQ1St$LR{go+@9DV;Mm5&N_fIcNH7<1s=BHO%;cxC*gM zk>W4zPF*%Ms?+3tR0LRqEwTzP^_i5cc>)=f7?dm^U=OE;h0+)^MBv>A^IC%A-szU# z?T8Wa{9LYgR2_(y1Os<@vh*`FhnMxf~aGvUUAACt~Wo_Im7iaI5%y!f}43 z*Zzlwssp*{ks+AV#85-+4!I!0i`%K+buzBOx4>O~cl7s{q-}v3uY(i4^(C3xBZJv4 zBZh{$Ooc@1HE60Y)4k4#EW~jYwwqFYQcV1%AJwA z%QdiRbqRW3u=qq=fBMZk24|X@@_B1JzB0@t$;2*pb z2R}F{ND!3oylU>ov5*^YqTjpGtlckMH@C*JFoubKzkbDr6i`}p_hCN${oGkl!XkV0uIY%|^UhL4jP8TZ$0IL)}#Vhcfc)*5wnKd8;6mYJo>KZzbDRPp24?PmehD zuB{tjL%lPfl|))MdDWdE4l zdlY+R`S;|zHQdbH#te1T3Y(e1q*4by#C938`l$SSi*;B$U^}|YIF;?eKQRxBSXn$^ zdx6V1mBrxJtQlM4+?(5Bu6#a97)F|>BP(gQn8XSkfDxA^pT+U-!-60d2!|!sZOuIP 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|_! literal 0 HcmV?d00001 diff --git a/feeds/ipq40xx/ipq-wifi/board-edgecore_ecw5410.qca9984 b/feeds/ipq40xx/ipq-wifi/board-edgecore_ecw5410.qca9984 new file mode 100644 index 0000000000000000000000000000000000000000..2c1992001d86268e0483b9e53ed4b563e224ada4 GIT binary patch literal 24324 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 literal 0 HcmV?d00001 diff --git a/feeds/ipq40xx/ipq-wifi/board-edgecore_oap100.qca4019 b/feeds/ipq40xx/ipq-wifi/board-edgecore_oap100.qca4019 new file mode 100644 index 0000000000000000000000000000000000000000..9f1b5c93b5ebc7561987aa86f138e86c00d954b6 GIT binary patch literal 24324 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 literal 0 HcmV?d00001 diff --git a/feeds/ipq40xx/ipq-wifi/board-engenius_eap2200.qca4019 b/feeds/ipq40xx/ipq-wifi/board-engenius_eap2200.qca4019 new file mode 100644 index 0000000000000000000000000000000000000000..337d896d1edd06375a76b19da6f0b3e0bf452fc1 GIT binary patch literal 24324 zcmeHPdr(tX8b3S~b+vLsK!kV=A%uj60D)@M$V;RkDOg(3phciQNNSLW0WoyJjt`0v zEl|oUiqt_~O%WOE6MWRx&M31p`_In)(eCV{JG0K(9qmp#v%9$8$>oLwhy;Z;!2ObQ z&UYT)Ip6u+M{aU{Id5)=366O?AuKd0I5s6FH4bSs8U&ITf@6dtA!KU{*JtHqi?cPV z;CFLWdBLh(>qAYs?EP5{759?;jR!04-fzG$rC3zdp`R4 zFQ=mD-~t`Ipxhd5cbXarJp+Nd;oRs}qw`DAVQvhHiE~Bn!!No8_L0^{(x?~rc%&21 z7MaK8BI;#T4H-7evLuS_=H@nU-aHozLFgu)sh#2p?JR>A%4A@0qOv$$k+{xea6d2z^V`8Yk&aO+i__MzYg0_GV{(L;P`Jfp=y@*Y<`r$GL?bS#6bB+BMmNw^k(HIGtO% zQ6=8)8TnO5$tNktC50>Az1CIS@WzSYV$PnvlQ{#bP&SSJ(eRyQOfzM(m$Hef)@O`|@5r zzlXeTcpiZ!d1Y1IIN;Vivv9d2$>I3;@OX}>jW;ubB#0O?h6p3Wh&=6~BOg}Pw|0Y4 z23k$Mxdi6e$`f~s+uMc0cA>OaYBb7+<%U^dv8v%+TU+hzT@UZZ#(EaXlCU1I2p`f% z;-hdU-3f0pmW-9eK8PhYk((r&6wzcfkw8jGsYLofN~|TFY!aYqfMW5ye_S3rfwdZtcBm8JoUqPdXYq#zI=AY>YX42$`u* z5`m{CBg8MX^@c5B^^@(=YoQS0`Sj4 zHE?g(KZn$&>#~}vexnhAJiZr|BNT=Nz|Ro?8;B27C>{iyo@Rx?Dh7vRUaT2bYN32= zDUY|KhL7Z8C-mcfglgRgr|1ZTgbN5HM{?K9`2=$IbY8RrQg?SJd+!WWHC3jcUl@UB zJ&W1SuDf6b0#=uuT^D=;at?%c;|j>jlqt5s&9$ZP8(V3hAb|gC25RMwTC1a0=M)d=+tOzV9Al=z9%2(5k|W_L z*eGr&j!=*ai9!*FB8DOeIVqRO6%kYR{d&ycb`^L@y$F&OFO4UXS*xV0h)7m?BYurF zra$NCbf!G;OqO>aW*6_Cy~4=}NcRU%n^@qUEr3cU@VDJ4bb!V5eBQls+IaVuC=W*B z>Ehj!#K;&3QT%te`7ZNZ%?x;iE@&2e)yia>DOM_R9 zO@_mIje6t2MPsX>5{#3L*YyqRqJ#vY@4ywq$0nCnVwY~+6^al{^{nxfL95RMmkfrZ z`h1dnd!aHK(}RVK+q zgO`ns`T})I0v{XPz9RyZE)6so3iTPfxWOw>S*Y8g-UM!*11zIuB-Az=iq#tumYWRj z!5k(d4*00gxMa@(WKd#IvVp*CI5licjVYe92-NrHUWlp1STTr#3 zRIKqzz5n^96XKHPd)&8n^z3bkujU_O@2T(1Jrh+aILOYr(4eY_)CTSKNNQ`}-?;9G ze*rtAu_LP?=7e7%E2Fke)hIvaU+A&pWYyO9BhbIq@{@e!-Nj*^eEA zrrj@`vN6VipDAJx7#D#twEL%{n%PVGnCf<;+?Z?GiFo&pxz`Ni)l}^Q1Q@@)w;Km7BtsBdLi?@9a9vrAJP2z~c{E!_Rkj z4MT3_i@4UomFwtu%q9OYFWwb+@!RU#?@b3Ue!8)=#kZ%+e@)Ik9{ZQ!-Q!)ds6WHt z?X-kK0loTW`X7=I3*JUcA`#OSc(*NTCn>zC7ToLU3dc$vf_IOR#R&8Hcz-bqbf>Ta zA0m9Pf`ahIWflhtA0&LRND_Y>SsbXzS2)(8ox9%Hvu13IYj0VO5yTtbktAO@TF1NJ v@%cd#T#mQD^Y$i9m$)q*w{sMEQQkeiNaS*Soyz5Si$LpmDrYyldH4SZO~~I9 literal 0 HcmV?d00001 diff --git a/feeds/ipq40xx/ipq-wifi/board-engenius_eap2200.qca9888 b/feeds/ipq40xx/ipq-wifi/board-engenius_eap2200.qca9888 new file mode 100644 index 0000000000000000000000000000000000000000..2e938f4785c5cf4dd088028bfe37c5985c3a9a5e GIT binary patch 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 literal 0 HcmV?d00001 diff --git a/feeds/ipq40xx/ipq-wifi/board-engenius_emd1.qca4019 b/feeds/ipq40xx/ipq-wifi/board-engenius_emd1.qca4019 new file mode 100644 index 0000000000000000000000000000000000000000..3a2d77597df2899722962245a3832e45b9f3bfa2 GIT binary patch literal 24316 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 M-<$he(lmSj12G&o9smFU literal 0 HcmV?d00001 diff --git a/feeds/ipq40xx/ipq-wifi/board-glinet_gl-ap1300.qca4019 b/feeds/ipq40xx/ipq-wifi/board-glinet_gl-ap1300.qca4019 new file mode 100644 index 0000000000000000000000000000000000000000..481dd81b5b15bda95569e4f4acdca078bc0be727 GIT binary patch literal 48596 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 L2*fwBdH4Sh_9QQ4 literal 0 HcmV?d00001 diff --git a/feeds/ipq40xx/ipq-wifi/board-linksys_ea8300.qca9888 b/feeds/ipq40xx/ipq-wifi/board-linksys_ea8300.qca9888 new file mode 100644 index 0000000000000000000000000000000000000000..e3c2039924f483ecc3679ee005c0a1f73c6bbcc4 GIT binary patch literal 48628 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 Y3=Rt&nS*)vCPAN`MyjX(-@N<(0qkJ6aR2}S literal 0 HcmV?d00001 diff --git a/feeds/ipq40xx/ipq-wifi/board-linksys_mr8300-v0.qca4019 b/feeds/ipq40xx/ipq-wifi/board-linksys_mr8300-v0.qca4019 new file mode 100644 index 0000000000000000000000000000000000000000..689d9c481dbe84def37a9d9a22c4bae4ef59e452 GIT binary patch literal 97268 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 RT3s&UvhIO<@8A1^{|8J-1^oa3 literal 0 HcmV?d00001 diff --git a/feeds/ipq40xx/ipq-wifi/board-linksys_mr8300-v0.qca9888 b/feeds/ipq40xx/ipq-wifi/board-linksys_mr8300-v0.qca9888 new file mode 100644 index 0000000000000000000000000000000000000000..90b6bac08ca6b2f05d4a6ba60b7c09422bbad2eb GIT binary patch literal 48644 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 literal 0 HcmV?d00001 diff --git a/feeds/ipq40xx/ipq-wifi/board-nec_wg2600hp3.qca9984 b/feeds/ipq40xx/ipq-wifi/board-nec_wg2600hp3.qca9984 new file mode 100644 index 0000000000000000000000000000000000000000..f95ccd251e785d4db96b9953b655801e95b02431 GIT binary patch literal 24332 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 Bvkw3O literal 0 HcmV?d00001 diff --git a/feeds/ipq40xx/ipq-wifi/board-plasmacloud_pa1200.qca4019 b/feeds/ipq40xx/ipq-wifi/board-plasmacloud_pa1200.qca4019 new file mode 100644 index 0000000000000000000000000000000000000000..27bfcfecc65dfa5844c138930c7103e0f24d2803 GIT binary patch literal 24324 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 literal 0 HcmV?d00001 diff --git a/feeds/ipq40xx/ipq-wifi/board-qxwlan_e2600ac.qca4019 b/feeds/ipq40xx/ipq-wifi/board-qxwlan_e2600ac.qca4019 new file mode 100644 index 0000000000000000000000000000000000000000..435b465d895d33a2df4c5ca510d225a495de4897 GIT binary patch literal 36464 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 SvE1>Q568KurQ3I$`+ot*{f0IG literal 0 HcmV?d00001 diff --git a/feeds/ipq40xx/ipq-wifi/board-tp-link_ec420-g1.qca4019 b/feeds/ipq40xx/ipq-wifi/board-tp-link_ec420-g1.qca4019 new file mode 100644 index 0000000000000000000000000000000000000000..58046713c3e25f2332d00550778b897b5524541c GIT binary patch literal 607304 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�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�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 RC%DMKNY1^rza=f}@BfIFW;6f* literal 0 HcmV?d00001 diff --git a/feeds/ipq40xx/ipq40xx/Makefile b/feeds/ipq40xx/ipq40xx/Makefile new file mode 100644 index 000000000..d1906048d --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/Makefile @@ -0,0 +1,25 @@ +include $(TOPDIR)/rules.mk + +ARCH:=arm +BOARD:=ipq40xx +BOARDNAME:=Qualcomm Atheros IPQ40XX +FEATURES:=squashfs fpu ramdisk nand +CPU_TYPE:=cortex-a7 +CPU_SUBTYPE:=neon-vfpv4 +SUBTARGETS:=generic mikrotik + +KERNEL_PATCHVER:=5.4 +KERNEL_TESTING_PATCHVER:=5.4 +DEVICE_TYPE:=qsdk + +KERNELNAME:=zImage Image dtbs + +include $(INCLUDE_DIR)/target.mk +DEFAULT_PACKAGES += \ + kmod-usb-dwc3-qcom \ + kmod-leds-gpio kmod-gpio-button-hotplug swconfig \ + kmod-ath10k-ct wpad-basic-wolfssl \ + kmod-usb3 kmod-usb-dwc3 ath10k-firmware-qca4019-ct \ + uboot-envtools + +$(eval $(call BuildTarget)) diff --git a/feeds/ipq40xx/ipq40xx/base-files/etc/board.d/01_leds b/feeds/ipq40xx/ipq40xx/base-files/etc/board.d/01_leds new file mode 100755 index 000000000..e16e916d3 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/base-files/etc/board.d/01_leds @@ -0,0 +1,91 @@ +#!/bin/sh +# +# Copyright (C) 2015 OpenWrt.org +# + +. /lib/functions/uci-defaults.sh + +board_config_update + +board=$(board_name) + +case "$board" in +alfa-network,ap120c-ac) + ucidef_set_led_netdev "wan" "WAN" "amber:wan" "eth1" + ;; +asus,rt-ac58u) + ucidef_set_led_netdev "wan" "WAN" "blue:wan" "eth1" + ucidef_set_led_switch "lan" "LAN" "blue:lan" "switch0" "0x1e" + ;; +avm,fritzbox-4040) + ucidef_set_led_wlan "wlan" "WLAN" "green:wlan" "phy0tpt" "phy1tpt" + ucidef_set_led_netdev "wan" "WAN" "green:wan" "eth1" + ucidef_set_led_switch "lan" "LAN" "green:lan" "switch0" "0x1e" + ;; +avm,fritzbox-7530 |\ +glinet,gl-b1300) + ucidef_set_led_wlan "wlan" "WLAN" "green:wlan" "phy0tpt" + ;; +edgecore,oap100 |\ +edgecore,oap100e) + ucidef_set_led_wlan "wlan2g" "WLAN2G" "blue:wlan2g" "phy0tpt" + ucidef_set_led_wlan "wlan5g" "WLAN5G" "blue:wlan5g" "phy1tpt" + ;; + +engenius,eap1300) + ucidef_set_led_netdev "lan" "LAN" "blue:lan" "eth0" + ucidef_set_led_wlan "wlan2g" "WLAN2G" "blue:wlan2g" "phy0tpt" + ucidef_set_led_wlan "wlan5g" "WLAN5G" "yellow:wlan5g" "phy1tpt" + ucidef_set_led_default "mesh" "MESH" "blue:mesh" "0" + ;; +engenius,eap2200) + ucidef_set_led_netdev "lan1" "LAN1" "blue:lan1" "eth0" + ucidef_set_led_netdev "lan2" "LAN2" "blue:lan2" "eth1" + ;; +engenius,ens620ext) + ucidef_set_led_wlan "wlan2g" "WLAN2G" "green:wlan2g" "phy0tpt" + ucidef_set_led_wlan "wlan5g" "WLAN5G" "green:wlan5g" "phy1tpt" + ucidef_set_led_netdev "lan1" "LAN1" "green:lan1" "eth0" + ucidef_set_led_netdev "lan2" "LAN2" "green:lan2" "eth1" + ;; +mikrotik,sxtsq-5-ac) + ucidef_set_rssimon "wlan0" "200000" "1" + ucidef_set_led_rssi "rssilow" "rssilow" "green:rssilow" "wlan0" "1" "100" + ucidef_set_led_rssi "rssimediumlow" "rssimediumlow" "green:rssimediumlow" "wlan0" "21" "100" + ucidef_set_led_rssi "rssimedium" "rssimedium" "green:rssimedium" "wlan0" "41" "100" + ucidef_set_led_rssi "rssimediumhigh" "rssimediumhigh" "green:rssimediumhigh" "wlan0" "61" "100" + ucidef_set_led_rssi "rssihigh" "rssihigh" "green:rssihigh" "wlan0" "81" "100" + ;; +mobipromo,cm520-79f) + ucidef_set_led_netdev "wan" "WAN" "blue:wan" "eth1" + ucidef_set_led_switch "lan1" "LAN1" "blue:lan1" "switch0" "0x10" + ucidef_set_led_switch "lan2" "LAN2" "blue:lan2" "switch0" "0x08" + ;; +netgear,ex6100v2 |\ +netgear,ex6150v2) + ucidef_set_led_wlan "wlan2g" "WLAN2G" "green:router" "phy0tpt" + ucidef_set_led_wlan "wlan5g" "WLAN5G" "green:client" "phy1tpt" + ;; +qxwlan,e2600ac-c1 |\ +qxwlan,e2600ac-c2) + ucidef_set_led_wlan "wlan2g" "WLAN0" "green:wlan0" "phy0tpt" + ucidef_set_led_wlan "wlan5g" "WLAN1" "green:wlan1" "phy1tpt" + ;; +edgecore,ecw5211 |\ +edgecore,spw2ac1200 |\ +edgecore,spw2ac1200-lan-poe |\ +cig,wf610d |\ +zyxel,nbg6617 |\ +zyxel,wre6606) + ucidef_set_led_wlan "wlan2g" "WLAN2G" "green:wlan2g" "phy0tpt" + ucidef_set_led_wlan "wlan5g" "WLAN5G" "green:wlan5g" "phy1tpt" + ;; +hfcl,ion4) + ucidef_set_led_wlan "wlan2g" "WLAN2G" "yellow:wlan2g" "phy0tpt" + ucidef_set_led_wlan "wlan5g" "WLAN5G" "red:wlan5g" "phy1tpt" + ;; +esac + +board_config_flush + +exit 0 diff --git a/feeds/ipq40xx/ipq40xx/base-files/etc/board.d/02_network b/feeds/ipq40xx/ipq40xx/base-files/etc/board.d/02_network new file mode 100755 index 000000000..efaf347b0 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/base-files/etc/board.d/02_network @@ -0,0 +1,211 @@ +#!/bin/sh +# +# Copyright (c) 2015 The Linux Foundation. All rights reserved. +# Copyright (c) 2011-2015 OpenWrt.org +# + +. /lib/functions/uci-defaults.sh +. /lib/functions/system.sh + +ipq40xx_setup_interfaces() +{ + local board="$1" + + case "$board" in + 8dev,habanero-dvk|\ + 8dev,jalapeno|\ + alfa-network,ap120c-ac|\ + edgecore,spw2ac1200-lan-poe |\ + engenius,emr3500|\ + engenius,ens620ext|\ + luma,wrtq-329acn|\ + plasmacloud,pa1200|\ + plasmacloud,pa2200|\ + wallys,dr40x9) + ucidef_set_interfaces_lan_wan "eth0" "eth1" + ;; + aruba,ap-303|\ + aruba,ap-365|\ + avm,fritzrepeater-1200|\ + dlink,dap-2610 |\ + engenius,eap1300|\ + engenius,emd1|\ + meraki,mr33|\ + mikrotik,sxtsq-5-ac|\ + netgear,ex6100v2|\ + netgear,ex6150v2|\ + tp-link,ec420-g1|\ + hfcl,ion4|\ + zyxel,wre6606) + ucidef_set_interface_wan "eth0" + ;; + aruba,ap-303h) + ucidef_set_interfaces_lan_wan "eth0" "eth1" + ucidef_add_switch "switch0" \ + "0u@eth0" "2:lan:1" "3:lan:2" "4:lan:3" "0u@eth1" "5:wan" + ;; + asus,map-ac2200|\ + cilab,meshpoint-one|\ + cig,wf610d|\ + edgecore,ecw5211|\ + edgecore,spw2ac1200 |\ + edgecore,oap100|\ + edgecore,oap100e|\ + udaya,a5-id2|\ + openmesh,a42|\ + openmesh,a62) + ucidef_set_interfaces_lan_wan "eth1" "eth0" + ;; + asus,rt-ac58u|\ + mikrotik,hap-ac2|\ + zyxel,nbg6617) + ucidef_set_interfaces_lan_wan "eth0" "eth1" + ucidef_add_switch "switch0" \ + "0u@eth0" "1:lan:4" "2:lan:3" "3:lan:2" "4:lan:1" + ;; + avm,fritzbox-4040|\ + linksys,ea6350v3|\ + linksys,ea8300|\ + linksys,mr8300) + ucidef_set_interfaces_lan_wan "eth0" "eth1" + ucidef_add_switch "switch0" \ + "0u@eth0" "1:lan" "2:lan" "3:lan" "4:lan" + ;; + avm,fritzbox-7530) + ucidef_add_switch "switch0" \ + "0u@eth0" "1:lan" "2:lan" "3:lan" "4:lan" + ;; + avm,fritzrepeater-3000) + ucidef_add_switch "switch0" \ + "0u@eth0" "4:lan:1" "5:lan:2" + ;; + compex,wpj419|\ + compex,wpj428|\ + engenius,eap2200) + ucidef_set_interface_lan "eth0 eth1" + ;; + buffalo,wtr-m2133hp) + ucidef_set_interfaces_lan_wan "eth0" "eth1" + ucidef_add_switch "switch0" \ + "0u@eth0" "2:lan:3" "3:lan:2" "4:lan:1" + ;; + cellc,rtl30vw) + ucidef_set_interface_lan "eth0" + ucidef_add_switch "switch0" \ + "0u@eth0" "3:lan" "4:lan" + ;; + devolo,magic-2-wifi-next) + ucidef_set_interface_lan "eth0 eth1 eth2" + ;; + ezviz,cs-w3-wd1200g-eup) + ucidef_set_interfaces_lan_wan "eth0" "eth1" + ucidef_add_switch "switch0" \ + "0u@eth0" "2:lan:3" "3:lan:2" "4:lan:1" "0u@eth1" "5:wan" + ;; + glinet,gl-ap1300 |\ + glinet,gl-b1300 |\ + glinet,gl-s1300) + ucidef_set_interfaces_lan_wan "eth0" "eth1" + ucidef_add_switch "switch0" \ + "0u@eth0" "3:lan" "4:lan" + ;; + mobipromo,cm520-79f) + ucidef_add_switch "switch0" \ + "0u@eth0" "3:lan:2" "4:lan:1" + ucidef_set_interface_wan "eth1" + ;; + qxwlan,e2600ac-c1 |\ + qxwlan,e2600ac-c2) + ucidef_set_interfaces_lan_wan "eth0" "eth1" + ucidef_add_switch "switch0" \ + "0u@eth0" "3:lan" "4:lan" "0u@eth1" "5:wan" + ;; + unielec,u4019-32m) + ucidef_set_interfaces_lan_wan "eth0" "eth1" + ucidef_add_switch "switch0" \ + "0u@eth0" "1:lan" "2:lan" "3:lan" "4:lan" "0u@eth1" "5:wan" + ;; + um-325ac |\ + um-510ac-v3 |\ + um-550ac) + ucidef_set_interface_wan "eth0" + ucidef_set_interface_lan "eth1" + ;; + *) + echo "Unsupported hardware. Network interfaces not initialized" + ;; + esac +} + +ipq40xx_setup_macs() +{ + local board="$1" + local lan_mac="" + local wan_mac="" + local label_mac="" + + case "$board" in + 8dev,habanero-dvk) + label_mac=$(mtd_get_mac_binary "ART" 0x1006) + ;; + asus,rt-ac58u) + CI_UBIPART=UBI_DEV + wan_mac=$(mtd_get_mac_binary_ubi Factory 0x1006) + lan_mac=$(mtd_get_mac_binary_ubi Factory 0x5006) + label_mac=$wan_mac + ;; + cilab,meshpoint-one) + label_mac=$(mtd_get_mac_binary "ART" 0x1006) + ;; + devolo,magic-2-wifi-next) + lan_mac=$(mtd_get_mac_ascii APPSBLENV MacAddress0) + label_mac=$lan_mac + ;; + dlink,dap-2610) + lan_mac=$(mtd_get_mac_ascii bdcfg lanmac) + label_mac=$lan_mac + ;; + engenius,eap2200|\ + engenius,emd1) + lan_mac=$(mtd_get_mac_ascii 0:APPSBLENV ethaddr) + label_mac=$lan_mac + ;; + engenius,emr3500) + wan_mac=$(mtd_get_mac_ascii 0:APPSBLENV wanaddr) + lan_mac=$(mtd_get_mac_ascii 0:APPSBLENV ethaddr) + label_mac=$wan_mac + ;; + engenius,ens620ext) + wan_mac=$(mtd_get_mac_ascii u-boot-env ethaddr) + lan_mac=$(macaddr_add "$wan_mac" 1) + ;; + ezviz,cs-w3-wd1200g-eup) + label_mac=$(mtd_get_mac_binary "ART" 0x6) + ;; + linksys,ea6350v3) + wan_mac=$(mtd_get_mac_ascii devinfo hw_mac_addr) + lan_mac=$(macaddr_add "$wan_mac" 1) + ;; + mikrotik,hap-ac2) + wan_mac=$(cat /sys/firmware/mikrotik/hard_config/mac_base) + lan_mac=$(macaddr_add $wan_mac 1) + label_mac="$wan_mac" + ;; + mikrotik,sxtsq-5-ac) + lan_mac=$(cat /sys/firmware/mikrotik/hard_config/mac_base) + 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 +board=$(board_name) +ipq40xx_setup_interfaces $board +ipq40xx_setup_macs $board +board_config_flush + +exit 0 diff --git a/feeds/ipq40xx/ipq40xx/base-files/etc/board.d/03_gpio_switches b/feeds/ipq40xx/ipq40xx/base-files/etc/board.d/03_gpio_switches new file mode 100755 index 000000000..e1f75fd4b --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/base-files/etc/board.d/03_gpio_switches @@ -0,0 +1,29 @@ +#!/bin/sh + +. /lib/functions/uci-defaults.sh + +board_config_update + +board=$(board_name) + +case "$board" in +cellc,rtl30vw) + ucidef_add_gpio_switch "w_disable" "W_DISABLE mPCIE pin" "398" "1" + ucidef_add_gpio_switch "pmd_resin_n" "PMD_RESIN_N pin" "399" "1" + ucidef_add_gpio_switch "mcpie_vcc" "LTE power" "400" "0" + ucidef_add_gpio_switch "usb_vcc" "USB power" "401" "0" + ;; +cilab,meshpoint-one) + ucidef_add_gpio_switch "poe_passtrough" "POE passtrough enable" "413" "1" + ;; +compex,wpj428) + ucidef_add_gpio_switch "sim_card_select" "SIM card select" "3" "0" + ;; +wallys,dr40x9) + ucidef_add_gpio_switch "sim_card_select" "SIM card select" "423" "0" + ;; +esac + +board_config_flush + +exit 0 diff --git a/feeds/ipq40xx/ipq40xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata b/feeds/ipq40xx/ipq40xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata new file mode 100644 index 000000000..cc4406e7e --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata @@ -0,0 +1,315 @@ +#!/bin/sh + +[ -e /lib/firmware/$FIRMWARE ] && exit 0 + +. /lib/functions/caldata.sh + +board=$(board_name) + +case "$FIRMWARE" in +"ath10k/cal-pci-0000:01:00.0.bin") + case "$board" in + meraki,mr33) + caldata_extract_ubi "ART" 0x9000 0x844 + caldata_valid "4408" || caldata_extract "ART" 0x9000 0x844 + ath10k_patch_mac $(macaddr_add $(get_mac_binary "/sys/bus/i2c/devices/0-0050/eeprom" 0x66) +1) + ;; + esac + ;; +"ath10k/pre-cal-pci-0000:01:00.0.bin") + case "$board" in + asus,map-ac2200) + caldata_extract_ubi "Factory" 0x9000 0x2f20 + ln -sf /lib/firmware/ath10k/pre-cal-pci-0000\:00\:00.0.bin \ + /lib/firmware/ath10k/QCA9888/hw2.0/board.bin + ;; + avm,fritzrepeater-3000) + /usr/bin/fritz_cal_extract -i 1 -s 0x3D000 -e 0x212 -l 12064 -o /lib/firmware/$FIRMWARE $(find_mtd_chardev "urlader0") || \ + /usr/bin/fritz_cal_extract -i 1 -s 0x3C800 -e 0x212 -l 12064 -o /lib/firmware/$FIRMWARE $(find_mtd_chardev "urlader0") || \ + /usr/bin/fritz_cal_extract -i 1 -s 0x3C000 -e 0x212 -l 12064 -o /lib/firmware/$FIRMWARE $(find_mtd_chardev "urlader0") || \ + /usr/bin/fritz_cal_extract -i 1 -s 0x3D000 -e 0x212 -l 12064 -o /lib/firmware/$FIRMWARE $(find_mtd_chardev "urlader1") || \ + /usr/bin/fritz_cal_extract -i 1 -s 0x3C800 -e 0x212 -l 12064 -o /lib/firmware/$FIRMWARE $(find_mtd_chardev "urlader1") || \ + /usr/bin/fritz_cal_extract -i 1 -s 0x3C000 -e 0x212 -l 12064 -o /lib/firmware/$FIRMWARE $(find_mtd_chardev "urlader1") + ;; + buffalo,wtr-m2133hp) + caldata_extract "ART" 0x9000 0x2f20 + ath10k_patch_mac $(mtd_get_mac_binary ORGDATA 0x32) + ;; + engenius,eap2200 |\ + openmesh,a62 |\ + plasmacloud,pa2200) + caldata_extract "0:ART" 0x9000 0x2f20 + ;; + linksys,ea8300 |\ + linksys,mr8300) + caldata_extract "ART" 0x9000 0x2f20 + # OEM assigns 4 sequential MACs + ath10k_patch_mac $(macaddr_setbit_la $(macaddr_add "$(cat /sys/class/net/eth0/address)" 4)) + ;; + tp-link,ec420-g1) + caldata_extract "0:ART" 0x9000 0x2f20 + ;; + esac + ;; +"ath10k/pre-cal-ahb-a000000.wifi.bin") + case "$board" in + 8dev,habanero-dvk |\ + 8dev,jalapeno |\ + alfa-network,ap120c-ac |\ + cilab,meshpoint-one |\ + ezviz,cs-w3-wd1200g-eup |\ + glinet,gl-ap1300 |\ + glinet,gl-b1300 |\ + glinet,gl-s1300 |\ + linksys,ea6350v3 |\ + mobipromo,cm520-79f |\ + udaya,a5-id2 |\ + qcom,ap-dk01.1-c1) + caldata_extract "ART" 0x1000 0x2f20 + ;; + aruba,ap-303 |\ + aruba,ap-303h |\ + aruba,ap-365) + caldata_extract "ART" 0x1000 0x2f20 + ath10k_patch_mac $(mtd_get_mac_binary mfginfo 0x1D) + ;; + asus,map-ac2200) + caldata_extract_ubi "Factory" 0x1000 0x2f20 + ;; + asus,rt-ac58u) + CI_UBIPART=UBI_DEV + caldata_extract_ubi "Factory" 0x1000 0x2f20 + ;; + avm,fritzbox-4040) + /usr/bin/fritz_cal_extract -i 1 -s 0x400 -e 0x207 -l 12064 -o /lib/firmware/$FIRMWARE $(find_mtd_chardev "urlader_config") + ;; + avm,fritzbox-7530 |\ + avm,fritzrepeater-1200 |\ + avm,fritzrepeater-3000) + /usr/bin/fritz_cal_extract -i 1 -s 0x3C000 -e 0x207 -l 12064 -o /lib/firmware/$FIRMWARE $(find_mtd_chardev "urlader0") || \ + /usr/bin/fritz_cal_extract -i 1 -s 0x3C800 -e 0x207 -l 12064 -o /lib/firmware/$FIRMWARE $(find_mtd_chardev "urlader0") || \ + /usr/bin/fritz_cal_extract -i 1 -s 0x3D000 -e 0x207 -l 12064 -o /lib/firmware/$FIRMWARE $(find_mtd_chardev "urlader0") || \ + /usr/bin/fritz_cal_extract -i 1 -s 0x3C000 -e 0x207 -l 12064 -o /lib/firmware/$FIRMWARE $(find_mtd_chardev "urlader1") || \ + /usr/bin/fritz_cal_extract -i 1 -s 0x3C800 -e 0x207 -l 12064 -o /lib/firmware/$FIRMWARE $(find_mtd_chardev "urlader1") || \ + /usr/bin/fritz_cal_extract -i 1 -s 0x3D000 -e 0x207 -l 12064 -o /lib/firmware/$FIRMWARE $(find_mtd_chardev "urlader1") + ;; + buffalo,wtr-m2133hp) + caldata_extract "ART" 0x1000 0x2f20 + ath10k_patch_mac $(mtd_get_mac_binary ORGDATA 0x26) + ;; + cig,wf610d) + caldata_extract "0:ART" 0x1000 0x2f20 + ath10kcal_patch_mac_crc $(macaddr_add $(mtd_get_mac_ascii 0:APPSBLENV ethaddr) +2) + ;; + cellc,rtl30vw |\ + compex,wpj419 |\ + compex,wpj428 |\ + edgecore,ecw5211 |\ + edgecore,spw2ac1200 |\ + edgecore,spw2ac1200-lan-poe |\ + edgecore,oap100 |\ + edgecore,oap100e |\ + engenius,eap1300 |\ + engenius,eap2200 |\ + luma,wrtq-329acn|\ + openmesh,a42 |\ + openmesh,a62 |\ + plasmacloud,pa1200 |\ + plasmacloud,pa2200 |\ + qxwlan,e2600ac-c1 |\ + qxwlan,e2600ac-c2 |\ + unielec,u4019-32m |\ + wallys,dr40x9) + caldata_extract "0:ART" 0x1000 0x2f20 + ;; + devolo,magic-2-wifi-next) + caldata_extract "ART" 0x1000 0x2f20 + ath10k_patch_mac $(mtd_get_mac_ascii APPSBLENV WiFiMacAddress0) + ;; + dlink,dap-2610) + caldata_extract "ART" 0x1000 0x2f20 + ath10k_patch_mac $(mtd_get_mac_ascii bdcfg wlanmac) + ;; + engenius,emd1) + caldata_extract "0:ART" 0x1000 0x2f20 + ath10k_patch_mac $(mtd_get_mac_ascii 0:APPSBLENV wlanaddr) + ;; + engenius,emr3500) + caldata_extract "0:ART" 0x1000 0x2f20 + ath10k_patch_mac $(mtd_get_mac_ascii 0:APPSBLENV ethaddr) + ;; + engenius,ens620ext) + caldata_extract "ART" 0x1000 0x2f20 + ath10k_patch_mac $(macaddr_add $(mtd_get_mac_ascii u-boot-env ethaddr) +2) + ;; + linksys,ea8300 |\ + linksys,mr8300) + caldata_extract "ART" 0x1000 0x2f20 + ath10k_patch_mac $(macaddr_add "$(cat /sys/class/net/eth0/address)" 2) + ;; + meraki,mr33) + caldata_extract_ubi "ART" 0x1000 0x2f20 + caldata_valid "202f" || caldata_extract "ART" 0x1000 0x2f20 + ath10k_patch_mac $(macaddr_add $(get_mac_binary "/sys/bus/i2c/devices/0-0050/eeprom" 0x66) +2) + ;; + mikrotik,hap-ac2) + wlan_data="/sys/firmware/mikrotik/hard_config/wlan_data" + ( [ -f "$wlan_data" ] && caldata_sysfsload_from_file "$wlan_data" 0x0 0x2f20 ) || \ + ( [ -d "$wlan_data" ] && caldata_sysfsload_from_file "$wlan_data/data_0" 0x0 0x2f20 ) + ;; + netgear,ex6100v2 |\ + netgear,ex6150v2) + caldata_extract "ART" 0x1000 0x2f20 + ath10k_patch_mac $(mtd_get_mac_binary dnidata 0x0) + ;; + zyxel,nbg6617 |\ + zyxel,wre6606) + caldata_extract "ART" 0x1000 0x2f20 + ath10k_patch_mac $(macaddr_add $(cat /sys/class/net/eth0/address) -2) + ;; + tp-link,ec420-g1) + caldata_extract "0:ART" 0x1000 0x2f20 + ;; + hfcl,ion4) + caldata_extract "0:ART" 4096 12064 + ath10k_patch_mac $(mtd_get_mac_ascii 0:ART WLAN0_BASEMAC) + ;; + um-325ac |\ + um-510ac-v3 |\ + um-550ac) + caldata_extract "ART" 0x1000 0x2f20 + ;; + esac + ;; +"ath10k/pre-cal-ahb-a800000.wifi.bin") + case "$board" in + 8dev,habanero-dvk |\ + 8dev,jalapeno |\ + alfa-network,ap120c-ac |\ + cilab,meshpoint-one |\ + ezviz,cs-w3-wd1200g-eup |\ + glinet,gl-ap1300 |\ + glinet,gl-b1300 |\ + glinet,gl-s1300 |\ + linksys,ea6350v3 |\ + mobipromo,cm520-79f |\ + udaya,a5-id2 |\ + qcom,ap-dk01.1-c1) + caldata_extract "ART" 0x5000 0x2f20 + ;; + aruba,ap-303 |\ + aruba,ap-303h |\ + aruba,ap-365) + caldata_extract "ART" 0x5000 0x2f20 + ath10k_patch_mac $(macaddr_add $(mtd_get_mac_binary mfginfo 0x1D) +1) + ;; + asus,map-ac2200) + caldata_extract_ubi "Factory" 0x5000 0x2f20 + ;; + asus,rt-ac58u) + CI_UBIPART=UBI_DEV + caldata_extract_ubi "Factory" 0x5000 0x2f20 + ;; + avm,fritzbox-4040) + /usr/bin/fritz_cal_extract -i 1 -s 0x400 -e 0x208 -l 12064 -o /lib/firmware/$FIRMWARE $(find_mtd_chardev "urlader_config") + ;; + avm,fritzbox-7530 |\ + avm,fritzrepeater-1200 |\ + avm,fritzrepeater-3000) + /usr/bin/fritz_cal_extract -i 1 -s 0x3C800 -e 0x208 -l 12064 -o /lib/firmware/$FIRMWARE $(find_mtd_chardev "urlader0") || \ + /usr/bin/fritz_cal_extract -i 1 -s 0x3D000 -e 0x208 -l 12064 -o /lib/firmware/$FIRMWARE $(find_mtd_chardev "urlader0") || \ + /usr/bin/fritz_cal_extract -i 1 -s 0x3C000 -e 0x208 -l 12064 -o /lib/firmware/$FIRMWARE $(find_mtd_chardev "urlader0") || \ + /usr/bin/fritz_cal_extract -i 1 -s 0x3C800 -e 0x208 -l 12064 -o /lib/firmware/$FIRMWARE $(find_mtd_chardev "urlader1") || \ + /usr/bin/fritz_cal_extract -i 1 -s 0x3D000 -e 0x208 -l 12064 -o /lib/firmware/$FIRMWARE $(find_mtd_chardev "urlader1") || \ + /usr/bin/fritz_cal_extract -i 1 -s 0x3C000 -e 0x208 -l 12064 -o /lib/firmware/$FIRMWARE $(find_mtd_chardev "urlader1") + ;; + buffalo,wtr-m2133hp) + caldata_extract "ART" 0x5000 0x2f20 + ath10k_patch_mac $(mtd_get_mac_binary ORGDATA 0x2c) + ;; + cig,wf610d) + caldata_extract "0:ART" 0x5000 0x2f20 + ath10kcal_patch_mac_crc $(macaddr_add $(mtd_get_mac_ascii 0:APPSBLENV ethaddr) +3) + ;; + cellc,rtl30vw |\ + compex,wpj419 |\ + compex,wpj428 |\ + edgecore,ecw5211 |\ + edgecore,spw2ac1200 |\ + edgecore,spw2ac1200-lan-poe |\ + edgecore,oap100 |\ + edgecore,oap100e |\ + engenius,eap1300 |\ + engenius,eap2200 |\ + luma,wrtq-329acn|\ + openmesh,a42 |\ + openmesh,a62 |\ + plasmacloud,pa1200 |\ + plasmacloud,pa2200 |\ + qxwlan,e2600ac-c1 |\ + qxwlan,e2600ac-c2 |\ + unielec,u4019-32m |\ + wallys,dr40x9) + caldata_extract "0:ART" 0x5000 0x2f20 + ;; + devolo,magic-2-wifi-next) + caldata_extract "ART" 0x5000 0x2f20 + ath10k_patch_mac $(mtd_get_mac_ascii APPSBLENV WiFiMacAddress1) + ;; + dlink,dap-2610) + caldata_extract "ART" 0x5000 0x2f20 + ath10k_patch_mac $(mtd_get_mac_ascii bdcfg wlanmac_a) + ;; + engenius,emd1) + caldata_extract "0:ART" 0x5000 0x2f20 + ath10k_patch_mac $(macaddr_add $(mtd_get_mac_ascii 0:APPSBLENV wlanaddr) +1) + ;; + engenius,emr3500) + caldata_extract "0:ART" 0x5000 0x2f20 + ath10k_patch_mac $(macaddr_add $(mtd_get_mac_ascii 0:APPSBLENV ethaddr) +1) + ;; + engenius,ens620ext) + caldata_extract "ART" 0x5000 0x2f20 + ath10k_patch_mac $(macaddr_add $(mtd_get_mac_ascii u-boot-env ethaddr) +3) + ;; + linksys,ea8300 |\ + linksys,mr8300) + caldata_extract "ART" 0x5000 0x2f20 + ath10k_patch_mac $(macaddr_add "$(cat /sys/class/net/eth0/address)" 3) + ;; + meraki,mr33) + caldata_extract_ubi "ART" 0x5000 0x2f20 + caldata_valid "202f" || caldata_extract "ART" 0x5000 0x2f20 + ath10k_patch_mac $(macaddr_add $(get_mac_binary "/sys/bus/i2c/devices/0-0050/eeprom" 0x66) +3) + ;; + mikrotik,hap-ac2|\ + mikrotik,sxtsq-5-ac) + wlan_data="/sys/firmware/mikrotik/hard_config/wlan_data" + ( [ -f "$wlan_data" ] && caldata_sysfsload_from_file "$wlan_data" 0x8000 0x2f20 ) || \ + ( [ -d "$wlan_data" ] && caldata_sysfsload_from_file "$wlan_data/data_2" 0x0 0x2f20 ) + ;; + netgear,ex6100v2 |\ + netgear,ex6150v2) + caldata_extract "ART" 0x5000 0x2f20 + ath10k_patch_mac $(mtd_get_mac_binary dnidata 0xc) + ;; + zyxel,nbg6617 |\ + zyxel,wre6606) + caldata_extract "ART" 0x5000 0x2f20 + ath10k_patch_mac $(macaddr_add $(cat /sys/class/net/eth0/address) -1) + ;; + hfcl,ion4) + caldata_extract "0:ART" 20480 12064 + ath10k_patch_mac $(mtd_get_mac_ascii 0:ART WLAN1_BASEMAC) + ;; + um-325ac |\ + um-510ac-v3 |\ + um-550ac) + caldata_extract "ART" 0x5000 0x2f20 + ;; + esac + ;; +*) + exit 1 + ;; +esac diff --git a/feeds/ipq40xx/ipq40xx/base-files/etc/hotplug.d/firmware/40-ct-fw-cfg b/feeds/ipq40xx/ipq40xx/base-files/etc/hotplug.d/firmware/40-ct-fw-cfg new file mode 100644 index 000000000..7e22cbd4f --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/base-files/etc/hotplug.d/firmware/40-ct-fw-cfg @@ -0,0 +1,32 @@ +#!/bin/sh + +[ -e /lib/firmware/$FIRMWARE ] && exit 0 + + +fwcfg_symlink() { + local chip=$1 + local path=$2 + + ln -s /lib/firmware/ath10k/fwcfg-${chip}.txt /lib/firmware/${FIRMWARE} +} + +case "$FIRMWARE" in +ath10k/fwcfg-ahb-a000000.wifi.txt|\ +ath10k/fwcfg-ahb-a800000.wifi.txt) + fwcfg_symlink ipq4019 + + ;; +ath10k/fwcfg-pci-0000:01:00.0.txt) + case "$(board_name)" in + linksys,ea8300) + fwcfg_symlink qca9888 + ;; + tp-link,ap2220|\ + tp-link,ec420-g1) + fwcfg_symlink qca9984 + ;; + esac + ;; +esac + +exit 0 diff --git a/feeds/ipq40xx/ipq40xx/base-files/etc/hotplug.d/net/20-smp-tune b/feeds/ipq40xx/ipq40xx/base-files/etc/hotplug.d/net/20-smp-tune new file mode 100644 index 000000000..ab9a90418 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/base-files/etc/hotplug.d/net/20-smp-tune @@ -0,0 +1,67 @@ +#!/bin/sh +[ "$ACTION" = add ] || exit + +NPROCS="$(grep -c "^processor.*:" /proc/cpuinfo)" +[ "$NPROCS" -gt 1 ] || exit + +PROC_MASK="$(( (1 << $NPROCS) - 1 ))" + +find_irq_cpu() { + local dev="$1" + local match="$(grep -m 1 "$dev\$" /proc/interrupts)" + local cpu=0 + + [ -n "$match" ] && { + set -- $match + shift + for cur in `seq 1 $NPROCS`; do + [ "$1" -gt 0 ] && { + cpu=$(($cur - 1)) + break + } + shift + done + } + + echo "$cpu" +} + +set_hex_val() { + local file="$1" + local val="$2" + val="$(printf %x "$val")" + [ -n "$DEBUG" ] && echo "$file = $val" + echo "$val" > "$file" +} + +default_ps="$(uci get "network.@globals[0].default_ps")" +[ -n "$default_ps" -a "$default_ps" != 1 ] && exit 0 + +exec 512>/var/lock/smp_tune.lock +flock 512 || exit 1 + +for dev in /sys/class/net/*; do + [ -d "$dev" ] || continue + + # ignore virtual interfaces + [ -n "$(ls "${dev}/" | grep '^lower_')" ] && continue + [ -d "${dev}/device" ] || continue + + device="$(readlink "${dev}/device")" + device="$(basename "$device")" + irq_cpu="$(find_irq_cpu "$device")" + irq_cpu_mask="$((1 << $irq_cpu))" + + for q in ${dev}/queues/rx-*; do + set_hex_val "$q/rps_cpus" "$(($PROC_MASK & ~$irq_cpu_mask))" + done + + ntxq="$(ls -d ${dev}/queues/tx-* | wc -l)" + + idx=$(($irq_cpu + 1)) + for q in ${dev}/queues/tx-*; do + set_hex_val "$q/xps_cpus" "$((1 << $idx))" + let "idx = idx + 1" + [ "$idx" -ge "$NPROCS" ] && idx=0 + done +done diff --git a/feeds/ipq40xx/ipq40xx/base-files/etc/init.d/bootcount b/feeds/ipq40xx/ipq40xx/base-files/etc/init.d/bootcount new file mode 100755 index 000000000..5cda1fc24 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/base-files/etc/init.d/bootcount @@ -0,0 +1,36 @@ +#!/bin/sh /etc/rc.common + +START=99 + +boot() { + case $(board_name) in + alfa-network,ap120c-ac) + [ -n "$(fw_printenv bootcount changed 2>/dev/null)" ] &&\ + echo -e "bootcount\nchanged\n" | /usr/sbin/fw_setenv -s - + ;; + linksys,ea6350v3|\ + linksys,ea8300|\ + linksys,mr8300) + mtd resetbc s_env || true + ;; + edgecore,ecw5211) + part="$(awk -F 'ubi.mtd=' '{printf $2}' /proc/cmdline | cut -d " " -f1)" + case "$part" in + rootfs1|\ + rootfs2) + avail=$(fw_printenv -n upgrade_available) + [ ${avail} -ne 1 ] && fw_setenv upgrade_available 1 + fw_setenv bootcount 0 + ;; + esac + ;; + edgecore,spw2ac1200|\ + edgecore,spw2ac1200-lan-poe) + avail=$(fw_printenv -n upgrade_available) + [ ${avail} -eq 0 ] || { + fw_setenv upgrade_available 0 + fw_setenv bootcount 0 + } + ;; + esac +} diff --git a/feeds/ipq40xx/ipq40xx/base-files/etc/inittab b/feeds/ipq40xx/ipq40xx/base-files/etc/inittab new file mode 100644 index 000000000..3181021a0 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/base-files/etc/inittab @@ -0,0 +1,5 @@ +# Copyright (c) 2013 The Linux Foundation. All rights reserved. +::sysinit:/etc/init.d/rcS S boot +::shutdown:/etc/init.d/rcS K shutdown +ttyMSM0::askfirst:/usr/libexec/login.sh +ttyMSM1::askfirst:/usr/libexec/login.sh diff --git a/feeds/ipq40xx/ipq40xx/base-files/etc/uci-defaults/04_led_migration b/feeds/ipq40xx/ipq40xx/base-files/etc/uci-defaults/04_led_migration new file mode 100644 index 000000000..c4f82b35d --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/base-files/etc/uci-defaults/04_led_migration @@ -0,0 +1,19 @@ +. /lib/functions/migrations.sh + +board=$(board_name) + +case "$board" in +engenius,emr3500) + migrate_leds "emr3500:=" + ;; +engenius,ens620ext|\ +zyxel,nbg6617) + migrate_leds ":wlan2G=:wlan2g" ":wlan5G=:wlan5g" + ;; +esac + +remove_devicename_leds + +migrations_apply system + +exit 0 diff --git a/feeds/ipq40xx/ipq40xx/base-files/lib/firmware/ath10k/fwcfg-ipq4019.txt b/feeds/ipq40xx/ipq40xx/base-files/lib/firmware/ath10k/fwcfg-ipq4019.txt new file mode 100644 index 000000000..7943173e5 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/base-files/lib/firmware/ath10k/fwcfg-ipq4019.txt @@ -0,0 +1,15 @@ +vdevs = 8 +peers = 147 +active_peers = 147 +stations = 147 +rate_ctrl_objs = 7 +#regdom = 840 +#fwname = firmware-5-htt-mgt-b.bin +#fwver = 5 +nohwcrypt = 0 +ct_sta_mode = 0 +tx_desc = 2000 +#max_nss = 3 +tids = 450 +skid_limit = 360 +max_amsdus = 3 diff --git a/feeds/ipq40xx/ipq40xx/base-files/lib/firmware/ath10k/fwcfg-qca9888.txt b/feeds/ipq40xx/ipq40xx/base-files/lib/firmware/ath10k/fwcfg-qca9888.txt new file mode 100644 index 000000000..560c8103d --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/base-files/lib/firmware/ath10k/fwcfg-qca9888.txt @@ -0,0 +1,16 @@ +# 9888 chip +vdevs = 8 +peers = 202 +active_peers = 202 +stations = 202 +rate_ctrl_objs = 7 +#regdom = 840 +#fwname = firmware-5-htt-mgt-b.bin +#fwver = 5 +nohwcrypt = 0 +ct_sta_mode = 0 +tx_desc = 2200 +#max_nss = 3 +tids = 450 +skid_limit = 360 +max_amsdus = 3 diff --git a/feeds/ipq40xx/ipq40xx/base-files/lib/firmware/ath10k/fwcfg-qca9984.txt b/feeds/ipq40xx/ipq40xx/base-files/lib/firmware/ath10k/fwcfg-qca9984.txt new file mode 100644 index 000000000..924a68900 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/base-files/lib/firmware/ath10k/fwcfg-qca9984.txt @@ -0,0 +1,16 @@ +# 9984 +vdevs = 8 +peers = 180 +active_peers = 180 +stations = 180 +rate_ctrl_objs = 7 +#regdom = 840 +#fwname = firmware-5-htt-mgt-b.bin +#fwver = 5 +nohwcrypt = 0 +ct_sta_mode = 0 +tx_desc = 2400 +#max_nss = 3 +tids = 450 +skid_limit = 360 +max_amsdus = 3 diff --git a/feeds/ipq40xx/ipq40xx/base-files/lib/preinit/05_set_iface_mac_ipq40xx.sh b/feeds/ipq40xx/ipq40xx/base-files/lib/preinit/05_set_iface_mac_ipq40xx.sh new file mode 100644 index 000000000..4d3b1df21 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/base-files/lib/preinit/05_set_iface_mac_ipq40xx.sh @@ -0,0 +1,39 @@ +. /lib/functions.sh + +preinit_set_mac_address() { + case $(board_name) in + asus,map-ac2200) + base_mac=$(mtd_get_mac_binary_ubi Factory 0x1006) + ip link set dev eth0 address $(macaddr_add "$base_mac" +1) + ip link set dev eth1 address $(macaddr_add "$base_mac" +3) + ;; + cig,wf610d) + base_mac=$(mtd_get_mac_ascii 0:APPSBLENV ethaddr) + ip link set eth0 address "${base_mac}" + ;; + ezviz,cs-w3-wd1200g-eup) + ip link set dev eth0 address $(mtd_get_mac_binary "ART" 0x6) + ip link set dev eth1 address $(mtd_get_mac_binary "ART" 0x0) + ;; + engenius,eap2200) + base_mac=$(cat /sys/class/net/eth0/address) + ip link set dev eth1 address $(macaddr_add "${base_mac}" +1) + ;; + linksys,ea8300|\ + linksys,mr8300) + base_mac=$(mtd_get_mac_ascii devinfo hw_mac_addr) + ip link set dev eth0 address "${base_mac}" + ip link set dev eth1 address $(macaddr_add "${base_mac}" 1) + ;; + meraki,mr33) + mac_lan=$(get_mac_binary "/sys/bus/i2c/devices/0-0050/eeprom" 0x66) + [ -n "$mac_lan" ] && ip link set dev eth0 address "$mac_lan" + ;; + zyxel,nbg6617) + base_mac=$(cat /sys/class/net/eth0/address) + ip link set dev eth0 address $(macaddr_add "$base_mac" +2) + ip link set dev eth1 address $(macaddr_add "$base_mac" +3) + esac +} + +boot_hook_add preinit_main preinit_set_mac_address diff --git a/feeds/ipq40xx/ipq40xx/base-files/lib/preinit/05_set_threading.sh b/feeds/ipq40xx/ipq40xx/base-files/lib/preinit/05_set_threading.sh new file mode 100644 index 000000000..66c865bc6 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/base-files/lib/preinit/05_set_threading.sh @@ -0,0 +1,7 @@ +. /lib/functions.sh + +preinit_set_threading() { + echo 1 > /sys/class/net/eth0/threaded +} + +boot_hook_add preinit_main preinit_set_threading diff --git a/feeds/ipq40xx/ipq40xx/base-files/lib/preinit/06_set_preinit_iface_ipq40xx.sh b/feeds/ipq40xx/ipq40xx/base-files/lib/preinit/06_set_preinit_iface_ipq40xx.sh new file mode 100644 index 000000000..e97133f10 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/base-files/lib/preinit/06_set_preinit_iface_ipq40xx.sh @@ -0,0 +1,22 @@ +set_preinit_iface() { + . /lib/functions.sh + + case $(board_name) in + aruba,ap-303| \ + asus,rt-ac58u| \ + avm,fritzbox-4040| \ + ezviz,cs-w3-wd1200g-eup| \ + glinet,gl-b1300| \ + linksys,ea8300| \ + linksys,mr8300| \ + meraki,mr33| \ + zyxel,nbg6617) + ifname=eth0 + ;; + devolo,magic-2-wifi-next) + ifname=eth1 + ;; + esac +} + +boot_hook_add preinit_main set_preinit_iface diff --git a/feeds/ipq40xx/ipq40xx/base-files/lib/upgrade/dualboot_datachk.sh b/feeds/ipq40xx/ipq40xx/base-files/lib/upgrade/dualboot_datachk.sh new file mode 100644 index 000000000..81418fe0b --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/base-files/lib/upgrade/dualboot_datachk.sh @@ -0,0 +1,108 @@ +# The U-Boot loader with the datachk patchset for dualbooting requires image +# sizes and checksums to be provided in the U-Boot environment. +# The devices come with 2 main partitions - while one is active +# sysupgrade will flash the other. The boot order is changed to boot the +# newly flashed partition. If the new partition can't be booted due to +# upgrade failures the previously used partition is loaded. + +platform_do_upgrade_dualboot_datachk() { + local tar_file="$1" + local restore_backup + local primary_kernel_mtd + + local setenv_script="/tmp/fw_env_upgrade" + + local kernel_mtd="$(find_mtd_index $PART_NAME)" + local kernel_offset="$(cat /sys/class/mtd/mtd${kernel_mtd}/offset)" + local total_size="$(cat /sys/class/mtd/mtd${kernel_mtd}/size)" + + # detect to which flash region the new image is written to. + # + # 1. check what is the mtd index for the first flash region on this + # device + # 2. check if the target partition ("inactive") has the mtd index of + # the first flash region + # + # - when it is: the new bootseq will be 1,2 and the first region is + # modified + # - when it isnt: bootseq will be 2,1 and the second region is + # modified + # + # The detection has to be done via the hardcoded mtd partition because + # the current boot might be done with the fallback region. Let us + # assume that the current bootseq is 1,2. The bootloader detected that + # the image in flash region 1 is corrupt and thus switches to flash + # region 2. The bootseq in the u-boot-env is now still the same and + # the sysupgrade code can now only rely on the actual mtd indexes and + # not the bootseq variable to detect the currently booted flash + # region/image. + # + # In the above example, an implementation which uses bootseq ("1,2") to + # detect the currently booted image would assume that region 1 is booted + # and then overwrite the variables for the wrong flash region (aka the + # one which isn't modified). This could result in a device which doesn't + # boot anymore to Linux until it was reflashed with ap51-flash. + local next_boot_part="1" + case "$(board_name)" in + plasmacloud,pa1200|\ + openmesh,a42) + primary_kernel_mtd=8 + ;; + plasmacloud,pa2200|\ + openmesh,a62) + primary_kernel_mtd=10 + ;; + *) + echo "failed to detect primary kernel mtd partition for board" + return 1 + ;; + esac + [ "$kernel_mtd" = "$primary_kernel_mtd" ] || next_boot_part="2" + + local board_dir=$(tar tf $tar_file | grep -m 1 '^sysupgrade-.*/$') + board_dir=${board_dir%/} + + local kernel_length=$(tar xf $tar_file ${board_dir}/kernel -O | wc -c) + local rootfs_length=$(tar xf $tar_file ${board_dir}/root -O | wc -c) + # rootfs without EOF marker + rootfs_length=$((rootfs_length-4)) + + local kernel_md5=$(tar xf $tar_file ${board_dir}/kernel -O | md5sum); kernel_md5="${kernel_md5%% *}" + # md5 checksum of rootfs with EOF marker + local rootfs_md5=$(tar xf $tar_file ${board_dir}/root -O | dd bs=1 count=$rootfs_length | md5sum); rootfs_md5="${rootfs_md5%% *}" + + # + # add tar support to get_image() to use default_do_upgrade() instead? + # + + # take care of restoring a saved config + [ -n "$UPGRADE_BACKUP" ] && restore_backup="${MTD_CONFIG_ARGS} -j ${UPGRADE_BACKUP}" + + mtd -q erase inactive + tar xf $tar_file ${board_dir}/root -O | mtd -n -p $kernel_length $restore_backup write - $PART_NAME + tar xf $tar_file ${board_dir}/kernel -O | mtd -n write - $PART_NAME + + # prepare new u-boot env + if [ "$next_boot_part" = "1" ]; then + echo "bootseq 1,2" > $setenv_script + else + echo "bootseq 2,1" > $setenv_script + fi + + printf "kernel_size_%i 0x%08x\n" $next_boot_part $kernel_length >> $setenv_script + printf "vmlinux_start_addr 0x%08x\n" ${kernel_offset} >> $setenv_script + printf "vmlinux_size 0x%08x\n" ${kernel_length} >> $setenv_script + printf "vmlinux_checksum %s\n" ${kernel_md5} >> $setenv_script + + printf "rootfs_size_%i 0x%08x\n" $next_boot_part $((total_size-kernel_length)) >> $setenv_script + printf "rootfs_start_addr 0x%08x\n" $((kernel_offset+kernel_length)) >> $setenv_script + printf "rootfs_size 0x%08x\n" ${rootfs_length} >> $setenv_script + printf "rootfs_checksum %s\n" ${rootfs_md5} >> $setenv_script + + # store u-boot env changes + mkdir -p /var/lock + fw_setenv -s $setenv_script || { + echo "failed to update U-Boot environment" + return 1 + } +} diff --git a/feeds/ipq40xx/ipq40xx/base-files/lib/upgrade/linksys.sh b/feeds/ipq40xx/ipq40xx/base-files/lib/upgrade/linksys.sh new file mode 100755 index 000000000..de09d34ae --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/base-files/lib/upgrade/linksys.sh @@ -0,0 +1,122 @@ +linksys_get_target_firmware() { + local cur_boot_part mtd_ubi0 + + cur_boot_part="$(/usr/sbin/fw_printenv -n boot_part)" + if [ -z "${cur_boot_part}" ]; then + mtd_ubi0=$(cat /sys/devices/virtual/ubi/ubi0/mtd_num) + case "$(grep -E "^mtd${mtd_ubi0}:" /proc/mtd | cut -d '"' -f 2)" in + kernel|rootfs) + cur_boot_part=1 + ;; + alt_kernel|alt_rootfs) + cur_boot_part=2 + ;; + esac + >&2 printf "Current boot_part='%s' selected from ubi0/mtd_num='%s'" \ + "${cur_boot_part}" "${mtd_ubi0}" + fi + + # OEM U-Boot for EA6350v3, EA8300 and MR8300; bootcmd= + # if test $auto_recovery = no; + # then bootipq; + # elif test $boot_part = 1; + # then run bootpart1; + # else run bootpart2; + # fi + + case "$cur_boot_part" in + 1) + fw_setenv -s - <<-EOF + boot_part 2 + auto_recovery yes + EOF + printf "alt_kernel" + return + ;; + 2) + fw_setenv -s - <<-EOF + boot_part 1 + auto_recovery yes + EOF + printf "kernel" + return + ;; + *) + return + ;; + esac +} + +linksys_get_root_magic() { + (get_image "$@" | dd skip=786432 bs=4 count=1 | hexdump -v -n 4 -e '1/1 "%02x"') 2>/dev/null +} + +platform_do_upgrade_linksys() { + local magic_long="$(get_magic_long "$1")" + + local rm_oem_fw_vols="squashfs ubifs" # from OEM [alt_]rootfs UBI + local vol + + mkdir -p /var/lock + local part_label="$(linksys_get_target_firmware)" + touch /var/lock/fw_printenv.lock + + if [ -z "$part_label" ]; then + echo "cannot find target partition" + exit 1 + fi + + local target_mtd=$(find_mtd_part "$part_label") + + [ "$magic_long" = "73797375" ] && { + CI_KERNPART="$part_label" + if [ "$part_label" = "kernel" ]; then + CI_UBIPART="rootfs" + else + CI_UBIPART="alt_rootfs" + fi + + local mtdnum="$(find_mtd_index "$CI_UBIPART")" + if [ ! "$mtdnum" ]; then + echo "cannot find ubi mtd partition $CI_UBIPART" + return 1 + fi + + local ubidev="$(nand_find_ubi "$CI_UBIPART")" + if [ ! "$ubidev" ]; then + ubiattach -m "$mtdnum" + sync + ubidev="$(nand_find_ubi "$CI_UBIPART")" + fi + + if [ "$ubidev" ]; then + for vol in $rm_oem_fw_vols; do + ubirmvol "/dev/$ubidev" -N "$vol" 2>/dev/null + done + fi + + # complete std upgrade + nand_upgrade_tar "$1" + } + + [ "$magic_long" = "27051956" ] && { + # This magic is for a uImage (which is a sysupgrade image) + # check firmwares' rootfs types + local oldroot="$(linksys_get_root_magic "$target_mtd")" + local newroot="$(linksys_get_root_magic "$1")" + + if [ "$newroot" = "55424923" ] && [ "$oldroot" = "55424923" ]; then + # we're upgrading from a firmware with UBI to one with UBI + # erase everything to be safe + # - Is that really needed? Won't remove (or comment) the if, + # because it may be needed in a future device. + #mtd erase $part_label + #get_image "$1" | mtd -n write - $part_label + echo "writing \"$1\" UBI image to \"$part_label\" (UBI)..." + get_image "$1" | mtd write - "$part_label" + else + echo "writing \"$1\" image to \"$part_label\"" + get_image "$1" | mtd write - "$part_label" + fi + } +} diff --git a/feeds/ipq40xx/ipq40xx/base-files/lib/upgrade/platform.sh b/feeds/ipq40xx/ipq40xx/base-files/lib/upgrade/platform.sh new file mode 100644 index 000000000..fa6a16cf4 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/base-files/lib/upgrade/platform.sh @@ -0,0 +1,160 @@ +PART_NAME=firmware +REQUIRE_IMAGE_METADATA=1 + +RAMFS_COPY_BIN='fw_printenv fw_setenv' +RAMFS_COPY_DATA='/etc/fw_env.config /var/lock/fw_printenv.lock' + +platform_check_image() { + case "$(board_name)" in + asus,rt-ac58u) + CI_UBIPART="UBI_DEV" + local ubidev=$(nand_find_ubi $CI_UBIPART) + local asus_root=$(nand_find_volume $ubidev jffs2) + + [ -n "$asus_root" ] || return 0 + + cat << EOF +jffs2 partition is still present. +There's probably no space left +to install the filesystem. + +You need to delete the jffs2 partition first: +# ubirmvol /dev/ubi0 --name=jffs2 + +Once this is done. Retry. +EOF + return 1 + ;; + esac + return 0; +} + +askey_do_upgrade() { + local tar_file="$1" + + local board_dir=$(tar tf $tar_file | grep -m 1 '^sysupgrade-.*/$') + board_dir=${board_dir%/} + + tar Oxf $tar_file ${board_dir}/root | mtd write - rootfs + + nand_do_upgrade "$1" +} + +zyxel_do_upgrade() { + local tar_file="$1" + + local board_dir=$(tar tf $tar_file | grep -m 1 '^sysupgrade-.*/$') + board_dir=${board_dir%/} + + tar Oxf $tar_file ${board_dir}/kernel | mtd write - kernel + + if [ -n "$UPGRADE_BACKUP" ]; then + tar Oxf $tar_file ${board_dir}/root | mtd -j "$UPGRADE_BACKUP" write - rootfs + else + tar Oxf $tar_file ${board_dir}/root | mtd write - rootfs + fi +} + +platform_do_upgrade() { + case "$(board_name)" in + 8dev,jalapeno |\ + aruba,ap-303 |\ + aruba,ap-303h |\ + aruba,ap-365 |\ + avm,fritzbox-7530 |\ + avm,fritzrepeater-1200 |\ + avm,fritzrepeater-3000 |\ + buffalo,wtr-m2133hp |\ + cilab,meshpoint-one |\ + edgecore,oap100 |\ + edgecore,oap100e |\ + engenius,eap2200 |\ + glinet,gl-ap1300 |\ + luma,wrtq-329acn |\ + mobipromo,cm520-79f |\ + qxwlan,e2600ac-c2 |\ + wallys,dr40x9 |\ + hfcl,ion4 |\ + tp-link,ec420-g1) + nand_do_upgrade "$1" + ;; + edgecore,ecw5211) + mkdir -p /var/lock/ + part="$(awk -F 'ubi.mtd=' '{printf $2}' /proc/cmdline | cut -d " " -f 1)" + case "$part" in + rootfs1) + fw_setenv active 2 || exit 1 + CI_UBIPART="rootfs2" + ;; + rootfs2) + fw_setenv active 1 || exit 1 + CI_UBIPART="rootfs1" + ;; + *) + # legacy bootloader + ;; + esac + nand_do_upgrade "$1" + ;; + alfa-network,ap120c-ac) + mkdir -p /var/lock/ + part="$(awk -F 'ubi.mtd=' '{printf $2}' /proc/cmdline | sed -e 's/ .*$//')" + if [ "$part" = "rootfs1" ]; then + fw_setenv active 2 || exit 1 + CI_UBIPART="rootfs2" + else + fw_setenv active 1 || exit 1 + CI_UBIPART="rootfs1" + fi + nand_do_upgrade "$1" + ;; + edgecore,spw2ac1200|\ + edgecore,spw2ac1200-lan-poe) + CI_UBIPART="$(awk -F 'ubi.mtd=' '{printf $2}' /proc/cmdline | sed -e 's/ .*$//')" + nand_do_upgrade "$1" + ;; + asus,map-ac2200) + CI_KERNPART="linux" + nand_do_upgrade "$1" + ;; + asus,rt-ac58u) + CI_UBIPART="UBI_DEV" + CI_KERNPART="linux" + nand_do_upgrade "$1" + ;; + cellc,rtl30vw) + CI_UBIPART="ubifs" + askey_do_upgrade "$1" + ;; + compex,wpj419) + nand_do_upgrade "$1" + ;; + linksys,ea6350v3 |\ + linksys,ea8300 |\ + linksys,mr8300) + platform_do_upgrade_linksys "$1" + ;; + meraki,mr33) + CI_KERNPART="part.safe" + nand_do_upgrade "$1" + ;; + mikrotik,hap-ac2|\ + mikrotik,sxtsq-5-ac) + [ "$(rootfs_type)" = "tmpfs" ] && mtd erase firmware + default_do_upgrade "$1" + ;; + openmesh,a42 |\ + openmesh,a62 |\ + plasmacloud,pa1200 |\ + plasmacloud,pa2200) + PART_NAME="inactive" + platform_do_upgrade_dualboot_datachk "$1" + ;; + zyxel,nbg6617) + zyxel_do_upgrade "$1" + ;; + *) + default_do_upgrade "$1" + ;; + esac +} diff --git a/feeds/ipq40xx/ipq40xx/config-5.4 b/feeds/ipq40xx/ipq40xx/config-5.4 new file mode 100644 index 000000000..0fb49355c --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/config-5.4 @@ -0,0 +1,470 @@ +CONFIG_ALIGNMENT_TRAP=y +# CONFIG_APQ_GCC_8084 is not set +# CONFIG_APQ_MMCC_8084 is not set +CONFIG_AR40XX_PHY=y +CONFIG_ARCH_32BIT_OFF_T=y +CONFIG_ARCH_CLOCKSOURCE_DATA=y +CONFIG_ARCH_HIBERNATION_POSSIBLE=y +CONFIG_ARCH_IPQ40XX=y +CONFIG_ARCH_KEEP_MEMBLOCK=y +# CONFIG_ARCH_MDM9615 is not set +CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y +# CONFIG_ARCH_MSM8960 is not set +# CONFIG_ARCH_MSM8974 is not set +# CONFIG_ARCH_MSM8X60 is not set +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_QCOM=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_ARM=y +CONFIG_ARM_AMBA=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_CPUIDLE=y +CONFIG_ARM_CPU_SUSPEND=y +# CONFIG_ARM_CPU_TOPOLOGY is not set +CONFIG_ARM_CRYPTO=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_PATCH_IDIV=y +CONFIG_ARM_PATCH_PHYS_VIRT=y +# CONFIG_ARM_QCOM_CPUFREQ_HW is not set +# CONFIG_ARM_SMMU is not set +CONFIG_ARM_THUMB=y +CONFIG_ARM_UNWIND=y +CONFIG_ARM_VIRT_EXT=y +CONFIG_AT803X_PHY=y +CONFIG_AUTO_ZRELADDR=y +CONFIG_BCH=y +CONFIG_BINFMT_FLAT_ARGVP_ENVP_ON_STACK=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_MQ_PCI=y +CONFIG_BOUNCE=y +# CONFIG_CACHE_L2X0 is not set +CONFIG_CLKDEV_LOOKUP=y +CONFIG_CLKSRC_QCOM=y +CONFIG_CLONE_BACKWARDS=y +CONFIG_COMMON_CLK=y +CONFIG_COMMON_CLK_QCOM=y +CONFIG_COMPAT_32BIT_TIME=y +CONFIG_CPUFREQ_DT=y +CONFIG_CPUFREQ_DT_PLATDEV=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_FREQ=y +CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set +CONFIG_CPU_FREQ_GOV_ATTR_SET=y +CONFIG_CPU_FREQ_GOV_COMMON=y +# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set +# CONFIG_CPU_FREQ_GOV_USERSPACE is not set +CONFIG_CPU_FREQ_STAT=y +CONFIG_CPU_HAS_ASID=y +CONFIG_CPU_IDLE=y +CONFIG_CPU_IDLE_GOV_LADDER=y +CONFIG_CPU_IDLE_GOV_MENU=y +CONFIG_CPU_IDLE_MULTIPLE_DRIVERS=y +CONFIG_CPU_PABRT_V7=y +CONFIG_CPU_PM=y +CONFIG_CPU_RMAP=y +CONFIG_CPU_SPECTRE=y +CONFIG_CPU_THERMAL=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_CRYPTO_ACOMP2=y +CONFIG_CRYPTO_AEAD=y +CONFIG_CRYPTO_AEAD2=y +CONFIG_CRYPTO_AES_ARM=y +CONFIG_CRYPTO_AES_ARM_BS=y +CONFIG_CRYPTO_CBC=y +CONFIG_CRYPTO_CRYPTD=y +CONFIG_CRYPTO_CTR=y +CONFIG_CRYPTO_DEFLATE=y +CONFIG_CRYPTO_DES=y +CONFIG_CRYPTO_DEV_QCE=y +# CONFIG_CRYPTO_DEV_QCE_ENABLE_ALL is not set +# CONFIG_CRYPTO_DEV_QCE_ENABLE_SHA is not set +CONFIG_CRYPTO_DEV_QCE_ENABLE_SKCIPHER=y +CONFIG_CRYPTO_DEV_QCE_SKCIPHER=y +CONFIG_CRYPTO_DEV_QCE_SW_MAX_LEN=512 +CONFIG_CRYPTO_DEV_QCOM_RNG=y +CONFIG_CRYPTO_DRBG=y +CONFIG_CRYPTO_DRBG_HMAC=y +CONFIG_CRYPTO_DRBG_MENU=y +CONFIG_CRYPTO_ECB=y +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_HASH_INFO=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_HW=y +CONFIG_CRYPTO_JITTERENTROPY=y +CONFIG_CRYPTO_LIB_DES=y +CONFIG_CRYPTO_LIB_SHA256=y +CONFIG_CRYPTO_LZO=y +CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_MANAGER2=y +CONFIG_CRYPTO_NULL=y +CONFIG_CRYPTO_NULL2=y +CONFIG_CRYPTO_RNG=y +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_RNG_DEFAULT=y +CONFIG_CRYPTO_SEQIV=y +CONFIG_CRYPTO_SHA256=y +CONFIG_CRYPTO_SHA256_ARM=y +CONFIG_CRYPTO_SIMD=y +CONFIG_CRYPTO_XTS=y +CONFIG_CRYPTO_ZSTD=y +CONFIG_DCACHE_WORD_ACCESS=y +CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S" +CONFIG_DEBUG_MISC=y +CONFIG_DMADEVICES=y +CONFIG_DMA_ENGINE=y +CONFIG_DMA_OF=y +CONFIG_DMA_REMAP=y +CONFIG_DMA_SHARED_BUFFER=y +CONFIG_DMA_VIRTUAL_CHANNELS=y +CONFIG_DTC=y +CONFIG_DT_IDLE_STATES=y +CONFIG_DYNAMIC_DEBUG=y +CONFIG_EDAC_ATOMIC_SCRUB=y +CONFIG_EDAC_SUPPORT=y +CONFIG_EEPROM_AT24=y +CONFIG_ESSEDMA=y +CONFIG_EXTCON=y +CONFIG_FIXED_PHY=y +CONFIG_FIX_EARLYCON_MEM=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_EARLY_IOREMAP=y +CONFIG_GENERIC_IDLE_POLL_SETUP=y +CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y +CONFIG_GENERIC_IRQ_MULTI_HANDLER=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_GENERIC_IRQ_SHOW_LEVEL=y +CONFIG_GENERIC_MSI_IRQ=y +CONFIG_GENERIC_MSI_IRQ_DOMAIN=y +CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_GENERIC_PHY=y +CONFIG_GENERIC_PINCONF=y +CONFIG_GENERIC_PINCTRL_GROUPS=y +CONFIG_GENERIC_PINMUX_FUNCTIONS=y +CONFIG_GENERIC_SCHED_CLOCK=y +CONFIG_GENERIC_SMP_IDLE_THREAD=y +CONFIG_GENERIC_STRNCPY_FROM_USER=y +CONFIG_GENERIC_STRNLEN_USER=y +CONFIG_GENERIC_TIME_VSYSCALL=y +CONFIG_GPIOLIB=y +CONFIG_GPIOLIB_IRQCHIP=y +CONFIG_GPIO_74X164=y +CONFIG_GPIO_WATCHDOG=y +CONFIG_GPIO_WATCHDOG_ARCH_INITCALL=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_HIGHMEM=y +# CONFIG_HIGHPTE is not set +CONFIG_HWSPINLOCK=y +CONFIG_HWSPINLOCK_QCOM=y +CONFIG_HW_RANDOM=y +CONFIG_HW_RANDOM_OPTEE=y +CONFIG_HZ=100 +CONFIG_HZ_100=y +CONFIG_HZ_FIXED=0 +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_HELPER_AUTO=y +CONFIG_I2C_QUP=y +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_IOMMU_DEBUGFS is not set +# CONFIG_IOMMU_IO_PGTABLE_ARMV7S is not set +# CONFIG_IOMMU_IO_PGTABLE_LPAE is not set +CONFIG_IOMMU_SUPPORT=y +CONFIG_IO_URING=y +CONFIG_IPQ_GCC_4019=y +# CONFIG_IPQ_GCC_806X is not set +# CONFIG_IPQ_GCC_8074 is not set +# CONFIG_IPQ_LCC_806X is not set +CONFIG_IRQCHIP=y +CONFIG_IRQ_DOMAIN=y +CONFIG_IRQ_DOMAIN_HIERARCHY=y +CONFIG_IRQ_FORCED_THREADING=y +CONFIG_IRQ_WORK=y +# CONFIG_KPSS_XCC is not set +# CONFIG_KRAITCC is not set +CONFIG_LEDS_LP5523=y +CONFIG_LEDS_LP5562=y +CONFIG_LEDS_LP55XX_COMMON=y +CONFIG_LIBFDT=y +CONFIG_LOCK_DEBUGGING_SUPPORT=y +CONFIG_LOCK_SPIN_ON_OWNER=y +CONFIG_LZO_COMPRESS=y +CONFIG_LZO_DECOMPRESS=y +CONFIG_MDIO_BITBANG=y +CONFIG_MDIO_BUS=y +CONFIG_MDIO_DEVICE=y +CONFIG_MDIO_GPIO=y +CONFIG_MDIO_IPQ4019=y +# CONFIG_MDM_GCC_9615 is not set +# CONFIG_MDM_LCC_9615 is not set +CONFIG_MEMFD_CREATE=y +# CONFIG_MFD_QCOM_RPM is not set +# CONFIG_MFD_SPMI_PMIC is not set +CONFIG_MFD_SYSCON=y +CONFIG_MIGHT_HAVE_CACHE_L2X0=y +CONFIG_MIGRATION=y +CONFIG_MMC=y +CONFIG_MMC_BLOCK=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_IO_ACCESSORS=y +CONFIG_MMC_SDHCI_MSM=y +# CONFIG_MMC_SDHCI_PCI is not set +CONFIG_MMC_SDHCI_PLTFM=y +CONFIG_MODULES_USE_ELF_REL=y +# CONFIG_MSM_GCC_8660 is not set +# CONFIG_MSM_GCC_8916 is not set +# CONFIG_MSM_GCC_8960 is not set +# CONFIG_MSM_GCC_8974 is not set +# CONFIG_MSM_GCC_8994 is not set +# CONFIG_MSM_GCC_8996 is not set +# CONFIG_MSM_GCC_8998 is not set +# CONFIG_MSM_LCC_8960 is not set +# CONFIG_MSM_MMCC_8960 is not set +# CONFIG_MSM_MMCC_8974 is not set +# CONFIG_MSM_MMCC_8996 is not set +CONFIG_MTD_CMDLINE_PARTS=y +CONFIG_MTD_NAND_CORE=y +CONFIG_MTD_NAND_ECC_SW_BCH=y +CONFIG_MTD_NAND_ECC_SW_HAMMING=y +CONFIG_MTD_NAND_QCOM=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_SPLIT_WRGG_FW=y +CONFIG_MTD_UBI=y +CONFIG_MTD_UBI_BEB_LIMIT=20 +CONFIG_MTD_UBI_BLOCK=y +CONFIG_MTD_UBI_WL_THRESHOLD=4096 +CONFIG_MUTEX_SPIN_ON_OWNER=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_NEON=y +CONFIG_NET_FLOW_LIMIT=y +CONFIG_NET_PTP_CLASSIFY=y +CONFIG_NLS=y +CONFIG_NO_HZ=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_EARLY_FLATTREE=y +CONFIG_OF_FLATTREE=y +CONFIG_OF_GPIO=y +CONFIG_OF_IRQ=y +CONFIG_OF_KOBJ=y +CONFIG_OF_MDIO=y +CONFIG_OF_NET=y +CONFIG_OLD_SIGACTION=y +CONFIG_OLD_SIGSUSPEND3=y +CONFIG_OPTEE=y +CONFIG_OPTEE_SHM_NUM_PRIV_PAGES=1 +CONFIG_PADATA=y +CONFIG_PAGE_OFFSET=0xC0000000 +CONFIG_PCI=y +CONFIG_PCIEAER=y +CONFIG_PCIEPORTBUS=y +CONFIG_PCIE_DW=y +CONFIG_PCIE_DW_HOST=y +CONFIG_PCIE_QCOM=y +CONFIG_PCI_DISABLE_COMMON_QUIRKS=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_PHY_QCOM_APQ8064_SATA is not set +CONFIG_PHY_QCOM_IPQ4019_USB=y +# CONFIG_PHY_QCOM_IPQ806X_SATA is not set +# CONFIG_PHY_QCOM_PCIE2 is not set +# CONFIG_PHY_QCOM_QMP is not set +# CONFIG_PHY_QCOM_QUSB2 is not set +# CONFIG_PHY_QCOM_UFS is not set +CONFIG_PINCTRL=y +# CONFIG_PINCTRL_APQ8064 is not set +# CONFIG_PINCTRL_APQ8084 is not set +CONFIG_PINCTRL_IPQ4019=y +# CONFIG_PINCTRL_IPQ8064 is not set +# CONFIG_PINCTRL_IPQ8074 is not set +# CONFIG_PINCTRL_MDM9615 is not set +CONFIG_PINCTRL_MSM=y +# CONFIG_PINCTRL_MSM8660 is not set +# CONFIG_PINCTRL_MSM8916 is not set +# CONFIG_PINCTRL_MSM8960 is not set +# CONFIG_PINCTRL_MSM8994 is not set +# CONFIG_PINCTRL_MSM8996 is not set +# CONFIG_PINCTRL_MSM8998 is not set +# CONFIG_PINCTRL_QCOM_SPMI_PMIC is not set +# CONFIG_PINCTRL_QCOM_SSBI_PMIC is not set +# CONFIG_PINCTRL_QCS404 is not set +# CONFIG_PINCTRL_SC7180 is not set +# CONFIG_PINCTRL_SDM660 is not set +# CONFIG_PINCTRL_SDM845 is not set +# CONFIG_PINCTRL_SM8150 is not set +CONFIG_PM_OPP=y +CONFIG_POWER_RESET=y +CONFIG_POWER_RESET_MSM=y +CONFIG_POWER_SUPPLY=y +CONFIG_PPS=y +CONFIG_PRINTK_TIME=y +CONFIG_PTP_1588_CLOCK=y +CONFIG_QCA807X_PHY=y +CONFIG_QCOM_A53PLL=y +CONFIG_QCOM_BAM_DMA=y +# CONFIG_QCOM_COMMAND_DB is not set +# CONFIG_QCOM_EBI2 is not set +# CONFIG_QCOM_GENI_SE is not set +# CONFIG_QCOM_GSBI is not set +# CONFIG_QCOM_HFPLL is not set +# CONFIG_QCOM_IOMMU is not set +# CONFIG_QCOM_LLCC is not set +# CONFIG_QCOM_PDC is not set +CONFIG_QCOM_PM=y +CONFIG_QCOM_QFPROM=y +# CONFIG_QCOM_RMTFS_MEM is not set +CONFIG_QCOM_SCM=y +CONFIG_QCOM_SCM_32=y +# CONFIG_QCOM_SCM_DOWNLOAD_MODE_DEFAULT is not set +CONFIG_QCOM_SMEM=y +# CONFIG_QCOM_SMSM is not set +# CONFIG_QCOM_SOCINFO is not set +CONFIG_QCOM_TCSR=y +# CONFIG_QCOM_TSENS is not set +CONFIG_QCOM_WDT=y +# CONFIG_QCS_GCC_404 is not set +# CONFIG_QCS_TURING_404 is not set +# CONFIG_QRTR is not set +CONFIG_RAS=y +CONFIG_RATIONAL=y +CONFIG_RCU_CPU_STALL_TIMEOUT=21 +CONFIG_RCU_NEED_SEGCBLIST=y +CONFIG_RCU_STALL_COMMON=y +CONFIG_REFCOUNT_FULL=y +CONFIG_REGMAP=y +CONFIG_REGMAP_I2C=y +CONFIG_REGMAP_MMIO=y +CONFIG_REGULATOR=y +CONFIG_REGULATOR_FIXED_VOLTAGE=y +# CONFIG_REGULATOR_QCOM_SPMI is not set +CONFIG_REGULATOR_VCTRL=y +CONFIG_REGULATOR_VQMMC_IPQ4019=y +CONFIG_RESET_CONTROLLER=y +# CONFIG_RESET_QCOM_AOSS is not set +# CONFIG_RESET_QCOM_PDC is not set +CONFIG_RFS_ACCEL=y +CONFIG_RPS=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_I2C_AND_SPI=y +CONFIG_RTC_MC146818_LIB=y +CONFIG_RWSEM_SPIN_ON_OWNER=y +# CONFIG_SDM_CAMCC_845 is not set +# CONFIG_SDM_DISPCC_845 is not set +# CONFIG_SDM_GCC_660 is not set +# CONFIG_SDM_GCC_845 is not set +# CONFIG_SDM_GPUCC_845 is not set +# CONFIG_SDM_LPASSCC_845 is not set +# CONFIG_SDM_VIDEOCC_845 is not set +CONFIG_SERIAL_8250_FSL=y +CONFIG_SERIAL_MCTRL_GPIO=y +CONFIG_SERIAL_MSM=y +CONFIG_SERIAL_MSM_CONSOLE=y +CONFIG_SGL_ALLOC=y +CONFIG_SMP=y +CONFIG_SMP_ON_UP=y +# CONFIG_SM_GCC_8150 is not set +CONFIG_SPARSE_IRQ=y +CONFIG_SPI=y +CONFIG_SPI_BITBANG=y +CONFIG_SPI_GPIO=y +CONFIG_SPI_MASTER=y +CONFIG_SPI_MEM=y +CONFIG_SPI_QUP=y +CONFIG_SPMI=y +CONFIG_SPMI_MSM_PMIC_ARB=y +# CONFIG_SPMI_PMIC_CLKDIV is not set +CONFIG_SRCU=y +CONFIG_SWCONFIG=y +CONFIG_SWCONFIG_LEDS=y +CONFIG_SWPHY=y +CONFIG_SWP_EMULATE=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_TEE=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_TREE_RCU=y +CONFIG_TREE_SRCU=y +CONFIG_UBIFS_FS=y +CONFIG_UBIFS_FS_ADVANCED_COMPR=y +CONFIG_UBIFS_FS_LZO=y +CONFIG_UBIFS_FS_ZLIB=y +CONFIG_UBIFS_FS_ZSTD=y +CONFIG_UEVENT_HELPER_PATH="" +CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h" +CONFIG_UNWINDER_ARM=y +CONFIG_USB=y +CONFIG_USB_COMMON=y +CONFIG_USB_SUPPORT=y +CONFIG_USE_OF=y +CONFIG_VFP=y +CONFIG_VFPv3=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/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-a42.dts b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-a42.dts new file mode 100644 index 000000000..f571da510 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-a42.dts @@ -0,0 +1,205 @@ +// SPDX-License-Identifier: ISC +/* Copyright (c) 2015, The Linux Foundation. All rights reserved. + * Copyright (c) 2017, Sven Eckelmann + */ + +#include "qcom-ipq4019.dtsi" +#include +#include +#include + +/ { + model = "OpenMesh A42"; + compatible = "openmesh,a42"; + + soc { + rng@22000 { + status = "okay"; + }; + + mdio@90000 { + status = "okay"; + }; + + ess-psgmii@98000 { + status = "okay"; + }; + + tcsr@194b000 { + /* select hostmode */ + compatible = "qcom,tcsr"; + reg = <0x194b000 0x100>; + qcom,usb-hsphy-mode-select = ; + status = "okay"; + }; + + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; + qcom,wifi_glb_cfg = ; + }; + + ess_tcsr@1953000 { + compatible = "qcom,tcsr"; + reg = <0x1953000 0x1000>; + qcom,ess-interface-select = ; + }; + + tcsr@1957000 { + compatible = "qcom,tcsr"; + reg = <0x1957000 0x100>; + qcom,wifi_noc_memtype_m0_m2 = ; + }; + + usb2: usb2@60f8800 { + status = "okay"; + }; + + crypto@8e3a000 { + status = "okay"; + }; + + watchdog@b017000 { + status = "okay"; + }; + + ess-switch@c000000 { + status = "okay"; + }; + + edma@c080000 { + status = "okay"; + }; + }; + + keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + gpios = <&tlmm 59 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + aliases { + led-boot = &led_status_green; + led-failsafe = &led_status_green; + led-running = &led_status_green; + led-upgrade = &led_status_green; + }; + + leds { + compatible = "gpio-leds"; + + status_red { + label = "red:status"; + gpios = <&tlmm 0 GPIO_ACTIVE_HIGH>; + }; + + led_status_green: status_green { + label = "green:status"; + gpios = <&tlmm 1 GPIO_ACTIVE_HIGH>; + }; + + status_blue { + label = "blue:status"; + gpios = <&tlmm 2 GPIO_ACTIVE_HIGH>; + }; + }; + + watchdog { + compatible = "linux,wdt-gpio"; + gpios = <&tlmm 5 GPIO_ACTIVE_LOW>; + hw_algo = "toggle"; + /* hw_margin_ms is actually 300s but driver limits it to 60s */ + hw_margin_ms = <60000>; + always-running; + }; +}; + +&tlmm { + serial_pins: serial_pinmux { + mux { + pins = "gpio60", "gpio61"; + function = "blsp_uart0"; + bias-disable; + }; + }; + + spi_0_pins: spi_0_pinmux { + pin { + function = "blsp_spi0"; + pins = "gpio55", "gpio56", "gpio57"; + drive-strength = <12>; + bias-disable; + }; + pin_cs { + function = "gpio"; + pins = "gpio54"; + drive-strength = <2>; + bias-disable; + output-high; + }; + }; +}; + +&blsp_dma { + status = "okay"; +}; + +&blsp1_spi1 { + pinctrl-0 = <&spi_0_pins>; + pinctrl-names = "default"; + status = "okay"; + cs-gpios = <&tlmm 54 GPIO_ACTIVE_HIGH>; + + flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <24000000>; + /* partitions are passed via bootloader */ + }; +}; + +&blsp1_uart1 { + pinctrl-0 = <&serial_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + +&cryptobam { + status = "okay"; +}; + +&gmac0 { + qcom,phy_mdio_addr = <4>; + qcom,poll_required = <1>; + qcom,forced_speed = <1000>; + qcom,forced_duplex = <1>; + vlan_tag = <2 0x20>; +}; + +&gmac1 { + qcom,phy_mdio_addr = <3>; + qcom,poll_required = <1>; + qcom,forced_speed = <1000>; + qcom,forced_duplex = <1>; + vlan_tag = <1 0x10>; +}; + +&usb2_hs_phy { + status = "okay"; +}; + +&wifi0 { + status = "okay"; + qcom,ath10k-calibration-variant = "OM-A42"; +}; + +&wifi1 { + status = "okay"; + qcom,ath10k-calibration-variant = "OM-A42"; +}; diff --git a/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-ap120c-ac.dts b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-ap120c-ac.dts new file mode 100644 index 000000000..c35ce5ccc --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-ap120c-ac.dts @@ -0,0 +1,350 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "qcom-ipq4019.dtsi" +#include +#include +#include + +/ { + model = "ALFA Network AP120C-AC"; + compatible = "alfa-network,ap120c-ac"; + + aliases { + led-boot = &status; + led-failsafe = &status; + led-running = &status; + led-upgrade = &status; + }; + + keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + gpios = <&tlmm 63 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + leds { + compatible = "gpio-leds"; + + status: status { + label = "blue:status"; + gpios = <&tlmm 5 GPIO_ACTIVE_LOW>; + default-state = "keep"; + }; + + wan { + label = "amber:wan"; + gpios = <ðphy4 1 GPIO_ACTIVE_HIGH>; + }; + + wlan2g { + label = "green:wlan2g"; + gpios = <&tlmm 3 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "phy0tpt"; + }; + + wlan5g { + label = "red:wlan5g"; + gpios = <&tlmm 2 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "phy1tpt"; + }; + }; + + soc { + rng@22000 { + status = "okay"; + }; + + mdio@90000 { + status = "okay"; + + pinctrl-0 = <&mdio_pins>; + pinctrl-names = "default"; + }; + + ess-psgmii@98000 { + status = "okay"; + }; + + counter@4a1000 { + compatible = "qcom,qca-gcnt"; + reg = <0x4a1000 0x4>; + }; + + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; + qcom,wifi_glb_cfg = ; + }; + + tcsr@194b000 { + compatible = "qcom,tcsr"; + reg = <0x194b000 0x100>; + qcom,usb-hsphy-mode-select = ; + }; + + ess_tcsr@1953000 { + compatible = "qcom,tcsr"; + reg = <0x1953000 0x1000>; + qcom,ess-interface-select = ; + }; + + tcsr@1957000 { + compatible = "qcom,tcsr"; + reg = <0x1957000 0x100>; + qcom,wifi_noc_memtype_m0_m2 = ; + }; + + usb2@60f8800 { + status = "okay"; + }; + + usb3@8af8800 { + status = "okay"; + + dwc3@8a00000 { + phys = <&usb3_hs_phy>; + phy-names = "usb2-phy"; + }; + }; + + crypto@8e3a000 { + status = "okay"; + }; + + watchdog@b017000 { + status = "okay"; + }; + + ess-switch@c000000 { + status = "okay"; + + switch_lan_bmp = <0x10>; + switch_wan_bmp = <0x20>; + }; + + edma@c080000 { + status = "okay"; + }; + }; +}; + +&blsp_dma { + status = "okay"; +}; + +&blsp1_i2c3 { + status = "okay"; + + pinctrl-0 = <&i2c0_pins>; + pinctrl-names = "default"; + + tpm@29 { + compatible = "atmel,at97sc3204t"; + reg = <0x29>; + }; +}; + +&blsp1_spi1 { + status = "okay"; + + pinctrl-0 = <&spi0_pins>; + pinctrl-names = "default"; + cs-gpios = <&tlmm 54 GPIO_ACTIVE_HIGH>, + <&tlmm 4 GPIO_ACTIVE_HIGH>; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <24000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "SBL1"; + reg = <0x00000000 0x00040000>; + read-only; + }; + + partition@40000 { + label = "MIBIB"; + reg = <0x00040000 0x00020000>; + read-only; + }; + + partition@60000 { + label = "QSEE"; + reg = <0x00060000 0x00060000>; + read-only; + }; + + partition@c0000 { + label = "CDT"; + reg = <0x000c0000 0x00010000>; + read-only; + }; + + partition@d0000 { + label = "DDRPARAMS"; + reg = <0x000d0000 0x00010000>; + read-only; + }; + + partition@e0000 { + label = "APPSBLENV"; + reg = <0x000e0000 0x00010000>; + }; + + partition@f0000 { + label = "APPSBL"; + reg = <0x000f0000 0x00080000>; + read-only; + }; + + partition@170000 { + label = "ART"; + reg = <0x00170000 0x00010000>; + read-only; + }; + + partition@180000 { + label = "priv_data1"; + reg = <0x00180000 0x00010000>; + read-only; + }; + + partition@190000 { + label = "priv_data2"; + reg = <0x00190000 0x00010000>; + read-only; + }; + }; + }; + + nand@1 { + compatible = "spi-nand"; + reg = <1>; + spi-max-frequency = <24000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "rootfs1"; + reg = <0x00000000 0x04000000>; + }; + + partition@4000000 { + label = "rootfs2"; + reg = <0x04000000 0x04000000>; + }; + }; + }; +}; + +&blsp1_uart1 { + status = "okay"; + + pinctrl-0 = <&serial0_pins>; + pinctrl-names = "default"; +}; + +&cryptobam { + status = "okay"; +}; + +ðphy4 { + gpio-controller; + #gpio-cells = <2>; +}; + +&gmac0 { + qcom,forced_duplex = <1>; + qcom,forced_speed = <1000>; + qcom,phy_mdio_addr = <3>; + qcom,poll_required = <1>; + vlan_tag = <1 0x10>; +}; + +&gmac1 { + qcom,forced_duplex = <1>; + qcom,forced_speed = <1000>; + qcom,phy_mdio_addr = <4>; + qcom,poll_required = <1>; + vlan_tag = <2 0x20>; +}; + +&tlmm { + i2c0_pins: i2c0_pinmux { + mux_i2c { + function = "blsp_i2c0"; + pins = "gpio58", "gpio59"; + drive-strength = <16>; + bias-disable; + }; + }; + + mdio_pins: mdio_pinmux { + mux_mdio { + pins = "gpio53"; + function = "mdio"; + bias-pull-up; + }; + + mux_mdc { + pins = "gpio52"; + function = "mdc"; + bias-pull-up; + }; + }; + + serial0_pins: serial0_pinmux { + mux_uart { + pins = "gpio60", "gpio61"; + function = "blsp_uart0"; + bias-disable; + }; + }; + + spi0_pins: spi0_pinmux { + mux_spi { + function = "blsp_spi0"; + pins = "gpio55", "gpio56", "gpio57"; + drive-strength = <12>; + bias-disable; + }; + + mux_cs { + function = "gpio"; + pins = "gpio54", "gpio4"; + drive-strength = <2>; + bias-disable; + output-high; + }; + }; +}; + +&usb2_hs_phy { + status = "okay"; +}; + +&usb3_hs_phy { + status = "okay"; +}; + +&wifi0 { + status = "okay"; +}; + +&wifi1 { + status = "okay"; + qcom,ath10k-calibration-variant = "ALFA-Network-AP120C-AC"; +}; diff --git a/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-cs-w3-wd1200g-eup.dts b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-cs-w3-wd1200g-eup.dts new file mode 100644 index 000000000..062826c7a --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-cs-w3-wd1200g-eup.dts @@ -0,0 +1,242 @@ +// SPDX-License-Identifier: GPL-2.0-only OR MIT + +#include "qcom-ipq4019.dtsi" +#include +#include +#include + +/ { + model = "EZVIZ CS-W3-WD1200G EUP"; + compatible = "ezviz,cs-w3-wd1200g-eup"; + + aliases { + led-boot = &led_status_green; + led-failsafe = &led_status_red; + led-running = &led_status_blue; + led-upgrade = &led_status_green; + }; + + soc { + rng@22000 { + status = "okay"; + }; + + mdio@90000 { + status = "okay"; + pinctrl-0 = <&mdio_pins>; + pinctrl-names = "default"; + reset-gpios = <&tlmm 59 GPIO_ACTIVE_LOW>; + reset-delay-us = <5000>; + }; + + ess-psgmii@98000 { + status = "okay"; + }; + + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; + qcom,wifi_glb_cfg = ; + }; + + tcsr@194b000 { + compatible = "qcom,tcsr"; + reg = <0x194b000 0x100>; + qcom,usb-hsphy-mode-select = ; + }; + + ess_tcsr@1953000 { + compatible = "qcom,tcsr"; + reg = <0x1953000 0x1000>; + qcom,ess-interface-select = ; + }; + + tcsr@1957000 { + compatible = "qcom,tcsr"; + reg = <0x1957000 0x100>; + qcom,wifi_noc_memtype_m0_m2 = ; + }; + + crypto@8e3a000 { + status = "okay"; + }; + + watchdog@b017000 { + status = "okay"; + }; + + ess-switch@c000000 { + status = "okay"; + }; + + edma@c080000 { + status = "okay"; + }; + }; + + leds { + compatible = "gpio-leds"; + + led_status_red: status_red { + label = "red:status"; + gpios = <&tlmm 0 GPIO_ACTIVE_LOW>; + }; + + led_status_green: status_green { + label = "green:status"; + gpios = <&tlmm 3 GPIO_ACTIVE_LOW>; + }; + + led_status_blue: status_blue { + label = "blue:status"; + gpios = <&tlmm 58 GPIO_ACTIVE_LOW>; + }; + }; + + keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + gpios = <&tlmm 63 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; +}; + +&tlmm { + serial_pins: serial_pinmux { + mux { + pins = "gpio60", "gpio61"; + function = "blsp_uart0"; + bias-disable; + }; + }; + + mdio_pins: mdio_pinmux { + mux_1 { + pins = "gpio53"; + function = "mdio"; + bias-pull-up; + }; + + mux_2 { + pins = "gpio52"; + function = "mdc"; + bias-pull-up; + }; + }; + + spi_0_pins: spi_0_pinmux { + pin { + function = "blsp_spi0"; + pins = "gpio55", "gpio56", "gpio57"; + drive-strength = <12>; + bias-disable; + }; + pin_cs { + function = "gpio"; + pins = "gpio54"; + drive-strength = <2>; + bias-disable; + output-high; + }; + }; +}; + +&blsp_dma { + status = "okay"; +}; + +&blsp1_spi1 { + pinctrl-0 = <&spi_0_pins>; + pinctrl-names = "default"; + status = "okay"; + cs-gpios = <&tlmm 54 GPIO_ACTIVE_HIGH>; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <24000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition0@0 { + label = "SBL1"; + reg = <0x00000000 0x00040000>; + read-only; + }; + + partition1@40000 { + label = "MIBIB"; + reg = <0x00040000 0x00020000>; + read-only; + }; + + partition2@60000 { + label = "QSEE"; + reg = <0x00060000 0x00060000>; + read-only; + }; + + partition3@c0000 { + label = "CDT"; + reg = <0x000c0000 0x00010000>; + read-only; + }; + + partition4@d0000 { + label = "DDRPARAMS"; + reg = <0x000d0000 0x00010000>; + read-only; + }; + + partition5@E0000 { + label = "APPSBLENV"; + reg = <0x000e0000 0x00010000>; + read-only; + }; + + partition6@F0000 { + label = "APPSBL"; + reg = <0x000f0000 0x00080000>; + read-only; + }; + + partition7@170000 { + label = "ART"; + reg = <0x00170000 0x00010000>; + read-only; + }; + + partition9@580000 { + compatible = "denx,fit"; + label = "firmware"; + reg = <0x00180000 0x00e80000>; + }; + }; + }; +}; + +&blsp1_uart1 { + pinctrl-0 = <&serial_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + +&cryptobam { + status = "okay"; +}; + +&wifi0 { + status = "okay"; + qcom,ath10k-calibration-variant = "ezviz-cs-w3-wd1200g-eup"; +}; + +&wifi1 { + status = "okay"; + qcom,ath10k-calibration-variant = "ezviz-cs-w3-wd1200g-eup"; +}; diff --git a/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-dap-2610.dts b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-dap-2610.dts new file mode 100644 index 000000000..e3afddb37 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-dap-2610.dts @@ -0,0 +1,241 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "qcom-ipq4019.dtsi" +#include +#include +#include + +/ { + model = "D-Link DAP 2610"; + compatible = "dlink,dap-2610"; + + aliases { + led-boot = &led_red; + led-failsafe = &led_red; + led-running = &led_green; + led-upgrade = &led_red; + }; + + soc { + edma@c080000 { + qcom,num_gmac = <1>; + status = "okay"; + }; + + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; + qcom,wifi_glb_cfg = ; + }; + + ess_tcsr@1953000 { + compatible = "qcom,tcsr"; + reg = <0x1953000 0x1000>; + qcom,ess-interface-select = ; + }; + + tcsr@1957000 { + compatible = "qcom,tcsr"; + reg = <0x1957000 0x100>; + qcom,wifi_noc_memtype_m0_m2 = ; + }; + + rng@22000 { + status = "okay"; + }; + + crypto@8e3a000 { + status = "okay"; + }; + + watchdog@b017000 { + status = "okay"; + }; + + ess-switch@c000000 { + status = "okay"; + switch_lan_bmp = <0x20>; + switch_wan_bmp = <0x00>; + }; + + ess-psgmii@98000 { + status = "okay"; + }; + }; + + leds { + compatible = "gpio-leds"; + + led_red: red { + label = "red:power"; + gpios = <&tlmm 4 GPIO_ACTIVE_LOW>; + }; + + led_green: green { + label = "green:power"; + gpios = <&tlmm 5 GPIO_ACTIVE_LOW>; + }; + }; + + keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + gpios = <&tlmm 63 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; +}; + +&blsp1_spi1 { + pinctrl-0 = <&spi_0_pins>; + pinctrl-names = "default"; + status = "okay"; + cs-gpios = <&tlmm 54 GPIO_ACTIVE_HIGH>; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <24000000>; + + partitions { + #address-cells = <1>; + #size-cells = <1>; + compatible = "fixed-partitions"; + + partition@0 { + label = "SBL1"; + reg = <0x0 0x40000>; + read-only; + }; + partition@40000 { + label = "MIBIB"; + reg = <0x40000 0x20000>; + read-only; + }; + partition@60000 { + label = "QSEE"; + reg = <0x60000 0x60000>; + read-only; + }; + partition@c0000 { + label = "CDT"; + reg = <0xc0000 0x10000>; + read-only; + }; + partition@d0000 { + label = "DDRPARAMS"; + reg = <0xd0000 0x10000>; + read-only; + }; + partition@e0000 { + label = "APPSBLENV"; + reg = <0xe0000 0x10000>; + read-only; + }; + partition@f0000 { + label = "APPSBL"; + reg = <0xf0000 0x80000>; + read-only; + }; + partition@170000 { + label = "ART"; + reg = <0x170000 0x10000>; + read-only; + }; + partition@180000 { + compatible = "wrg"; + label = "firmware"; + reg = <0x180000 0xdc0000>; + }; + partition@fb0000 { + label = "rgbd"; + reg = <0xfb0000 0x10000>; + read-only; + }; + partition@fc0000 { + label = "bdcfg"; + reg = <0xfc0000 0x10000>; + read-only; + }; + partition@fd0000 { + label = "langpack"; + reg = <0xfd0000 0x20000>; + read-only; + }; + partition@ff0000 { + label = "certificate"; + reg = <0xff0000 0x10000>; + read-only; + }; + partition@f40000 { + label = "captival"; + reg = <0xf40000 0x70000>; + read-only; + }; + }; + }; +}; + +&blsp_dma { + status = "okay"; +}; + +&blsp1_uart1 { + pinctrl-0 = <&serial_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + +&cryptobam { + status = "okay"; +}; + +&gmac0 { + qcom,phy_mdio_addr = <4>; + qcom,poll_required = <1>; + qcom,forced_speed = <1000>; + qcom,forced_duplex = <1>; + vlan_tag = <1 0x20>; +}; + +&mdio { + status = "okay"; +}; + +&tlmm { + serial_pins: serial_pinmux { + mux { + pins = "gpio60", "gpio61"; + function = "blsp_uart0"; + bias-disable; + }; + }; + + spi_0_pins: spi_0_pinmux { + mux { + function = "blsp_spi0"; + pins = "gpio55", "gpio56", "gpio57"; + drive-strength = <12>; + bias-disable; + }; + mux_cs { + function = "gpio"; + pins = "gpio54"; + drive-strength = <2>; + bias-disable; + output-high; + }; + }; +}; + +&wifi0 { + status = "okay"; + qcom,ath10k-calibration-variant = "dlink,dap-2610"; +}; + +&wifi1 { + status = "okay"; + qcom,ath10k-calibration-variant = "dlink,dap-2610"; +}; diff --git a/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-ea6350v3.dts b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-ea6350v3.dts new file mode 100644 index 000000000..cfaba0f41 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-ea6350v3.dts @@ -0,0 +1,277 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "qcom-ipq4019.dtsi" +#include +#include +#include + +/ { + model = "Linksys EA6350v3"; + compatible = "linksys,ea6350v3"; + + aliases { + led-boot = &power; + led-failsafe = &power; + led-running = &power; + led-upgrade = &power; + }; + + soc { + rng@22000 { + status = "okay"; + }; + + mdio@90000 { + status = "okay"; + }; + + ess-psgmii@98000 { + status = "okay"; + }; + + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; + qcom,wifi_glb_cfg = ; + }; + + tcsr@194b000 { + compatible = "qcom,tcsr"; + reg = <0x194b000 0x100>; + qcom,usb-hsphy-mode-select = ; + }; + + ess_tcsr@1953000 { + compatible = "qcom,tcsr"; + reg = <0x1953000 0x1000>; + qcom,ess-interface-select = ; + }; + + tcsr@1957000 { + compatible = "qcom,tcsr"; + reg = <0x1957000 0x100>; + qcom,wifi_noc_memtype_m0_m2 = ; + }; + + usb2@60f8800 { + status = "okay"; + }; + + usb3@8af8800 { + status = "okay"; + }; + + crypto@8e3a000 { + status = "okay"; + }; + + watchdog@b017000 { + status = "okay"; + }; + + ess-switch@c000000 { + status = "okay"; + }; + + edma@c080000 { + status = "okay"; + }; + }; + + keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + gpios = <&tlmm 63 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + + wps { + label = "wps"; + gpios = <&tlmm 0 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + leds { + compatible = "gpio-leds"; + + power: status { + label = "green:status"; + gpios = <&tlmm 2 GPIO_ACTIVE_HIGH>; + }; + }; +}; + +&blsp1_uart1 { + pinctrl-0 = <&serial_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + +&cryptobam { + status = "okay"; +}; + +&wifi0 { + status = "okay"; + qcom,ath10k-calibration-variant = "linksys-ea6350v3"; +}; + +&wifi1 { + status = "okay"; + qcom,ath10k-calibration-variant = "linksys-ea6350v3"; +}; + + +&blsp_dma { + status = "okay"; +}; + +&tlmm { + serial_pins: serial_pinmux { + mux { + pins = "gpio60", "gpio61"; + function = "blsp_uart0"; + bias-disable; + }; + }; + + spi_0_pins: spi_0_pinmux { + mux { + function = "blsp_spi0"; + pins = "gpio55", "gpio56", "gpio57"; + drive-strength = <12>; + bias-disable; + }; + + mux_cs { + function = "gpio"; + pins = "gpio54", "gpio59"; + drive-strength = <2>; + bias-disable; + output-high; + }; + }; +}; + +&blsp1_spi1 { /* BLSP1 QUP1 */ + pinctrl-0 = <&spi_0_pins>; + pinctrl-names = "default"; + status = "okay"; + cs-gpios = <&tlmm 54 GPIO_ACTIVE_HIGH>, + <&tlmm 59 GPIO_ACTIVE_HIGH>; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <24000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + SBL1@0 { + label = "SBL1"; + reg = <0x00000000 0x00040000>; + read-only; + }; + MBIB@40000 { + label = "MIBIB"; + reg = <0x00040000 0x00020000>; + read-only; + }; + QSEE@60000 { + label = "QSEE"; + reg = <0x00060000 0x00060000>; + read-only; + }; + CDT@c0000 { + label = "CDT"; + reg = <0x000c0000 0x00010000>; + read-only; + }; + APPSBLENV@d0000 { + label = "APPSBLENV"; + reg = <0x000d0000 0x00010000>; + read-only; + }; + APPSBL@e0000 { + label = "APPSBL"; /* uboot */ + reg = <0x000e0000 0x00080000>; + read-only; + }; + ART@160000 { + label = "ART"; + reg = <0x00160000 0x00010000>; + read-only; + }; + u_env@170000 { + label = "u_env"; + reg = <0x00170000 0x00020000>; + }; + s_env@190000 { + label = "s_env"; + reg = <0x00190000 0x00020000>; + }; + devinfo@1b0000 { + label = "devinfo"; + reg = <0x001b0000 0x00010000>; + }; + /* 0x001c0000 - 0x00200000 unused */ + }; + }; + + flash@1 { + status = "okay"; + compatible = "spi-nand"; + reg = <1>; + spi-max-frequency = <24000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + kernel@0 { + label = "kernel"; + reg = <0x00000000 0x02800000>; + }; + rootfs@300000 { + label = "rootfs"; + reg = <0x00300000 0x02500000>; + }; + alt_kernel@2800000 { + label = "alt_kernel"; + reg = <0x02800000 0x02800000>; + }; + alt_rootfs@2b00000 { + label = "alt_rootfs"; + reg = <0x02b00000 0x02500000>; + }; + sysdiag@5000000 { + label = "sysdiag"; + reg = <0x05000000 0x00100000>; + }; + syscfg@5100000 { + label = "syscfg"; + reg = <0x05100000 0x02F00000>; + }; + /* 0x00000000 - 0x08000000: 128 MiB */ + }; + }; +}; + +&usb3_ss_phy { + status = "okay"; +}; + +&usb3_hs_phy { + status = "okay"; +}; + +&usb2_hs_phy { + status = "okay"; +}; diff --git a/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-eap1300.dts b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-eap1300.dts new file mode 100644 index 000000000..f08ddd0ab --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-eap1300.dts @@ -0,0 +1,235 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "qcom-ipq4019.dtsi" +#include +#include +#include + +/ { + model = "EnGenius EAP1300"; + compatible = "engenius,eap1300"; + + soc { + rng@22000 { + status = "okay"; + }; + + mdio@90000 { + status = "okay"; + }; + + ess-psgmii@98000 { + status = "okay"; + }; + + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; + qcom,wifi_glb_cfg = ; + }; + + ess_tcsr@1953000 { + compatible = "qcom,tcsr"; + reg = <0x1953000 0x1000>; + qcom,ess-interface-select = ; + }; + + tcsr@1957000 { + compatible = "qcom,tcsr"; + reg = <0x1957000 0x100>; + qcom,wifi_noc_memtype_m0_m2 = ; + }; + + crypto@8e3a000 { + status = "okay"; + }; + + watchdog@b017000 { + status = "okay"; + }; + + ess-switch@c000000 { + status = "okay"; + }; + + edma@c080000 { + status = "okay"; + }; + }; + + keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + gpios = <&tlmm 18 GPIO_ACTIVE_HIGH>; + linux,code = ; + }; + }; + + aliases { + led-boot = &power; + led-failsafe = &power; + led-running = &power; + led-upgrade = &power; + }; + + leds { + compatible = "gpio-leds"; + + power: orange { + label = "orange:power"; + gpios = <&tlmm 58 GPIO_ACTIVE_LOW>; + }; + + lan { + label = "blue:lan"; + gpios = <&tlmm 2 GPIO_ACTIVE_HIGH>; + }; + + mesh { + label = "blue:mesh"; + gpios = <&tlmm 1 GPIO_ACTIVE_HIGH>; + }; + + wlan2g { + label = "blue:wlan2g"; + gpios = <&tlmm 3 GPIO_ACTIVE_HIGH>; + }; + + wlan5g { + label = "yellow:wlan5g"; + gpios = <&tlmm 0 GPIO_ACTIVE_HIGH>; + }; + }; +}; + +&tlmm { + serial_pins: serial_pinmux { + mux { + pins = "gpio60", "gpio61"; + function = "blsp_uart0"; + bias-disable; + }; + }; + + spi_0_pins: spi_0_pinmux { + pin { + function = "blsp_spi0"; + pins = "gpio54", "gpio55", "gpio56", "gpio57"; + drive-strength = <12>; + bias-disable; + }; + pin_cs { + function = "gpio"; + pins = "gpio54"; + drive-strength = <2>; + bias-disable; + output-high; + }; + }; +}; + +&blsp_dma { + status = "okay"; +}; + +&blsp1_spi1 { + pinctrl-0 = <&spi_0_pins>; + pinctrl-names = "default"; + status = "okay"; + cs-gpios = <&tlmm 54 GPIO_ACTIVE_HIGH>; + + m25p80@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <24000000>; + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "0:SBL1"; + reg = <0x00000000 0x00040000>; + read-only; + }; + partition1@40000 { + label = "0:MIBIB"; + reg = <0x00040000 0x00020000>; + read-only; + }; + partition2@60000 { + label = "0:QSEE"; + reg = <0x00060000 0x00060000>; + read-only; + }; + partition3@c0000 { + label = "0:CDT"; + reg = <0x000c0000 0x00010000>; + read-only; + }; + partition4@d0000 { + label = "0:DDRPARAMS"; + reg = <0x000d0000 0x00010000>; + read-only; + }; + partition5@e0000 { + label = "0:APPSBLENV"; + reg = <0x000e0000 0x00010000>; + read-only; + }; + partition6@f0000 { + label = "0:APPSBL"; + reg = <0x000f0000 0x00090000>; + read-only; + }; + partition7@180000 { + label = "0:ART"; + reg = <0x00180000 0x00010000>; + read-only; + }; + partition8@190000 { + compatible = "denx,fit"; + label = "firmware"; + reg = <0x190000 0x1dc0000>; + }; + partition9@1f50000 { + label = "u-boot-env"; + reg = <0x01f50000 0x00010000>; + }; + partition10@1f60000 { + label = "userconfig"; + reg = <0x01f60000 0x000a0000>; + }; + }; + }; +}; + +&blsp1_uart1 { + pinctrl-0 = <&serial_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + +&cryptobam { + status = "okay"; +}; + +&gmac0 { + vlan_tag = <2 0x20>; +}; + +&gmac1 { + vlan_tag = <1 0x10>; +}; + +&wifi0 { + status = "okay"; + qcom,ath10k-calibration-variant = "EnGenius-EAP1300"; +}; + +&wifi1 { + status = "okay"; + qcom,ath10k-calibration-variant = "EnGenius-EAP1300"; +}; diff --git a/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-ecw5211.dts b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-ecw5211.dts new file mode 100644 index 000000000..d8c0853c5 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-ecw5211.dts @@ -0,0 +1,333 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "qcom-ipq4019.dtsi" +#include +#include +#include + +/ { + model = "Edgecore ECW5211"; + compatible = "edgecore,ecw5211"; + + aliases { + led-boot = &led_power; + led-failsafe = &led_power; + led-running = &led_power; + led-upgrade = &led_power; + label-mac-device = &gmac0; + }; + + chosen { + bootargs-append = " root=/dev/ubiblock0_1"; + }; + + keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + gpios = <&tlmm 63 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + leds { + compatible = "gpio-leds"; + + led_power: power { + label = "yellow:power"; + gpios = <&tlmm 5 GPIO_ACTIVE_LOW>; + }; + + wlan2g { + label = "green:wlan2g"; + gpios = <&tlmm 3 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "phy0tpt"; + }; + + wlan5g { + label = "green:wlan5g"; + gpios = <&tlmm 2 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "phy1tpt"; + }; + }; + + soc { + rng@22000 { + status = "okay"; + }; + + ess-psgmii@98000 { + status = "okay"; + }; + + counter@4a1000 { + compatible = "qcom,qca-gcnt"; + reg = <0x4a1000 0x4>; + }; + + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; + qcom,wifi_glb_cfg = ; + }; + + tcsr@194b000 { + compatible = "qcom,tcsr"; + reg = <0x194b000 0x100>; + qcom,usb-hsphy-mode-select = ; + }; + + ess_tcsr@1953000 { + compatible = "qcom,tcsr"; + reg = <0x1953000 0x1000>; + qcom,ess-interface-select = ; + }; + + tcsr@1957000 { + compatible = "qcom,tcsr"; + reg = <0x1957000 0x100>; + qcom,wifi_noc_memtype_m0_m2 = ; + }; + + usb2@60f8800 { + status = "okay"; + }; + + usb3@8af8800 { + status = "okay"; + + dwc3@8a00000 { + phys = <&usb3_hs_phy>; + phy-names = "usb2-phy"; + }; + }; + + crypto@8e3a000 { + status = "okay"; + }; + + watchdog@b017000 { + status = "okay"; + }; + + ess-switch@c000000 { + status = "okay"; + + switch_lan_bmp = <0x10>; + switch_wan_bmp = <0x20>; + }; + + edma@c080000 { + status = "okay"; + }; + }; +}; + +&tlmm { + mdio_pins: mdio_pinmux { + mux_mdio { + pins = "gpio53"; + function = "mdio"; + bias-pull-up; + }; + + mux_mdc { + pins = "gpio52"; + function = "mdc"; + bias-pull-up; + }; + }; + + serial_pins: serial_pinmux { + mux { + pins = "gpio60", "gpio61"; + function = "blsp_uart0"; + bias-disable; + }; + }; + + spi0_pins: spi0_pinmux { + pin { + function = "blsp_spi0"; + pins = "gpio55", "gpio56", "gpio57"; + drive-strength = <2>; + bias-disable; + }; + + pin_cs { + function = "gpio"; + pins = "gpio54", "gpio4"; + drive-strength = <2>; + bias-disable; + output-high; + }; + }; + + i2c0_pins: i2c0_pinmux { + mux_i2c { + function = "blsp_i2c0"; + pins = "gpio58", "gpio59"; + drive-strength = <16>; + bias-disable; + }; + }; +}; + +&blsp_dma { + status = "okay"; +}; + +&blsp1_spi1 { + status = "okay"; + + pinctrl-0 = <&spi0_pins>; + pinctrl-names = "default"; + cs-gpios = <&tlmm 54 GPIO_ACTIVE_HIGH>, <&tlmm 4 GPIO_ACTIVE_HIGH>; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <24000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "0:SBL1"; + reg = <0x00000000 0x00040000>; + read-only; + }; + + partition@40000 { + label = "0:MIBIB"; + reg = <0x00040000 0x00020000>; + read-only; + }; + + partition@60000 { + label = "0:QSEE"; + reg = <0x00060000 0x00060000>; + read-only; + }; + + partition@c0000 { + label = "0:CDT"; + reg = <0x000c0000 0x00010000>; + read-only; + }; + + partition@d0000 { + label = "0:DDRPARAMS"; + reg = <0x000d0000 0x00010000>; + read-only; + }; + + partition@e0000 { + label = "0:APPSBLENV"; /* uboot env */ + reg = <0x000e0000 0x00010000>; + }; + + partition@f0000 { + label = "0:APPSBL"; /* uboot */ + reg = <0x000f0000 0x00080000>; + read-only; + }; + + partition@170000 { + label = "0:ART"; + reg = <0x00170000 0x00010000>; + read-only; + }; + }; + }; + + flash@1 { + compatible = "spi-nand"; + reg = <1>; + spi-max-frequency = <24000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "rootfs"; + reg = <0x00000000 0x04000000>; + }; + + partition@1 { + label = "rootfs1"; + reg = <0x00000000 0x04000000>; + }; + + partition@4000000 { + label = "rootfs2"; + reg = <0x04000000 0x04000000>; + }; + }; + }; +}; + +&blsp1_i2c3 { + status = "okay"; + + pinctrl-0 = <&i2c0_pins>; + pinctrl-names = "default"; + + tpm@29 { + compatible = "atmel,at97sc3204t"; + reg = <0x29>; + }; +}; + +&blsp1_uart1 { + status = "okay"; + + pinctrl-0 = <&serial_pins>; + pinctrl-names = "default"; +}; + +&cryptobam { + status = "okay"; +}; + +&mdio { + status = "okay"; + + pinctrl-0 = <&mdio_pins>; + pinctrl-names = "default"; +}; + +&gmac0 { + qcom,poll_required = <1>; + qcom,phy_mdio_addr = <4>; + vlan_tag = <2 0x20>; +}; + +&gmac1 { + qcom,poll_required = <1>; + qcom,phy_mdio_addr = <3>; + vlan_tag = <1 0x10>; +}; + +&wifi0 { + status = "okay"; +}; + +&wifi1 { + status = "okay"; + + qcom,ath10k-calibration-variant = "ALFA-Network-AP120C-AC"; +}; + +&usb3_hs_phy { + status = "okay"; +}; + +&usb2_hs_phy { + status = "okay"; +}; diff --git a/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-emd1.dts b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-emd1.dts new file mode 100644 index 000000000..b40586713 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-emd1.dts @@ -0,0 +1,233 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "qcom-ipq4019.dtsi" +#include +#include +#include + +/ { + model = "EnGenius EMD1"; + compatible = "engenius,emd1"; + + aliases { + led-boot = &led_power; + led-failsafe = &led_power; + led-running = &led_power; + led-upgrade = &led_power; + }; + + soc { + rng@22000 { + status = "okay"; + }; + + mdio@90000 { + status = "okay"; + }; + + ess-psgmii@98000 { + status = "okay"; + }; + + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; + qcom,wifi_glb_cfg = ; + }; + + ess_tcsr@1953000 { + compatible = "qcom,tcsr"; + reg = <0x1953000 0x1000>; + qcom,ess-interface-select = ; + }; + + tcsr@1957000 { + compatible = "qcom,tcsr"; + reg = <0x1957000 0x100>; + qcom,wifi_noc_memtype_m0_m2 = ; + }; + + crypto@8e3a000 { + status = "okay"; + }; + + watchdog@b017000 { + status = "okay"; + }; + + ess-switch@c000000 { + status = "okay"; + switch_lan_bmp = <0x20>; + switch_wan_bmp = <0x00>; + }; + + edma@c080000 { + status = "okay"; + qcom,num_gmac = <1>; + }; + }; + + keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + gpios = <&tlmm 63 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + leds { + compatible = "gpio-leds"; + + led_power: power { + label = "white:power"; + gpios = <&tlmm 58 GPIO_ACTIVE_LOW>; + }; + + wlan2g { + label = "red:wlan2g"; + gpios = <&tlmm 2 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "phy0tpt"; + }; + + wlan5g { + label = "blue:wlan5g"; + gpios = <&tlmm 3 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "phy1tpt"; + }; + + mesh { + label = "orange:mesh"; + gpios = <&tlmm 0 GPIO_ACTIVE_HIGH>; + }; + }; +}; + +&tlmm { + serial_pins: serial_pinmux { + mux { + pins = "gpio60", "gpio61"; + function = "blsp_uart0"; + bias-disable; + }; + }; + + spi_0_pins: spi_0_pinmux { + pin { + function = "blsp_spi0"; + pins = "gpio54", "gpio55", "gpio56", "gpio57"; + drive-strength = <12>; + bias-disable; + }; + + pin_cs { + function = "gpio"; + pins = "gpio54"; + drive-strength = <2>; + bias-disable; + output-high; + }; + }; +}; + +&blsp_dma { + status = "okay"; +}; + +&blsp1_spi1 { + pinctrl-0 = <&spi_0_pins>; + pinctrl-names = "default"; + status = "okay"; + cs-gpios = <&tlmm 54 GPIO_ACTIVE_HIGH>; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <24000000>; + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition0@0 { + label = "0:SBL1"; + reg = <0x00000000 0x00040000>; + read-only; + }; + partition1@40000 { + label = "0:MIBIB"; + reg = <0x00040000 0x00020000>; + read-only; + }; + partition2@60000 { + label = "0:QSEE"; + reg = <0x00060000 0x00060000>; + read-only; + }; + partition3@c0000 { + label = "0:CDT"; + reg = <0x000c0000 0x00010000>; + read-only; + }; + partition4@d0000 { + label = "0:DDRPARAMS"; + reg = <0x000d0000 0x00010000>; + read-only; + }; + partition5@e0000 { + label = "0:APPSBLENV"; + reg = <0x000e0000 0x00010000>; + read-only; + }; + partition6@f0000 { + label = "0:APPSBL"; + reg = <0x000f0000 0x00080000>; + read-only; + }; + partition7@170000 { + label = "0:ART"; + reg = <0x00170000 0x00010000>; + read-only; + }; + partition8@180000 { + label = "userconfig"; + reg = <0x00180000 0x00080000>; + read-only; + }; + partition9@200000 { + compatible = "denx,fit"; + label = "firmware"; + reg = <0x200000 0x01e00000>; + }; + }; + }; +}; + +&blsp1_uart1 { + pinctrl-0 = <&serial_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + +&gmac0 { + qcom,phy_mdio_addr = <4>; + qcom,poll_required = <1>; + qcom,forced_speed = <1000>; + qcom,forced_duplex = <1>; + vlan_tag = <1 0x20>; +}; + +&cryptobam { + status = "okay"; +}; + +&wifi0 { + status = "okay"; + qcom,ath10k-calibration-variant = "EnGenius-EMD1"; +}; + +&wifi1 { + status = "okay"; + qcom,ath10k-calibration-variant = "EnGenius-EMD1"; +}; diff --git a/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-emr3500.dts b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-emr3500.dts new file mode 100644 index 000000000..848e5c236 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-emr3500.dts @@ -0,0 +1,235 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "qcom-ipq4019.dtsi" +#include +#include +#include + +/ { + model = "EnGenius EMR3500"; + compatible = "engenius,emr3500"; + + soc { + rng@22000 { + status = "okay"; + }; + + mdio@90000 { + status = "okay"; + }; + + ess-psgmii@98000 { + status = "okay"; + }; + + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; + qcom,wifi_glb_cfg = ; + }; + + ess_tcsr@1953000 { + compatible = "qcom,tcsr"; + reg = <0x1953000 0x1000>; + qcom,ess-interface-select = ; + }; + + tcsr@1957000 { + compatible = "qcom,tcsr"; + reg = <0x1957000 0x100>; + qcom,wifi_noc_memtype_m0_m2 = ; + }; + + usb2_hs_phy: hsphy@a8000 { + status = "okay"; + }; + + crypto@8e3a000 { + status = "okay"; + }; + + watchdog@b017000 { + status = "okay"; + }; + + ess-switch@c000000 { + status = "okay"; + }; + + edma@c080000 { + status = "okay"; + }; + }; + + keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + gpios = <&tlmm 59 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + aliases { + led-boot = &power; + led-failsafe = &power; + led-running = &power; + led-upgrade = &power; + }; + + leds { + compatible = "gpio-leds"; + + power: white { + label = "white:power"; + gpios = <&tlmm 4 GPIO_ACTIVE_HIGH>; + }; + + blue { + label = "blue"; + gpios = <&tlmm 2 GPIO_ACTIVE_HIGH>; + }; + + red { + label = "red"; + gpios = <&tlmm 0 GPIO_ACTIVE_HIGH>; + }; + + orange { + label = "orange"; + gpios = <&tlmm 1 GPIO_ACTIVE_HIGH>; + }; + }; +}; + +&tlmm { + serial_pins: serial_pinmux { + mux { + pins = "gpio60", "gpio61"; + function = "blsp_uart0"; + bias-disable; + }; + }; + + spi_0_pins: spi_0_pinmux { + pin { + function = "blsp_spi0"; + pins = "gpio54", "gpio55", "gpio56", "gpio57"; + drive-strength = <12>; + bias-disable; + }; + pin_cs { + function = "gpio"; + pins = "gpio54"; + drive-strength = <2>; + bias-disable; + output-high; + }; + }; +}; + +&blsp_dma { + status = "okay"; +}; + +&blsp1_spi1 { + pinctrl-0 = <&spi_0_pins>; + pinctrl-names = "default"; + status = "okay"; + cs-gpios = <&tlmm 54 GPIO_ACTIVE_HIGH>; + + m25p80@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <24000000>; + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "0:SBL1"; + reg = <0x00000000 0x00040000>; + read-only; + }; + partition@40000 { + label = "0:MIBIB"; + reg = <0x00040000 0x00020000>; + read-only; + }; + partition@60000 { + label = "0:QSEE"; + reg = <0x00060000 0x00060000>; + read-only; + }; + partition@c0000 { + label = "0:CDT"; + reg = <0x000c0000 0x00010000>; + read-only; + }; + partition@d0000 { + label = "0:DDRPARAMS"; + reg = <0x000d0000 0x00010000>; + read-only; + }; + partition@e0000 { + label = "0:APPSBLENV"; + reg = <0x000e0000 0x00010000>; + read-only; + }; + partition@f0000 { + label = "0:APPSBL"; + reg = <0x000f0000 0x00080000>; + read-only; + }; + partition@170000 { + label = "0:ART"; + reg = <0x00170000 0x00010000>; + read-only; + }; + partition@180000 { + label = "userconfig"; + reg = <0x00180000 0x00080000>; + read-only; + }; + partition@200000 { + compatible = "denx,fit"; + label = "firmware"; + reg = <0x200000 0x1e00000>; + }; + }; + }; +}; + +&blsp1_uart1 { + pinctrl-0 = <&serial_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + +&cryptobam { + status = "okay"; +}; + +&gmac0 { + vlan_tag = <1 0x10>; +}; + +&gmac1 { + vlan_tag = <2 0x20>; +}; + +&usb2_hs_phy { + status = "okay"; +}; + +&wifi0 { + status = "okay"; + qcom,ath10k-calibration-variant = "EnGenius-EMR3500"; +}; + +&wifi1 { + status = "okay"; + qcom,ath10k-calibration-variant = "EnGenius-EMR3500"; +}; diff --git a/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-ens620ext.dts b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-ens620ext.dts new file mode 100644 index 000000000..b765d68b5 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-ens620ext.dts @@ -0,0 +1,265 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "qcom-ipq4019.dtsi" +#include +#include +#include + +/ { + model = "EnGenius ENS620EXT"; + compatible = "engenius,ens620ext"; + + memory { + device_type = "memory"; + reg = <0x80000000 0x10000000>; + }; + + aliases { + led-boot = &power; + led-failsafe = &power; + led-running = &power; + led-upgrade = &power; + }; + + soc { + rng@22000 { + status = "okay"; + }; + + mdio@90000 { + status = "okay"; + }; + + ess-psgmii@98000 { + status = "okay"; + }; + + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; + qcom,wifi_glb_cfg = ; + }; + + ess_tcsr@1953000 { + compatible = "qcom,tcsr"; + reg = <0x1953000 0x1000>; + qcom,ess-interface-select = ; + }; + + tcsr@1957000 { + compatible = "qcom,tcsr"; + reg = <0x1957000 0x100>; + qcom,wifi_noc_memtype_m0_m2 = ; + }; + + crypto@8e3a000 { + status = "okay"; + }; + + watchdog@b017000 { + status = "okay"; + }; + + ess-switch@c000000 { + status = "okay"; + }; + + edma@c080000 { + status = "okay"; + }; + + /* + * Disable the broken restart as a workaround for the buggy + * 3.0.0/3.0.1 U-boots that ship with the device. + * Note: The watchdog is now used to restart this device. + */ + restart@4ab000 { + status = "disabled"; + }; + }; + + buttons { + compatible = "gpio-keys"; + + wps { + label = "wps"; + gpios = <&tlmm 63 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + leds { + compatible = "gpio-leds"; + + power: power { + label = "amber:power"; + gpios = <&tlmm 58 GPIO_ACTIVE_LOW>; + }; + + lan1 { + label = "green:lan1"; + gpios = <&tlmm 1 GPIO_ACTIVE_LOW>; + }; + + lan2 { + label = "green:lan2"; + gpios = <&tlmm 2 GPIO_ACTIVE_LOW>; + }; + + wlan2g { + label = "green:wlan2g"; + gpios = <&tlmm 3 GPIO_ACTIVE_HIGH>; + }; + + wlan5g { + label = "green:wlan5g"; + gpios = <&tlmm 0 GPIO_ACTIVE_LOW>; + }; + }; +}; + +&cryptobam { + status = "okay"; +}; + +&blsp_dma { + status = "okay"; +}; + +&tlmm { + serial_pins: serial_pinmux { + mux { + pins = "gpio60", "gpio61"; + function = "blsp_uart0"; + bias-disable; + }; + }; + + spi_0_pins: spi_0_pinmux { + mux { + function = "blsp_spi0"; + pins = "gpio55", "gpio56", "gpio57"; + drive-strength = <12>; + bias-disable; + }; + + mux_cs { + function = "gpio"; + pins = "gpio54"; + drive-strength = <2>; + bias-disable; + output-high; + }; + }; +}; + +&blsp1_spi1 { /* BLSP1 QUP1 */ + pinctrl-0 = <&spi_0_pins>; + pinctrl-names = "default"; + status = "okay"; + cs-gpios = <&tlmm 54 GPIO_ACTIVE_HIGH>; + + flash@0 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <50000000>; + m25p,fast-read; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "SBL1"; + reg = <0x00000000 0x00040000>; + read-only; + }; + partition@40000 { + label = "MIBIB"; + reg = <0x00040000 0x00020000>; + read-only; + }; + partition@60000 { + label = "QSEE"; + reg = <0x00060000 0x00060000>; + read-only; + }; + partition@c0000 { + label = "CDT"; + reg = <0x000c0000 0x00010000>; + read-only; + }; + partition@d0000 { + label = "DDRPARAMS"; + reg = <0x000d0000 0x00010000>; + read-only; + }; + partition@e0000 { + label = "APPSBLENV"; /* uboot env*/ + reg = <0x000e0000 0x00010000>; + read-only; + }; + partition@f0000 { + label = "APPSBL"; /* uboot */ + reg = <0x000f0000 0x00090000>; + read-only; + }; + partition@180000 { + label = "ART"; + reg = <0x00180000 0x00010000>; + read-only; + }; + partition@190000 { + compatible = "denx,fit"; + label = "firmware"; + reg = <0x00190000 0x14d0000>; + }; + partition@1660000 { + label = "failsafe"; + reg = <0x01660000 0x008F0000>; + read-only; + }; + partition@1f50000 { + label = "u-boot-env"; + reg = <0x01f50000 0x00010000>; + read-only; + }; + partition@1f60000 { + label = "userconfig"; + reg = <0x01f60000 0x000a0000>; + read-only; + }; + }; + }; +}; + +&blsp1_uart1 { + pinctrl-0 = <&serial_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + +&usb3_ss_phy { + status = "okay"; +}; + +&usb3_hs_phy { + status = "okay"; +}; + +&usb2_hs_phy { + status = "okay"; +}; + +&wifi0 { + status = "okay"; + qcom,ath10k-calibration-variant = "EnGenius-ENS620EXT"; +}; + +&wifi1 { + status = "okay"; + qcom,ath10k-calibration-variant = "EnGenius-ENS620EXT"; +}; diff --git a/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-ex6100v2.dts b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-ex6100v2.dts new file mode 100644 index 000000000..1495c64da --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-ex6100v2.dts @@ -0,0 +1,31 @@ +/* Copyright (c) 2015, The Linux Foundation. All rights reserved. + * Copyright (c) 2018, David Bauer + * + * 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 "qcom-ipq4018-ex61x0v2.dtsi" + +/ { + model = "Netgear EX6100v2"; + compatible = "netgear,ex6100v2"; +}; + +&wifi0 { + qcom,ath10k-calibration-variant = "Netgear-EX6100v2"; +}; + +&wifi1 { + qcom,ath10k-calibration-variant = "Netgear-EX6100v2"; +}; diff --git a/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-ex6150v2.dts b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-ex6150v2.dts new file mode 100644 index 000000000..ce24466e5 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-ex6150v2.dts @@ -0,0 +1,31 @@ +/* Copyright (c) 2015, The Linux Foundation. All rights reserved. + * Copyright (c) 2018, David Bauer + * + * 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 "qcom-ipq4018-ex61x0v2.dtsi" + +/ { + model = "Netgear EX6150v2"; + compatible = "netgear,ex6150v2"; +}; + +&wifi0 { + qcom,ath10k-calibration-variant = "Netgear-EX6150v2"; +}; + +&wifi1 { + qcom,ath10k-calibration-variant = "Netgear-EX6150v2"; +}; diff --git a/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-ex61x0v2.dtsi b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-ex61x0v2.dtsi new file mode 100644 index 000000000..c026f70d0 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-ex61x0v2.dtsi @@ -0,0 +1,312 @@ +/* Copyright (c) 2015, The Linux Foundation. All rights reserved. + * Copyright (c) 2018, David Bauer + * + * 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 "qcom-ipq4019.dtsi" +#include +#include +#include + +/ { + model = "Netgear EX61X0v2"; + compatible = "netgear,ex61x0v2"; + + soc { + rng@22000 { + status = "okay"; + }; + + mdio@90000 { + status = "okay"; + }; + + ess-psgmii@98000 { + status = "okay"; + }; + + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; + qcom,wifi_glb_cfg = ; + }; + + ess_tcsr@1953000 { + compatible = "qcom,tcsr"; + reg = <0x1953000 0x1000>; + qcom,ess-interface-select = ; + }; + + tcsr@1957000 { + compatible = "qcom,tcsr"; + reg = <0x1957000 0x100>; + qcom,wifi_noc_memtype_m0_m2 = ; + }; + + crypto@8e3a000 { + status = "okay"; + }; + + watchdog@b017000 { + status = "okay"; + }; + + ess-switch@c000000 { + status = "okay"; + }; + + edma@c080000 { + status = "okay"; + qcom,num_gmac = <1>; + }; + }; + + aliases { + led-boot = &power_amber; + led-failsafe = &power_amber; + led-running = &power_green; + led-upgrade = &power_amber; + label-mac-device = &gmac0; + }; + + keys { + compatible = "gpio-keys"; + + wps { + label = "wps"; + gpios = <&tlmm 0 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + + reset { + label = "reset"; + gpios = <&tlmm 63 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + led_spi { + compatible = "spi-gpio"; + #address-cells = <1>; + #size-cells = <0>; + + sck-gpios = <&tlmm 5 GPIO_ACTIVE_HIGH>; + mosi-gpios = <&tlmm 4 GPIO_ACTIVE_HIGH>; + num-chipselects = <0>; + + led_gpio: led_gpio@0 { + compatible = "fairchild,74hc595"; + reg = <0>; + gpio-controller; + #gpio-cells = <2>; + registers-number = <1>; + spi-max-frequency = <1000000>; + }; + }; + + leds { + compatible = "gpio-leds"; + + power_amber: power_amber { + label = "amber:power"; + gpios = <&led_gpio 7 GPIO_ACTIVE_LOW>; + }; + + power_green: power_green { + label = "green:power"; + gpios = <&led_gpio 6 GPIO_ACTIVE_LOW>; + }; + + right { + label = "blue:right"; + gpios = <&led_gpio 5 GPIO_ACTIVE_LOW>; + }; + + left { + label = "blue:left"; + gpios = <&led_gpio 4 GPIO_ACTIVE_LOW>; + }; + + client_green { + label = "green:client"; + gpios = <&led_gpio 3 GPIO_ACTIVE_LOW>; + }; + + client_red { + label = "red:client"; + gpios = <&led_gpio 2 GPIO_ACTIVE_LOW>; + }; + + router_green { + label = "green:router"; + gpios = <&led_gpio 1 GPIO_ACTIVE_LOW>; + }; + + router_red { + label = "red:router"; + gpios = <&led_gpio 0 GPIO_ACTIVE_LOW>; + }; + + wps { + label = "green:wps"; + gpios = <&tlmm 1 GPIO_ACTIVE_LOW>; + }; + }; +}; + +&tlmm { + serial_pins: serial_pinmux { + mux { + pins = "gpio60", "gpio61"; + function = "blsp_uart0"; + bias-disable; + }; + }; + + spi_0_pins: spi_0_pinmux { + pin { + function = "blsp_spi0"; + pins = "gpio55", "gpio56", "gpio57"; + drive-strength = <12>; + bias-disable; + }; + pin_cs { + function = "gpio"; + pins = "gpio54"; + drive-strength = <2>; + bias-disable; + output-high; + }; + }; +}; + +&blsp1_spi1 { + pinctrl-0 = <&spi_0_pins>; + pinctrl-names = "default"; + status = "okay"; + cs-gpios = <&tlmm 54 GPIO_ACTIVE_HIGH>; + + mx25l12805d@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <24000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition0@0 { + label = "SBL1"; + reg = <0x00000000 0x00040000>; + read-only; + }; + + partition1@40000 { + label = "MIBIB"; + reg = <0x00040000 0x00020000>; + read-only; + }; + + partition2@60000 { + label = "QSEE"; + reg = <0x00060000 0x00060000>; + read-only; + }; + + partition3@c0000 { + label = "CDT"; + reg = <0x000c0000 0x00010000>; + read-only; + }; + + partition4@d0000 { + label = "DDRPARAMS"; + reg = <0x000d0000 0x00010000>; + read-only; + }; + + partition5@E0000 { + label = "APPSBLENV"; + reg = <0x000e0000 0x00010000>; + read-only; + }; + + partition6@F0000 { + label = "APPSBL"; + reg = <0x000f0000 0x00080000>; + read-only; + }; + + partition7@170000 { + label = "ART"; + reg = <0x00170000 0x00010000>; + read-only; + }; + + partition8@180000 { + label = "config"; + reg = <0x00180000 0x00010000>; + read-only; + }; + + partition9@190000 { + label = "pot"; + reg = <0x00190000 0x00010000>; + read-only; + }; + + partition10@1a0000 { + label = "dnidata"; + reg = <0x001a0000 0x00010000>; + read-only; + }; + + partition11@1b0000 { + compatible = "denx,fit"; + label = "firmware"; + reg = <0x001b0000 0x00e10000>; + }; + + partition12@fc0000 { + label = "language"; + reg = <0x00fc0000 0x00040000>; + read-only; + }; + }; + }; +}; + +&blsp1_uart1 { + pinctrl-0 = <&serial_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + +&blsp_dma { + status = "okay"; +}; + +&cryptobam { + status = "okay"; +}; + +&wifi0 { + status = "okay"; +}; + +&wifi1 { + status = "okay"; +}; diff --git a/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-fritzbox-4040.dts b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-fritzbox-4040.dts new file mode 100644 index 000000000..77b1810f0 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-fritzbox-4040.dts @@ -0,0 +1,309 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "qcom-ipq4019.dtsi" +#include +#include +#include + +/ { + model = "AVM FRITZ!Box 4040"; + compatible = "avm,fritzbox-4040"; + + aliases { + led-boot = &power; + led-failsafe = &flash; + led-running = &power; + led-upgrade = &flash; + label-mac-device = &gmac0; + }; + + soc { + rng@22000 { + status = "okay"; + }; + + mdio@90000 { + status = "okay"; + }; + + ess-psgmii@98000 { + status = "okay"; + }; + + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; + qcom,wifi_glb_cfg = ; + }; + + tcsr@194b000 { + compatible = "qcom,tcsr"; + reg = <0x194b000 0x100>; + qcom,usb-hsphy-mode-select = ; + }; + + ess_tcsr@1953000 { + compatible = "qcom,tcsr"; + reg = <0x1953000 0x1000>; + qcom,ess-interface-select = ; + }; + + tcsr@1957000 { + compatible = "qcom,tcsr"; + reg = <0x1957000 0x100>; + qcom,wifi_noc_memtype_m0_m2 = ; + }; + + usb2@60f8800 { + status = "okay"; + }; + + usb3@8af8800 { + status = "okay"; + }; + + crypto@8e3a000 { + status = "okay"; + }; + + watchdog@b017000 { + status = "okay"; + }; + + ess-switch@c000000 { + status = "okay"; + }; + + edma@c080000 { + status = "okay"; + }; + }; + + keys { + compatible = "gpio-keys"; + + wlan { + label = "wlan"; + gpios = <&tlmm 58 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + + wps { + label = "wps"; + gpios = <&tlmm 63 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + switch-leds { + compatible = "gpio-leds"; + + wlan { + label = "green:wlan"; + gpios = <ðphy0 0 GPIO_ACTIVE_HIGH>; + }; + + panic: info_red { + label = "red:info"; + gpios = <ðphy0 1 GPIO_ACTIVE_HIGH>; + panic-indicator; + }; + + wan { + label = "green:wan"; + gpios = <ðphy1 0 GPIO_ACTIVE_HIGH>; + }; + + power: power { + label = "green:power"; + gpios = <ðphy2 1 GPIO_ACTIVE_HIGH>; + }; + + lan { + label = "green:lan"; + gpios = <ðphy3 0 GPIO_ACTIVE_HIGH>; + }; + + flash: info_amber { + label = "amber:info"; + gpios = <ðphy3 1 GPIO_ACTIVE_HIGH>; + }; + }; +}; + +&tlmm { + serial_pins: serial_pinmux { + mux { + pins = "gpio60", "gpio61"; + function = "blsp_uart0"; + bias-disable; + }; + }; + + spi_0_pins: spi_0_pinmux { + mux { + function = "blsp_spi0"; + pins = "gpio55", "gpio56", "gpio57"; + drive-strength = <12>; + bias-disable; + }; + + mux_cs { + function = "gpio"; + pins = "gpio54"; + drive-strength = <2>; + bias-disable; + output-high; + }; + }; +}; + +&cryptobam { + status = "okay"; +}; + +&blsp_dma { + status = "okay"; +}; + +&blsp1_spi1 { /* BLSP1 QUP1 */ + pinctrl-0 = <&spi_0_pins>; + pinctrl-names = "default"; + status = "okay"; + cs-gpios = <&tlmm 54 GPIO_ACTIVE_HIGH>; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <24000000>; + status = "okay"; + m25p,fast-read; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition0@0 { + label = "SBL1"; + reg = <0x00000000 0x00040000>; + read-only; + }; + partition1@40000 { + label = "MIBIB"; + reg = <0x00040000 0x00020000>; + read-only; + }; + partition2@60000 { + label = "QSEE"; + reg = <0x00060000 0x00060000>; + read-only; + }; + partition3@c0000 { + label = "CDT"; + reg = <0x000c0000 0x00010000>; + read-only; + }; + partition4@d0000 { + label = "DDRPARAMS"; + reg = <0x000d0000 0x00010000>; + read-only; + }; + partition5@e0000 { + label = "APPSBLENV"; /* uboot env - empty */ + reg = <0x000e0000 0x00010000>; + read-only; + }; + partition6@f0000 { + label = "urlader"; /* APPSBL */ + reg = <0x000f0000 0x0002dc000>; + read-only; + }; + partition7@11dc00 { + /* make a backup of this partition! */ + label = "urlader_config"; + reg = <0x0011dc00 0x00002400>; + read-only; + }; + partition8@120000 { + label = "tffs1"; + reg = <0x00120000 0x00080000>; + read-only; + }; + partition9@1a0000 { + label = "tffs2"; + reg = <0x001a0000 0x00080000>; + read-only; + }; + partition10@220000 { + label = "uboot"; + reg = <0x00220000 0x00080000>; + read-only; + }; + partition11@2A0000 { + compatible = "denx,fit"; + label = "firmware"; + reg = <0x002a0000 0x01c60000>; + }; + partition12@1f00000 { + label = "jffs2"; + reg = <0x01f00000 0x00100000>; + }; + }; + }; +}; + +&blsp1_uart1 { + pinctrl-0 = <&serial_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + +ðphy0 { + gpio-controller; + #gpio-cells = <2>; +}; + +ðphy1 { + gpio-controller; + #gpio-cells = <2>; + + enable-usb-power { + gpio-hog; + line-name = "enable USB3 power"; + gpios = <1 GPIO_ACTIVE_HIGH>; + output-high; + }; +}; + +ðphy2 { + gpio-controller; + #gpio-cells = <2>; +}; + +ðphy3 { + gpio-controller; + #gpio-cells = <2>; +}; + +&usb3_ss_phy { + status = "okay"; +}; + +&usb3_hs_phy { + status = "okay"; +}; + +&usb2_hs_phy { + status = "okay"; +}; + +&wifi0 { + status = "okay"; + qcom,ath10k-calibration-variant = "AVM-FRITZBox-4040"; +}; + +&wifi1 { + status = "okay"; + qcom,ath10k-calibration-variant = "AVM-FRITZBox-4040"; +}; diff --git a/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-gl-ap1300.dts b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-gl-ap1300.dts new file mode 100644 index 000000000..3fd5406d3 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-gl-ap1300.dts @@ -0,0 +1,269 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "qcom-ipq4019.dtsi" +#include +#include +#include + +/ { + model = "GL.iNet GL-AP1300"; + compatible = "glinet,gl-ap1300"; + + aliases { + led-boot = &led_power; + led-failsafe = &led_power; + led-running = &led_power; + led-upgrade = &led_power; + }; + + memory { + device_type = "memory"; + reg = <0x80000000 0x10000000>; + }; + + chosen { + bootargs-append = " ubi.mtd=ubi root=/dev/ubiblock0_1 clk_ignore_unused"; + }; + + soc { + rng@22000 { + status = "okay"; + }; + + mdio@90000 { + status = "okay"; + }; + + ess-psgmii@98000 { + status = "okay"; + }; + + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; + qcom,wifi_glb_cfg = ; + }; + + tcsr@194b000 { + /* select hostmode */ + compatible = "qcom,tcsr"; + reg = <0x194b000 0x100>; + qcom,usb-hsphy-mode-select = ; + status = "okay"; + }; + + ess_tcsr@1953000 { + compatible = "qcom,tcsr"; + reg = <0x1953000 0x1000>; + qcom,ess-interface-select = ; + }; + + tcsr@1957000 { + compatible = "qcom,tcsr"; + reg = <0x1957000 0x100>; + qcom,wifi_noc_memtype_m0_m2 = ; + }; + + usb2@60f8800 { + status = "okay"; + }; + + usb3@8af8800 { + status = "okay"; + }; + + crypto@8e3a000 { + status = "okay"; + }; + + watchdog@b017000 { + status = "okay"; + }; + + ess-switch@c000000 { + status = "okay"; + switch_lan_bmp = <0x18>; + switch_wan_bmp = <0x20>; + }; + + edma@c080000 { + status = "okay"; + }; + }; + + keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + gpios = <&tlmm 63 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + leds { + compatible = "gpio-leds"; + + led_power: power { + label = "green:power"; + gpios = <&tlmm 2 GPIO_ACTIVE_HIGH>; + default-state = "on"; + }; + + wan { + label = "green:wan"; + gpios = <&tlmm 3 GPIO_ACTIVE_HIGH>; + }; + }; +}; + +&blsp_dma { + status = "okay"; +}; + +&cryptobam { + status = "okay"; +}; + +&blsp1_spi1 { + status = "okay"; + + pinctrl-0 = <&spi0_pins>; + pinctrl-names = "default"; + cs-gpios = <&tlmm 54 GPIO_ACTIVE_HIGH>, <&tlmm 5 GPIO_ACTIVE_HIGH>; + + flash@0 { + status = "okay"; + + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <24000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "SBL1"; + reg = <0x00000000 0x00040000>; + read-only; + }; + + partition@40000 { + label = "MIBIB"; + reg = <0x00040000 0x00020000>; + read-only; + }; + + partition@60000 { + label = "QSEE"; + reg = <0x00060000 0x00060000>; + read-only; + }; + + partition@c0000 { + label = "CDT"; + reg = <0x000c0000 0x00010000>; + read-only; + }; + + partition@d0000 { + label = "DDRPARAMS"; + reg = <0x000d0000 0x00010000>; + read-only; + }; + + partition@e0000 { + label = "APPSBLENV"; /* uboot env*/ + reg = <0x000e0000 0x00010000>; + }; + + partition@f0000 { + label = "APPSBL"; /* uboot */ + reg = <0x000f0000 0x00080000>; + read-only; + }; + + partition@170000 { + label = "ART"; + reg = <0x00170000 0x00010000>; + read-only; + }; + }; + }; + + spi-nand@1 { + status = "okay"; + + compatible = "spi-nand"; + reg = <1>; + spi-max-frequency = <24000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "ubi"; + reg = <0x00000000 0x08000000>; + }; + }; + }; +}; + +&blsp1_uart1 { + pinctrl-0 = <&serial_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + +&tlmm { + serial_pins: serial_pinmux { + mux { + pins = "gpio60", "gpio61"; + function = "blsp_uart0"; + bias-disable; + }; + }; + + spi0_pins: spi0_pinmux { + mux_spi { + function = "blsp_spi0"; + pins = "gpio55", "gpio56", "gpio57"; + drive-strength = <12>; + bias-disable; + }; + + mux_cs { + function = "gpio"; + pins = "gpio54", "gpio5"; + drive-strength = <2>; + bias-disable; + output-high; + }; + }; +}; + +&usb2_hs_phy { + status = "okay"; +}; + +&usb3_hs_phy { + status = "okay"; +}; + +&usb3_ss_phy { + status = "okay"; +}; + +&wifi0 { + status = "okay"; + qcom,ath10k-calibration-variant = "GL-AP1300"; +}; + +&wifi1 { + status = "okay"; + qcom,ath10k-calibration-variant = "GL-AP1300"; +}; diff --git a/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-hap-ac2.dts b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-hap-ac2.dts new file mode 100644 index 000000000..d03409b55 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-hap-ac2.dts @@ -0,0 +1,273 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT +/* Copyright (c) 2020, Robert Marko */ + +#include "qcom-ipq4019.dtsi" +#include +#include +#include + +/ { + model = "MikroTik hAP ac2"; + compatible = "mikrotik,hap-ac2"; + + memory { + device_type = "memory"; + reg = <0x80000000 0x08000000>; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + aliases { + led-boot = &led_user; + led-failsafe = &led_user; + led-running = &led_user; + led-upgrade = &led_user; + }; + + soc { + rng@22000 { + status = "okay"; + }; + + counter@4a1000 { + compatible = "qcom,qca-gcnt"; + reg = <0x4a1000 0x4>; + }; + + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; + qcom,wifi_glb_cfg = ; + }; + + tcsr@194b000 { + /* select hostmode */ + compatible = "qcom,tcsr"; + reg = <0x194b000 0x100>; + qcom,usb-hsphy-mode-select = ; + status = "okay"; + }; + + ess_tcsr@1953000 { + compatible = "qcom,tcsr"; + reg = <0x1953000 0x1000>; + qcom,ess-interface-select = ; + }; + + tcsr@1957000 { + compatible = "qcom,tcsr"; + reg = <0x1957000 0x100>; + qcom,wifi_noc_memtype_m0_m2 = ; + }; + + usb3@8af8800 { + status = "okay"; + + dwc3@8a00000 { + phys = <&usb3_hs_phy>; + phy-names = "usb2-phy"; + }; + }; + + crypto@8e3a000 { + status = "okay"; + }; + + watchdog@b017000 { + status = "okay"; + }; + + ess-switch@c000000 { + status = "okay"; + }; + + edma@c080000 { + status = "okay"; + }; + }; + + keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + gpios = <&tlmm 63 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + + mode { + label = "mode"; + gpios = <&tlmm 5 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + leds { + compatible = "gpio-leds"; + + power { + label = "green:power"; + gpios = <&tlmm 0 GPIO_ACTIVE_HIGH>; + default-state = "keep"; + panic-indicator; + }; + + led_user: user { + label = "green:user"; + gpios = <&tlmm 3 GPIO_ACTIVE_HIGH>; + }; + }; +}; + +&tlmm { + serial_pins: serial_pinmux { + mux { + pins = "gpio60", "gpio61"; + function = "blsp_uart0"; + bias-disable; + }; + }; + + spi_0_pins: spi_0_pinmux { + pin { + function = "blsp_spi0"; + pins = "gpio55", "gpio56", "gpio57"; + drive-strength = <2>; + bias-disable; + }; + pin_cs { + function = "gpio"; + pins = "gpio54"; + drive-strength = <2>; + bias-disable; + output-high; + }; + }; + + enable-usb-power { + gpio-hog; + gpios = <2 GPIO_ACTIVE_HIGH>; + output-high; + line-name = "enable USB power"; + }; +}; + +&blsp_dma { + status = "okay"; +}; + +&blsp1_spi1 { + status = "okay"; + + pinctrl-0 = <&spi_0_pins>; + pinctrl-names = "default"; + cs-gpios = <&tlmm 54 GPIO_ACTIVE_HIGH>; + + flash@0 { + reg = <0>; + compatible = "jedec,spi-nor"; + spi-max-frequency = <40000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "Qualcomm"; + reg = <0x0 0x80000>; + read-only; + }; + + partition@80000 { + compatible = "mikrotik,routerboot-partitions"; + #address-cells = <1>; + #size-cells = <1>; + label = "RouterBoot"; + reg = <0x80000 0x80000>; + read-only; + + hard_config { + read-only; + size = <0x2000>; + }; + + dtb_config { + read-only; + }; + + soft_config { + }; + }; + + partition@100000 { + compatible = "mikrotik,minor"; + label = "firmware"; + reg = <0x100000 0xf00000>; + }; + }; + }; +}; + +&blsp1_uart1 { + status = "okay"; + + pinctrl-0 = <&serial_pins>; + pinctrl-names = "default"; +}; + +&cryptobam { + status = "okay"; +}; + +&usb3_hs_phy { + status = "okay"; +}; + +&mdio { + status = "okay"; +}; + +ðphy0 { + qcom,single-led-1000; + qcom,single-led-100; + qcom,single-led-10; +}; + +ðphy1 { + qcom,single-led-1000; + qcom,single-led-100; + qcom,single-led-10; +}; + +ðphy2 { + qcom,single-led-1000; + qcom,single-led-100; + qcom,single-led-10; +}; + +ðphy3 { + qcom,single-led-1000; + qcom,single-led-100; + qcom,single-led-10; +}; + +ðphy4 { + qcom,single-led-1000; + qcom,single-led-100; + qcom,single-led-10; +}; + +&wifi0 { + status = "okay"; + + qcom,ath10k-calibration-variant = "MikroTik-hAP-ac2"; +}; + +&wifi1 { + status = "okay"; + + qcom,ath10k-calibration-variant = "MikroTik-hAP-ac2"; +}; diff --git a/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-jalapeno.dts b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-jalapeno.dts new file mode 100644 index 000000000..988b86b68 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-jalapeno.dts @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT +// Copyright (c) 2018, Robert Marko + +#include "qcom-ipq4018-jalapeno.dtsi" + +/ { + model = "8devices Jalapeno"; + compatible = "8dev,jalapeno"; +}; diff --git a/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-jalapeno.dtsi b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-jalapeno.dtsi new file mode 100644 index 000000000..3af6de1f6 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-jalapeno.dtsi @@ -0,0 +1,269 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT +// Copyright (c) 2018, Robert Marko + +#include "qcom-ipq4019.dtsi" +#include +#include +#include + +/ { + soc { + rng@22000 { + status = "okay"; + }; + + mdio@90000 { + status = "okay"; + + pinctrl-0 = <&mdio_pins>; + pinctrl-names = "default"; + }; + + ess-psgmii@98000 { + status = "okay"; + }; + + counter@4a1000 { + compatible = "qcom,qca-gcnt"; + reg = <0x4a1000 0x4>; + }; + + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; + qcom,wifi_glb_cfg = ; + }; + + tcsr@194b000 { + status = "okay"; + + compatible = "qcom,tcsr"; + reg = <0x194b000 0x100>; + qcom,usb-hsphy-mode-select = ; + }; + + ess_tcsr@1953000 { + compatible = "qcom,tcsr"; + reg = <0x1953000 0x1000>; + qcom,ess-interface-select = ; + }; + + tcsr@1957000 { + compatible = "qcom,tcsr"; + reg = <0x1957000 0x100>; + qcom,wifi_noc_memtype_m0_m2 = ; + }; + + usb2: usb2@60f8800 { + status = "okay"; + }; + + usb3: usb3@8af8800 { + status = "okay"; + }; + + crypto@8e3a000 { + status = "okay"; + }; + + watchdog@b017000 { + status = "okay"; + }; + + ess-switch@c000000 { + status = "okay"; + + switch_lan_bmp = <0x10>; /* lan port bitmap */ + }; + + edma@c080000 { + status = "okay"; + }; + }; +}; + +&tlmm { + mdio_pins: mdio_pinmux { + pinmux_1 { + pins = "gpio53"; + function = "mdio"; + }; + + pinmux_2 { + pins = "gpio52"; + function = "mdc"; + }; + + pinconf { + pins = "gpio52", "gpio53"; + bias-pull-up; + }; + }; + + serial_pins: serial_pinmux { + mux { + pins = "gpio60", "gpio61"; + function = "blsp_uart0"; + bias-disable; + }; + }; + + spi_0_pins: spi_0_pinmux { + pin { + function = "blsp_spi0"; + pins = "gpio55", "gpio56", "gpio57"; + drive-strength = <2>; + bias-disable; + }; + + pin_cs { + function = "gpio"; + pins = "gpio54", "gpio59"; + drive-strength = <2>; + bias-disable; + output-high; + }; + }; +}; + +&blsp_dma { + status = "okay"; +}; + +&blsp1_spi1 { + status = "okay"; + + pinctrl-0 = <&spi_0_pins>; + pinctrl-names = "default"; + cs-gpios = <&tlmm 54 GPIO_ACTIVE_HIGH>, <&tlmm 59 GPIO_ACTIVE_HIGH>; + + flash@0 { + status = "okay"; + + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <24000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "SBL1"; + reg = <0x00000000 0x00040000>; + read-only; + }; + + partition@40000 { + label = "MIBIB"; + reg = <0x00040000 0x00020000>; + read-only; + }; + + partition@60000 { + label = "QSEE"; + reg = <0x00060000 0x00060000>; + read-only; + }; + + partition@c0000 { + label = "CDT"; + reg = <0x000c0000 0x00010000>; + read-only; + }; + + partition@d0000 { + label = "DDRPARAMS"; + reg = <0x000d0000 0x00010000>; + read-only; + }; + + partition@e0000 { + label = "APPSBLENV"; /* uboot env*/ + reg = <0x000e0000 0x00010000>; + read-only; + }; + + partition@f0000 { + label = "APPSBL"; /* uboot */ + reg = <0x000f0000 0x00080000>; + read-only; + }; + + partition@170000 { + label = "ART"; + reg = <0x00170000 0x00010000>; + read-only; + }; + }; + }; + + spi-nand@1 { + status = "okay"; + + compatible = "spi-nand"; + reg = <1>; + spi-max-frequency = <24000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "ubi"; + reg = <0x00000000 0x08000000>; + }; + }; + }; +}; + +&blsp1_uart1 { + status = "okay"; + + pinctrl-0 = <&serial_pins>; + pinctrl-names = "default"; +}; + +&cryptobam { + status = "okay"; +}; + +&gmac0 { + qcom,poll_required = <1>; + qcom,poll_required_dynamic = <1>; + qcom,phy_mdio_addr = <3>; + vlan_tag = <1 0x10>; +}; + +&gmac1 { + qcom,poll_required = <1>; + qcom,poll_required_dynamic = <1>; + qcom,phy_mdio_addr = <4>; + vlan_tag = <2 0x20>; +}; + +&wifi0 { + status = "okay"; + + qcom,ath10k-calibration-variant = "8devices-Jalapeno"; +}; + +&wifi1 { + status = "okay"; + + qcom,ath10k-calibration-variant = "8devices-Jalapeno"; +}; + +&usb3_ss_phy { + status = "okay"; +}; + +&usb3_hs_phy { + status = "okay"; +}; + +&usb2_hs_phy { + status = "okay"; +}; diff --git a/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-magic-2-wifi-next.dts b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-magic-2-wifi-next.dts new file mode 100644 index 000000000..2709aef50 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-magic-2-wifi-next.dts @@ -0,0 +1,268 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "qcom-ipq4019.dtsi" +#include +#include + +/ { + model = "devolo Magic 2 WiFi next"; + compatible = "devolo,magic-2-wifi-next"; + + memory { + device_type = "memory"; + reg = <0x80000000 0x10000000>; + }; + + soc { + rng@22000 { + status = "okay"; + }; + + mdio@90000 { + status = "okay"; + pinctrl-0 = <&mdio_pins>; + pinctrl-names = "default"; + reset-gpios = <&tlmm 59 GPIO_ACTIVE_LOW>; + reset-delay-us = <2000>; + + /delete-node/ ethernet-phy@0; + /delete-node/ ethernet-phy@1; + }; + + ess-psgmii@98000 { + status = "okay"; + }; + + crypto@8e3a000 { + status = "okay"; + }; + + watchdog@b017000 { + status = "okay"; + }; + + ess-switch@c000000 { + status = "okay"; + switch_lan_bmp = <0x3e>; + switch_wan_bmp = <0x0>; + }; + + edma@c080000 { + status = "okay"; + qcom,num_gmac = <3>; + + gmac0 { + qcom,phy_mdio_addr = <3>; + qcom,poll_required = <1>; + /delete-property/ qcom,forced_speed; + /delete-property/ qcom,forced_duplex; + vlan_tag = <1 0x10>; + }; + + gmac1 { + qcom,phy_mdio_addr = <2>; + qcom,poll_required = <1>; + /delete-property/ qcom,forced_speed; + /delete-property/ qcom,forced_duplex; + vlan_tag = <1 0x08>; + }; + + gmac2 { + local-mac-address = [00 00 00 00 00 00]; + qcom,phy_mdio_addr = <4>; + qcom,poll_required = <1>; + /delete-property/ qcom,forced_speed; + /delete-property/ qcom,forced_duplex; + vlan_tag = <1 0x20>; + }; + }; + + gpio_export { + compatible = "gpio-export"; + #size-cells = <0>; + + plc { + gpio-export,name = "plc-enable"; + gpio-export,output = <1>; + gpios = <&tlmm 63 GPIO_ACTIVE_HIGH>; + }; + }; + + }; + + keys { + compatible = "gpio-keys"; + + wlan { + label = "WLAN"; + gpios = <&tlmm 5 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + + reset { + label = "Reset"; + gpios = <&tlmm 0 GPIO_ACTIVE_HIGH>; + linux,code = ; + }; + }; + + leds { + compatible = "gpio-leds"; + + status_dlan { + label = "white:dlan"; + gpios = <&tlmm 4 GPIO_ACTIVE_LOW>; + default-state = "keep"; + }; + + status_wlan { + label = "white:wlan"; + gpios = <&tlmm 58 GPIO_ACTIVE_LOW>; + default-state = "keep"; + }; + + error_dlan { + label = "red:dlan"; + gpios = <&tlmm 3 GPIO_ACTIVE_HIGH>; + default-state = "keep"; + }; + }; +}; + +&tlmm { + spi_0_pins: spi_0_pinmux { + mux { + function = "blsp_spi0"; + pins = "gpio55", "gpio56", "gpio57"; + drive-strength = <12>; + bias-disable; + }; + + mux_cs { + function = "gpio"; + pins = "gpio54"; + drive-strength = <2>; + bias-disable; + output-high; + }; + }; + + mdio_pins: mdio_pinmux { + mux_1 { + pins = "gpio53"; + function = "mdio"; + bias-pull-up; + }; + mux_2 { + pins = "gpio52"; + function = "mdc"; + bias-pull-up; + }; + }; + + serial_pins: serial_pinmux { + mux { + pins = "gpio61", "gpio60"; + function = "blsp_uart0"; + bias-disable; + }; + }; + + button_pins: button_pinmux { + mux { + function = "gpio"; + pins = "gpio0", "gpio5"; + bias-disable; + input; + }; + }; +}; + +&cryptobam { + status = "okay"; +}; + +&blsp_dma { + status = "okay"; +}; + +&blsp1_uart1 { + pinctrl-0 = <&serial_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + +&wifi0 { + status = "okay"; + qcom,ath10k-calibration-variant = "devolo,magic-2-wifi-next"; +}; + +&wifi1 { + status = "okay"; + qcom,ath10k-calibration-variant = "devolo,magic-2-wifi-next"; +}; + +&blsp1_spi1 { + pinctrl-0 = <&spi_0_pins>; + pinctrl-names = "default"; + status = "okay"; + cs-gpios = <&tlmm 54 GPIO_ACTIVE_HIGH>; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + linux,modalias = "n25q128a11"; + spi-max-frequency = <24000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "SBL1"; + reg = <0x00000000 0x00040000>; + read-only; + }; + partition@40000 { + label = "MIBIB"; + reg = <0x00040000 0x00020000>; + read-only; + }; + partition@60000 { + label = "QSEE"; + reg = <0x00060000 0x00060000>; + read-only; + }; + partition@c0000 { + label = "CDT"; + reg = <0x000c0000 0x00010000>; + read-only; + }; + partition@d0000 { + label = "DDRPARAMS"; + reg = <0x000d0000 0x00010000>; + read-only; + }; + partition@e0000 { + label = "APPSBLENV"; /* uboot env*/ + reg = <0x000e0000 0x00010000>; + }; + partition@f0000 { + label = "APPSBL"; /* uboot */ + reg = <0x000f0000 0x00080000>; + read-only; + }; + partition@170000 { + label = "ART"; + reg = <0x00170000 0x00010000>; + read-only; + }; + firmware@180000 { + compatible = "denx,fit"; + label = "firmware"; + reg = <0x00180000 0x01a80000>; + }; + }; + }; +}; diff --git a/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-meshpoint-one.dts b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-meshpoint-one.dts new file mode 100644 index 000000000..62ba76802 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-meshpoint-one.dts @@ -0,0 +1,81 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT +/* Copyright (c) 2019, CRISIS INNOVATION LAB d.o.o. + * Author: Robert Marko + */ + +#include "qcom-ipq4018-jalapeno.dtsi" + +/ { + model = "Crisis Innovation Lab MeshPoint.One"; + compatible = "cilab,meshpoint-one"; + + aliases { + led-boot = &led_status; + led-failsafe = &led_status; + led-running = &led_status; + led-upgrade = &led_status; + }; + + soc { + i2c-gpio { + status = "okay"; + + #address-cells = <1>; + #size-cells = <0>; + + compatible = "i2c-gpio"; + gpios = <&tlmm 0 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN) /* sda */ + &tlmm 4 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN) /* scl */ + >; + + bme280@76 { + status = "okay"; + + compatible = "bosch,bme280"; + reg = <0x76>; + }; + + pcf2129@51 { + status = "okay"; + + compatible = "nxp,pcf2129"; + reg = <0x51>; + }; + + ina230@40 { + status = "okay"; + + compatible = "ti,ina230"; + reg = <0x40>; + shunt-resistor = <2000>; + }; + + ina230@44 { + status = "okay"; + + compatible = "ti,ina230"; + reg = <0x44>; + shunt-resistor = <2000>; + }; + }; + }; + + keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + gpios = <&tlmm 5 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + leds { + compatible = "gpio-leds"; + + led_status: status { + label = "blue:status"; + gpios = <&tlmm 63 GPIO_ACTIVE_HIGH>; + }; + }; +}; diff --git a/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-nbg6617.dts b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-nbg6617.dts new file mode 100644 index 000000000..4d17325c8 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-nbg6617.dts @@ -0,0 +1,337 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "qcom-ipq4019.dtsi" +#include +#include +#include +#include + +/ { + model = "ZyXEL NBG6617"; + compatible = "zyxel,nbg6617"; + + chosen { + /* + * the vendor u-boot adds root and mtdparts cmdline parameters + * which we don't want... but we have to overwrite them or else + * the kernel will take them at face value. + */ + bootargs-append = " mtdparts= root=31:13"; + }; + + aliases { + led-boot = &power; + led-failsafe = &power; + led-running = &power; + led-upgrade = &power; + }; + + soc { + rng@22000 { + status = "okay"; + }; + + mdio@90000 { + status = "okay"; + }; + + ess-psgmii@98000 { + status = "okay"; + }; + + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; + qcom,wifi_glb_cfg = ; + }; + + tcsr@194b000 { + compatible = "qcom,tcsr"; + reg = <0x194b000 0x100>; + qcom,usb-hsphy-mode-select = ; + }; + + ess_tcsr@1953000 { + compatible = "qcom,tcsr"; + reg = <0x1953000 0x1000>; + qcom,ess-interface-select = ; + }; + + tcsr@1957000 { + compatible = "qcom,tcsr"; + reg = <0x1957000 0x100>; + qcom,wifi_noc_memtype_m0_m2 = ; + }; + + usb2@60f8800 { + status = "okay"; + + dwc3@6000000 { + #address-cells = <1>; + #size-cells = <0>; + + usb2_port1: port@1 { + reg = <1>; + #trigger-source-cells = <0>; + }; + }; + }; + + usb3@8af8800 { + status = "okay"; + + dwc3@8a00000 { + #address-cells = <1>; + #size-cells = <0>; + + usb3_port1: port@1 { + reg = <1>; + #trigger-source-cells = <0>; + }; + + usb3_port2: port@2 { + reg = <2>; + #trigger-source-cells = <0>; + }; + }; + }; + + crypto@8e3a000 { + status = "okay"; + }; + + watchdog@b017000 { + status = "okay"; + }; + + ess-switch@c000000 { + status = "okay"; + }; + + edma@c080000 { + status = "okay"; + }; + }; + + keys { + compatible = "gpio-keys"; + + wlan { + label = "wlan"; + gpios = <&tlmm 2 GPIO_ACTIVE_HIGH>; + linux,code = ; + linux,input-type = ; + }; + + wps { + label = "wps"; + gpios = <&tlmm 63 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + + reset { + label = "reset"; + gpios = <&tlmm 4 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-0 = <&led_pins>; + pinctrl-names = "default"; + + power: power { + label = "green:power"; + gpios = <&tlmm 3 GPIO_ACTIVE_HIGH>; + }; + + usb { + label = "green:usb"; + gpios = <&tlmm 0 GPIO_ACTIVE_HIGH>; + trigger-sources = <&usb2_port1>, <&usb3_port1>, <&usb3_port2>; + linux,default-trigger = "usbport"; + }; + + wlan2g { + label = "green:wlan2g"; + gpios = <&tlmm 58 GPIO_ACTIVE_HIGH>; + }; + + wlan5g { + label = "green:wlan5g"; + gpios = <&tlmm 5 GPIO_ACTIVE_HIGH>; + }; + + wps { + label = "green:wps"; + gpios = <&tlmm 1 GPIO_ACTIVE_HIGH>; + }; + }; +}; + +&tlmm { + serial_pins: serial_pinmux { + mux { + pins = "gpio60", "gpio61"; + function = "blsp_uart0"; + bias-disable; + }; + }; + spi_0_pins: spi_0_pinmux { + mux { + function = "blsp_spi0"; + pins = "gpio55", "gpio56", "gpio57"; + drive-strength = <12>; + bias-disable; + }; + + mux_cs { + function = "gpio"; + pins = "gpio54"; + drive-strength = <2>; + bias-disable; + output-low; + }; + }; + led_pins: led_pinmux { + mux { + pins = "gpio0", "gpio1", "gpio3", "gpio5", "gpio58"; + drive-strength = <0x8>; + bias-disable; + output-low; + }; + }; +}; + +&blsp1_spi1 { /* BLSP1 QUP1 */ + pinctrl-0 = <&spi_0_pins>; + pinctrl-names = "default"; + status = "okay"; + cs-gpios = <&tlmm 54 GPIO_ACTIVE_HIGH>; + + mx25l25635f@0 { + compatible = "mx25l25635f", "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <24000000>; + status = "okay"; + m25p,fast-read; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition0@0 { + label = "SBL1"; + reg = <0x00000000 0x00040000>; + read-only; + }; + partition1@40000 { + label = "MIBIB"; + reg = <0x00040000 0x00020000>; + read-only; + }; + partition2@60000 { + label = "QSEE"; + reg = <0x00060000 0x00060000>; + read-only; + }; + partition3@c0000 { + label = "CDT"; + reg = <0x000c0000 0x00010000>; + read-only; + }; + partition4@d0000 { + label = "DDRPARAMS"; + reg = <0x000d0000 0x00010000>; + read-only; + }; + partition5@e0000 { + label = "APPSBL"; /* u-boot */ + reg = <0x000e0000 0x00080000>; + /* U-Boot Standalone App "zloader" is located at 0x64000 */ + read-only; + }; + partition6@160000 { + label = "APPSBLENV"; /* u-boot env */ + reg = <0x00160000 0x00010000>; + }; + partition7@170000 { + /* make a backup of this partition! */ + label = "ART"; + reg = <0x00170000 0x00010000>; + read-only; + }; + partition8@180000 { + label = "kernel"; + reg = <0x00180000 0x00400000>; + }; + partition9@580000 { + label = "dualflag"; + reg = <0x00580000 0x00010000>; + read-only; + }; + partition10@590000 { + label = "header"; + reg = <0x00590000 0x00010000>; + }; + partition11@5a0000 { + label = "romd"; + reg = <0x005a0000 0x00100000>; + read-only; + }; + partition12@6a0000 { + label = "not_root_data"; + /* + * for some strange reason, someone at ZyXEL + * had the "great" idea to put the rootfs_data + * in front of rootfs... Don't do that! + * As a result this one, full MebiByte remains + * unused. + */ + reg = <0x006a0000 0x00100000>; + }; + partition13@7a0000 { + label = "rootfs"; + reg = <0x007a0000 0x01860000>; + }; + }; + }; +}; + +&blsp1_uart1 { + pinctrl-0 = <&serial_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + +&cryptobam { + status = "okay"; +}; + +&blsp_dma { + status = "okay"; +}; + +&wifi0 { + status = "okay"; + qcom,ath10k-calibration-variant = "ZyXEL-NBG6617"; +}; + +&wifi1 { + status = "okay"; + qcom,ath10k-calibration-variant = "ZyXEL-NBG6617"; +}; + +&usb3_ss_phy { + status = "okay"; +}; + +&usb3_hs_phy { + status = "okay"; +}; + +&usb2_hs_phy { + status = "okay"; +}; diff --git a/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-pa1200.dts b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-pa1200.dts new file mode 100644 index 000000000..bcb9552ce --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-pa1200.dts @@ -0,0 +1,197 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT +/* Copyright (c) 2017-2020, Sven Eckelmann + * Copyright (c) 2018, Marek Lindner + */ + +#include "qcom-ipq4019.dtsi" +#include +#include +#include + +/ { + model = "Plasma Cloud PA1200"; + compatible = "plasmacloud,pa1200"; + + soc { + rng@22000 { + status = "okay"; + }; + + mdio@90000 { + status = "okay"; + }; + + ess-psgmii@98000 { + status = "okay"; + }; + + tcsr@194b000 { + /* select hostmode */ + compatible = "qcom,tcsr"; + reg = <0x194b000 0x100>; + qcom,usb-hsphy-mode-select = ; + status = "okay"; + }; + + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; + qcom,wifi_glb_cfg = ; + }; + + ess_tcsr@1953000 { + compatible = "qcom,tcsr"; + reg = <0x1953000 0x1000>; + qcom,ess-interface-select = ; + }; + + tcsr@1957000 { + compatible = "qcom,tcsr"; + reg = <0x1957000 0x100>; + qcom,wifi_noc_memtype_m0_m2 = ; + }; + + usb2: usb2@60f8800 { + status = "okay"; + }; + + crypto@8e3a000 { + status = "okay"; + }; + + watchdog@b017000 { + status = "okay"; + }; + + ess-switch@c000000 { + status = "okay"; + }; + + edma@c080000 { + status = "okay"; + }; + }; + + keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + gpios = <&tlmm 59 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + aliases { + led-boot = &led_status_purple; + led-failsafe = &led_status_yellow; + led-running = &led_status_cyan; + led-upgrade = &led_status_yellow; + }; + + leds { + compatible = "gpio-leds"; + + led_status_cyan: status_cyan { + label = "cyan:status"; + gpios = <&tlmm 0 GPIO_ACTIVE_HIGH>; + }; + + led_status_purple: status_purple { + label = "purple:status"; + gpios = <&tlmm 1 GPIO_ACTIVE_HIGH>; + }; + + led_status_yellow: status_yellow { + label = "yellow:status"; + gpios = <&tlmm 2 GPIO_ACTIVE_HIGH>; + }; + }; + +}; + +&tlmm { + serial_pins: serial_pinmux { + mux { + pins = "gpio60", "gpio61"; + function = "blsp_uart0"; + bias-disable; + }; + }; + + spi_0_pins: spi_0_pinmux { + pin { + function = "blsp_spi0"; + pins = "gpio55", "gpio56", "gpio57"; + drive-strength = <12>; + bias-disable; + }; + pin_cs { + function = "gpio"; + pins = "gpio54"; + drive-strength = <2>; + bias-disable; + output-high; + }; + }; +}; + +&blsp_dma { + status = "okay"; +}; + +&blsp1_spi1 { + pinctrl-0 = <&spi_0_pins>; + pinctrl-names = "default"; + status = "okay"; + cs-gpios = <&tlmm 54 GPIO_ACTIVE_HIGH>; + + flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <24000000>; + /* partitions are passed via bootloader */ + }; +}; + +&blsp1_uart1 { + pinctrl-0 = <&serial_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + +&cryptobam { + status = "okay"; +}; + +&gmac0 { + qcom,phy_mdio_addr = <4>; + qcom,poll_required = <1>; + qcom,forced_speed = <1000>; + qcom,forced_duplex = <1>; + vlan_tag = <2 0x20>; +}; + +&gmac1 { + qcom,phy_mdio_addr = <3>; + qcom,poll_required = <1>; + qcom,forced_speed = <1000>; + qcom,forced_duplex = <1>; + vlan_tag = <1 0x10>; +}; + +&usb2_hs_phy { + status = "okay"; +}; + +&wifi0 { + status = "okay"; + qcom,ath10k-calibration-variant = "PlasmaCloud-PA1200"; +}; + +&wifi1 { + status = "okay"; + qcom,ath10k-calibration-variant = "PlasmaCloud-PA1200"; +}; diff --git a/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-rt-ac58u.dts b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-rt-ac58u.dts new file mode 100644 index 000000000..bd0c6b71d --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-rt-ac58u.dts @@ -0,0 +1,309 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "qcom-ipq4019.dtsi" +#include +#include +#include + +/ { + model = "ASUS RT-AC58U"; + compatible = "asus,rt-ac58u"; + + memory { + device_type = "memory"; + reg = <0x80000000 0x8000000>; + }; + + aliases { + led-boot = &led_power; + led-failsafe = &led_power; + led-running = &led_power; + led-upgrade = &led_power; + }; + + chosen { + bootargs-append = " ubi.mtd=UBI_DEV"; + }; + + soc { + rng@22000 { + status = "okay"; + }; + + mdio@90000 { + status = "okay"; + }; + + ess-psgmii@98000 { + status = "okay"; + }; + + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; + qcom,wifi_glb_cfg = ; + }; + + tcsr@194b000 { + compatible = "qcom,tcsr"; + reg = <0x194b000 0x100>; + qcom,usb-hsphy-mode-select = ; + }; + + ess_tcsr@1953000 { + compatible = "qcom,tcsr"; + reg = <0x1953000 0x1000>; + qcom,ess-interface-select = ; + }; + + tcsr@1957000 { + compatible = "qcom,tcsr"; + reg = <0x1957000 0x100>; + qcom,wifi_noc_memtype_m0_m2 = ; + }; + + usb3@8af8800 { + status = "okay"; + + dwc3@8a00000 { + #address-cells = <1>; + #size-cells = <0>; + + usb3_port1: port@1 { + reg = <1>; + #trigger-source-cells = <0>; + }; + + usb3_port2: port@2 { + reg = <2>; + #trigger-source-cells = <0>; + }; + }; + }; + + crypto@8e3a000 { + status = "okay"; + }; + + watchdog@b017000 { + status = "okay"; + }; + + ess-switch@c000000 { + status = "okay"; + }; + + edma@c080000 { + status = "okay"; + }; + }; + + keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + gpios = <&tlmm 4 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + + wps { + label = "wps"; + gpios = <&tlmm 63 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + leds { + compatible = "gpio-leds"; + + led_power: status { + label = "blue:status"; + gpios = <&tlmm 3 GPIO_ACTIVE_HIGH>; + }; + + wan { + label = "blue:wan"; + gpios = <&tlmm 1 GPIO_ACTIVE_HIGH>; + }; + + wlan2G { + label = "blue:wlan2G"; + gpios = <&tlmm 58 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "phy0tpt"; + }; + + wlan5G { + label = "blue:wlan5G"; + gpios = <&tlmm 5 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "phy1tpt"; + }; + + usb { + label = "blue:usb"; + gpios = <&tlmm 0 GPIO_ACTIVE_HIGH>; + trigger-sources = <&usb3_port1>, <&usb3_port2>; + linux,default-trigger = "usbport"; + }; + + lan { + label = "blue:lan"; + gpios = <&tlmm 2 GPIO_ACTIVE_HIGH>; + }; + }; +}; + +&cryptobam { + status = "okay"; +}; + +&blsp_dma { + status = "okay"; +}; + +&tlmm { + serial_pins: serial_pinmux { + mux { + pins = "gpio60", "gpio61"; + function = "blsp_uart0"; + bias-disable; + }; + }; + + spi_0_pins: spi_0_pinmux { + mux { + function = "blsp_spi0"; + pins = "gpio55", "gpio56", "gpio57"; + drive-strength = <12>; + bias-disable; + }; + + mux_cs { + function = "gpio"; + pins = "gpio54", "gpio59"; + drive-strength = <2>; + bias-disable; + output-high; + }; + }; +}; + +&blsp1_spi1 { /* BLSP1 QUP1 */ + pinctrl-0 = <&spi_0_pins>; + pinctrl-names = "default"; + status = "okay"; + cs-gpios = <&tlmm 54 GPIO_ACTIVE_HIGH>, + <&tlmm 59 GPIO_ACTIVE_HIGH>; + + flash@0 { + /* + * U-boot looks for "n25q128a11" node, + * if we don't have it, it will spit out the following warning: + * "ipq: fdt fixup unable to find compatible node". + */ + compatible = "jedec,spi-nor"; + reg = <0>; + linux,modalias = "m25p80", "mx25l1606e", "n25q128a11"; + spi-max-frequency = <30000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "SBL1"; + reg = <0x00000000 0x00040000>; + read-only; + }; + partition@40000 { + label = "MIBIB"; + reg = <0x00040000 0x00020000>; + read-only; + }; + partition@60000 { + label = "QSEE"; + reg = <0x00060000 0x00060000>; + read-only; + }; + partition@c0000 { + label = "CDT"; + reg = <0x000c0000 0x00010000>; + read-only; + }; + partition@d0000 { + label = "DDRPARAMS"; + reg = <0x000d0000 0x00010000>; + read-only; + }; + partition@e0000 { + label = "APPSBLENV"; /* uboot env*/ + reg = <0x000e0000 0x00010000>; + read-only; + }; + partition@f0000 { + label = "APPSBL"; /* uboot */ + reg = <0x000f0000 0x00080000>; + read-only; + }; + partition@170000 { + label = "ART"; + reg = <0x00170000 0x00010000>; + read-only; + }; + /* 0x00180000 - 0x00200000 unused */ + }; + }; + + spi-nand@1 { + compatible = "spi-nand"; + reg = <1>; + spi-max-frequency = <30000000>; + + /* + * U-boot looks for "spinand,mt29f" node, + * if we don't have it, it will spit out the following warning: + * "ipq: fdt fixup unable to find compatible node". + */ + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + /* + * TODO: change to label = "ubi" once we drop 4.14. + * also drop the bootargs-append and all the + * userspace CI_UBIPART="UBI_DEV" remains. + */ + label = "UBI_DEV"; + reg = <0x00000000 0x08000000>; + }; + }; + }; +}; + +&blsp1_uart1 { + pinctrl-0 = <&serial_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + +&usb3_ss_phy { + status = "okay"; +}; + +&usb3_hs_phy { + status = "okay"; +}; + +&wifi0 { + status = "okay"; + qcom,ath10k-calibration-variant = "RT-AC58U"; +}; + +&wifi1 { + status = "okay"; + qcom,ath10k-calibration-variant = "RT-AC58U"; +}; diff --git a/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-spw2ac1200-lan-poe.dts b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-spw2ac1200-lan-poe.dts new file mode 100644 index 000000000..1c2a2a862 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-spw2ac1200-lan-poe.dts @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "qcom-ipq4018-spw2ac1200.dts" +/ { + compatible = "edgecore,spw2ac1200-lan-poe"; +}; diff --git a/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-spw2ac1200.dts b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-spw2ac1200.dts new file mode 100644 index 000000000..a152ba57f --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-spw2ac1200.dts @@ -0,0 +1,332 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "qcom-ipq4019.dtsi" +#include +#include +#include + +/ { + model = "Edgecore SPW2AC1200"; + compatible = "edgecore,spw2ac1200"; + + aliases { + led-boot = &led_power; + led-failsafe = &led_power; + led-running = &led_power; + led-upgrade = &led_power; + label-mac-device = &gmac0; + }; + + chosen { + bootargs-append = " root="; + }; + + keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + gpios = <&tlmm 63 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + leds { + compatible = "gpio-leds"; + + led_power: power { + label = "yellow:power"; + gpios = <&tlmm 5 GPIO_ACTIVE_LOW>; + }; + + wlan2g { + label = "green:wlan2g"; + gpios = <&tlmm 3 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "phy0tpt"; + }; + + wlan5g { + label = "green:wlan5g"; + gpios = <&tlmm 2 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "phy1tpt"; + }; + }; + + soc { + rng@22000 { + status = "okay"; + }; + + ess-psgmii@98000 { + status = "okay"; + }; + + counter@4a1000 { + compatible = "qcom,qca-gcnt"; + reg = <0x4a1000 0x4>; + }; + + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; + qcom,wifi_glb_cfg = ; + }; + + tcsr@194b000 { + compatible = "qcom,tcsr"; + reg = <0x194b000 0x100>; + qcom,usb-hsphy-mode-select = ; + }; + + ess_tcsr@1953000 { + compatible = "qcom,tcsr"; + reg = <0x1953000 0x1000>; + qcom,ess-interface-select = ; + }; + + tcsr@1957000 { + compatible = "qcom,tcsr"; + reg = <0x1957000 0x100>; + qcom,wifi_noc_memtype_m0_m2 = ; + }; + + usb2@60f8800 { + status = "okay"; + }; + + usb3@8af8800 { + status = "okay"; + + dwc3@8a00000 { + phys = <&usb3_hs_phy>; + phy-names = "usb2-phy"; + }; + }; + + crypto@8e3a000 { + status = "okay"; + }; + + watchdog@b017000 { + status = "okay"; + }; + + ess-switch@c000000 { + status = "okay"; + + switch_lan_bmp = <0x10>; + switch_wan_bmp = <0x20>; + }; + + edma@c080000 { + status = "okay"; + }; + }; +}; + +&tlmm { + mdio_pins: mdio_pinmux { + mux_mdio { + pins = "gpio53"; + function = "mdio"; + bias-pull-up; + }; + + mux_mdc { + pins = "gpio52"; + function = "mdc"; + bias-pull-up; + }; + }; + + serial_pins: serial_pinmux { + mux { + pins = "gpio60", "gpio61"; + function = "blsp_uart0"; + bias-disable; + }; + }; + + spi0_pins: spi0_pinmux { + pin { + function = "blsp_spi0"; + pins = "gpio55", "gpio56", "gpio57"; + drive-strength = <2>; + bias-disable; + }; + + pin_cs { + function = "gpio"; + pins = "gpio54", "gpio4"; + drive-strength = <2>; + bias-disable; + output-high; + }; + }; + + i2c0_pins: i2c0_pinmux { + mux_i2c { + function = "blsp_i2c0"; + pins = "gpio58", "gpio59"; + drive-strength = <16>; + bias-disable; + }; + }; +}; + +&blsp_dma { + status = "okay"; +}; + +&blsp1_spi1 { + status = "okay"; + + pinctrl-0 = <&spi0_pins>; + pinctrl-names = "default"; + cs-gpios = <&tlmm 54 GPIO_ACTIVE_HIGH>, <&tlmm 4 GPIO_ACTIVE_HIGH>; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <24000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "0:SBL1"; + reg = <0x00000000 0x00040000>; + read-only; + }; + + partition@40000 { + label = "0:MIBIB"; + reg = <0x00040000 0x00020000>; + read-only; + }; + + partition@60000 { + label = "0:QSEE"; + reg = <0x00060000 0x00060000>; + read-only; + }; + + partition@c0000 { + label = "0:CDT"; + reg = <0x000c0000 0x00010000>; + read-only; + }; + + partition@d0000 { + label = "0:DDRPARAMS"; + reg = <0x000d0000 0x00010000>; + read-only; + }; + + partition@e0000 { + label = "0:APPSBLENV"; /* uboot env */ + reg = <0x000e0000 0x00010000>; + }; + + partition@f0000 { + label = "0:APPSBL"; /* uboot */ + reg = <0x000f0000 0x00080000>; + read-only; + }; + + partition@170000 { + label = "0:ART"; + reg = <0x00170000 0x00010000>; + read-only; + }; + + partition@180000 { + label = "certificates"; + reg = <0x00180000 0x00010000>; + }; + }; + }; + + flash@1 { + compatible = "spi-nand"; + reg = <1>; + spi-max-frequency = <24000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "rootfs1"; + reg = <0x00000000 0x04000000>; + }; + + partition@4000000 { + label = "rootfs2"; + reg = <0x04000000 0x04000000>; + }; + }; + }; +}; + +&blsp1_i2c3 { + status = "okay"; + + pinctrl-0 = <&i2c0_pins>; + pinctrl-names = "default"; + + tpm@29 { + compatible = "atmel,at97sc3204t"; + reg = <0x29>; + }; +}; + +&blsp1_uart1 { + status = "okay"; + + pinctrl-0 = <&serial_pins>; + pinctrl-names = "default"; +}; + +&cryptobam { + status = "okay"; +}; + +&mdio { + status = "okay"; + + pinctrl-0 = <&mdio_pins>; + pinctrl-names = "default"; +}; + +&gmac0 { + qcom,poll_required = <1>; + qcom,phy_mdio_addr = <4>; + vlan_tag = <2 0x20>; +}; + +&gmac1 { + qcom,poll_required = <1>; + qcom,phy_mdio_addr = <3>; + vlan_tag = <1 0x10>; +}; + +&wifi0 { + status = "okay"; +}; + +&wifi1 { + status = "okay"; + qcom,ath10k-calibration-variant = "ALFA-Network-AP120C-AC"; +}; + +&usb3_hs_phy { + status = "okay"; +}; + +&usb2_hs_phy { + status = "okay"; +}; diff --git a/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-sxtsq-5-ac.dts b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-sxtsq-5-ac.dts new file mode 100644 index 000000000..fd11229db --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-sxtsq-5-ac.dts @@ -0,0 +1,242 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT +/* Copyright (c) 2020, Robert Marko */ + +#include "qcom-ipq4019.dtsi" +#include +#include +#include + +/ { + model = "MikroTik SXTsq 5 ac (RBSXTsqG-5acD)"; + compatible = "mikrotik,sxtsq-5-ac"; + + memory { + device_type = "memory"; + reg = <0x80000000 0x10000000>; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + aliases { + led-boot = &led_user; + led-failsafe = &led_user; + led-running = &led_user; + led-upgrade = &led_user; + }; + + soc { + rng@22000 { + status = "okay"; + }; + + mdio@90000 { + status = "okay"; + }; + + counter@4a1000 { + compatible = "qcom,qca-gcnt"; + reg = <0x4a1000 0x4>; + }; + + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; + qcom,wifi_glb_cfg = ; + }; + + ess_tcsr@1953000 { + compatible = "qcom,tcsr"; + reg = <0x1953000 0x1000>; + qcom,ess-interface-select = ; + }; + + tcsr@1957000 { + compatible = "qcom,tcsr"; + reg = <0x1957000 0x100>; + qcom,wifi_noc_memtype_m0_m2 = ; + }; + + crypto@8e3a000 { + status = "okay"; + }; + + watchdog@b017000 { + status = "okay"; + }; + + ess-psgmii@98000 { + status = "okay"; + }; + + edma@c080000 { + status = "okay"; + phy-mode = "rgmii"; + qcom,num_gmac = <1>; + qcom,single-phy; + }; + }; + + keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + gpios = <&tlmm 63 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + leds { + compatible = "gpio-leds"; + + power { + label = "blue:power"; + gpios = <&tlmm 0 GPIO_ACTIVE_HIGH>; + default-state = "keep"; + panic-indicator; + }; + + led_user: user { + label = "green:user"; + gpios = <&tlmm 3 GPIO_ACTIVE_HIGH>; + }; + + rssilow { + label = "green:rssilow"; + gpios = <&tlmm 58 GPIO_ACTIVE_HIGH>; + }; + + rssimediumlow { + label = "green:rssimediumlow"; + gpios = <&tlmm 1 GPIO_ACTIVE_HIGH>; + }; + + rssimedium { + label = "green:rssimedium"; + gpios = <&tlmm 2 GPIO_ACTIVE_HIGH>; + }; + + rssimediumhigh { + label = "green:rssimediumhigh"; + gpios = <&tlmm 4 GPIO_ACTIVE_HIGH>; + }; + + rssihigh { + label = "green:rssihigh"; + gpios = <&tlmm 5 GPIO_ACTIVE_HIGH>; + }; + }; +}; + +&tlmm { + serial_pins: serial_pinmux { + mux { + pins = "gpio60", "gpio61"; + function = "blsp_uart0"; + bias-disable; + }; + }; + + spi_0_pins: spi_0_pinmux { + pin { + function = "blsp_spi0"; + pins = "gpio55", "gpio56", "gpio57"; + drive-strength = <2>; + bias-disable; + }; + pin_cs { + function = "gpio"; + pins = "gpio54"; + drive-strength = <2>; + bias-disable; + output-high; + }; + }; +}; + +&blsp_dma { + status = "okay"; +}; + +&blsp1_spi1 { + status = "okay"; + + pinctrl-0 = <&spi_0_pins>; + pinctrl-names = "default"; + cs-gpios = <&tlmm 54 GPIO_ACTIVE_HIGH>; + + flash@0 { + reg = <0>; + compatible = "jedec,spi-nor"; + spi-max-frequency = <40000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "Qualcomm"; + reg = <0x0 0x80000>; + read-only; + }; + + partition@80000 { + compatible = "mikrotik,routerboot-partitions"; + #address-cells = <1>; + #size-cells = <1>; + label = "RouterBoot"; + reg = <0x80000 0x80000>; + read-only; + + hard_config { + read-only; + }; + + dtb_config { + read-only; + }; + + soft_config { + }; + }; + + partition@100000 { + compatible = "mikrotik,minor"; + label = "firmware"; + reg = <0x100000 0xf00000>; + }; + }; + }; +}; + +&blsp1_uart1 { + status = "okay"; + + pinctrl-0 = <&serial_pins>; + pinctrl-names = "default"; +}; + +&cryptobam { + status = "okay"; +}; + +&wifi1 { + status = "okay"; + + qcom,ath10k-calibration-variant = "MikroTik-SXTsq-5-ac"; +}; + +&gmac0 { + qcom,phy_mdio_addr = <4>; + qcom,poll_required = <1>; + qcom,forced_speed = <1000>; + qcom,forced_duplex = <1>; + vlan_tag = <1 0x20>; +}; + +&mdio { + status = "okay"; +}; diff --git a/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-udaya-a5-id2.dts b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-udaya-a5-id2.dts new file mode 100644 index 000000000..ee2d4ac37 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-udaya-a5-id2.dts @@ -0,0 +1,114 @@ +/* Copyright (c) 2015, 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 "qcom-ipq4019-ap.dk01.1.dtsi" +#include +#include + +/ { + model = "udaya A5-ID2"; + compatible = "udaya,a5-id2", "qcom,ap-dk01.1-c1", "qcom,ap-dk01.2-c1"; + + aliases { + led-boot = &led_power; + led-failsafe = &led_power; + led-running = &led_power; + led-upgrade = &led_power; + }; + + memory { + device_type = "memory"; + reg = <0x80000000 0x10000000>; + }; + + keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + gpios = <&tlmm 63 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + leds { + compatible = "gpio-leds"; + + led_power: power { + label = "green:power"; + gpios = <&tlmm 58 GPIO_ACTIVE_HIGH>; + }; + }; +}; + +&blsp1_spi1 { + mx25l25635f@0 { + compatible = "mx25l25635f", "jedec,spi-nor"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0>; + spi-max-frequency = <24000000>; + + SBL1@0 { + label = "SBL1"; + reg = <0x0 0x40000>; + read-only; + }; + MIBIB@40000 { + label = "MIBIB"; + reg = <0x40000 0x20000>; + read-only; + }; + QSEE@60000 { + label = "QSEE"; + reg = <0x60000 0x60000>; + read-only; + }; + CDT@c0000 { + label = "CDT"; + reg = <0xc0000 0x10000>; + read-only; + }; + DDRPARAMS@d0000 { + label = "DDRPARAMS"; + reg = <0xd0000 0x10000>; + read-only; + }; + APPSBLENV@e0000 { + label = "APPSBLENV"; + reg = <0xe0000 0x10000>; + read-only; + }; + APPSBL@f0000 { + label = "APPSBL"; + reg = <0xf0000 0x80000>; + read-only; + }; + ART@170000 { + label = "ART"; + reg = <0x170000 0x10000>; + read-only; + }; + firmware@180000 { + label = "firmware"; + reg = <0x180000 0x1e70000>; + }; + certificates@1ff0000 { + label = "certificates"; + reg = <0x1ff0000 0x10000>; + }; + }; +}; diff --git a/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-wre6606.dts b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-wre6606.dts new file mode 100644 index 000000000..8fa5a3190 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-wre6606.dts @@ -0,0 +1,265 @@ +/* Copyright (c) 2015, The Linux Foundation. All rights reserved. + * Copyright (c) 2018, David Bauer + * + * 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 "qcom-ipq4019.dtsi" +#include +#include +#include + +/ { + model = "ZyXEL WRE6606"; + compatible = "zyxel,wre6606"; + + aliases { + led-boot = &power; + led-failsafe = &power; + led-running = &power; + led-upgrade = &power; + }; + + chosen { + bootargs-append = " mtdparts="; + }; + + soc { + rng@22000 { + status = "okay"; + }; + + mdio@90000 { + status = "okay"; + }; + + ess-psgmii@98000 { + status = "okay"; + }; + + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; + qcom,wifi_glb_cfg = ; + }; + + ess_tcsr@1953000 { + compatible = "qcom,tcsr"; + reg = <0x1953000 0x1000>; + qcom,ess-interface-select = ; + }; + + tcsr@1957000 { + compatible = "qcom,tcsr"; + reg = <0x1957000 0x100>; + qcom,wifi_noc_memtype_m0_m2 = ; + }; + + crypto@8e3a000 { + status = "okay"; + }; + + watchdog@b017000 { + status = "okay"; + }; + + ess-switch@c000000 { + status = "okay"; + }; + + edma@c080000 { + status = "okay"; + qcom,num_gmac = <1>; + }; + }; + + leds { + compatible = "gpio-leds"; + + wps { + label = "green:wps"; + gpios = <&tlmm 1 GPIO_ACTIVE_HIGH>; + }; + + wlan5g_green { + label = "green:wlan5g"; + gpios = <&tlmm 3 GPIO_ACTIVE_HIGH>; + }; + + power: power { + label = "green:power"; + gpios = <&tlmm 4 GPIO_ACTIVE_HIGH>; + }; + + wlan5g_red { + label = "red:wlan5g"; + gpios = <&tlmm 5 GPIO_ACTIVE_HIGH>; + }; + + wlan2g_red { + label = "red:wlan2g"; + gpios = <&tlmm 58 GPIO_ACTIVE_HIGH>; + }; + + wlan2g_green { + label = "green:wlan2g"; + gpios = <&tlmm 59 GPIO_ACTIVE_HIGH>; + }; + }; + + keys { + compatible = "gpio-keys"; + + wps { + label = "wps"; + gpios = <&tlmm 63 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; +}; + +&tlmm { + serial_pins: serial_pinmux { + mux { + pins = "gpio60", "gpio61"; + function = "blsp_uart0"; + bias-disable; + }; + }; + + spi_0_pins: spi_0_pinmux { + pin { + function = "blsp_spi0"; + pins = "gpio55", "gpio56", "gpio57"; + drive-strength = <12>; + bias-disable; + }; + pin_cs { + function = "gpio"; + pins = "gpio54"; + drive-strength = <2>; + bias-disable; + output-high; + }; + }; +}; + +&blsp_dma { + status = "okay"; +}; + +&blsp1_spi1 { + pinctrl-0 = <&spi_0_pins>; + pinctrl-names = "default"; + status = "okay"; + cs-gpios = <&tlmm 54 GPIO_ACTIVE_HIGH>; + + mx25l12805d@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <24000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition0@0 { + label = "SBL1"; + reg = <0x00000000 0x00040000>; + read-only; + }; + + partition1@40000 { + label = "MIBIB"; + reg = <0x00040000 0x00020000>; + read-only; + }; + + partition2@60000 { + label = "QSEE"; + reg = <0x00060000 0x00060000>; + read-only; + }; + + partition3@c0000 { + label = "CDT"; + reg = <0x000c0000 0x00010000>; + read-only; + }; + + partition4@d0000 { + label = "DDRPARAMS"; + reg = <0x000d0000 0x00010000>; + read-only; + }; + + partition5@E0000 { + label = "APPSBLENV"; + reg = <0x000e0000 0x00010000>; + read-only; + }; + + partition6@F0000 { + label = "APPSBL"; + reg = <0x000f0000 0x00080000>; + read-only; + }; + + partition7@170000 { + label = "ART"; + reg = <0x00170000 0x00010000>; + read-only; + }; + + partition8@180000 { + compatible = "denx,fit"; + label = "firmware"; + reg = <0x00180000 0x00ce0000>; + }; + + partition9@e60000 { + label = "manufacture"; + reg = <0x00e60000 0x00050000>; + read-only; + }; + + partition10@eb0000 { + label = "storage"; + reg = <0x00eb0000 0x00150000>; + read-only; + }; + }; + }; +}; + +&blsp1_uart1 { + pinctrl-0 = <&serial_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + +&cryptobam { + status = "okay"; +}; + +&wifi0 { + status = "okay"; + qcom,ath10k-calibration-variant = "ZyXEL-WRE6606"; +}; + +&wifi1 { + status = "okay"; + qcom,ath10k-calibration-variant = "ZyXEL-WRE6606"; +}; diff --git a/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-wrtq-329acn.dts b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-wrtq-329acn.dts new file mode 100644 index 000000000..2465348a8 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-wrtq-329acn.dts @@ -0,0 +1,275 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "qcom-ipq4019.dtsi" +#include +#include +#include + +/ { + model = "Luma Home WRTQ-329ACN"; + compatible = "luma,wrtq-329acn"; + + i2c-gpio { + compatible = "i2c-gpio"; + sda-gpios = <&tlmm 1 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>; + scl-gpios = <&tlmm 0 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>; + #address-cells = <1>; + #size-cells = <0>; + + /* No driver exists */ + led_ring@48 { + compatible = "ti,msp430"; + reg = <0x48>; + }; + + eeprom@50 { + compatible = "atmel,24c16"; + reg = <0x50>; + pagesize = <16>; + read-only; + }; + }; + + keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + gpios = <&tlmm 63 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + soc { + rng@22000 { + status = "okay"; + }; + + mdio@90000 { + status = "okay"; + + /delete-node/ ethernet-phy@0; + /delete-node/ ethernet-phy@1; + /delete-node/ ethernet-phy@3; + }; + + ess-psgmii@98000 { + status = "okay"; + }; + + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; + qcom,wifi_glb_cfg = ; + }; + + tcsr@194b000 { + compatible = "qcom,tcsr"; + reg = <0x194b000 0x100>; + qcom,usb-hsphy-mode-select = ; + }; + + ess_tcsr@1953000 { + compatible = "qcom,tcsr"; + reg = <0x1953000 0x1000>; + qcom,ess-interface-select = ; + }; + + tcsr@1957000 { + compatible = "qcom,tcsr"; + reg = <0x1957000 0x100>; + qcom,wifi_noc_memtype_m0_m2 = ; + }; + + usb2@60f8800 { + status = "okay"; + }; + + usb3@8af8800 { + status = "okay"; + }; + + crypto@8e3a000 { + status = "okay"; + }; + + watchdog@b017000 { + status = "okay"; + }; + + ess-switch@c000000 { + status = "okay"; + + switch_lan_bmp = <0x1e>; + switch_wan_bmp = <0x20>; + }; + + edma@c080000 { + status = "okay"; + }; + }; +}; + +&blsp_dma { + status = "okay"; +}; + + +&blsp1_spi1 { + status = "okay"; + + cs-gpios = <&tlmm 54 GPIO_ACTIVE_HIGH>, + <&tlmm 59 GPIO_ACTIVE_HIGH>; + pinctrl-0 = <&spi0_pins>; + pinctrl-names = "default"; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <24000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "0:SBL1"; + reg = <0x000000 0x040000>; + read-only; + }; + + partition@40000 { + label = "0:MIBIB"; + reg = <0x040000 0x020000>; + read-only; + }; + + partition@60000 { + label = "0:QSEE"; + reg = <0x060000 0x060000>; + read-only; + }; + + partition@c0000 { + label = "0:CDT"; + reg = <0x0c0000 0x010000>; + read-only; + }; + + partition@d0000 { + label = "0:DDRPARAMS"; + reg = <0x0d0000 0x010000>; + read-only; + }; + + partition@e0000 { + label = "0:APPSBLENV"; + reg = <0x0e0000 0x010000>; + }; + + partition@f0000 { + label = "0:APPSBL"; + reg = <0x0f0000 0x080000>; + read-only; + }; + + partition@170000 { + label = "0:ART"; + reg = <0x170000 0x010000>; + read-only; + }; + }; + }; + + flash@1 { + status = "okay"; + + compatible = "spi-nand"; + reg = <1>; + spi-max-frequency = <24000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "ubi"; + reg = <0x0000000 0x8000000>; + }; + }; + }; +}; + +&blsp1_uart1 { + status = "okay"; + + pinctrl-0 = <&serial0_pins>; + pinctrl-names = "default"; +}; + +&cryptobam { + status = "okay"; +}; + +&gmac0 { + qcom,phy_mdio_addr = <2>; + qcom,poll_required = <1>; +}; + +&gmac1 { + qcom,phy_mdio_addr = <4>; + qcom,poll_required = <1>; +}; + +&tlmm { + serial0_pins: serial0_pinmux { + mux { + function = "blsp_uart0"; + pins = "gpio60", "gpio61"; + bias-disable; + }; + }; + + spi0_pins: spi0_pinmux { + mux { + function = "blsp_spi0"; + pins = "gpio55", "gpio56", "gpio57"; + bias-disable; + drive-strength = <12>; + }; + + mux_cs { + function = "gpio"; + pins = "gpio54", "gpio59"; + bias-disable; + drive-strength = <2>; + output-high; + }; + }; +}; + +&usb2_hs_phy { + status = "okay"; +}; + +&usb3_hs_phy { + status = "okay"; +}; + +&usb3_ss_phy { + status = "okay"; +}; + +&wifi0 { + status = "okay"; + + qcom,ath10k-calibration-variant = "Luma-WRTQ-329ACN"; +}; + +&wifi1 { + status = "okay"; + + qcom,ath10k-calibration-variant = "Luma-WRTQ-329ACN"; +}; diff --git a/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-a62.dts b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-a62.dts new file mode 100644 index 000000000..279050fa1 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-a62.dts @@ -0,0 +1,229 @@ +// SPDX-License-Identifier: ISC +/* Copyright (c) 2015, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2018, Sven Eckelmann + */ + +#include "qcom-ipq4019.dtsi" +#include +#include +#include + +/ { + model = "OpenMesh A62"; + compatible = "openmesh,a62"; + + soc { + rng@22000 { + status = "okay"; + }; + + mdio@90000 { + status = "okay"; + }; + + ess-psgmii@98000 { + status = "okay"; + }; + + tcsr@194b000 { + /* select hostmode */ + compatible = "qcom,tcsr"; + reg = <0x194b000 0x100>; + qcom,usb-hsphy-mode-select = ; + status = "okay"; + }; + + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; + qcom,wifi_glb_cfg = ; + }; + + ess_tcsr@1953000 { + compatible = "qcom,tcsr"; + reg = <0x1953000 0x1000>; + qcom,ess-interface-select = ; + }; + + tcsr@1957000 { + compatible = "qcom,tcsr"; + reg = <0x1957000 0x100>; + qcom,wifi_noc_memtype_m0_m2 = ; + }; + + usb2: usb2@60f8800 { + status = "okay"; + }; + + crypto@8e3a000 { + status = "okay"; + }; + + watchdog@b017000 { + status = "okay"; + }; + + ess-switch@c000000 { + switch_lan_bmp = <0x10>; + switch_wan_bmp = <0x20>; + + status = "okay"; + }; + + edma@c080000 { + status = "okay"; + }; + }; + + keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + gpios = <&tlmm 18 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + aliases { + led-boot = &led_status_green; + led-failsafe = &led_status_green; + led-running = &led_status_green; + led-upgrade = &led_status_green; + }; + + leds { + compatible = "gpio-leds"; + + status_red { + label = "red:status"; + gpios = <&tlmm 43 GPIO_ACTIVE_HIGH>; + }; + + led_status_green: status_green { + label = "green:status"; + gpios = <&tlmm 45 GPIO_ACTIVE_HIGH>; + }; + + status_blue { + label = "blue:status"; + gpios = <&tlmm 46 GPIO_ACTIVE_HIGH>; + }; + }; + + watchdog { + compatible = "linux,wdt-gpio"; + gpios = <&tlmm 59 GPIO_ACTIVE_LOW>; + hw_algo = "toggle"; + /* hw_margin_ms is actually 300s but driver limits it to 60s */ + hw_margin_ms = <60000>; + always-running; + }; +}; + +&tlmm { + serial_pins: serial_pinmux { + mux { + pins = "gpio16", "gpio17"; + function = "blsp_uart0"; + bias-disable; + }; + }; + + spi_0_pins: spi_0_pinmux { + pin { + function = "blsp_spi0"; + pins = "gpio13", "gpio14", "gpio15"; + drive-strength = <12>; + bias-disable; + }; + pin_cs { + function = "gpio"; + pins = "gpio12"; + drive-strength = <2>; + bias-disable; + output-high; + }; + }; + + enable-usb-power { + gpio-hog; + gpios = <58 GPIO_ACTIVE_HIGH>; + output-low; + line-name = "enable USB2 power"; + }; +}; + +&blsp_dma { + status = "okay"; +}; + +&blsp1_spi1 { + pinctrl-0 = <&spi_0_pins>; + pinctrl-names = "default"; + status = "okay"; + cs-gpios = <&tlmm 12 GPIO_ACTIVE_HIGH>; + + flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <24000000>; + /* partitions are passed via bootloader */ + }; +}; + +&blsp1_uart1 { + pinctrl-0 = <&serial_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + +&cryptobam { + status = "okay"; +}; + +&gmac0 { + qcom,phy_mdio_addr = <3>; + qcom,poll_required = <1>; + qcom,forced_speed = <1000>; + qcom,forced_duplex = <1>; + vlan_tag = <1 0x10>; +}; + +&usb2_hs_phy { + status = "okay"; +}; + +&pcie0 { + status = "okay"; + perst-gpio = <&tlmm 38 GPIO_ACTIVE_LOW>; + wake-gpio = <&tlmm 50 GPIO_ACTIVE_LOW>; + + bridge@0,0 { + reg = <0x00000000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + ranges; + + wifi2: wifi@1,0 { + compatible = "qcom,ath10k"; + status = "okay"; + reg = <0x00010000 0 0 0 0>; + qcom,ath10k-calibration-variant = "OM-A62"; + ieee80211-freq-limit = <5170000 5350000>; + }; + }; +}; + +&wifi0 { + status = "okay"; + qcom,ath10k-calibration-variant = "OM-A62"; +}; + +&wifi1 { + status = "okay"; + qcom,ath10k-calibration-variant = "OM-A62"; + ieee80211-freq-limit = <5470000 5875000>; +}; diff --git a/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-cm520-79f.dts b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-cm520-79f.dts new file mode 100644 index 000000000..167094d4a --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-cm520-79f.dts @@ -0,0 +1,354 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "qcom-ipq4019.dtsi" +#include +#include +#include + +/ { + model = "MobiPromo CM520-79F"; + compatible = "mobipromo,cm520-79f"; + + aliases { + led-boot = &led_sys; + led-failsafe = &led_sys; + led-running = &led_sys; + led-upgrade = &led_sys; + }; + + soc { + rng@22000 { + status = "okay"; + }; + + mdio@90000 { + status = "okay"; + pinctrl-0 = <&mdio_pins>; + pinctrl-names = "default"; + reset-gpios = <&tlmm 47 GPIO_ACTIVE_LOW>; + reset-delay-us = <1000>; + }; + + ess-psgmii@98000 { + status = "okay"; + }; + + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; + qcom,wifi_glb_cfg = ; + }; + + tcsr@194b000 { + compatible = "qcom,tcsr"; + reg = <0x194b000 0x100>; + qcom,usb-hsphy-mode-select = ; + }; + + ess_tcsr@1953000 { + compatible = "qcom,tcsr"; + reg = <0x1953000 0x1000>; + qcom,ess-interface-select = ; + }; + + tcsr@1957000 { + compatible = "qcom,tcsr"; + reg = <0x1957000 0x100>; + qcom,wifi_noc_memtype_m0_m2 = ; + }; + + usb2@60f8800 { + status = "okay"; + + dwc3@6000000 { + #address-cells = <1>; + #size-cells = <0>; + + usb2_port1: port@1 { + reg = <1>; + #trigger-source-cells = <0>; + }; + }; + }; + + usb3@8af8800 { + status = "okay"; + + dwc3@8a00000 { + #address-cells = <1>; + #size-cells = <0>; + + usb3_port1: port@1 { + reg = <1>; + #trigger-source-cells = <0>; + }; + + usb3_port2: port@2 { + reg = <2>; + #trigger-source-cells = <0>; + }; + }; + }; + + crypto@8e3a000 { + status = "okay"; + }; + + watchdog@b017000 { + status = "okay"; + }; + + ess-switch@c000000 { + status = "okay"; + }; + + edma@c080000 { + status = "okay"; + }; + }; + + led_spi { + compatible = "spi-gpio"; + #address-cells = <1>; + #size-cells = <0>; + + sck-gpios = <&tlmm 40 GPIO_ACTIVE_HIGH>; + mosi-gpios = <&tlmm 36 GPIO_ACTIVE_HIGH>; + num-chipselects = <0>; + + led_gpio: led_gpio@0 { + compatible = "fairchild,74hc595"; + reg = <0>; + gpio-controller; + #gpio-cells = <2>; + registers-number = <1>; + spi-max-frequency = <1000000>; + }; + }; + + leds { + compatible = "gpio-leds"; + + usb { + label = "blue:usb"; + gpios = <&tlmm 10 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "usbport"; + trigger-sources = <&usb3_port1>, <&usb3_port2>, <&usb2_port1>; + }; + + led_sys: can { + label = "blue:can"; + gpios = <&tlmm 11 GPIO_ACTIVE_HIGH>; + }; + + wan { + label = "blue:wan"; + gpios = <&led_gpio 0 GPIO_ACTIVE_LOW>; + }; + + lan1 { + label = "blue:lan1"; + gpios = <&led_gpio 1 GPIO_ACTIVE_LOW>; + }; + + lan2 { + label = "blue:lan2"; + gpios = <&led_gpio 2 GPIO_ACTIVE_LOW>; + }; + + wlan2g { + label = "blue:wlan2g"; + gpios = <&led_gpio 5 GPIO_ACTIVE_LOW>; + linux,default-trigger = "phy0tpt"; + }; + + wlan5g { + label = "blue:wlan5g"; + gpios = <&led_gpio 6 GPIO_ACTIVE_LOW>; + linux,default-trigger = "phy1tpt"; + }; + }; + + keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + gpios = <&tlmm 18 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; +}; + +&blsp_dma { + status = "okay"; +}; + +&blsp1_uart1 { + status = "okay"; +}; + +&blsp1_uart2 { + status = "okay"; +}; + +&cryptobam { + status = "okay"; +}; + +&gmac0 { + mtd-mac-address = <&art 0x1006>; +}; + +&gmac1 { + mtd-mac-address = <&art 0x5006>; +}; + +&nand { + pinctrl-0 = <&nand_pins>; + pinctrl-names = "default"; + status = "okay"; + + nand@0 { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "SBL1"; + reg = <0x0 0x100000>; + read-only; + }; + + partition@100000 { + label = "MIBIB"; + reg = <0x100000 0x100000>; + read-only; + }; + + partition@200000 { + label = "BOOTCONFIG"; + reg = <0x200000 0x100000>; + }; + + partition@300000 { + label = "QSEE"; + reg = <0x300000 0x100000>; + read-only; + }; + + partition@400000 { + label = "QSEE_1"; + reg = <0x400000 0x100000>; + read-only; + }; + + partition@500000 { + label = "CDT"; + reg = <0x500000 0x80000>; + read-only; + }; + + partition@580000 { + label = "CDT_1"; + reg = <0x580000 0x80000>; + read-only; + }; + + partition@600000 { + label = "BOOTCONFIG1"; + reg = <0x600000 0x80000>; + }; + + partition@680000 { + label = "APPSBLENV"; + reg = <0x680000 0x80000>; + }; + + partition@700000 { + label = "APPSBL"; + reg = <0x700000 0x200000>; + read-only; + }; + + partition@900000 { + label = "APPSBL_1"; + reg = <0x900000 0x200000>; + read-only; + }; + + art: partition@b00000 { + label = "ART"; + reg = <0xb00000 0x80000>; + read-only; + }; + + partition@b80000 { + label = "ubi"; + reg = <0xb80000 0x7480000>; + }; + }; + }; +}; + +&qpic_bam { + status = "okay"; +}; + +&tlmm { + mdio_pins: mdio_pinmux { + mux_1 { + pins = "gpio6"; + function = "mdio"; + bias-pull-up; + }; + + mux_2 { + pins = "gpio7"; + function = "mdc"; + bias-pull-up; + }; + }; + + nand_pins: nand_pins { + pullups { + pins = "gpio52", "gpio53", "gpio58", + "gpio59"; + function = "qpic"; + bias-pull-up; + }; + + pulldowns { + pins = "gpio54", "gpio55", "gpio56", + "gpio57", "gpio60", "gpio61", + "gpio62", "gpio63", "gpio64", + "gpio65", "gpio66", "gpio67", + "gpio68", "gpio69"; + function = "qpic"; + bias-pull-down; + }; + }; +}; + +&usb3_ss_phy { + status = "okay"; +}; + +&usb3_hs_phy { + status = "okay"; +}; + +&usb2_hs_phy { + status = "okay"; +}; + +&wifi0 { + status = "okay"; + qcom,ath10k-calibration-variant = "CM520-79F"; +}; + +&wifi1 { + status = "okay"; + qcom,ath10k-calibration-variant = "CM520-79F"; +}; diff --git a/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-e2600ac-c1.dts b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-e2600ac-c1.dts new file mode 100644 index 000000000..df1df2529 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-e2600ac-c1.dts @@ -0,0 +1,80 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later OR MIT + * + * Copyright (c) 2018 Peng Zhang + * + */ + +#include "qcom-ipq4019-e2600ac.dtsi" +#include +#include + +/ { + model = "Qxwlan E2600AC c1"; + compatible = "qxwlan,e2600ac-c1"; +}; + +&blsp1_spi1 { + pinctrl-0 = <&spi_0_pins>; + pinctrl-names = "default"; + status = "okay"; + cs-gpios = <&tlmm 12 GPIO_ACTIVE_LOW>; + + flash@0 { + reg = <0>; + compatible = "jedec,spi-nor"; + spi-max-frequency = <24000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "0:SBL1"; + reg = <0x0 0x40000>; + read-only; + }; + partition@40000 { + label = "0:MIBIB"; + reg = <0x40000 0x20000>; + read-only; + }; + partition@60000 { + label = "0:QSEE"; + reg = <0x60000 0x60000>; + read-only; + }; + partition@c0000 { + label = "0:CDT"; + reg = <0xc0000 0x10000>; + read-only; + }; + partition@d0000 { + label = "0:DDRPARAMS"; + reg = <0xd0000 0x10000>; + read-only; + }; + partition@e0000 { + label = "0:APPSBLENV"; + reg = <0xe0000 0x10000>; + read-only; + }; + partition@f0000 { + label = "0:APPSBL"; + reg = <0xf0000 0x80000>; + read-only; + }; + partition@170000 { + label = "0:ART"; + reg = <0x170000 0x10000>; + read-only; + }; + partition@180000 { + compatible = "denx,fit"; + label = "firmware"; + reg = <0x180000 0x1e80000>; + }; + }; + }; +}; + diff --git a/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-e2600ac-c2.dts b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-e2600ac-c2.dts new file mode 100644 index 000000000..9348ef4ee --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-e2600ac-c2.dts @@ -0,0 +1,115 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later OR MIT + * + * Copyright (c) 2018 Peng Zhang + * + */ + +#include "qcom-ipq4019-e2600ac.dtsi" +#include +#include + +/ { + model = "Qxwlan E2600AC c2"; + compatible = "qxwlan,e2600ac-c2"; +}; + +&blsp1_spi1 { + pinctrl-0 = <&spi_0_pins>; + pinctrl-names = "default"; + status = "okay"; + cs-gpios = <&tlmm 12 GPIO_ACTIVE_LOW>; + + flash@0 { + reg = <0>; + compatible = "jedec,spi-nor"; + spi-max-frequency = <24000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "0:SBL1"; + reg = <0x0 0x40000>; + read-only; + }; + partition@40000 { + label = "0:MIBIB"; + reg = <0x40000 0x20000>; + read-only; + }; + partition@60000 { + label = "0:QSEE"; + reg = <0x60000 0x60000>; + read-only; + }; + partition@c0000 { + label = "0:CDT"; + reg = <0xc0000 0x10000>; + read-only; + }; + partition@d0000 { + label = "0:DDRPARAMS"; + reg = <0xd0000 0x10000>; + read-only; + }; + partition@e0000 { + label = "0:APPSBLENV"; + reg = <0xe0000 0x10000>; + read-only; + }; + partition@f0000 { + label = "0:APPSBL"; + reg = <0xf0000 0x80000>; + read-only; + }; + partition@170000 { + label = "0:ART"; + reg = <0x170000 0x10000>; + read-only; + }; + }; + }; +}; + +&nand { + pinctrl-0 = <&nand_pins>; + pinctrl-names = "default"; + status = "okay"; + + nand@0 { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "ubi"; + reg = <0x00000000 0x04000000>; + }; + }; + }; +}; + +&tlmm { + nand_pins: nand-pins { + + pullups { + pins = "gpio53", "gpio58", "gpio59"; + function = "qpic"; + bias-pull-up; + }; + + pulldowns { + pins = "gpio54", "gpio55", "gpio56", + "gpio57", "gpio60", "gpio61", + "gpio62", "gpio63", "gpio64", + "gpio65", "gpio66", "gpio67", + "gpio68", "gpio69"; + function = "qpic"; + bias-pull-down; + }; + }; +}; + diff --git a/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-e2600ac.dtsi b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-e2600ac.dtsi new file mode 100644 index 000000000..57d607849 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-e2600ac.dtsi @@ -0,0 +1,266 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later OR MIT + * + * Copyright (c) 2018 Peng Zhang + * + */ + +#include "qcom-ipq4019.dtsi" +#include +#include +#include + +/ { + + model = "Qxwlan E2600AC"; + compatible = "qcom,ipq4019"; + + memory { + device_type = "memory"; + reg = <0x80000000 0x10000000>; /* 256MB */ + }; + + soc { + rng@22000 { + status = "okay"; + }; + + mdio@90000 { + status = "okay"; + pinctrl-0 = <&mdio_pins>; + pinctrl-names = "default"; + }; + + ess-psgmii@98000 { + status = "okay"; + }; + + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; + qcom,wifi_glb_cfg = ; + }; + + tcsr@194b000 { + /* select hostmode */ + compatible = "qcom,tcsr"; + reg = <0x194b000 0x100>; + qcom,usb-hsphy-mode-select = ; + status = "okay"; + }; + + ess_tcsr@1953000 { + compatible = "qcom,tcsr"; + reg = <0x1953000 0x1000>; + qcom,ess-interface-select = ; + }; + + tcsr@1957000 { + compatible = "qcom,tcsr"; + reg = <0x1957000 0x100>; + qcom,wifi_noc_memtype_m0_m2 = ; + }; + + usb2: usb2@60f8800 { + status = "okay"; + + dwc3@6000000 { + #address-cells = <1>; + #size-cells = <0>; + + usb2_port1: port@1 { + reg = <1>; + #trigger-source-cells = <0>; + }; + }; + }; + + serial@78af000 { + pinctrl-0 = <&serial_0_pins>; + pinctrl-names = "default"; + status = "okay"; + }; + + serial@78b0000 { + pinctrl-0 = <&serial_1_pins>; + pinctrl-names = "default"; + status = "okay"; + }; + + i2c@78b7000 { /* BLSP1 QUP2 */ + pinctrl-0 = <&i2c_0_pins>; + pinctrl-names = "default"; + + status = "okay"; + }; + + usb3: usb3@8af8800 { + status = "okay"; + + dwc3@8a00000 { + #address-cells = <1>; + #size-cells = <0>; + + usb3_port1: port@1 { + reg = <1>; + #trigger-source-cells = <0>; + }; + + usb3_port2: port@2 { + reg = <2>; + #trigger-source-cells = <0>; + }; + }; + }; + + crypto@8e3a000 { + status = "okay"; + }; + + watchdog@b017000 { + status = "okay"; + }; + + ess-switch@c000000 { + status = "okay"; + }; + + edma@c080000 { + status = "okay"; + }; + + leds { + compatible = "gpio-leds"; + + led1 { + label = "green:wlan0"; + gpios = <&tlmm 50 GPIO_ACTIVE_LOW>; + }; + + led2 { + label = "green:wlan1"; + gpios = <&tlmm 36 GPIO_ACTIVE_LOW>; + }; + + led3 { + label = "green:usb"; + gpios = <&tlmm 32 GPIO_ACTIVE_LOW>; + trigger-sources = <&usb2_port1>, <&usb3_port1>, <&usb3_port2>; + linux,default-trigger = "usbport"; + }; + + led4 { + label = "green:ctrl1"; + gpios = <&tlmm 51 GPIO_ACTIVE_LOW>; + }; + + led5 { + label = "green:ctrl2"; + gpios = <&tlmm 30 GPIO_ACTIVE_LOW>; + }; + + led6 { + label = "green:ctrl3"; + gpios = <&tlmm 31 GPIO_ACTIVE_LOW>; + }; + }; + + keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + gpios = <&tlmm 18 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + }; +}; + +&blsp_dma { + status = "okay"; +}; + +&cryptobam { + status = "okay"; +}; + +&qpic_bam { + status = "okay"; +}; + +&tlmm { + i2c_0_pins: i2c-0-pinmux { + mux { + pins = "gpio20", "gpio21"; + function = "blsp_i2c0"; + bias-disable; + }; + }; + + mdio_pins: mdio_pinmux { + mux_1 { + pins = "gpio6"; + function = "mdio"; + bias-pull-up; + }; + mux_2 { + pins = "gpio7"; + function = "mdc"; + bias-pull-up; + }; + }; + + serial_0_pins: serial0-pinmux { + mux { + pins = "gpio16", "gpio17"; + function = "blsp_uart0"; + bias-disable; + }; + }; + + serial_1_pins: serial1_pinmux { + mux { + pins = "gpio8", "gpio9"; + function = "blsp_uart1"; + bias-disable; + }; + }; + + spi_0_pins: spi_0_pinmux { + pinmux { + function = "blsp_spi0"; + pins = "gpio13", "gpio14", "gpio15"; + drive-strength = <12>; + bias-disable; + }; + pinmux_cs { + function = "gpio"; + pins = "gpio12"; + drive-strength = <2>; + bias-disable; + output-high; + }; + }; +}; + +&usb3_ss_phy { + status = "okay"; +}; + +&usb3_hs_phy { + status = "okay"; +}; + +&usb2_hs_phy { + status = "okay"; +}; + +&wifi0 { + status = "okay"; + qcom,ath10k-calibration-variant = "Qxwlan-E2600AC"; +}; + +&wifi1 { + status = "okay"; + qcom,ath10k-calibration-variant = "Qxwlan-E2600AC"; +}; diff --git a/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-ea8300.dts b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-ea8300.dts new file mode 100644 index 000000000..5a738da33 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-ea8300.dts @@ -0,0 +1,95 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "qcom-ipq4019-xx8300.dtsi" + +/ { + model = "Linksys EA8300 (Dallas)"; + compatible = "linksys,ea8300", "qcom,ipq4019"; + + + aliases { + led-boot = &led_wps_amber; + led-failsafe = &led_wps; + led-running = &led_linksys; + led-upgrade = &led_world; + serial0 = &blsp1_uart1; + }; + + + leds { + compatible = "gpio-leds"; + + // Retain node names from running OEM on EA8300 + + // Front panel LEDs, top to bottom + + led_plug: diag { + label = "amber:plug"; + gpios = <&tlmm 47 GPIO_ACTIVE_HIGH>; + }; + + led_world: internet { + label = "amber:world"; + gpios = <&tlmm 49 GPIO_ACTIVE_HIGH>; + }; + + led_wps: wps { + label = "white:wps"; + gpios = <&tlmm 46 GPIO_ACTIVE_HIGH>; + }; + + led_wps_amber: wps_amber { + label = "amber:wps"; + gpios = <&tlmm 22 GPIO_ACTIVE_HIGH>; + panic-indicator; + }; + + led_linksys: pwr { + label = "white:linksys"; + gpios = <&tlmm 45 GPIO_ACTIVE_HIGH>; + }; + + // On back panel, above USB socket + + led_usb: usb { + label = "green:usb"; + gpios = <&tlmm 61 GPIO_ACTIVE_LOW>; + trigger-sources = <&usb3_port1>, <&usb3_port2>, + <&usb2_port1>; + linux,default-trigger = "usbport"; + }; + }; + + keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + linux,code = ; + gpios = <&tlmm 50 GPIO_ACTIVE_LOW>; + }; + + wps { + label = "wps"; + linux,code = ; + gpios = <&tlmm 18 GPIO_ACTIVE_LOW>; + }; + }; +}; + +&wifi0 { + status = "okay"; + qcom,ath10k-calibration-variant = "linksys-ea8300-fcc"; +}; + +&wifi1 { + status = "okay"; + ieee80211-freq-limit = <5170000 5330000>; + qcom,ath10k-calibration-variant = "linksys-ea8300-fcc"; +}; + +&wifi2 { + status = "okay"; + ieee80211-freq-limit = <5490000 5835000>; + qcom,ath10k-calibration-variant = "linksys-ea8300-fcc"; +}; diff --git a/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-eap2200.dts b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-eap2200.dts new file mode 100644 index 000000000..95e616695 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-eap2200.dts @@ -0,0 +1,282 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "qcom-ipq4019.dtsi" +#include +#include + +/ { + model = "EnGenius EAP2200"; + compatible = "engenius,eap2200"; + + aliases { + led-boot = &led_power; + led-failsafe = &led_power; + led-running = &led_power; + led-upgrade = &led_power; + }; + + keys { + compatible = "gpio-keys"; + + wps { + label = "wps"; + gpios = <&tlmm 18 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + leds { + compatible = "gpio-leds"; + + led_power: power { + label = "amber:power"; + gpios = <&tlmm 43 GPIO_ACTIVE_LOW>; + }; + + lan1 { + label = "blue:lan1"; + gpios = <&tlmm 44 GPIO_ACTIVE_LOW>; + }; + + lan2 { + label = "blue:lan2"; + gpios = <&tlmm 45 GPIO_ACTIVE_LOW>; + }; + + wlan2g { + label = "blue:wlan2g"; + gpios = <&tlmm 46 GPIO_ACTIVE_LOW>; + linux,default-trigger = "phy0tpt"; + }; + + wlan5g { + label = "yellow:wlan5g"; + gpios = <&tlmm 47 GPIO_ACTIVE_LOW>; + linux,default-trigger = "phy1tpt"; + }; + + wlan5g2 { + label = "yellow:wlan5g2"; + gpios = <&tlmm 48 GPIO_ACTIVE_LOW>; + linux,default-trigger = "phy2tpt"; + }; + + mode { + label = "blue:mode"; + gpios = <&tlmm 50 GPIO_ACTIVE_LOW>; + }; + }; + + soc { + rng@22000 { + status = "okay"; + }; + + mdio@90000 { + status = "okay"; + }; + + ess-psgmii@98000 { + status = "okay"; + }; + + crypto@8e3a000 { + status = "okay"; + }; + + watchdog@b017000 { + status = "okay"; + }; + + ess-switch@c000000 { + status = "okay"; + switch_lan_bmp = <0x10>; + }; + + edma@c080000 { + status = "okay"; + }; + }; +}; + +&blsp_dma { + status = "okay"; +}; + +&blsp1_spi1 { + pinctrl-0 = <&spi_0_pins>; + pinctrl-names = "default"; + status = "okay"; + cs-gpios = <&tlmm 12 GPIO_ACTIVE_HIGH>; + + flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <24000000>; + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition0@0 { + label = "0:SBL1"; + reg = <0x00000000 0x00040000>; + read-only; + }; + partition1@40000 { + label = "0:MIBIB"; + reg = <0x00040000 0x00020000>; + read-only; + }; + partition2@60000 { + label = "0:QSEE"; + reg = <0x00060000 0x00060000>; + read-only; + }; + partition3@c0000 { + label = "0:CDT"; + reg = <0x000c0000 0x00010000>; + read-only; + }; + partition4@d0000 { + label = "0:DDRPARAMS"; + reg = <0x000d0000 0x00010000>; + read-only; + }; + partition5@e0000 { + label = "0:APPSBLENV"; + reg = <0x000e0000 0x00010000>; + read-only; + }; + partition6@f0000 { + label = "0:APPSBL"; + reg = <0x000f0000 0x00080000>; + read-only; + }; + partition7@170000 { + label = "0:ART"; + reg = <0x00170000 0x00010000>; + read-only; + }; + }; + }; +}; + +&blsp1_uart1 { + pinctrl-0 = <&serial_0_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + +&cryptobam { + status = "okay"; +}; + +&gmac0 { + vlan_tag = <1 0x10>; +}; + +&nand { + pinctrl-0 = <&nand_pins>; + pinctrl-names = "default"; + status = "okay"; + + nand@0 { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "rootfs1"; + reg = <0x00000000 0x04000000>; + }; + partition@40000000 { + label = "ubi"; + reg = <0x04000000 0x04000000>; + }; + + }; + }; +}; + +&pcie0 { + status = "okay"; + perst-gpio = <&tlmm 38 GPIO_ACTIVE_LOW>; + wake-gpio = <&tlmm 50 GPIO_ACTIVE_LOW>; + + bridge@0,0 { + reg = <0x00000000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + ranges; + + wifi2: wifi@1,0 { + compatible = "qcom,ath10k"; + reg = <0x00010000 0 0 0 0>; + ieee80211-freq-limit = <5470000 5875000>; + qcom,ath10k-calibration-variant = "EnGenius-EAP2200"; + }; + }; +}; + +&qpic_bam { + status = "okay"; +}; + +&tlmm { + nand_pins: nand_pins { + pullups { + pins = "gpio53", "gpio58", "gpio59"; + function = "qpic"; + bias-pull-up; + }; + + pulldowns { + pins = "gpio54", "gpio55", "gpio56", + "gpio57", "gpio60", "gpio61", + "gpio62", "gpio63", "gpio64", + "gpio65", "gpio66", "gpio67", + "gpio68", "gpio69"; + function = "qpic"; + bias-pull-down; + }; + }; + + serial_0_pins: serial_pinmux { + mux { + pins = "gpio16", "gpio17"; + function = "blsp_uart0"; + bias-disable; + }; + }; + + spi_0_pins: spi_0_pinmux { + pinmux { + function = "blsp_spi0"; + pins = "gpio13", "gpio14", "gpio15"; + drive-strength = <12>; + bias-disable; + }; + pinmux_cs { + function = "gpio"; + pins = "gpio12"; + drive-strength = <2>; + bias-disable; + output-high; + }; + }; +}; + +&wifi0 { + status = "okay"; + qcom,ath10k-calibration-variant = "EnGenius-EAP2200"; +}; + +&wifi1 { + status = "okay"; + ieee80211-freq-limit = <5170000 5350000>; + qcom,ath10k-calibration-variant = "EnGenius-EAP2200"; +}; diff --git a/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-fritzbox-7530.dts b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-fritzbox-7530.dts new file mode 100644 index 000000000..dcd336e71 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-fritzbox-7530.dts @@ -0,0 +1,303 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "qcom-ipq4019.dtsi" +#include +#include +#include + +/ { + model = "AVM FRITZ!Box 7530"; + compatible = "avm,fritzbox-7530"; + + aliases { + led-boot = &power_green; + led-failsafe = &info_red; + led-running = &power_green; + led-upgrade = &info_green; + }; + + soc { + rng@22000 { + status = "okay"; + }; + + mdio@90000 { + status = "okay"; + }; + + ess-psgmii@98000 { + status = "okay"; + }; + + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; + qcom,wifi_glb_cfg = ; + }; + + tcsr@194b000 { + compatible = "qcom,tcsr"; + reg = <0x194b000 0x100>; + qcom,usb-hsphy-mode-select = ; + }; + + ess_tcsr@1953000 { + compatible = "qcom,tcsr"; + reg = <0x1953000 0x1000>; + qcom,ess-interface-select = ; + }; + + tcsr@1957000 { + compatible = "qcom,tcsr"; + reg = <0x1957000 0x100>; + qcom,wifi_noc_memtype_m0_m2 = ; + }; + + usb3@8af8800 { + status = "okay"; + }; + + crypto@8e3a000 { + status = "okay"; + }; + + watchdog@b017000 { + status = "okay"; + }; + + ess-switch@c000000 { + status = "okay"; + }; + + edma@c080000 { + status = "okay"; + qcom,num_gmac = <1>; + }; + }; + + keys { + compatible = "gpio-keys"; + + wlan { + label = "wlan"; + gpios = <&tlmm 42 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + + wps { + label = "wps"; + gpios = <&tlmm 41 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + + dect { + label = "dect"; + gpios = <&tlmm 43 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + leds { + compatible = "gpio-leds"; + + info_red: info_red { + label = "red:info"; + gpios = <&tlmm 32 GPIO_ACTIVE_LOW>; + }; + + info_green: info { + label = "green:info"; + gpios = <&tlmm 33 GPIO_ACTIVE_LOW>; + }; + + wlan { + label = "green:wlan"; + gpios = <&tlmm 34 GPIO_ACTIVE_LOW>; + }; + + fon { + label = "green:fon"; + gpios = <&tlmm 35 GPIO_ACTIVE_LOW>; + }; + + power_green: power { + label = "green:power"; + gpios = <&tlmm 39 GPIO_ACTIVE_LOW>; + }; + + wps { + label = "green:wps"; + gpios = <&tlmm 45 GPIO_ACTIVE_LOW>; + }; + }; +}; + +&tlmm { + serial_0_pins: serial_pinmux { + mux { + pins = "gpio16", "gpio17"; + function = "blsp_uart0"; + bias-disable; + }; + }; + + nand_pins: nand_pins { + pullups { + pins = "gpio53", "gpio58", "gpio59"; + function = "qpic"; + bias-pull-up; + }; + + pulldowns { + pins = "gpio54", "gpio55", "gpio56", + "gpio57", "gpio60", "gpio61", + "gpio62", "gpio63", "gpio64", + "gpio65", "gpio66", "gpio67", + "gpio68", "gpio69"; + function = "qpic"; + bias-pull-down; + }; + }; + + usb-power { + line-name = "enable USB3 power"; + gpios = <49 GPIO_ACTIVE_HIGH>; + gpio-hog; + output-high; + }; +}; + +&nand { + pinctrl-0 = <&nand_pins>; + pinctrl-names = "default"; + status = "okay"; + + nand@0 { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "SBL1"; + reg = <0x000000 0x80000>; + read-only; + }; + + partition@80000 { + label = "MIBIB"; + reg = <0x080000 0x80000>; + read-only; + }; + + partition@100000 { + label = "QSEE"; + reg = <0x100000 0x80000>; + read-only; + }; + + partition@180000 { + label = "CDT"; + reg = <0x180000 0x40000>; + read-only; + }; + + partition@1c0000 { + label = "QSEE_B"; + reg = <0x1c0000 0x80000>; + read-only; + }; + + partition@240000 { + label = "urlader0"; + reg = <0x240000 0x40000>; + read-only; + }; + + partition@280000 { + label = "urlader1"; + reg = <0x280000 0x40000>; + read-only; + }; + + partition@2c0000 { + label = "nand-tffs"; + reg = <0x2c0000 0x840000>; + read-only; + }; + + partition@b00000 { + /* 'kernel1' in AVM firmware */ + label = "uboot0"; + reg = <0xb00000 0x400000>; + }; + + partition@f00000 { + /* 'kernel2' in AVM firmware */ + label = "uboot1"; + reg = <0xf00000 0x400000>; + }; + + partition@1300000 { + label = "ubi"; + reg = <0x1300000 0x6d00000>; + }; + }; + }; +}; + +&cryptobam { + status = "okay"; +}; + +&blsp_dma { + status = "okay"; +}; + +&blsp1_uart1 { + pinctrl-0 = <&serial_0_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + +&usb3_ss_phy { + status = "okay"; +}; + +&usb3_hs_phy { + status = "okay"; +}; + +&qpic_bam { + status = "okay"; +}; + +&wifi0 { + status = "okay"; + qcom,ath10k-calibration-variant = "AVM-FRITZBox-7530"; +}; + +&wifi1 { + status = "okay"; + qcom,ath10k-calibration-variant = "AVM-FRITZBox-7530"; +}; + +&pcie0 { + status = "okay"; + + perst-gpio = <&tlmm 38 GPIO_ACTIVE_LOW>; + wake-gpio = <&tlmm 50 GPIO_ACTIVE_LOW>; + + bridge@0,0 { + reg = <0x00000000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + ranges; + + dsl@1,0 { + compatible = "intel,vrx518"; + status = "okay"; + reg = <0x00010000 0 0 0 0>; + }; + }; +}; diff --git a/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-fritzrepeater-1200.dts b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-fritzrepeater-1200.dts new file mode 100644 index 000000000..2d20d5928 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-fritzrepeater-1200.dts @@ -0,0 +1,273 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "qcom-ipq4019.dtsi" +#include +#include +#include + +/ { + model = "AVM FRITZ!Repeater 1200"; + compatible = "avm,fritzrepeater-1200"; + + aliases { + led-boot = &power_green; + led-failsafe = &power_red; + led-running = &power_green; + led-upgrade = &power_red; + label-mac-device = &wifi0; + }; + + soc { + rng@22000 { + status = "okay"; + }; + + mdio@90000 { + status = "okay"; + pinctrl-0 = <&mdio_pins>; + pinctrl-names = "default"; + + /delete-node/ ethernet-phy@1; + /delete-node/ ethernet-phy@2; + /delete-node/ ethernet-phy@3; + /delete-node/ ethernet-phy@4; + /delete-node/ psgmii-phy@5; + }; + + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; + qcom,wifi_glb_cfg = ; + }; + + ess_tcsr@1953000 { + compatible = "qcom,tcsr"; + reg = <0x1953000 0x1000>; + qcom,ess-interface-select = ; + }; + + tcsr@1957000 { + compatible = "qcom,tcsr"; + reg = <0x1957000 0x100>; + qcom,wifi_noc_memtype_m0_m2 = ; + }; + + crypto@8e3a000 { + status = "okay"; + }; + + watchdog@b017000 { + status = "okay"; + }; + + ess-switch@c000000 { + switch_mac_mode = <0x3>; /* mac mode for RGMII RMII */ + switch_lan_bmp = <0x0>; /* lan port bitmap */ + switch_wan_bmp = <0x10>; /* wan port bitmap */ + }; + + edma@c080000 { + status = "okay"; + phy-mode = "rgmii-id"; + qcom,num_gmac = <1>; + qcom,single-phy; + }; + }; + + key { + compatible = "gpio-keys"; + + wps { + label = "WPS button"; + gpios = <&tlmm 10 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + leds { + compatible = "gpio-leds"; + + power_red: power_red { + label = "red:power"; + gpios = <&tlmm 50 GPIO_ACTIVE_LOW>; + }; + + power_green: power_green { + label = "green:power"; + gpios = <&tlmm 45 GPIO_ACTIVE_HIGH>; + }; + + power_yellow { + label = "yellow:power"; + gpios = <&tlmm 49 GPIO_ACTIVE_LOW>; + }; + }; +}; + +&tlmm { + serial_0_pins: serial_pinmux { + mux { + pins = "gpio16", "gpio17"; + function = "blsp_uart0"; + bias-disable; + }; + }; + + nand_pins: nand_pins { + pullups { + pins = "gpio53", "gpio58", "gpio59"; + function = "qpic"; + bias-pull-up; + }; + + pulldowns { + pins = "gpio54", "gpio55", "gpio56", + "gpio57", "gpio60", "gpio61", + "gpio62", "gpio63", "gpio64", + "gpio65", "gpio66", "gpio67", + "gpio68", "gpio69"; + function = "qpic"; + bias-pull-down; + }; + }; + + mdio_pins: mdio_pinmux { + mux_1 { + pins = "gpio6"; + function = "mdio"; + bias-pull-up; + }; + mux_2 { + pins = "gpio7"; + function = "mdc"; + bias-pull-up; + }; + }; + + phy-reset { + line-name = "PHY-reset"; + gpios = <19 GPIO_ACTIVE_HIGH>; + gpio-hog; + output-high; + }; + + phy-reset-2 { + line-name = "PHY-reset-2"; + gpios = <47 GPIO_ACTIVE_HIGH>; + gpio-hog; + output-high; + }; +}; + +&nand { + pinctrl-0 = <&nand_pins>; + pinctrl-names = "default"; + status = "okay"; + + nand@0 { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "SBL1"; + reg = <0x0 0x80000>; + read-only; + }; + + partition@80000 { + label = "MIBIB"; + reg = <0x80000 0x80000>; + read-only; + }; + + partition@100000 { + label = "QSEE"; + reg = <0x100000 0x80000>; + read-only; + }; + + partition@180000 { + label = "CDT"; + reg = <0x180000 0x40000>; + read-only; + }; + + partition@1c0000 { + label = "QSEE_B"; + reg = <0x1c0000 0x80000>; + read-only; + }; + + partition@240000 { + label = "urlader0"; + reg = <0x240000 0x40000>; + read-only; + }; + + partition@280000 { + label = "urlader1"; + reg = <0x280000 0x40000>; + read-only; + }; + + partition@2c0000 { + label = "nand-tffs"; + reg = <0x2c0000 0x840000>; + read-only; + }; + + partition@b00000 { + /* 'kernel1' in AVM firmware */ + label = "uboot0"; + reg = <0xb00000 0x400000>; + }; + + partition@f00000 { + /* 'kernel2' in AVM firmware */ + label = "uboot1"; + reg = <0xf00000 0x400000>; + }; + + partition@1300000 { + label = "ubi"; + reg = <0x1300000 0x6d00000>; + }; + }; + }; +}; + +&cryptobam { + status = "okay"; +}; + +&blsp_dma { + status = "okay"; +}; + +&blsp1_uart1 { + pinctrl-0 = <&serial_0_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + +&qpic_bam { + status = "okay"; +}; + +&wifi0 { + status = "okay"; + qcom,ath10k-calibration-variant = "AVM-FRITZRepeater-1200"; +}; + +&wifi1 { + status = "okay"; + qcom,ath10k-calibration-variant = "AVM-FRITZRepeater-1200"; +}; + +&gmac0 { + qcom,phy_mdio_addr = <0>; + qcom,poll_required = <1>; + vlan_tag = <0 0x20>; +}; diff --git a/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-fritzrepeater-3000.dts b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-fritzrepeater-3000.dts new file mode 100644 index 000000000..2e4bfd69b --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-fritzrepeater-3000.dts @@ -0,0 +1,269 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "qcom-ipq4019.dtsi" +#include +#include +#include + +/ { + model = "AVM FRITZ!Repeater 3000"; + compatible = "avm,fritzrepeater-3000"; + + aliases { + led-boot = &power_led; + led-failsafe = &power_led; + led-running = &power_led; + led-upgrade = &power_led; + }; + + soc { + rng@22000 { + status = "okay"; + }; + + mdio@90000 { + status = "okay"; + }; + + ess-psgmii@98000 { + status = "okay"; + }; + + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; + qcom,wifi_glb_cfg = ; + }; + + ess_tcsr@1953000 { + compatible = "qcom,tcsr"; + reg = <0x1953000 0x1000>; + qcom,ess-interface-select = ; + }; + + tcsr@1957000 { + compatible = "qcom,tcsr"; + reg = <0x1957000 0x100>; + qcom,wifi_noc_memtype_m0_m2 = ; + }; + + crypto@8e3a000 { + status = "okay"; + }; + + watchdog@b017000 { + status = "okay"; + }; + + ess-switch@c000000 { + status = "okay"; + + switch_lan_bmp = <0x30>; + switch_wan_bmp = <0x02>; + }; + + edma@c080000 { + status = "okay"; + qcom,num_gmac = <1>; + }; + }; + + key { + compatible = "gpio-keys"; + + connect { + label = "Connect"; + gpios = <&tlmm 10 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + leds { + compatible = "gpio-leds"; + + connect_red { + label = "red:connect"; + gpios = <&tlmm 30 GPIO_ACTIVE_LOW>; + }; + + connect_green { + label = "green:connect"; + gpios = <&tlmm 31 GPIO_ACTIVE_LOW>; + }; + + connect_blue { + label = "blue:connect"; + gpios = <&tlmm 32 GPIO_ACTIVE_LOW>; + }; + + power_led: power { + label = "green:power"; + gpios = <&tlmm 33 GPIO_ACTIVE_LOW>; + }; + }; +}; + +&tlmm { + serial_0_pins: serial_pinmux { + mux { + pins = "gpio16", "gpio17"; + function = "blsp_uart0"; + bias-disable; + }; + }; + + nand_pins: nand_pins { + pullups { + pins = "gpio53", "gpio58", "gpio59"; + function = "qpic"; + bias-pull-up; + }; + + pulldowns { + pins = "gpio54", "gpio55", "gpio56", + "gpio57", "gpio60", "gpio61", + "gpio62", "gpio63", "gpio64", + "gpio65", "gpio66", "gpio67", + "gpio68", "gpio69"; + function = "qpic"; + bias-pull-down; + }; + }; +}; + +&nand { + pinctrl-0 = <&nand_pins>; + pinctrl-names = "default"; + status = "okay"; + + nand@0 { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "SBL1"; + reg = <0x000000 0x80000>; + read-only; + }; + + partition@80000 { + label = "MIBIB"; + reg = <0x080000 0x80000>; + read-only; + }; + + partition@100000 { + label = "QSEE"; + reg = <0x100000 0x80000>; + read-only; + }; + + partition@180000 { + label = "CDT"; + reg = <0x180000 0x40000>; + read-only; + }; + + partition@1c0000 { + label = "QSEE_B"; + reg = <0x1c0000 0x80000>; + read-only; + }; + + partition@240000 { + label = "urlader0"; + reg = <0x240000 0x40000>; + read-only; + }; + + partition@280000 { + label = "urlader1"; + reg = <0x280000 0x40000>; + read-only; + }; + + partition@2c0000 { + label = "nand-tffs"; + reg = <0x2c0000 0x840000>; + read-only; + }; + + partition@b00000 { + /* 'kernel1' in AVM firmware */ + label = "uboot0"; + reg = <0xb00000 0x400000>; + }; + + partition@f00000 { + /* 'kernel2' in AVM firmware */ + label = "uboot1"; + reg = <0xf00000 0x400000>; + }; + + partition@1300000 { + label = "ubi"; + reg = <0x1300000 0x6d00000>; + }; + }; + }; +}; + +&gmac0 { + vlan_tag = <1 0x30>; +}; + +&cryptobam { + status = "okay"; +}; + +&blsp_dma { + status = "okay"; +}; + +&blsp1_uart1 { + pinctrl-0 = <&serial_0_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + +&qpic_bam { + status = "okay"; +}; + +&wifi0 { + status = "okay"; + /* BDFs are identical for the FRITZ!Box 7530 and the FRITZ!Repeater 3000 */ + qcom,ath10k-calibration-variant = "AVM-FRITZRepeater-3000"; +}; + +&wifi1 { + status = "okay"; + ieee80211-freq-limit = <5170000 5350000>; + /* BDFs are identical for the FRITZ!Box 7530 and the FRITZ!Repeater 3000 */ + qcom,ath10k-calibration-variant = "AVM-FRITZRepeater-3000"; +}; + +&pcie0 { + status = "okay"; + + perst-gpio = <&tlmm 35 GPIO_ACTIVE_LOW>; + wake-gpio = <&tlmm 50 GPIO_ACTIVE_LOW>; + + bridge@0,0 { + reg = <0x00000000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + ranges; + + wifi@1,0 { + /* QCA9984 */ + compatible = "qcom,ath10k"; + status = "okay"; + reg = <0x00010000 0 0 0 0>; + ieee80211-freq-limit = <5470000 5875000>; + /* Uses the reference BDF */ + }; + }; +}; diff --git a/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-habanero-dvk.dts b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-habanero-dvk.dts new file mode 100644 index 000000000..49cf2cabf --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-habanero-dvk.dts @@ -0,0 +1,357 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT +/* Copyright (c) 2019, Robert Marko */ + +#include "qcom-ipq4019.dtsi" +#include +#include +#include + +/ { + model = "8devices Habanero DVK"; + compatible = "8dev,habanero-dvk"; + + aliases { + led-boot = &led_status; + led-failsafe = &led_status; + led-running = &led_status; + led-upgrade = &led_upgrade; + }; + + soc { + rng@22000 { + status = "okay"; + }; + + mdio@90000 { + status = "okay"; + + pinctrl-0 = <&mdio_pins>; + pinctrl-names = "default"; + }; + + ess-psgmii@98000 { + status = "okay"; + }; + + counter@4a1000 { + compatible = "qcom,qca-gcnt"; + reg = <0x4a1000 0x4>; + }; + + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; + qcom,wifi_glb_cfg = ; + }; + + tcsr@194b000 { + status = "okay"; + + compatible = "qcom,tcsr"; + reg = <0x194b000 0x100>; + qcom,usb-hsphy-mode-select = ; + }; + + ess_tcsr@1953000 { + compatible = "qcom,tcsr"; + reg = <0x1953000 0x1000>; + qcom,ess-interface-select = ; + }; + + tcsr@1957000 { + compatible = "qcom,tcsr"; + reg = <0x1957000 0x100>; + qcom,wifi_noc_memtype_m0_m2 = ; + }; + + usb2: usb2@60f8800 { + status = "okay"; + }; + + usb3: usb3@8af8800 { + status = "okay"; + }; + + crypto@8e3a000 { + status = "okay"; + }; + + watchdog@b017000 { + status = "okay"; + }; + + ess-switch@c000000 { + status = "okay"; + }; + + edma@c080000 { + status = "okay"; + }; + }; + + keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + gpios = <&tlmm 8 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + leds { + compatible = "gpio-leds"; + + led_status: status { + label = "green:status"; + gpios = <&tlmm 37 GPIO_ACTIVE_HIGH>; + panic-indicator; + }; + + led_upgrade: upgrade { + label = "green:upgrade"; + gpios = <&tlmm 40 GPIO_ACTIVE_HIGH>; + }; + + wlan2g { + label = "green:wlan2g"; + gpios = <&tlmm 46 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "phy0tpt"; + }; + + wlan5g { + label = "green:wlan5g"; + gpios = <&tlmm 48 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "phy1tpt"; + }; + }; +}; + +&vqmmc { + status = "okay"; +}; + +&sdhci { + status = "okay"; + + pinctrl-0 = <&sd_pins>; + pinctrl-names = "default"; + cd-gpios = <&tlmm 22 GPIO_ACTIVE_LOW>; + vqmmc-supply = <&vqmmc>; +}; + +&qpic_bam { + status = "okay"; +}; + +&tlmm { + mdio_pins: mdio_pinmux { + mux_1 { + pins = "gpio6"; + function = "mdio"; + bias-pull-up; + }; + + mux_2 { + pins = "gpio7"; + function = "mdc"; + bias-pull-up; + }; + }; + + serial_pins: serial_pinmux { + mux { + pins = "gpio16", "gpio17"; + function = "blsp_uart0"; + bias-disable; + }; + }; + + spi_0_pins: spi_0_pinmux { + pinmux { + function = "blsp_spi0"; + pins = "gpio13", "gpio14", "gpio15"; + drive-strength = <12>; + bias-disable; + }; + + pinmux_cs { + function = "gpio"; + pins = "gpio12"; + drive-strength = <2>; + bias-disable; + output-high; + }; + }; + + nand_pins: nand_pins { + pullups { + pins = "gpio52", "gpio53", "gpio58", "gpio59"; + function = "qpic"; + bias-pull-up; + }; + + pulldowns { + pins = "gpio54", "gpio55", "gpio56", "gpio57", + "gpio60", "gpio62", "gpio63", "gpio64", + "gpio65", "gpio66", "gpio67", "gpio68", + "gpio69"; + function = "qpic"; + bias-pull-down; + }; + }; + + sd_pins: sd_pins { + pinmux { + function = "sdio"; + pins = "gpio23", "gpio24", "gpio25", "gpio26", + "gpio28", "gpio29", "gpio30", "gpio31"; + drive-strength = <10>; + }; + + pinmux_sd_clk { + function = "sdio"; + pins = "gpio27"; + drive-strength = <16>; + }; + + pinmux_sd7 { + function = "sdio"; + pins = "gpio32"; + drive-strength = <10>; + bias-disable; + }; + }; +}; + +&blsp_dma { + status = "okay"; +}; + +&blsp1_spi1 { + status = "okay"; + + pinctrl-0 = <&spi_0_pins>; + pinctrl-names = "default"; + cs-gpios = <&tlmm 12 GPIO_ACTIVE_HIGH>; + + flash@0 { + compatible = "jedec,spi-nor"; + spi-max-frequency = <24000000>; + reg = <0>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "SBL1"; + reg = <0x00000000 0x00040000>; + read-only; + }; + partition@40000 { + label = "MIBIB"; + reg = <0x00040000 0x00020000>; + read-only; + }; + partition@60000 { + label = "QSEE"; + reg = <0x00060000 0x00060000>; + read-only; + }; + partition@c0000 { + label = "CDT"; + reg = <0x000c0000 0x00010000>; + read-only; + }; + partition@d0000 { + label = "DDRPARAMS"; + reg = <0x000d0000 0x00010000>; + read-only; + }; + partition@e0000 { + label = "APPSBLENV"; /* uboot env */ + reg = <0x000e0000 0x00010000>; + read-only; + }; + partition@f0000 { + label = "APPSBL"; /* uboot */ + reg = <0x000f0000 0x00080000>; + read-only; + }; + partition@170000 { + label = "ART"; + reg = <0x00170000 0x00010000>; + read-only; + }; + partition@180000 { + label = "cfg"; + reg = <0x00180000 0x00040000>; + }; + partition@1c0000 { + label = "firmware"; + compatible = "denx,fit"; + reg = <0x001c0000 0x01e40000>; + }; + }; + }; +}; + +/* Some DVK boards ship without NAND */ +&nand { + status = "okay"; + + pinctrl-0 = <&nand_pins>; + pinctrl-names = "default"; +}; + +&blsp1_uart1 { + status = "okay"; + + pinctrl-0 = <&serial_pins>; + pinctrl-names = "default"; +}; + +&cryptobam { + status = "okay"; +}; + +&pcie0 { + status = "okay"; + + perst-gpio = <&tlmm 38 GPIO_ACTIVE_LOW>; + wake-gpio = <&tlmm 50 GPIO_ACTIVE_LOW>; + + /* Free slot for use */ + bridge@0,0 { + reg = <0x00000000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + ranges; + }; +}; + +&wifi0 { + status = "okay"; + + qcom,ath10k-calibration-variant = "8devices-Habanero"; +}; + +&wifi1 { + status = "okay"; + + qcom,ath10k-calibration-variant = "8devices-Habanero"; +}; + +&usb3_ss_phy { + status = "okay"; +}; + +&usb3_hs_phy { + status = "okay"; +}; + +&usb2_hs_phy { + status = "okay"; +}; diff --git a/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-hfcl-ion4.dts b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-hfcl-ion4.dts new file mode 100644 index 000000000..bb247c5b7 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-hfcl-ion4.dts @@ -0,0 +1,236 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "qcom-ipq4019.dtsi" +#include +#include +#include + +/ { + model = "HFCL Ltd, ION4"; + compatible = "hfcl,ion4"; + + aliases { +/* led-boot = &power_green; + led-failsafe = &power_red; + led-running = &power_green; + led-upgrade = &power_red; + label-mac-device = &wifi0; + */ + }; + + soc { + rng@22000 { + status = "okay"; + }; + + mdio@90000 { + status = "okay"; + pinctrl-0 = <&mdio_pins>; + pinctrl-names = "default"; + + /delete-node/ ethernet-phy@1; + /delete-node/ ethernet-phy@2; + /delete-node/ ethernet-phy@3; + /delete-node/ ethernet-phy@4; + /delete-node/ psgmii-phy@5; + }; + + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; + qcom,wifi_glb_cfg = ; + }; + + ess_tcsr@1953000 { + compatible = "qcom,tcsr"; + reg = <0x1953000 0x1000>; + qcom,ess-interface-select = ; + }; + + tcsr@1957000 { + compatible = "qcom,tcsr"; + reg = <0x1957000 0x100>; + qcom,wifi_noc_memtype_m0_m2 = ; + }; + + crypto@8e3a000 { + status = "okay"; + }; + + watchdog@b017000 { + status = "okay"; + }; + + ess-switch@c000000 { + switch_mac_mode = <0x3>; /* mac mode for RGMII RMII */ + switch_lan_bmp = <0x0>; /* lan port bitmap */ + switch_wan_bmp = <0x10>; /* wan port bitmap */ + }; + + edma@c080000 { + status = "okay"; + phy-mode = "rgmii-id"; + qcom,num_gmac = <1>; + qcom,single-phy; + }; + }; + + gpio_key { + compatible = "gpio-keys"; + button@1 { + label = "reset"; + linux,code = ; + gpios = <&tlmm 18 GPIO_ACTIVE_LOW>; + linux,input-type = <1>; + }; + }; + + leds { + compatible = "gpio-leds"; + + power_red: power_red { + label = "yellow:wlan2g"; + gpios = <&tlmm 45 GPIO_ACTIVE_HIGH>; + }; + + power_green: power_green { + label = "red:wlan5g"; + gpios = <&tlmm 46 GPIO_ACTIVE_HIGH>; + }; + }; +}; + +&tlmm { + serial_0_pins: serial_pinmux { + mux { + pins = "gpio16", "gpio17"; + function = "blsp_uart0"; + bias-disable; + }; + }; + + nand_pins: nand_pins { + pullups { + pins = "gpio53", "gpio58", "gpio59"; + function = "qpic"; + bias-pull-up; + }; + + pulldowns { + pins = "gpio54", "gpio55", "gpio56", + "gpio57", "gpio60", "gpio61", + "gpio62", "gpio63", "gpio64", + "gpio65", "gpio66", "gpio67", + "gpio68", "gpio69"; + function = "qpic"; + bias-pull-down; + }; + }; + + mdio_pins: mdio_pinmux { + mux_1 { + pins = "gpio6"; + function = "mdio"; + bias-pull-up; + }; + mux_2 { + pins = "gpio7"; + function = "mdc"; + bias-pull-up; + }; + }; +}; + +&nand { + pinctrl-0 = <&nand_pins>; + pinctrl-names = "default"; + status = "okay"; + + nand@0 { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition0@0 { + label = "0:SBL1"; + reg = <0x00000000 0x00100000>; + read-only; + }; + partition1@100000 { + label = "0:MIBIB"; + reg = <0x00100000 0x00100000>; + read-only; + }; + partition2@200000 { + label = "0:BOOTCONFIG"; + reg = <0x00200000 0x00100000>; + read-only; + }; + partition3@300000 { + label = "0:QSEE"; + reg = <0x00300000 0x00200000>; + read-only; + }; + partition4@500000 { + label = "0:CDT"; + reg = <0x00500000 0x00180000>; + read-only; + }; + partition5@680000 { + label = "0:APPSBLENV"; + reg = <0x00680000 0x00080000>; + }; + partition6@700000 { + label = "0:APPSBL"; + reg = <0x00700000 0x00400000>; + read-only; + }; + partition7@b00000 { + label = "0:ART"; + reg = <0x00b00000 0x00080000>; + read-only; + }; + partition8@b80000 { + label = "kernel"; + reg = <0x00b80000 0x1000000>; + }; + partition8@180000 { + label = "ubi"; + reg = <0x02b80000 0x5480000>; + }; + }; + }; +}; + +&cryptobam { + status = "okay"; +}; + +&blsp_dma { + status = "okay"; +}; + +&blsp1_uart1 { + pinctrl-0 = <&serial_0_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + +&qpic_bam { + status = "okay"; +}; + +&wifi0 { + status = "okay"; +}; + +&wifi1 { + status = "okay"; +}; + +&gmac0 { + qcom,phy_mdio_addr = <0>; + qcom,poll_required = <1>; + vlan_tag = <0 0x20>; +}; diff --git a/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-map-ac2200.dts b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-map-ac2200.dts new file mode 100644 index 000000000..3b9078bc0 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-map-ac2200.dts @@ -0,0 +1,326 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "qcom-ipq4019.dtsi" +#include +#include +#include + +/ { + model = "ASUS Lyra MAP-AC2200"; + compatible = "asus,map-ac2200"; + + aliases { + led-boot = &led_blue0; + led-failsafe = &led_red0; + led-running = &led_blue0; + led-upgrade = &led_red0; + }; + + soc { + rng@22000 { + status = "okay"; + }; + + mdio@90000 { + status = "okay"; + }; + + ess-psgmii@98000 { + status = "okay"; + }; + + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; + qcom,wifi_glb_cfg = ; + }; + + ess_tcsr@1953000 { + compatible = "qcom,tcsr"; + reg = <0x1953000 0x1000>; + qcom,ess-interface-select = ; + }; + + tcsr@1957000 { + compatible = "qcom,tcsr"; + reg = <0x1957000 0x100>; + qcom,wifi_noc_memtype_m0_m2 = ; + }; + + usb2@60f8800 { + status = "okay"; + }; + + crypto@8e3a000 { + status = "okay"; + }; + + watchdog@b017000 { + status = "okay"; + }; + + ess-switch@c000000 { + status = "okay"; + }; + + edma@c080000 { + status = "okay"; + }; + }; + + keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + gpios = <&tlmm 34 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + + wps { + label = "wps"; + gpios = <&tlmm 18 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; +}; + +&nand { + pinctrl-0 = <&nand_pins>; + pinctrl-names = "default"; + status = "okay"; + + nand@0 { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "SBL1"; + reg = <0x0 0x80000>; + read-only; + }; + + partition@80000 { + label = "MIBIB"; + reg = <0x80000 0x80000>; + read-only; + }; + + partition@100000 { + label = "QSEE"; + reg = <0x100000 0x100000>; + read-only; + }; + + partition@200000 { + label = "CDT"; + reg = <0x200000 0x80000>; + read-only; + }; + + partition@280000 { + label = "APPSBL"; + reg = <0x280000 0x140000>; + read-only; + }; + + partition@3c0000 { + label = "APPSBLENV"; + reg = <0x3c0000 0x40000>; + read-only; + }; + + partition@400000 { + label = "ubi"; + reg = <0x400000 0x7c00000>; + }; + }; + }; +}; + +&tlmm { + i2c_0_pins: i2c_0_pinmux { + pinmux { + function = "blsp_i2c0"; + pins = "gpio20", "gpio21"; + drive-strength = <16>; + bias-disable; + }; + }; + + serial_pins: serial_pinmux { + mux { + pins = "gpio16", "gpio17"; + function = "blsp_uart0"; + bias-disable; + }; + }; + + nand_pins: nand_pins { + pullups { + pins = "gpio52", "gpio53", "gpio58", + "gpio59"; + function = "qpic"; + bias-pull-up; + }; + + pulldowns { + pins = "gpio54", "gpio55", "gpio56", + "gpio57", "gpio60", "gpio61", + "gpio62", "gpio63", "gpio64", + "gpio65", "gpio66", "gpio67", + "gpio68", "gpio69"; + function = "qpic"; + bias-pull-down; + }; + }; + enable_ext_pa_high { + gpio-hog; + gpios = <44 GPIO_ACTIVE_HIGH>, + <46 GPIO_ACTIVE_HIGH>; + output-high; + bias-pull-down; + line-name = "enable external PA output-high"; + }; + enable_ext_pa_low { + gpio-hog; + gpios = <45 GPIO_ACTIVE_HIGH>, + <47 GPIO_ACTIVE_HIGH>; + output-low; + bias-pull-down; + line-name = "enable external PA output-low"; + }; +}; + +&cryptobam { + status = "okay"; +}; + +&blsp_dma { + status = "okay"; +}; + +&qpic_bam { + status = "okay"; +}; + +&wifi0 { + status = "okay"; + qcom,ath10k-calibration-variant = "ASUS-MAP-AC2200"; +}; + +&wifi1 { + status = "okay"; + qcom,ath10k-calibration-variant = "ASUS-MAP-AC2200"; + ieee80211-freq-limit = <5470000 5875000>; +}; + +&pcie0 { + status = "okay"; + perst-gpio = <&tlmm 38 GPIO_ACTIVE_LOW>; + wake-gpio = <&tlmm 50 GPIO_ACTIVE_LOW>; + + bridge@0,0 { + reg = <0x00000000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + ranges; + + wifi2: wifi@1,0 { + compatible = "qcom,ath10k"; + status = "okay"; + reg = <0x00010000 0 0 0 0>; + qcom,ath10k-calibration-variant = "ASUS-MAP-AC2200"; + ieee80211-freq-limit = <5170000 5350000>; + }; + }; +}; + +&usb2_hs_phy { + /* Bluetooth module attached via USB */ + status = "okay"; +}; + +&blsp1_i2c3 { + pinctrl-0 = <&i2c_0_pins>; + pinctrl-names = "default"; + status = "okay"; + + led-controller@32 { + /* 9-channel RGB LED controller */ + compatible = "national,lp5523"; + reg = <0x32>; + clock-mode = [01]; + + led_blue0: blue0 { + chan-name = "blue0"; + label = "blue:chan0"; + led-cur = [fa]; + max-cur = [ff]; + }; + + blue1 { + chan-name = "blue1"; + label = "blue:chan1"; + led-cur = [fa]; + max-cur = [ff]; + }; + + blue2 { + chan-name = "blue2"; + label = "blue:chan2"; + led-cur = [fa]; + max-cur = [ff]; + }; + + led_green0: green0 { + chan-name = "green0"; + label = "green:chan0"; + led-cur = [fa]; + max-cur = [ff]; + }; + + green1 { + chan-name = "green1"; + label = "green:chan1"; + led-cur = [fa]; + max-cur = [ff]; + }; + + green2 { + chan-name = "green2"; + label = "green:chan2"; + led-cur = [fa]; + max-cur = [ff]; + }; + + led_red0: red0 { + chan-name = "red0"; + label = "red:chan0"; + led-cur = [fa]; + max-cur = [ff]; + }; + + red1 { + chan-name = "red1"; + label = "red:chan1"; + led-cur = [fa]; + max-cur = [ff]; + }; + + red2 { + chan-name = "red2"; + label = "red:chan2"; + led-cur = [fa]; + max-cur = [ff]; + }; + }; +}; + +&blsp1_uart1 { + pinctrl-0 = <&serial_pins>; + pinctrl-names = "default"; + status = "okay"; +}; diff --git a/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-mr8300.dts b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-mr8300.dts new file mode 100644 index 000000000..057aa8802 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-mr8300.dts @@ -0,0 +1,80 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "qcom-ipq4019-xx8300.dtsi" + +/ { + model = "Linksys MR8300 (Dallas)"; + compatible = "linksys,mr8300", "qcom,ipq4019"; + + aliases { + led-boot = &led_blue; + led-failsafe = &led_red; + led-running = &led_blue; + led-upgrade = &led_amber; + serial0 = &blsp1_uart1; + }; + + // Top panel LEDs, above Linksys logo + leds { + compatible = "gpio-leds"; + + led_red: red { + label = "red:alarm"; + gpios = <&tlmm 47 GPIO_ACTIVE_HIGH>; + }; + + led_amber: amber { + label = "amber:programming"; + gpios = <&tlmm 22 GPIO_ACTIVE_HIGH>; + panic-indicator; + }; + + led_blue: blue { + label = "blue:power"; + gpios = <&tlmm 46 GPIO_ACTIVE_HIGH>; + }; + + // On back panel, above USB socket + + led_usb: usb { + label = "green:usb"; + gpios = <&tlmm 61 GPIO_ACTIVE_LOW>; + trigger-sources = <&usb3_port1>, <&usb3_port2>, + <&usb2_port1>; + linux,default-trigger = "usbport"; + }; + }; + + keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + linux,code = ; + gpios = <&tlmm 50 GPIO_ACTIVE_LOW>; + }; + + wps { + label = "wps"; + linux,code = ; + gpios = <&tlmm 18 GPIO_ACTIVE_LOW>; + }; + }; +}; + +&wifi0 { + status = "okay"; + qcom,ath10k-calibration-variant = "linksys-mr8300-v0-fcc"; +}; + +&wifi1 { + status = "okay"; + ieee80211-freq-limit = <5170000 5330000>; + qcom,ath10k-calibration-variant = "linksys-mr8300-v0-fcc"; +}; + +&wifi2 { + status = "okay"; + ieee80211-freq-limit = <5490000 5835000>; + qcom,ath10k-calibration-variant = "linksys-mr8300-v0-fcc"; +}; diff --git a/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-oap100.dts b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-oap100.dts new file mode 100644 index 000000000..69423ce02 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-oap100.dts @@ -0,0 +1,339 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "qcom-ipq4019.dtsi" +#include +#include +#include + +/ { + model = "EdgeCore OAP-100"; + compatible = "edgecore,oap100"; + + aliases { + led-boot = &led_system; + led-failsafe = &led_system; + led-running = &led_system; + led-upgrade = &led_system; + }; + + chosen { + bootargs-append = " root=/dev/ubiblock0_1"; + }; + + soc { + mdio@90000 { + status = "okay"; + pinctrl-0 = <&mdio_pins>; + pinctrl-names = "default"; + }; + + ess-psgmii@98000 { + status = "okay"; + }; + + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; + qcom,wifi_glb_cfg = ; + }; + + ess_tcsr@1953000 { + compatible = "qcom,tcsr"; + reg = <0x1953000 0x1000>; + qcom,ess-interface-select = ; + }; + + tcsr@1957000 { + compatible = "qcom,tcsr"; + reg = <0x1957000 0x100>; + qcom,wifi_noc_memtype_m0_m2 = ; + }; + + tcsr@194b000 { + /* select hostmode */ + compatible = "qcom,tcsr"; + reg = <0x194b000 0x100>; + qcom,usb-hsphy-mode-select = ; + status = "okay"; + }; + + usb2@60f8800 { + status = "okay"; + + dwc3@6000000 { + #address-cells = <1>; + #size-cells = <0>; + + usb2_port1: port@1 { + reg = <1>; + #trigger-source-cells = <0>; + }; + }; + }; + + usb3@8af8800 { + status = "okay"; + + dwc3@8a00000 { + #address-cells = <1>; + #size-cells = <0>; + + usb3_port1: port@1 { + reg = <1>; + #trigger-source-cells = <0>; + }; + + usb3_port2: port@2 { + reg = <2>; + #trigger-source-cells = <0>; + }; + }; + }; + + crypto@8e3a000 { + status = "okay"; + }; + + watchdog@b017000 { + status = "okay"; + }; + + ess-switch@c000000 { + status = "okay"; + switch_mac_mode = <0x0>; /* mac mode for RGMII RMII */ + switch_initvlas = <0x0007c 0x54>; /* port0 status */ + switch_lan_bmp = <0x10>; + }; + + edma@c080000 { + status = "okay"; + }; + }; + + key { + compatible = "gpio-keys"; + + button@1 { + label = "reset"; + linux,code = ; + gpios = <&tlmm 18 GPIO_ACTIVE_LOW>; + linux,input-type = <1>; + }; + }; + + leds { + compatible = "gpio-leds"; + + led_system: led_system { + label = "green:system"; + gpios = <&tlmm 22 GPIO_ACTIVE_HIGH>; + }; + + led_2g { + label = "blue:wlan2g"; + gpios = <&tlmm 34 GPIO_ACTIVE_HIGH>; + }; + + led_5g { + label = "blue:wlan5g"; + gpios = <&tlmm 35 GPIO_ACTIVE_HIGH>; + }; + }; + + gpio_export { + compatible = "gpio-export"; + #size-cells = <0>; + + usb { + gpio-export,name = "usb-power"; + gpio-export,output = <1>; + gpios = <&tlmm 44 GPIO_ACTIVE_HIGH>; + }; + + poe { + gpio-export,name = "poe-power"; + gpio-export,output = <0>; + gpios = <&tlmm 45 GPIO_ACTIVE_HIGH>; + }; + }; +}; + +&tlmm { + serial_0_pins: serial_pinmux { + mux { + pins = "gpio16", "gpio17"; + function = "blsp_uart0"; + bias-disable; + }; + }; + + spi_0_pins: spi_0_pinmux { + pinmux { + function = "blsp_spi0"; + pins = "gpio13", "gpio14", "gpio15"; + drive-strength = <12>; + bias-disable; + }; + + pinmux_cs { + function = "gpio"; + pins = "gpio12"; + drive-strength = <2>; + bias-disable; + output-high; + }; + }; + + nand_pins: nand_pins { + pullups { + pins = "gpio53", "gpio58", "gpio59"; + function = "qpic"; + bias-pull-up; + }; + + pulldowns { + pins = "gpio54", "gpio55", "gpio56", + "gpio57", "gpio60", "gpio61", + "gpio62", "gpio63", "gpio64", + "gpio65", "gpio66", "gpio67", + "gpio68", "gpio69"; + function = "qpic"; + bias-pull-down; + }; + }; + + mdio_pins: mdio_pinmux { + mux_1 { + pins = "gpio6"; + function = "mdio"; + bias-pull-up; + }; + mux_2 { + pins = "gpio7"; + function = "mdc"; + bias-pull-up; + }; + }; +}; + +&cryptobam { + status = "okay"; +}; + +&blsp1_spi1 { + pinctrl-0 = <&spi_0_pins>; + pinctrl-names = "default"; + status = "okay"; + cs-gpios = <&tlmm 12 GPIO_ACTIVE_HIGH>; + + flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "jedec,spi-nor"; + reg = <0>; + linux,modalias = "m25p80", "gd25q256"; + spi-max-frequency = <24000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition0@0 { + label = "0:SBL1"; + reg = <0x00000000 0x00040000>; + read-only; + }; + partition1@40000 { + label = "0:MIBIB"; + reg = <0x00040000 0x00020000>; + read-only; + }; + partition2@60000 { + label = "0:QSEE"; + reg = <0x00060000 0x00060000>; + read-only; + }; + partition3@c0000 { + label = "0:CDT"; + reg = <0x000c0000 0x00010000>; + read-only; + }; + partition4@d0000 { + label = "0:DDRPARAMS"; + reg = <0x000d0000 0x00010000>; + read-only; + }; + partition5@e0000 { + label = "0:APPSBLENV"; + reg = <0x000e0000 0x00010000>; + read-only; + }; + partition6@f0000 { + label = "0:APPSBL"; + reg = <0x000f0000 0x00080000>; + read-only; + }; + partition7@170000 { + label = "0:ART"; + reg = <0x00170000 0x00010000>; + read-only; + }; + }; + }; +}; + +&nand { + pinctrl-0 = <&nand_pins>; + pinctrl-names = "default"; + status = "okay"; + + nand@0 { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "rootfs"; + reg = <0x00000000 0x4000000>; + }; + }; + }; +}; + +&blsp_dma { + status = "okay"; +}; + +&blsp1_uart1 { + pinctrl-0 = <&serial_0_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + +&qpic_bam { + status = "okay"; +}; + +&wifi0 { + status = "okay"; + qcom,ath10k-calibration-variant = "Edgecore OAP100"; +}; + +&wifi1 { + status = "okay"; + qcom,ath10k-calibration-variant = "Edgecore OAP100"; +}; + +&usb3_ss_phy { + status = "okay"; +}; + +&usb3_hs_phy { + status = "okay"; +}; + +&usb2_hs_phy { + status = "okay"; +}; diff --git a/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-oap100e.dts b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-oap100e.dts new file mode 100644 index 000000000..d3891ddb4 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-oap100e.dts @@ -0,0 +1,351 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "qcom-ipq4019.dtsi" +#include +#include +#include + +/ { + model = "EdgeCore OAP-100e"; + compatible = "edgecore,oap100e"; + + aliases { + led-boot = &led_system; + led-failsafe = &led_system; + led-running = &led_system; + led-upgrade = &led_system; + }; + + chosen { + bootargs-append = " root=/dev/ubiblock0_1"; + }; + + soc { + mdio@90000 { + status = "okay"; + pinctrl-0 = <&mdio_pins>; + pinctrl-names = "default"; + }; + + ess-psgmii@98000 { + status = "okay"; + }; + + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; + qcom,wifi_glb_cfg = ; + }; + + ess_tcsr@1953000 { + compatible = "qcom,tcsr"; + reg = <0x1953000 0x1000>; + qcom,ess-interface-select = ; + }; + + tcsr@1957000 { + compatible = "qcom,tcsr"; + reg = <0x1957000 0x100>; + qcom,wifi_noc_memtype_m0_m2 = ; + }; + + tcsr@194b000 { + /* select hostmode */ + compatible = "qcom,tcsr"; + reg = <0x194b000 0x100>; + qcom,usb-hsphy-mode-select = ; + status = "okay"; + }; + + usb2@60f8800 { + status = "okay"; + + dwc3@6000000 { + #address-cells = <1>; + #size-cells = <0>; + + usb2_port1: port@1 { + reg = <1>; + #trigger-source-cells = <0>; + }; + }; + }; + + usb3@8af8800 { + status = "okay"; + + dwc3@8a00000 { + #address-cells = <1>; + #size-cells = <0>; + + usb3_port1: port@1 { + reg = <1>; + #trigger-source-cells = <0>; + }; + + usb3_port2: port@2 { + reg = <2>; + #trigger-source-cells = <0>; + }; + }; + }; + + crypto@8e3a000 { + status = "okay"; + }; + + watchdog@b017000 { + status = "okay"; + }; + + ess-switch@c000000 { + status = "okay"; + switch_mac_mode = <0x0>; /* mac mode for RGMII RMII */ + switch_initvlas = <0x0007c 0x54>; /* port0 status */ + switch_lan_bmp = <0x10>; + }; + + edma@c080000 { + status = "okay"; + }; + }; + + key { + compatible = "gpio-keys"; + + button@1 { + label = "reset"; + linux,code = ; + gpios = <&tlmm 18 GPIO_ACTIVE_LOW>; + linux,input-type = <1>; + }; + }; + + leds { + compatible = "gpio-leds"; + + led_system: led_system { + label = "green:system"; + gpios = <&tlmm 22 GPIO_ACTIVE_HIGH>; + }; + + led_2g { + label = "blue:wlan2g"; + gpios = <&tlmm 34 GPIO_ACTIVE_HIGH>; + }; + + led_5g { + label = "blue:wlan5g"; + gpios = <&tlmm 35 GPIO_ACTIVE_HIGH>; + }; + }; + + gpio_export { + compatible = "gpio-export"; + #size-cells = <0>; + + usb { + gpio-export,name = "usb-power"; + gpio-export,output = <1>; + gpios = <&tlmm 44 GPIO_ACTIVE_HIGH>; + }; + + poe { + gpio-export,name = "poe-power"; + gpio-export,output = <0>; + gpios = <&tlmm 45 GPIO_ACTIVE_HIGH>; + }; + + external_antenna_1 { + gpio-export,name = "gpio458"; + gpio-export,output = <1>; + gpios = <&tlmm 46 GPIO_ACTIVE_HIGH>; + }; + + external_antenna_2 { + gpio-export,name = "gpio459"; + gpio-export,output = <1>; + gpios = <&tlmm 47 GPIO_ACTIVE_HIGH>; + }; + }; +}; + +&tlmm { + serial_0_pins: serial_pinmux { + mux { + pins = "gpio16", "gpio17"; + function = "blsp_uart0"; + bias-disable; + }; + }; + + spi_0_pins: spi_0_pinmux { + pinmux { + function = "blsp_spi0"; + pins = "gpio13", "gpio14", "gpio15"; + drive-strength = <12>; + bias-disable; + }; + + pinmux_cs { + function = "gpio"; + pins = "gpio12"; + drive-strength = <2>; + bias-disable; + output-high; + }; + }; + + nand_pins: nand_pins { + pullups { + pins = "gpio53", "gpio58", "gpio59"; + function = "qpic"; + bias-pull-up; + }; + + pulldowns { + pins = "gpio54", "gpio55", "gpio56", + "gpio57", "gpio60", "gpio61", + "gpio62", "gpio63", "gpio64", + "gpio65", "gpio66", "gpio67", + "gpio68", "gpio69"; + function = "qpic"; + bias-pull-down; + }; + }; + + mdio_pins: mdio_pinmux { + mux_1 { + pins = "gpio6"; + function = "mdio"; + bias-pull-up; + }; + mux_2 { + pins = "gpio7"; + function = "mdc"; + bias-pull-up; + }; + }; +}; + +&cryptobam { + status = "okay"; +}; + +&blsp1_spi1 { + pinctrl-0 = <&spi_0_pins>; + pinctrl-names = "default"; + status = "okay"; + cs-gpios = <&tlmm 12 GPIO_ACTIVE_HIGH>; + + flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "jedec,spi-nor"; + reg = <0>; + linux,modalias = "m25p80", "gd25q256"; + spi-max-frequency = <24000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition0@0 { + label = "0:SBL1"; + reg = <0x00000000 0x00040000>; + read-only; + }; + partition1@40000 { + label = "0:MIBIB"; + reg = <0x00040000 0x00020000>; + read-only; + }; + partition2@60000 { + label = "0:QSEE"; + reg = <0x00060000 0x00060000>; + read-only; + }; + partition3@c0000 { + label = "0:CDT"; + reg = <0x000c0000 0x00010000>; + read-only; + }; + partition4@d0000 { + label = "0:DDRPARAMS"; + reg = <0x000d0000 0x00010000>; + read-only; + }; + partition5@e0000 { + label = "0:APPSBLENV"; + reg = <0x000e0000 0x00010000>; + read-only; + }; + partition6@f0000 { + label = "0:APPSBL"; + reg = <0x000f0000 0x00080000>; + read-only; + }; + partition7@170000 { + label = "0:ART"; + reg = <0x00170000 0x00010000>; + read-only; + }; + }; + }; +}; + +&nand { + pinctrl-0 = <&nand_pins>; + pinctrl-names = "default"; + status = "okay"; + + nand@0 { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "rootfs"; + reg = <0x00000000 0x4000000>; + }; + }; + }; +}; + +&blsp_dma { + status = "okay"; +}; + +&blsp1_uart1 { + pinctrl-0 = <&serial_0_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + +&qpic_bam { + status = "okay"; +}; + +&wifi0 { + status = "okay"; + qcom,ath10k-calibration-variant = "Edgecore OAP100e"; +}; + +&wifi1 { + status = "okay"; + qcom,ath10k-calibration-variant = "Edgecore OAP100e"; +}; + +&usb3_ss_phy { + status = "okay"; +}; + +&usb3_hs_phy { + status = "okay"; +}; + +&usb2_hs_phy { + status = "okay"; +}; diff --git a/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-pa2200.dts b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-pa2200.dts new file mode 100644 index 000000000..2d0655114 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-pa2200.dts @@ -0,0 +1,210 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT +/* Copyright (c) 2017-2020, Sven Eckelmann + * Copyright (c) 2018, Marek Lindner + */ + +#include "qcom-ipq4019.dtsi" +#include +#include +#include + +/ { + model = "Plasma Cloud PA2200"; + compatible = "plasmacloud,pa2200"; + + soc { + rng@22000 { + status = "okay"; + }; + + mdio@90000 { + status = "okay"; + }; + + ess-psgmii@98000 { + status = "okay"; + }; + + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; + qcom,wifi_glb_cfg = ; + }; + + ess_tcsr@1953000 { + compatible = "qcom,tcsr"; + reg = <0x1953000 0x1000>; + qcom,ess-interface-select = ; + }; + + tcsr@1957000 { + compatible = "qcom,tcsr"; + reg = <0x1957000 0x100>; + qcom,wifi_noc_memtype_m0_m2 = ; + }; + + crypto@8e3a000 { + status = "okay"; + }; + + watchdog@b017000 { + status = "okay"; + }; + + ess-switch@c000000 { + switch_lan_bmp = <0x10>; + switch_wan_bmp = <0x20>; + + status = "okay"; + }; + + edma@c080000 { + status = "okay"; + }; + }; + + keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + gpios = <&tlmm 18 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + aliases { + led-boot = &led_power_orange; + led-failsafe = &led_status_blue; + led-running = &led_power_orange; + led-upgrade = &led_status_blue; + }; + + leds { + compatible = "gpio-leds"; + + led_power_orange: power_orange { + label = "orange:power"; + gpios = <&tlmm 43 GPIO_ACTIVE_LOW>; + }; + + 2g_blue { + label = "blue:2g"; + gpios = <&tlmm 46 GPIO_ACTIVE_LOW>; + linux,default-trigger = "phy1tpt"; + }; + + 2g_green { + label = "green:5g1"; + gpios = <&tlmm 47 GPIO_ACTIVE_LOW>; + linux,default-trigger = "phy0tpt"; + }; + + 5g2_green { + label = "green:5g2"; + gpios = <&tlmm 48 GPIO_ACTIVE_LOW>; + linux,default-trigger = "phy2tpt"; + }; + + led_status_blue: status_blue { + label = "blue:status"; + gpios = <&tlmm 50 GPIO_ACTIVE_LOW>; + }; + }; +}; + +&tlmm { + serial_pins: serial_pinmux { + mux { + pins = "gpio16", "gpio17"; + function = "blsp_uart0"; + bias-disable; + }; + }; + + spi_0_pins: spi_0_pinmux { + pin { + function = "blsp_spi0"; + pins = "gpio13", "gpio14", "gpio15"; + drive-strength = <12>; + bias-disable; + }; + pin_cs { + function = "gpio"; + pins = "gpio12"; + drive-strength = <2>; + bias-disable; + output-high; + }; + }; +}; + +&blsp_dma { + status = "okay"; +}; + +&blsp1_spi1 { + pinctrl-0 = <&spi_0_pins>; + pinctrl-names = "default"; + status = "okay"; + cs-gpios = <&tlmm 12 GPIO_ACTIVE_HIGH>; + + flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <24000000>; + /* partitions are passed via bootloader */ + }; +}; + +&blsp1_uart1 { + pinctrl-0 = <&serial_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + +&cryptobam { + status = "okay"; +}; + +&gmac0 { + qcom,phy_mdio_addr = <3>; + qcom,poll_required = <1>; + qcom,forced_speed = <1000>; + qcom,forced_duplex = <1>; + vlan_tag = <1 0x10>; +}; + +&pcie0 { + status = "okay"; + perst-gpio = <&tlmm 38 GPIO_ACTIVE_LOW>; + wake-gpio = <&tlmm 50 GPIO_ACTIVE_LOW>; + + bridge@0,0 { + reg = <0x00000000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + ranges; + + wifi2: wifi@1,0 { + compatible = "qcom,ath10k"; + status = "okay"; + reg = <0x00010000 0 0 0 0>; + qcom,ath10k-calibration-variant = "PlasmaCloud-PA2200"; + ieee80211-freq-limit = <5170000 5350000>; + }; + }; +}; + +&wifi0 { + status = "okay"; + qcom,ath10k-calibration-variant = "PlasmaCloud-PA2200"; +}; + +&wifi1 { + status = "okay"; + qcom,ath10k-calibration-variant = "PlasmaCloud-PA2200"; + ieee80211-freq-limit = <5470000 5875000>; +}; diff --git a/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-rtl30vw.dts b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-rtl30vw.dts new file mode 100644 index 000000000..0caa0255d --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-rtl30vw.dts @@ -0,0 +1,385 @@ +// SPDX-License-Identifier: ISC +// Copyright (c) 2015, The Linux Foundation. All rights reserved. +// Copyright (c) 2019, Cezary Jackiewicz . +// Copyright (c) 2020, Pawel Dembicki . + +#include "qcom-ipq4019.dtsi" +#include +#include +#include + +/ { + model = "Cell C RTL30VW"; + compatible = "cellc,rtl30vw"; + + aliases { + led-boot = &led_power_blue; + led-failsafe = &led_power_red; + led-running = &led_power_blue; + led-upgrade = &led_power_red; + }; + + chosen { + bootargs-append = "ubi.mtd=ubifs root=/dev/ubiblock0_0 rootfstype=squashfs ro"; + }; + + led_spi { + compatible = "spi-gpio"; + #address-cells = <1>; + #size-cells = <0>; + num-chipselects = <1>; + + mosi-gpios = <&tlmm 2 GPIO_ACTIVE_LOW>; + cs-gpios = <&tlmm 4 GPIO_ACTIVE_LOW>; + sck-gpios = <&tlmm 58 GPIO_ACTIVE_LOW>; + + led_gpio: led_gpio@0 { + compatible = "fairchild,74hc595"; + reg = <0>; + gpio-controller; + #gpio-cells = <2>; + registers-number = <2>; + spi-max-frequency = <1000000>; + }; + }; + + leds { + compatible = "gpio-leds"; + + led_power_blue: power_blue { + gpios = <&led_gpio 0 GPIO_ACTIVE_HIGH>; + label = "blue:power"; + default-state = "on"; + }; + + led_power_red: power_red { + gpios = <&led_gpio 1 GPIO_ACTIVE_HIGH>; + label = "red:power"; + }; + + tp28 { + gpios = <&led_gpio 6 GPIO_ACTIVE_LOW>; + label = "ext:tp28"; + default-state = "keep"; + }; + + tp27 { + gpios = <&led_gpio 7 GPIO_ACTIVE_LOW>; + label = "ext:tp27"; + default-state = "keep"; + }; + + wlan2g { + gpios = <&led_gpio 8 GPIO_ACTIVE_HIGH>; + label = "blue:wlan2g"; + linux,default-trigger = "phy0tpt"; + }; + + wlan5g { + gpios = <&led_gpio 9 GPIO_ACTIVE_HIGH>; + label = "blue:wlan5g"; + linux,default-trigger = "phy1tpt"; + }; + + wps { + gpios = <&led_gpio 10 GPIO_ACTIVE_HIGH>; + label = "blue:wps"; + }; + + voip { + gpios = <&led_gpio 11 GPIO_ACTIVE_HIGH>; + label = "blue:voip"; + }; + + s1 { + gpios = <&led_gpio 12 GPIO_ACTIVE_HIGH>; + label = "blue:s1"; + }; + + s2 { + gpios = <&led_gpio 13 GPIO_ACTIVE_HIGH>; + label = "blue:s2"; + }; + + s3 { + gpios = <&led_gpio 14 GPIO_ACTIVE_HIGH>; + label = "blue:s3"; + }; + + s4 { + gpios = <&led_gpio 15 GPIO_ACTIVE_HIGH>; + label = "blue:s4"; + }; + + signal { + gpios = <&tlmm 3 GPIO_ACTIVE_HIGH>; + label = "red:signal"; + }; + }; + + keys { + compatible = "gpio-keys"; + + wps { + label = "wps"; + linux,code = ; + gpios = <&tlmm 5 GPIO_ACTIVE_LOW>; + }; + + reset { + label = "reset"; + linux,code = ; + gpios = <&tlmm 63 GPIO_ACTIVE_LOW>; + }; + }; + + soc { + rng@22000 { + status = "okay"; + }; + + mdio@90000 { + status = "okay"; + }; + + ess-psgmii@98000 { + status = "okay"; + }; + + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; + qcom,wifi_glb_cfg = ; + }; + + tcsr@194b000 { + /* select hostmode */ + compatible = "qcom,tcsr"; + reg = <0x194b000 0x100>; + qcom,usb-hsphy-mode-select = ; + status = "okay"; + }; + + ess_tcsr@1953000 { + compatible = "qcom,tcsr"; + reg = <0x1953000 0x1000>; + qcom,ess-interface-select = ; + }; + + tcsr@1957000 { + compatible = "qcom,tcsr"; + reg = <0x1957000 0x100>; + qcom,wifi_noc_memtype_m0_m2 = ; + }; + + usb2@60f8800 { + status = "okay"; + }; + + usb3@8af8800 { + status = "okay"; + }; + + crypto@8e3a000 { + status = "okay"; + }; + + watchdog@b017000 { + status = "okay"; + }; + + ess-switch@c000000 { + status = "okay"; + }; + + edma@c080000 { + status = "okay"; + }; + }; +}; + +&blsp_dma { + status = "okay"; +}; + +&blsp1_spi1 { + pinctrl-0 = <&spi_0_pins>; + pinctrl-names = "default"; + status = "okay"; + cs-gpios = <&tlmm 54 GPIO_ACTIVE_HIGH>, <&tlmm 59 GPIO_ACTIVE_HIGH>; + + flash@0 { + /*"n25q128a11" is required for proper nand recognition in u-boot. */ + compatible = "jedec,spi-nor", "n25q128a11"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0>; + spi-max-frequency = <24000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "0:SBL1"; + reg = <0x0 0x40000>; + read-only; + }; + + partition@40000 { + label = "0:MIBIB"; + reg = <0x40000 0x20000>; + read-only; + }; + + partition@60000 { + label = "0:QSEE"; + reg = <0x60000 0x60000>; + read-only; + }; + + partition@c0000 { + label = "0:CDT"; + reg = <0xc0000 0x10000>; + read-only; + }; + + partition@d0000 { + label = "0:DDRPARAMS"; + reg = <0xd0000 0x10000>; + read-only; + }; + + partition@e0000 { + label = "0:APPSBLENV"; + reg = <0xe0000 0x10000>; + read-only; + }; + + partition@f0000 { + label = "0:APPSBL"; + reg = <0xf0000 0x80000>; + read-only; + }; + + partition@170000 { + label = "0:ART"; + reg = <0x170000 0x10000>; + read-only; + }; + + partition@180000 { + label = "0:BOOTCONFIG"; + reg = <0x180000 0x10000>; + read-only; + }; + }; + }; + + flash@1 { + /* + * Factory U-boot looks in 0:BOOTCONFIG partition for active + * partitions settings and mangle partition config. So kernel + * /kernel_1 and rootfs/rootfs_1 pairs can be swaped. + * It isn't a problem but we never can be sure where OFW put + * factory images. "spinand,mt29f" value is required for proper + * nand recognition in u-boot. + */ + compatible = "spi-nand","spinand,mt29f"; + #address-cells = <1>; + #size-cells = <0>; + reg = <1>; + spi-max-frequency = <24000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "kernel"; + reg = <0x0 0x400000>; + }; + + partition@400000 { + label = "rootfs"; + reg = <0x400000 0x2000000>; + }; + + partition@2400000 { + label = "kernel_1"; + reg = <0x2400000 0x400000>; + }; + + partition@2800000 { + label = "rootfs_1"; + reg = <0x2800000 0x2000000>; + }; + + partition@4800000 { + label = "ubifs"; + reg = <0x4800000 0x3800000>; + }; + }; + }; +}; + +&blsp1_uart1 { + pinctrl-0 = <&serial_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + +&cryptobam { + status = "okay"; +}; + +&tlmm { + serial_pins: serial_pinmux { + mux { + pins = "gpio60", "gpio61"; + function = "blsp_uart0"; + bias-disable; + }; + }; + + spi_0_pins: spi_0_pinmux { + pinmux { + function = "blsp_spi0"; + pins = "gpio55", "gpio56", "gpio57"; + drive-strength = <12>; + bias-disable; + }; + + pinmux_cs { + function = "gpio"; + pins = "gpio54", "gpio59"; + drive-strength = <2>; + bias-disable; + output-high; + }; + }; +}; + +&usb2_hs_phy { + status = "okay"; +}; + +&usb3_ss_phy { + status = "okay"; +}; + +&usb3_hs_phy { + status = "okay"; +}; + +&wifi0 { + status = "okay"; + qcom,ath10k-calibration-variant = "cellc,rtl30vw"; +}; + +&wifi1 { + status = "okay"; + qcom,ath10k-calibration-variant = "cellc,rtl30vw"; +}; diff --git a/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-tp-link-ec420-g1.dts b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-tp-link-ec420-g1.dts new file mode 100755 index 000000000..9f6fdd5e7 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-tp-link-ec420-g1.dts @@ -0,0 +1,275 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "qcom-ipq4019.dtsi" +#include +#include +#include + +/ { + model = "tp-link EC420 G1"; + compatible = "tp-link,ec420-g1"; + + aliases { + led-boot = &led_green; + led-failsafe = &led_green; + led-running = &led_green; + led-upgrade = &led_green; + }; + + soc { + mdio@90000 { + status = "okay"; + }; + + ess-psgmii@98000 { + status = "okay"; + }; + + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; + qcom,wifi_glb_cfg = ; + }; + + ess_tcsr@1953000 { + compatible = "qcom,tcsr"; + reg = <0x1953000 0x1000>; + qcom,ess-interface-select = ; + }; + + tcsr@1957000 { + compatible = "qcom,tcsr"; + reg = <0x1957000 0x100>; + qcom,wifi_noc_memtype_m0_m2 = ; + }; + + crypto@8e3a000 { + status = "okay"; + }; + + watchdog@b017000 { + status = "okay"; + }; + + ess-switch@c000000 { + status = "okay"; + switch_mac_mode = <0x0>; /* mac mode for RGMII RMII */ + switch_initvlas = <0x0007c 0x54>; /* port0 status */ + switch_lan_bmp = <0x10>; + }; + + edma@c080000 { + status = "okay"; + }; + }; + + key { + compatible = "gpio-keys"; + + button@1 { + label = "reset"; + linux,code = ; + gpios = <&tlmm 18 GPIO_ACTIVE_LOW>; + linux,input-type = <1>; + }; + }; + + leds { + compatible = "gpio-leds"; + + led_red { + label = "ec420:red:status"; + gpios = <&tlmm 20 GPIO_ACTIVE_HIGH>; + }; + + led_green: power { + label = "ec420:green:status"; + gpios = <&tlmm 21 GPIO_ACTIVE_HIGH>; + }; + + led_blue { + label = "ec420:blue:status"; + gpios = <&tlmm 24 GPIO_ACTIVE_HIGH>; + }; + }; +}; + +&tlmm { + serial_0_pins: serial_pinmux { + mux { + pins = "gpio16", "gpio17"; + function = "blsp_uart0"; + bias-disable; + }; + }; + +spi_0_pins: spi_0_pinmux { + pinmux { + function = "blsp_spi0"; + pins = "gpio13", "gpio14", "gpio15"; + drive-strength = <12>; + bias-disable; + }; + + pinmux_cs { + function = "gpio"; + pins = "gpio12"; + drive-strength = <2>; + bias-disable; + output-high; + }; +}; + +nand_pins: nand_pins { + pullups { + pins = "gpio53", "gpio58", "gpio59"; + function = "qpic"; + bias-pull-up; + }; + + pulldowns { + pins = "gpio54", "gpio55", "gpio56", + "gpio57", "gpio60", "gpio61", + "gpio62", "gpio63", "gpio64", + "gpio65", "gpio66", "gpio67", + "gpio68", "gpio69"; + function = "qpic"; + bias-pull-down; + }; + }; +}; + +&cryptobam { + status = "okay"; +}; + +&blsp1_spi1 { + pinctrl-0 = <&spi_0_pins>; + pinctrl-names = "default"; + status = "okay"; + cs-gpios = <&tlmm 12 GPIO_ACTIVE_HIGH>; + + flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "jedec,spi-nor"; + reg = <0>; + linux,modalias = "m25p80", "gd25q256"; + spi-max-frequency = <24000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition0@0 { + label = "0:SBL1"; + reg = <0x00000000 0x00040000>; + read-only; + }; + partition1@40000 { + label = "0:MIBIB"; + reg = <0x00040000 0x00020000>; + read-only; + }; + partition2@60000 { + label = "0:QSEE"; + reg = <0x00060000 0x00060000>; + read-only; + }; + partition3@c0000 { + label = "0:CDT"; + reg = <0x000c0000 0x00010000>; + read-only; + }; + partition4@d0000 { + label = "0:DDRPARAMS"; + reg = <0x000d0000 0x00010000>; + read-only; + }; + partition5@e0000 { + label = "0:APPSBLENV"; + reg = <0x000e0000 0x00010000>; + }; + partition6@f0000 { + label = "0:APPSBL"; + reg = <0x000f0000 0x00080000>; + read-only; + }; + partition7@170000 { + label = "0:ART"; + reg = <0x00170000 0x00010000>; + read-only; + }; + partition8@180000 { + label = "product_info"; + reg = <0x00180000 0x00010000>; + }; + partition9@190000 { + label = "factory_fw"; + reg = <0x00190000 0x01e70000>; + }; + }; + }; +}; + +&nand { + pinctrl-0 = <&nand_pins>; + pinctrl-names = "default"; + status = "okay"; + + nand@0 { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "ubi"; + reg = <0x00000000 0x10000000>; + }; + }; + }; +}; + +&blsp_dma { + status = "okay"; +}; + +&blsp1_uart1 { + pinctrl-0 = <&serial_0_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + +&qpic_bam { + status = "okay"; +}; + +&wifi0 { + status = "okay"; +}; + +&wifi1 { + status = "disabled"; +}; + +&pcie0 { + status = "okay"; + perst-gpio = <&tlmm 38 GPIO_ACTIVE_LOW>; + wake-gpio = <&tlmm 40 GPIO_ACTIVE_LOW>; + + bridge@0,0 { + reg = <0x00000000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + ranges; + + wifi2: wifi@1,0 { + compatible = "qcom,ath10k"; + status = "okay"; + reg = <0x00010000 0 0 0 0>; + }; + }; +}; + diff --git a/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-u4019-32m.dts b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-u4019-32m.dts new file mode 100644 index 000000000..811c82b9c --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-u4019-32m.dts @@ -0,0 +1,77 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "qcom-ipq4019-u4019.dtsi" +#include +#include + +/ { + model = "Unielec U4019 (32M)"; + compatible = "unielec,u4019-32m","unielec,u4019","qcom,ipq4019"; +}; + +&blsp1_spi1 { + pinctrl-0 = <&spi_0_pins>; + pinctrl-names = "default"; + status = "okay"; + cs-gpios = <&tlmm 12 GPIO_ACTIVE_LOW>; + + flash@0 { + reg = <0>; + compatible = "jedec,spi-nor"; + spi-max-frequency = <24000000>; + broken-flash-reset; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "0:SBL1"; + reg = <0x0 0x40000>; + read-only; + }; + partition@40000 { + label = "0:MIBIB"; + reg = <0x40000 0x20000>; + read-only; + }; + partition@60000 { + label = "0:QSEE"; + reg = <0x60000 0x60000>; + read-only; + }; + partition@c0000 { + label = "0:CDT"; + reg = <0xc0000 0x10000>; + read-only; + }; + partition@d0000 { + label = "0:DDRPARAMS"; + reg = <0xd0000 0x10000>; + read-only; + }; + partition@e0000 { + label = "0:APPSBLENV"; + reg = <0xe0000 0x10000>; + read-only; + }; + partition@f0000 { + label = "0:APPSBL"; + reg = <0xf0000 0x80000>; + read-only; + }; + partition@170000 { + label = "0:ART"; + reg = <0x170000 0x10000>; + read-only; + }; + partition@180000 { + compatible = "denx,fit"; + label = "firmware"; + reg = <0x180000 0x1e80000>; + }; + }; + }; +}; + diff --git a/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-u4019.dtsi b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-u4019.dtsi new file mode 100644 index 000000000..4435d1fd2 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-u4019.dtsi @@ -0,0 +1,224 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "qcom-ipq4019.dtsi" +#include +#include +#include + +/ { + compatible = "unielec,u4019","qcom,ipq4019"; + + soc { + rng@22000 { + status = "okay"; + }; + + mdio@90000 { + status = "okay"; + pinctrl-0 = <&mdio_pins>; + pinctrl-names = "default"; + reset-gpios = <&tlmm 47 GPIO_ACTIVE_LOW>; + reset-delay-us = <2000>; + }; + + ess-psgmii@98000 { + status = "okay"; + }; + + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; + qcom,wifi_glb_cfg = ; + }; + + tcsr@194b000 { + compatible = "qcom,tcsr"; + reg = <0x194b000 0x100>; + qcom,usb-hsphy-mode-select = ; + status = "okay"; + }; + + ess_tcsr@1953000 { + compatible = "qcom,tcsr"; + reg = <0x1953000 0x1000>; + qcom,ess-interface-select = ; + }; + + tcsr@1957000 { + compatible = "qcom,tcsr"; + reg = <0x1957000 0x100>; + qcom,wifi_noc_memtype_m0_m2 = ; + }; + + usb2@60f8800 { + status = "okay"; + + dwc3@6000000 { + #address-cells = <1>; + #size-cells = <0>; + + port@1 { + reg = <1>; + #trigger-source-cells = <0>; + }; + }; + }; + + usb3@8af8800 { + status = "okay"; + + dwc3@8a00000 { + #address-cells = <1>; + #size-cells = <0>; + + port@1 { + reg = <1>; + #trigger-source-cells = <0>; + }; + + port@2 { + reg = <2>; + #trigger-source-cells = <0>; + }; + }; + }; + + watchdog@b017000 { + status = "okay"; + }; + + ess-switch@c000000 { + status = "okay"; + }; + + edma@c080000 { + status = "okay"; + }; + + aliases { + led-boot = &led_status; + led-failsafe = &led_status; + led-running = &led_status; + led-upgrade = &led_status; + serial0 = &blsp1_uart1; + serial1 = &blsp1_uart2; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-0 = <&led_pins>; + pinctrl-names = "default"; + + led_status: led2 { + label = "green:led2"; + gpios = <&tlmm 68 GPIO_ACTIVE_LOW>; + }; + }; + + keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + gpios = <&tlmm 18 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + }; +}; + +&blsp_dma { + status = "okay"; +}; + +&blsp1_uart1 { + pinctrl-0 = <&serial_0_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + +&blsp1_uart2 { + pinctrl-0 = <&serial_1_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + +&qpic_bam { + status = "okay"; +}; + +&tlmm { + mdio_pins: mdio_pinmux { + mux_1 { + pins = "gpio6"; + function = "mdio"; + bias-pull-up; + }; + mux_2 { + pins = "gpio7"; + function = "mdc"; + bias-pull-up; + }; + }; + + serial_0_pins: serial0-pinmux { + mux { + pins = "gpio16", "gpio17"; + function = "blsp_uart0"; + bias-disable; + }; + }; + serial_1_pins: serial1_pinmux { + mux { + pins = "gpio8", "gpio9"; + function = "blsp_uart1"; + bias-disable; + }; + }; + + spi_0_pins: spi_0_pinmux { + pinmux { + function = "blsp_spi0"; + pins = "gpio13", "gpio14", "gpio15"; + drive-strength = <12>; + bias-disable; + }; + + pinmux_cs { + function = "gpio"; + pins = "gpio12"; + drive-strength = <2>; + bias-disable; + output-high; + }; + }; + + led_pins: led_pinmux { + mux { + function = "gpio"; + pins = "gpio68"; + bias-disabled; + output-low; + }; + }; +}; + +&usb3_ss_phy { + status = "okay"; +}; + +&usb3_hs_phy { + status = "okay"; +}; + +&usb2_hs_phy { + status = "okay"; +}; + +&wifi0 { + status = "okay"; +}; + +&wifi1 { + status = "okay"; +}; diff --git a/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-um-325ac.dts b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-um-325ac.dts new file mode 100644 index 000000000..0ab70a68c --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-um-325ac.dts @@ -0,0 +1,94 @@ +/* Copyright (c) 2015, 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 "qcom-ipq4019-um-325ac.dtsi" + +/ { + model = "Indio Networks UM-325AC"; + compatible = "um-325ac"; + + memory { + device_type = "memory"; + reg = <0x80000000 0x10000000>; + }; +}; + +&blsp1_spi1 { + mx25l25635f@0 { + compatible = "mx25l25635f", "jedec,spi-nor"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0>; + spi-max-frequency = <24000000>; + + SBL1@0 { + label = "SBL1"; + reg = <0x0 0x40000>; + read-only; + }; + MIBIB@40000 { + label = "MIBIB"; + reg = <0x40000 0x20000>; + read-only; + }; + QSEE@60000 { + label = "QSEE"; + reg = <0x60000 0x60000>; + read-only; + }; + CDT@c0000 { + label = "CDT"; + reg = <0xc0000 0x10000>; + read-only; + }; + DDRPARAMS@d0000 { + label = "DDRPARAMS"; + reg = <0xd0000 0x10000>; + read-only; + }; + APPSBLENV@e0000 { + label = "APPSBLENV"; + reg = <0xe0000 0x10000>; + read-only; + }; + APPSBL@f0000 { + label = "APPSBL"; + reg = <0xf0000 0x80000>; + read-only; + }; + ART@170000 { + label = "ART"; + reg = <0x170000 0x10000>; + read-only; + }; + kernel@180000 { + label = "kernel"; + reg = <0x180000 0x400000>; + }; + rootfs@580000 { + label = "rootfs"; + reg = <0x580000 0x15F0000>; + }; + certificates@1b80000 { + label = "certificates"; + reg = <0x1b80000 0x10000>; + }; + firmware@180000 { + label = "firmware"; + reg = <0x180000 0x1a00000>; + }; + }; +}; diff --git a/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-um-325ac.dtsi b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-um-325ac.dtsi new file mode 100644 index 000000000..6fccf0d1d --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-um-325ac.dtsi @@ -0,0 +1,168 @@ +/* Copyright (c) 2015, 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 "qcom-ipq4019.dtsi" +#include + +/ { + model = "Indio Networks UM-325AC"; + compatible = "um-325ac"; + + aliases { + serial0 = &blsp1_uart1; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + soc { + tcsr@194b000 { + /* select hostmode */ + compatible = "qcom,tcsr"; + reg = <0x194b000 0x100>; + qcom,usb-hsphy-mode-select = ; + status = "okay"; + }; + + ess_tcsr@1953000 { + compatible = "qcom,tcsr"; + reg = <0x1953000 0x1000>; + qcom,ess-interface-select = ; + }; + + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; + qcom,wifi_glb_cfg = ; + }; + + tcsr@1957000 { + compatible = "qcom,tcsr"; + reg = <0x1957000 0x100>; + qcom,wifi_noc_memtype_m0_m2 = ; + }; + + rng@22000 { + status = "ok"; + }; + + pinctrl@1000000 { + serial_pins: serial_pinmux { + mux { + pins = "gpio60", "gpio61"; + function = "blsp_uart0"; + bias-disable; + }; + }; + + spi_0_pins: spi_0_pinmux { + pinmux { + function = "blsp_spi0"; + pins = "gpio55", "gpio56", "gpio57"; + }; + pinmux_cs { + function = "gpio"; + pins = "gpio54"; + }; + pinconf { + pins = "gpio55", "gpio56", "gpio57"; + drive-strength = <12>; + bias-disable; + }; + pinconf_cs { + pins = "gpio54"; + drive-strength = <2>; + bias-disable; + output-high; + }; + }; + }; + + blsp_dma: dma@7884000 { + status = "ok"; + }; + + spi@78b5000 { + pinctrl-0 = <&spi_0_pins>; + pinctrl-names = "default"; + status = "ok"; + cs-gpios = <&tlmm 54 0>; + }; + + serial@78af000 { + pinctrl-0 = <&serial_pins>; + pinctrl-names = "default"; + status = "ok"; + }; + + cryptobam: dma@8e04000 { + status = "ok"; + }; + + crypto@8e3a000 { + status = "ok"; + }; + + watchdog@b017000 { + status = "ok"; + }; + + wifi@a000000 { + status = "ok"; + }; + + wifi@a800000 { + status = "ok"; + }; + + mdio@90000 { + status = "okay"; + }; + + ess-switch@c000000 { + status = "okay"; + }; + + ess-psgmii@98000 { + status = "okay"; + }; + + edma@c080000 { + status = "okay"; + }; + + usb3_ss_phy: ssphy@9a000 { + status = "okay"; + }; + + usb3_hs_phy: hsphy@a6000 { + status = "okay"; + }; + + usb3: usb3@8af8800 { + status = "okay"; + }; + + usb2_hs_phy: hsphy@a8000 { + status = "okay"; + }; + + usb2: usb2@60f8800 { + status = "okay"; + }; + }; +}; diff --git a/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-um-510ac-v3.dts b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-um-510ac-v3.dts new file mode 100644 index 000000000..e0854189c --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-um-510ac-v3.dts @@ -0,0 +1,94 @@ +/* Copyright (c) 2015, 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 "qcom-ipq4019-um-510ac-v3.dtsi" + +/ { + model = "Indio Networks UM-510AC-V3"; + compatible = "um-510ac-v3"; + + memory { + device_type = "memory"; + reg = <0x80000000 0x10000000>; + }; +}; + +&blsp1_spi1 { + mx25l25635f@0 { + compatible = "mx25l25635f", "jedec,spi-nor"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0>; + spi-max-frequency = <24000000>; + + SBL1@0 { + label = "SBL1"; + reg = <0x0 0x40000>; + read-only; + }; + MIBIB@40000 { + label = "MIBIB"; + reg = <0x40000 0x20000>; + read-only; + }; + QSEE@60000 { + label = "QSEE"; + reg = <0x60000 0x60000>; + read-only; + }; + CDT@c0000 { + label = "CDT"; + reg = <0xc0000 0x10000>; + read-only; + }; + DDRPARAMS@d0000 { + label = "DDRPARAMS"; + reg = <0xd0000 0x10000>; + read-only; + }; + APPSBLENV@e0000 { + label = "APPSBLENV"; + reg = <0xe0000 0x10000>; + read-only; + }; + APPSBL@f0000 { + label = "APPSBL"; + reg = <0xf0000 0x80000>; + read-only; + }; + ART@170000 { + label = "ART"; + reg = <0x170000 0x10000>; + read-only; + }; + kernel@180000 { + label = "kernel"; + reg = <0x180000 0x400000>; + }; + rootfs@580000 { + label = "rootfs"; + reg = <0x580000 0x15F0000>; + }; + certificates@1b80000 { + label = "certificates"; + reg = <0x1b80000 0x10000>; + }; + firmware@180000 { + label = "firmware"; + reg = <0x180000 0x1a00000>; + }; + }; +}; diff --git a/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-um-510ac-v3.dtsi b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-um-510ac-v3.dtsi new file mode 100644 index 000000000..a8ad081f0 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-um-510ac-v3.dtsi @@ -0,0 +1,168 @@ +/* Copyright (c) 2015, 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 "qcom-ipq4019.dtsi" +#include + +/ { + model = "Indio Networks UM-510AC-V3"; + compatible = "um-510ac-v3"; + + aliases { + serial0 = &blsp1_uart1; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + soc { + tcsr@194b000 { + /* select hostmode */ + compatible = "qcom,tcsr"; + reg = <0x194b000 0x100>; + qcom,usb-hsphy-mode-select = ; + status = "okay"; + }; + + ess_tcsr@1953000 { + compatible = "qcom,tcsr"; + reg = <0x1953000 0x1000>; + qcom,ess-interface-select = ; + }; + + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; + qcom,wifi_glb_cfg = ; + }; + + tcsr@1957000 { + compatible = "qcom,tcsr"; + reg = <0x1957000 0x100>; + qcom,wifi_noc_memtype_m0_m2 = ; + }; + + rng@22000 { + status = "ok"; + }; + + pinctrl@1000000 { + serial_pins: serial_pinmux { + mux { + pins = "gpio60", "gpio61"; + function = "blsp_uart0"; + bias-disable; + }; + }; + + spi_0_pins: spi_0_pinmux { + pinmux { + function = "blsp_spi0"; + pins = "gpio55", "gpio56", "gpio57"; + }; + pinmux_cs { + function = "gpio"; + pins = "gpio54"; + }; + pinconf { + pins = "gpio55", "gpio56", "gpio57"; + drive-strength = <12>; + bias-disable; + }; + pinconf_cs { + pins = "gpio54"; + drive-strength = <2>; + bias-disable; + output-high; + }; + }; + }; + + blsp_dma: dma@7884000 { + status = "ok"; + }; + + spi@78b5000 { + pinctrl-0 = <&spi_0_pins>; + pinctrl-names = "default"; + status = "ok"; + cs-gpios = <&tlmm 54 0>; + }; + + serial@78af000 { + pinctrl-0 = <&serial_pins>; + pinctrl-names = "default"; + status = "ok"; + }; + + cryptobam: dma@8e04000 { + status = "ok"; + }; + + crypto@8e3a000 { + status = "ok"; + }; + + watchdog@b017000 { + status = "ok"; + }; + + wifi@a000000 { + status = "ok"; + }; + + wifi@a800000 { + status = "ok"; + }; + + mdio@90000 { + status = "okay"; + }; + + ess-switch@c000000 { + status = "okay"; + }; + + ess-psgmii@98000 { + status = "okay"; + }; + + edma@c080000 { + status = "okay"; + }; + + usb3_ss_phy: ssphy@9a000 { + status = "okay"; + }; + + usb3_hs_phy: hsphy@a6000 { + status = "okay"; + }; + + usb3: usb3@8af8800 { + status = "okay"; + }; + + usb2_hs_phy: hsphy@a8000 { + status = "okay"; + }; + + usb2: usb2@60f8800 { + status = "okay"; + }; + }; +}; diff --git a/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-um-550ac.dts b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-um-550ac.dts new file mode 100644 index 000000000..a15df3f91 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-um-550ac.dts @@ -0,0 +1,94 @@ +/* Copyright (c) 2015, 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 "qcom-ipq4019-um-550ac.dtsi" + +/ { + model = "Indio Networks UM-550AC"; + compatible = "um-550ac"; + + memory { + device_type = "memory"; + reg = <0x80000000 0x10000000>; + }; +}; + +&blsp1_spi1 { + mx25l25635f@0 { + compatible = "mx25l25635f", "jedec,spi-nor"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0>; + spi-max-frequency = <24000000>; + + SBL1@0 { + label = "SBL1"; + reg = <0x0 0x40000>; + read-only; + }; + MIBIB@40000 { + label = "MIBIB"; + reg = <0x40000 0x20000>; + read-only; + }; + QSEE@60000 { + label = "QSEE"; + reg = <0x60000 0x60000>; + read-only; + }; + CDT@c0000 { + label = "CDT"; + reg = <0xc0000 0x10000>; + read-only; + }; + DDRPARAMS@d0000 { + label = "DDRPARAMS"; + reg = <0xd0000 0x10000>; + read-only; + }; + APPSBLENV@e0000 { + label = "APPSBLENV"; + reg = <0xe0000 0x10000>; + read-only; + }; + APPSBL@f0000 { + label = "APPSBL"; + reg = <0xf0000 0x80000>; + read-only; + }; + ART@170000 { + label = "ART"; + reg = <0x170000 0x10000>; + read-only; + }; + kernel@180000 { + label = "kernel"; + reg = <0x180000 0x400000>; + }; + rootfs@580000 { + label = "rootfs"; + reg = <0x580000 0x15F0000>; + }; + certificates@1b80000 { + label = "certificates"; + reg = <0x1b80000 0x10000>; + }; + firmware@180000 { + label = "firmware"; + reg = <0x180000 0x1a00000>; + }; + }; +}; diff --git a/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-um-550ac.dtsi b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-um-550ac.dtsi new file mode 100644 index 000000000..5f4c8a103 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-um-550ac.dtsi @@ -0,0 +1,168 @@ +/* Copyright (c) 2015, 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 "qcom-ipq4019.dtsi" +#include + +/ { + model = "Indio Networks UM-550AC"; + compatible = "um-550ac"; + + aliases { + serial0 = &blsp1_uart1; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + soc { + tcsr@194b000 { + /* select hostmode */ + compatible = "qcom,tcsr"; + reg = <0x194b000 0x100>; + qcom,usb-hsphy-mode-select = ; + status = "okay"; + }; + + ess_tcsr@1953000 { + compatible = "qcom,tcsr"; + reg = <0x1953000 0x1000>; + qcom,ess-interface-select = ; + }; + + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; + qcom,wifi_glb_cfg = ; + }; + + tcsr@1957000 { + compatible = "qcom,tcsr"; + reg = <0x1957000 0x100>; + qcom,wifi_noc_memtype_m0_m2 = ; + }; + + rng@22000 { + status = "ok"; + }; + + pinctrl@1000000 { + serial_pins: serial_pinmux { + mux { + pins = "gpio60", "gpio61"; + function = "blsp_uart0"; + bias-disable; + }; + }; + + spi_0_pins: spi_0_pinmux { + pinmux { + function = "blsp_spi0"; + pins = "gpio55", "gpio56", "gpio57"; + }; + pinmux_cs { + function = "gpio"; + pins = "gpio54"; + }; + pinconf { + pins = "gpio55", "gpio56", "gpio57"; + drive-strength = <12>; + bias-disable; + }; + pinconf_cs { + pins = "gpio54"; + drive-strength = <2>; + bias-disable; + output-high; + }; + }; + }; + + blsp_dma: dma@7884000 { + status = "ok"; + }; + + spi@78b5000 { + pinctrl-0 = <&spi_0_pins>; + pinctrl-names = "default"; + status = "ok"; + cs-gpios = <&tlmm 54 0>; + }; + + serial@78af000 { + pinctrl-0 = <&serial_pins>; + pinctrl-names = "default"; + status = "ok"; + }; + + cryptobam: dma@8e04000 { + status = "ok"; + }; + + crypto@8e3a000 { + status = "ok"; + }; + + watchdog@b017000 { + status = "ok"; + }; + + wifi@a000000 { + status = "ok"; + }; + + wifi@a800000 { + status = "ok"; + }; + + mdio@90000 { + status = "okay"; + }; + + ess-switch@c000000 { + status = "okay"; + }; + + ess-psgmii@98000 { + status = "okay"; + }; + + edma@c080000 { + status = "okay"; + }; + + usb3_ss_phy: ssphy@9a000 { + status = "okay"; + }; + + usb3_hs_phy: hsphy@a6000 { + status = "okay"; + }; + + usb3: usb3@8af8800 { + status = "okay"; + }; + + usb2_hs_phy: hsphy@a8000 { + status = "okay"; + }; + + usb2: usb2@60f8800 { + status = "okay"; + }; + }; +}; diff --git a/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-wpj419.dts b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-wpj419.dts new file mode 100644 index 000000000..e8b7d3a89 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-wpj419.dts @@ -0,0 +1,385 @@ +/* Copyright (c) 2015, The Linux Foundation. All rights reserved. + * Copyright (c) 2019, Nguyen Dinh Phi + * + * 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 "qcom-ipq4019.dtsi" +#include +#include +#include + +/ { + model = "Compex WPJ419"; + compatible = "compex,wpj419", "qcom,ipq4019"; + + memory { + device_type = "memory"; + reg = <0x80000000 0x10000000>; + }; + + reserved-memory { + ranges; + rsvd1@87000000 { + /* Reserved for other subsystem */ + reg = <0x87000000 0x500000>; + no-map; + }; + wifi_dump@87500000 { + reg = <0x87500000 0x600000>; + no-map; + }; + + rsvd2@87B00000 { + /* Reserved for other subsystem */ + reg = <0x87B00000 0x500000>; + no-map; + }; + }; + + chosen { + bootargs-append = " ubi.mtd=ubi root=/dev/ubiblock0_1 clk_ignore_unused"; + }; + + soc { + pinctrl@1000000 { + mdio_pins: mdio_pinmux { + mux_1 { + pins = "gpio6"; + function = "mdio"; + bias-pull-up; + }; + + mux_2 { + pins = "gpio7"; + function = "mdc"; + bias-pull-up; + }; + }; + + serial_0_pins: serial_pinmux { + mux { + pins = "gpio16", "gpio17"; + function = "blsp_uart0"; + bias-disable; + }; + }; + + serial_1_pins: serial1_pinmux { + mux { + pins = "gpio8", "gpio9", "gpio10", "gpio11"; + function = "blsp_uart1"; + bias-disable; + }; + }; + + spi_0_pins: spi_0_pinmux { + pinmux { + function = "blsp_spi0"; + pins = "gpio13", "gpio14", "gpio15"; + bias-disable; + }; + + pinmux_cs { + function = "gpio"; + pins = "gpio12"; + bias-disable; + output-high; + }; + }; + + i2c_0_pins: i2c_0_pinmux { + mux { + pins = "gpio20", "gpio21"; + function = "blsp_i2c0"; + bias-disable; + }; + }; + + nand_pins: nand_pins { + pullups { + pins = "gpio52", "gpio53", "gpio58", "gpio59"; + function = "qpic"; + bias-pull-up; + }; + + pulldowns { + pins = "gpio54", "gpio55", "gpio56", + "gpio57", "gpio60", "gpio61", + "gpio62", "gpio63", "gpio64", + "gpio65", "gpio66", "gpio67", + "gpio68", "gpio69"; + function = "qpic"; + bias-pull-down; + }; + }; + + led_0_pins: led0_pinmux { + mux_1 { + pins = "gpio36"; + function = "led0"; + bias-pull-down; + }; + mux_2 { + pins = "gpio40"; + function = "led4"; + bias-pull-down; + }; + }; + }; + + blsp_dma: dma@7884000 { + status = "okay"; + }; + + spi_0: spi@78b5000 { + pinctrl-0 = <&spi_0_pins>; + pinctrl-names = "default"; + status = "okay"; + cs-gpios = <&tlmm 12 GPIO_ACTIVE_HIGH>, <&tlmm 41 GPIO_ACTIVE_HIGH>; + num-cs = <2>; + + flash0@0 { + reg = <0>; + compatible = "jedec,spi-nor"; + spi-max-frequency = <24000000>; + broken-flash-reset; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "0:SBL1"; + reg = <0x000000 0x040000>; + read-only; + }; + + partition@40000 { + label = "0:MIBIB"; + reg = <0x040000 0x020000>; + read-only; + }; + + partition@60000 { + label = "0:QSEE"; + reg = <0x060000 0x060000>; + read-only; + }; + + partition@c0000 { + label = "0:CDT"; + reg = <0x0c0000 0x010000>; + read-only; + }; + + partition@d0000 { + label = "0:DDRPARAMS"; + reg = <0x0d0000 0x010000>; + read-only; + }; + + partition@e0000 { + label = "u-boot-env"; + reg = <0x0e0000 0x010000>; + }; + + partition@f0000 { + label = "u-boot"; + reg = <0x0f0000 0x080000>; + read-only; + }; + + partition@170000 { + label = "0:ART"; + reg = <0x170000 0x010000>; + read-only; + }; + }; + }; + + nand@1 { + reg = <1>; + status = "okay"; + compatible = "spi-nand"; + spi-max-frequency = <24000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + /* The device has 128MB, but we can only address + * 64MB because of the bootloader's default settings. + * This is due to the old mt29f driver, + * which detected the deivce with only 64MB + */ + partition@0 { + label = "ubi"; + reg = <0x0000000 0x4000000>; + }; + }; + }; + }; + + mdio@90000 { + status = "okay"; + pinctrl-0 = <&mdio_pins>; + pinctrl-names = "default"; + reset-gpios = <&tlmm 47 GPIO_ACTIVE_LOW>; + reset-delay-us = <5000>; + }; + + ess-psgmii@98000 { + status = "okay"; + }; + + tcsr@194b000 { + /* select hostmode */ + compatible = "qcom,tcsr"; + reg = <0x194b000 0x100>; + qcom,usb-hsphy-mode-select = ; + status = "okay"; + }; + + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; + qcom,wifi_glb_cfg = ; + }; + + ess_tcsr@1953000 { + compatible = "qcom,tcsr"; + reg = <0x1953000 0x1000>; + qcom,ess-interface-select = ; + }; + + tcsr@1957000 { + compatible = "qcom,tcsr"; + reg = <0x1957000 0x100>; + qcom,wifi_noc_memtype_m0_m2 = ; + }; + + i2c_0: i2c@78b7000 { + pinctrl-0 = <&i2c_0_pins>; + pinctrl-names = "default"; + status = "okay"; + }; + + serial@78af000 { + pinctrl-0 = <&serial_0_pins>; + pinctrl-names = "default"; + status = "okay"; + }; + + serial@78b0000 { + pinctrl-0 = <&serial_1_pins>; + pinctrl-names = "default"; + status = "okay"; + }; + + usb3_ss_phy: ssphy@9a000 { + status = "okay"; + }; + + usb3_hs_phy: hsphy@a6000 { + status = "okay"; + }; + + usb3: usb3@8af8800 { + status = "okay"; + }; + + usb2_hs_phy: hsphy@a8000 { + status = "okay"; + }; + + usb2: usb2@60f8800 { + status = "okay"; + }; + + cryptobam: dma@8e04000 { + status = "okay"; + }; + + crypto@8e3a000 { + status = "okay"; + }; + + watchdog@b017000 { + status = "okay"; + }; + + ess-switch@c000000 { + switch_lan_bmp = <0x1e>; + switch_wan_bmp = <0x20>; + status = "okay"; + }; + + edma@c080000 { + status = "okay"; + }; + + qpic_bam: dma@7984000 { + status = "okay"; + }; + + pcie0: pci@40000000 { + status = "okay"; + perst-gpio = <&tlmm 38 GPIO_ACTIVE_LOW>; + wake-gpio = <&tlmm 50 GPIO_ACTIVE_LOW>; + }; + + nand: qpic-nand@79b0000 { + pinctrl-0 = <&nand_pins>; + pinctrl-names = "default"; + status = "okay"; + }; + }; + + keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + gpios = <&tlmm 18 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; +}; + +&gmac0 { + qcom,phy_mdio_addr = <4>; + qcom,poll_required = <1>; + qcom,forced_speed = <1000>; + qcom,forced_duplex = <1>; + vlan_tag = <2 0x20>; +}; + +&gmac1 { + qcom,phy_mdio_addr = <3>; + qcom,poll_required = <1>; + qcom,forced_speed = <1000>; + qcom,forced_duplex = <1>; + vlan_tag = <1 0x10>; +}; + +&wifi0 { + status = "okay"; +}; + +&wifi1 { + status = "okay"; +}; diff --git a/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-wtr-m2133hp.dts b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-wtr-m2133hp.dts new file mode 100644 index 000000000..cdf0cfe64 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-wtr-m2133hp.dts @@ -0,0 +1,419 @@ +// SPDX-License-Identifier: ISC +/* + * Copyright (c) 2015 - 2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2020 Yanase Yuki + */ + +#include "qcom-ipq4019.dtsi" +#include +#include +#include + +/ { + model = "Buffalo WTR-M2133HP"; + compatible = "buffalo,wtr-m2133hp", "qcom,ipq4019"; + + memory { + device_type = "memory"; + reg = <0x80000000 0x20000000>; + }; + + chosen { + /* + * U-Boot adds "ubi.mtd=rootfs root=mtd:ubi_rootfs" to + * kernel command line. But we use different partition names, + * so we have to set correct parameters. + */ + bootargs-append = " ubi.mtd=ubi root=/dev/ubiblock0_1"; + }; + + aliases { + led-boot = &led_power_blue; + led-failsafe = &led_power_orange; + led-running = &led_power_white; + led-upgrade = &led_power_blue; + label-mac-device = &gmac0; + }; + + soc { + rng@22000 { + status = "okay"; + }; + + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; + qcom,wifi_glb_cfg = ; + }; + + tcsr@194b000 { + compatible = "qcom,tcsr"; + reg = <0x194b000 0x100>; + qcom,usb-hsphy-mode-select = ; + status = "okay"; + }; + + ess_tcsr@1953000 { + compatible = "qcom,tcsr"; + reg = <0x1953000 0x1000>; + qcom,ess-interface-select = ; + }; + + tcsr@1957000 { + compatible = "qcom,tcsr"; + reg = <0x1957000 0x100>; + qcom,wifi_noc_memtype_m0_m2 = ; + }; + + crypto@8e3a000 { + status = "okay"; + }; + + watchdog@b017000 { + status = "okay"; + }; + + ess-switch@c000000 { + status = "okay"; + switch_lan_bmp = <0x1c>; + }; + + ess-psgmii@98000 { + status = "okay"; + }; + + edma@c080000 { + status = "okay"; + }; + + usb3@8af8800 { + status = "okay"; + }; + }; + + leds { + compatible = "gpio-leds"; + + led_power_white: power_white { + label = "white:power"; + gpios = <&tlmm 40 GPIO_ACTIVE_HIGH>; + }; + + led_power_orange: power_orange { + label = "orange:power"; + gpios = <&tlmm 25 GPIO_ACTIVE_HIGH>; + }; + + led_power_blue: power_blue { + label = "blue:power"; + gpios = <&tlmm 43 GPIO_ACTIVE_HIGH>; + }; + + router_white { + label = "white:router"; + gpios = <&tlmm 28 GPIO_ACTIVE_HIGH>; + }; + + router_orange { + label = "orange:router"; + gpios = <&tlmm 46 GPIO_ACTIVE_HIGH>; + }; + + internet_white { + label = "white:internet"; + gpios = <&tlmm 27 GPIO_ACTIVE_HIGH>; + }; + + internet_orange { + label = "orange:internet"; + gpios = <&tlmm 45 GPIO_ACTIVE_HIGH>; + }; + + wireless_white { + label = "white:wireless"; + gpios = <&tlmm 24 GPIO_ACTIVE_HIGH>; + }; + + wireless_orange { + label = "orange:wireless"; + gpios = <&tlmm 44 GPIO_ACTIVE_HIGH>; + }; + }; + + keys { + compatible = "gpio-keys"; + + auto_mode { + label = "auto_mode"; + gpios = <&tlmm 9 GPIO_ACTIVE_LOW>; + linux,code = ; + linux,input-type = ; + }; + + router_mode { + label = "router_mode"; + gpios = <&tlmm 10 GPIO_ACTIVE_LOW>; + linux,code = ; + linux,input-type = ; + }; + + ap_mode { + label = "ap_mode"; + gpios = <&tlmm 11 GPIO_ACTIVE_LOW>; + linux,code = ; + linux,input-type = ; + }; + + reset { + label = "reset"; + gpios = <&tlmm 18 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + + wps { + label = "AOSS Button"; + gpios = <&tlmm 32 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; +}; + +&tlmm { + serial_0_pins: serial0_pinmux { + mux { + pins = "gpio16", "gpio17"; + function = "blsp_uart0"; + bias-disable; + }; + }; + + mdio_pins: mdio_pinmux { + mux_1 { + pins = "gpio6"; + function = "mdio"; + bias-pull-up; + }; + + mux_2 { + pins = "gpio7"; + function = "mdc"; + bias-pull-up; + }; + }; + + nand_pins: nand_pins { + pullups { + pins = "gpio52", "gpio53", "gpio58", + "gpio59"; + function = "qpic"; + bias-pull-up; + }; + + pulldowns { + pins = "gpio54", "gpio55", "gpio56", + "gpio57", "gpio60", "gpio61", + "gpio62", "gpio63", "gpio64", + "gpio65", "gpio66", "gpio67", + "gpio68", "gpio69"; + function = "qpic"; + bias-pull-down; + }; + }; + + usb_power { + line-name = "USB power"; + gpios = <34 GPIO_ACTIVE_HIGH>; + gpio-hog; + output-high; + }; +}; + +&blsp_dma { + status = "okay"; +}; + +&blsp1_uart1 { + pinctrl-0 = <&serial_0_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + +&cryptobam { + status = "okay"; +}; + +&pcie0 { + status = "okay"; + + bridge@0,0 { + reg = <0x00000000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + ranges; + + wifi@0,0 { + compatible = "qcom,ath10k"; + reg = <0 0 0 0 0>; + + qcom,ath10k-calibration-variant = "Buffalo-WTR-M2133HP"; + }; + }; +}; + +&qpic_bam { + status = "okay"; +}; + +&nand { + pinctrl-0 = <&nand_pins>; + pinctrl-names = "default"; + status = "okay"; + + nand@0 { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "SBL1"; + reg = <0x0000000 0x0100000>; + read-only; + }; + + partition@100000 { + label = "MIBIB"; + reg = <0x0100000 0x0100000>; + read-only; + }; + + partition@200000 { + label = "BOOTCONFIG"; + reg = <0x0200000 0x0100000>; + read-only; + }; + + partition@300000 { + label = "QSEE"; + reg = <0x0300000 0x0100000>; + read-only; + }; + + partition@400000 { + label = "QSEE_1"; + reg = <0x0400000 0x0100000>; + read-only; + }; + + partition@500000 { + label = "CDT"; + reg = <0x0500000 0x0080000>; + read-only; + }; + + partition@580000 { + label = "CDT_1"; + reg = <0x0580000 0x0080000>; + read-only; + }; + + partition@600000 { + label = "BOOTCONFIG1"; + reg = <0x0600000 0x0080000>; + read-only; + }; + + partition@680000 { + label = "APPSBLENV"; + reg = <0x0680000 0x0080000>; + }; + + partition@700000 { + label = "APPSBL"; + reg = <0x0700000 0x0200000>; + read-only; + }; + + partition@900000 { + label = "APPSBL_1"; + reg = <0x0900000 0x0200000>; + read-only; + }; + + art: partition@b00000 { + label = "ART"; + reg = <0x0b00000 0x0080000>; + read-only; + }; + + partition@b80000 { + label = "ART_1"; + reg = <0x0b80000 0x0080000>; + read-only; + }; + + orgdata: partition@c00000 { + label = "ORGDATA"; + reg = <0x0c00000 0x0080000>; + read-only; + }; + + partition@c80000 { + label = "ORGDATA_1"; + reg = <0x0c80000 0x0080000>; + read-only; + }; + + partition@d00000 { + label = "ubi"; + reg = <0x0d00000 0x2900000>; + }; + + partition@3600000 { + label = "rootfs_recover"; + reg = <0x3600000 0x2900000>; + read-only; + }; + + partition@5f00000 { + label = "user_property"; + reg = <0x5f00000 0x1a20000>; + read-only; + }; + }; + }; +}; + +&wifi0 { + status = "okay"; + qcom,ath10k-calibration-variant = "Buffalo-WTR-M2133HP"; + ieee80211-freq-limit = <2400000 2483000>; +}; + +&wifi1 { + status = "okay"; + qcom,ath10k-calibration-variant = "Buffalo-WTR-M2133HP"; +}; + +&mdio { + status = "okay"; + pinctrl-0 = <&mdio_pins>; + pinctrl-names = "default"; + reset-gpios = <&tlmm 47 GPIO_ACTIVE_LOW>; +}; + +&gmac0 { + mtd-mac-address = <&orgdata 0x20>; +}; + +&gmac1 { + mtd-mac-address = <&orgdata 0x20>; +}; + +&usb3_ss_phy { + status = "okay"; +}; + +&usb3_hs_phy { + status = "okay"; +}; diff --git a/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-xx8300.dtsi b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-xx8300.dtsi new file mode 100644 index 000000000..0f1f083a5 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-xx8300.dtsi @@ -0,0 +1,299 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +/* + * Device Tree Source for Linksys xx8300 (Dallas) + * + * Copyright (C) 2019 Jeff Kletsky + * Updated 2020 Hans Geiblinger + * + */ + +#include "qcom-ipq4019.dtsi" +#include +#include +#include + + // + // OEM U-Boot provides either + // init=/sbin/init rootfstype=ubifs ubi.mtd=11,2048 \ + // root=ubi0:ubifs rootwait rw + // or the same with ubi.mtd=13,2048 + // + +/ { + chosen { + bootargs-append = " root=/dev/ubiblock0_0 rootfstype=squashfs ro"; + }; + + + soc { + rng@22000 { + status = "okay"; + }; + + mdio@90000 { + status = "okay"; + }; + + ess-psgmii@98000 { + status = "okay"; + }; + + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; + qcom,wifi_glb_cfg = ; + }; + + tcsr@194b000 { + compatible = "qcom,tcsr"; + reg = <0x194b000 0x100>; + qcom,usb-hsphy-mode-select = ; + }; + + ess_tcsr@1953000 { + compatible = "qcom,tcsr"; + reg = <0x1953000 0x1000>; + qcom,ess-interface-select = ; + }; + + tcsr@1957000 { + compatible = "qcom,tcsr"; + reg = <0x1957000 0x100>; + qcom,wifi_noc_memtype_m0_m2 = ; + }; + + usb2@60f8800 { + status = "okay"; + + dwc3@6000000 { + #address-cells = <1>; + #size-cells = <0>; + + usb2_port1: port@1 { + reg = <1>; + #trigger-source-cells = <0>; + }; + }; + }; + + usb3@8af8800 { + status = "okay"; + + dwc3@8a00000 { + #address-cells = <1>; + #size-cells = <0>; + + usb3_port1: port@1 { + reg = <1>; + #trigger-source-cells = <0>; + }; + + usb3_port2: port@2 { + reg = <2>; + #trigger-source-cells = <0>; + }; + }; + }; + + crypto@8e3a000 { + status = "okay"; + }; + + watchdog@b017000 { + status = "okay"; + }; + + ess-switch@c000000 { + status = "okay"; + }; + + edma@c080000 { + status = "okay"; + }; + }; +}; + + +&blsp_dma { + status = "okay"; +}; + +&blsp1_uart1 { + status = "okay"; + pinctrl-0 = <&serial_0_pins>; + pinctrl-names = "default"; + +}; + +&cryptobam { + status = "okay"; +}; + +&nand { + status = "okay"; + + pinctrl-0 = <&nand_pins>; + pinctrl-names = "default"; + + nand@0 { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "sbl1"; + reg = <0x0 0x100000>; + read-only; + }; + + partition@100000 { + label = "mibib"; + reg = <0x100000 0x100000>; + read-only; + }; + + partition@200000 { + label = "qsee"; + reg = <0x200000 0x100000>; + read-only; + }; + + partition@300000 { + label = "cdt"; + reg = <0x300000 0x80000>; + read-only; + }; + + partition@380000 { + label = "appsblenv"; + reg = <0x380000 0x80000>; + read-only; + }; + + partition@400000 { + label = "ART"; + reg = <0x400000 0x80000>; + read-only; + }; + + partition@480000 { + label = "appsbl"; + reg = <0x480000 0x200000>; + read-only; + }; + + partition@680000 { + label = "u_env"; + reg = <0x680000 0x80000>; + // writable -- U-Boot environment + }; + + partition@700000 { + label = "s_env"; + reg = <0x700000 0x40000>; + // writable -- Boot counter records + }; + + partition@740000 { + label = "devinfo"; + reg = <0x740000 0x40000>; + read-only; + }; + + partition@780000 { + label = "kernel"; + reg = <0x780000 0x5800000>; + }; + + partition@a80000 { + label = "rootfs"; + reg = <0xa80000 0x5500000>; + }; + + partition@5f80000 { + label = "alt_kernel"; + reg = <0x5f80000 0x5800000>; + }; + + partition@6280000 { + label = "alt_rootfs"; + reg = <0x6280000 0x5500000>; + }; + + partition@b780000 { + label = "sysdiag"; + reg = <0xb780000 0x100000>; + read-only; + }; + + partition@b880000 { + label = "certificates"; + reg = <0xb880000 0x4680000>; + }; + }; + }; +}; + +&pcie0 { + status = "okay"; + + perst-gpio = <&tlmm 38 GPIO_ACTIVE_LOW>; + wake-gpio = <&tlmm 50 GPIO_ACTIVE_LOW>; + + bridge@0,0 { + reg = <0x00000000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + ranges; + + wifi2: wifi@1,0 { + compatible = "qcom,ath10k"; + reg = <0x00010000 0 0 0 0>; + }; + }; +}; + +&qpic_bam { + status = "okay"; +}; + +&tlmm { + serial_0_pins: serial0-pinmux { + pins = "gpio16", "gpio17"; + function = "blsp_uart0"; + bias-disable; + }; + + nand_pins: nand_pins { + pullups { + pins = "gpio53", "gpio58", "gpio59"; + function = "qpic"; + bias-pull-up; + }; + + // gpio61 controls led_usb + + pulldowns { + pins = "gpio55", "gpio56", "gpio57", + "gpio60", "gpio62", "gpio63", + "gpio64", "gpio65", "gpio66", + "gpio67", "gpio68", "gpio69"; + function = "qpic"; + bias-pull-down; + }; + }; +}; + +&usb2_hs_phy { + status = "okay"; +}; + +&usb3_hs_phy { + status = "okay"; +}; + +&usb3_ss_phy { + status = "okay"; +}; diff --git a/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4028-wpj428.dts b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4028-wpj428.dts new file mode 100644 index 000000000..79f4c04ed --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4028-wpj428.dts @@ -0,0 +1,288 @@ +/* Copyright (c) 2015, The Linux Foundation. All rights reserved. + * Copyright (c) 2017, Christian Mehlis + * Copyright (c) 2017-2018, Sven Eckelmann + * + * 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 "qcom-ipq4019.dtsi" +#include +#include +#include + +/ { + model = "Compex WPJ428"; + compatible = "compex,wpj428"; + + soc { + rng@22000 { + status = "okay"; + }; + + mdio@90000 { + status = "okay"; + pinctrl-0 = <&mdio_pins>; + pinctrl-names = "default"; + reset-gpios = <&tlmm 59 GPIO_ACTIVE_LOW>; + reset-delay-us = <2000>; + }; + + ess-psgmii@98000 { + status = "okay"; + }; + + tcsr@194b000 { + /* select hostmode */ + compatible = "qcom,tcsr"; + reg = <0x194b000 0x100>; + qcom,usb-hsphy-mode-select = ; + status = "okay"; + }; + + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; + qcom,wifi_glb_cfg = ; + }; + + ess_tcsr@1953000 { + compatible = "qcom,tcsr"; + reg = <0x1953000 0x1000>; + qcom,ess-interface-select = ; + }; + + tcsr@1957000 { + compatible = "qcom,tcsr"; + reg = <0x1957000 0x100>; + qcom,wifi_noc_memtype_m0_m2 = ; + }; + + usb2: usb2@60f8800 { + status = "okay"; + }; + + usb3: usb3@8af8800 { + status = "okay"; + }; + + crypto@8e3a000 { + status = "okay"; + }; + + watchdog@b017000 { + status = "okay"; + }; + + ess-switch@c000000 { + switch_lan_bmp = <0x10>; + switch_wan_bmp = <0x20>; + + status = "okay"; + }; + + edma@c080000 { + status = "okay"; + }; + }; + + keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + gpios = <&tlmm 63 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + aliases { + led-boot = &status; + led-failsafe = &status; + led-upgrade = &status; + }; + + leds { + compatible = "gpio-leds"; + + status: rss4 { + label = "green:rss4"; + gpios = <&tlmm 5 GPIO_ACTIVE_HIGH>; + }; + + rss3 { + label = "green:rss3"; + gpios = <&tlmm 4 GPIO_ACTIVE_HIGH>; + }; + }; + + beeper: beeper { + compatible = "gpio-beeper"; + gpios = <&tlmm 58 GPIO_ACTIVE_HIGH>; + }; +}; + +&tlmm { + mdio_pins: mdio_pinmux { + mux_1 { + pins = "gpio53"; + function = "mdio"; + bias-pull-up; + }; + + mux_2 { + pins = "gpio52"; + function = "mdc"; + bias-pull-up; + }; + }; + + serial_pins: serial_pinmux { + mux { + pins = "gpio60", "gpio61"; + function = "blsp_uart0"; + bias-disable; + }; + }; + + spi_0_pins: spi_0_pinmux { + pin { + function = "blsp_spi0"; + pins = "gpio55", "gpio56", "gpio57"; + drive-strength = <12>; + bias-disable; + }; + pin_cs { + function = "gpio"; + pins = "gpio54"; + drive-strength = <2>; + bias-disable; + output-high; + }; + }; +}; + +&blsp_dma { + status = "okay"; +}; + +&blsp1_spi1 { + pinctrl-0 = <&spi_0_pins>; + pinctrl-names = "default"; + status = "okay"; + cs-gpios = <&tlmm 54 GPIO_ACTIVE_HIGH>; + + m25p80@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <24000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition0@0 { + label = "0:SBL1"; + reg = <0x00000000 0x00040000>; + read-only; + }; + partition1@40000 { + label = "0:MIBIB"; + reg = <0x00040000 0x00020000>; + read-only; + }; + partition2@60000 { + label = "0:QSEE"; + reg = <0x00060000 0x00060000>; + read-only; + }; + partition3@c0000 { + label = "0:CDT"; + reg = <0x000c0000 0x00010000>; + read-only; + }; + partition4@d0000 { + label = "0:DDRPARAMS"; + reg = <0x000d0000 0x00010000>; + read-only; + }; + partition5@e0000 { + label = "0:APPSBLENV"; /* uboot env*/ + reg = <0x000e0000 0x00010000>; + read-only; + }; + partition5@f0000 { + label = "0:APPSBL"; /* uboot */ + reg = <0x000f0000 0x00080000>; + read-only; + }; + partition5@170000 { + label = "0:ART"; + reg = <0x00170000 0x00010000>; + read-only; + }; + partition6@180000 { + compatible = "denx,fit"; + label = "firmware"; + reg = <0x00180000 0x01e80000>; + }; + }; + }; +}; + +&blsp1_uart1 { + pinctrl-0 = <&serial_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + +&cryptobam { + status = "okay"; +}; + +&gmac0 { + qcom,phy_mdio_addr = <4>; + qcom,poll_required = <1>; + qcom,forced_speed = <1000>; + qcom,forced_duplex = <1>; + vlan_tag = <2 0x20>; +}; + +&gmac1 { + qcom,phy_mdio_addr = <3>; + qcom,poll_required = <1>; + qcom,forced_speed = <1000>; + qcom,forced_duplex = <1>; + vlan_tag = <1 0x10>; +}; + +&usb3_ss_phy { + status = "okay"; +}; + +&usb3_hs_phy { + status = "okay"; +}; + +&usb2_hs_phy { + status = "okay"; +}; + +&wifi0 { + status = "okay"; +}; + +&wifi1 { + status = "okay"; +}; diff --git a/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4029-ap-303.dts b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4029-ap-303.dts new file mode 100644 index 000000000..13f89d810 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4029-ap-303.dts @@ -0,0 +1,178 @@ +// SPDX-License-Identifier: GPL-2.0-only OR MIT + +#include "qcom-ipq4029-aruba-glenmorangie.dtsi" +#include + +/ { + model = "Aruba AP-303"; + compatible = "aruba,ap-303"; + + aliases { + led-boot = &led_system_green; + led-failsafe = &led_system_red; + led-running = &led_system_green; + led-upgrade = &led_system_red; + }; + + leds { + compatible = "gpio-leds"; + + wifi_green { + label = "green:wifi"; + gpios = <&tlmm 39 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "phy0tpt"; + }; + + wifi_amber { + label = "amber:wifi"; + gpios = <&tlmm 40 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "phy1tpt"; + }; + + led_system_red: system_red { + label = "red:system"; + gpios = <&tlmm 46 GPIO_ACTIVE_HIGH>; + }; + + led_system_green: system_green { + label = "green:system"; + gpios = <&tlmm 47 GPIO_ACTIVE_HIGH>; + }; + }; +}; + +&tlmm { + /* + * In addition to the Pins listed below, + * the following GPIOs have "features": + * 54 - out - active low to force HW reset + * 41 - out - active low to reset TPM + * 43 - out - active low to reset BLE radio + * 19 - in - active high when DC powered + */ + + phy-reset { + line-name = "PHY-reset"; + gpios = <42 GPIO_ACTIVE_HIGH>; + gpio-hog; + output-high; + }; +}; + +&blsp1_spi1 { + pinctrl-0 = <&spi_0_pins>; + pinctrl-names = "default"; + status = "okay"; + cs-gpios = <&tlmm 12 GPIO_ACTIVE_HIGH>; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <24000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + /* + * There is no partition map for the NOR flash + * in the stock firmware. + * + * All partitions here are based on offsets + * found in the U-Boot GPL code and information + * from smem. + */ + + partition@0 { + label = "sbl1"; + reg = <0x0 0x40000>; + read-only; + }; + + partition@40000 { + label = "mibib"; + reg = <0x40000 0x20000>; + read-only; + }; + + partition@60000 { + label = "qsee"; + reg = <0x60000 0x60000>; + read-only; + }; + + partition@c0000 { + label = "cdt"; + reg = <0xc0000 0x10000>; + read-only; + }; + + partition@d0000 { + label = "ddrparams"; + reg = <0xd0000 0x10000>; + read-only; + }; + + partition@e0000 { + label = "ART"; + reg = <0xe0000 0x10000>; + read-only; + }; + + partition@f0000 { + label = "appsbl"; + reg = <0xf0000 0xf0000>; + read-only; + }; + + partition@1e0000 { + label = "mfginfo"; + reg = <0x1e0000 0x10000>; + read-only; + }; + + partition@1f0000 { + label = "apcd"; + reg = <0x1f0000 0x10000>; + read-only; + }; + + partition@200000 { + label = "osss"; + reg = <0x200000 0x180000>; + read-only; + }; + + partition@380000 { + label = "appsblenv"; + reg = <0x380000 0x10000>; + }; + + partition@390000 { + label = "pds"; + reg = <0x390000 0x10000>; + read-only; + }; + + partition@3a0000 { + label = "fcache"; + reg = <0x3a0000 0x10000>; + read-only; + }; + + partition@3b0000 { + /* Called osss1 in smem */ + label = "u-boot-env-bak"; + reg = <0x3b0000 0x10000>; + read-only; + }; + + partition@3f0000 { + label = "u-boot-env"; + reg = <0x3f0000 0x10000>; + read-only; + }; + }; + }; +}; diff --git a/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4029-ap-303h.dts b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4029-ap-303h.dts new file mode 100644 index 000000000..707ed18e3 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4029-ap-303h.dts @@ -0,0 +1,421 @@ +// SPDX-License-Identifier: GPL-2.0-only OR MIT + +#include "qcom-ipq4019.dtsi" +#include +#include +#include + +/ { + model = "Aruba AP-303H"; + compatible = "aruba,ap-303h"; + + aliases { + led-boot = &led_system_green; + led-failsafe = &led_system_red; + led-running = &led_system_green; + led-upgrade = &led_system_amber; + }; + + memory { + device_type = "memory"; + reg = <0x80000000 0x10000000>; + }; + + soc { + rng@22000 { + status = "okay"; + }; + + mdio@90000 { + status = "okay"; + pinctrl-0 = <&mdio_pins>; + pinctrl-names = "default"; + + reset-gpios = <&tlmm 19 GPIO_ACTIVE_LOW>; + reset-delay-us = <2000>; + }; + + counter@4a1000 { + compatible = "qcom,qca-gcnt"; + reg = <0x4a1000 0x4>; + }; + + ess_tcsr@1953000 { + compatible = "qcom,tcsr"; + reg = <0x1953000 0x1000>; + qcom,ess-interface-select = ; + }; + + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; + qcom,wifi_glb_cfg = ; + }; + + tcsr@194b000 { + compatible = "qcom,tcsr"; + reg = <0x194b000 0x100>; + qcom,usb-hsphy-mode-select = ; + }; + + tcsr@1957000 { + compatible = "qcom,tcsr"; + reg = <0x1957000 0x100>; + qcom,wifi_noc_memtype_m0_m2 = ; + }; + + usb2@60f8800 { + status = "okay"; + }; + + crypto@8e3a000 { + status = "okay"; + }; + + watchdog@b017000 { + status = "okay"; + }; + + ess-switch@c000000 { + status = "okay"; + }; + + edma@c080000 { + status = "okay"; + }; + + i2c_0: i2c@78b7000 { + pinctrl-0 = <&i2c_0_pins>; + pinctrl-names = "default"; + status = "okay"; + + tpm@29 { + /* No Driver */ + compatible = "atmel,at97sc3203"; + reg = <0x29>; + read-only; + }; + + power-monitor@40 { + /* No driver */ + compatible = "isl,isl28022"; + reg = <0x40>; + }; + }; + }; + + leds { + compatible = "gpio-leds"; + + wifi_green { + label = "green:wifi"; + gpios = <&tlmm 27 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "phy0tpt"; + }; + + wifi_amber { + label = "amber:wifi"; + gpios = <&tlmm 28 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "phy1tpt"; + }; + + pse { + label = "green:pse"; + gpios = <&tlmm 42 GPIO_ACTIVE_HIGH>; + }; + + led_system_red: system_red { + label = "red:system"; + gpios = <&tlmm 25 GPIO_ACTIVE_HIGH>; + }; + + led_system_green: system_green { + label = "green:system"; + gpios = <&tlmm 24 GPIO_ACTIVE_HIGH>; + }; + + led_system_amber: system_amber { + label = "amber:system"; + gpios = <&tlmm 26 GPIO_ACTIVE_HIGH>; + }; + }; + + keys { + compatible = "gpio-keys"; + + reset { + label = "Reset button"; + gpios = <&tlmm 18 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; +}; + +&blsp_dma { + status = "okay"; +}; + +&blsp1_uart1 { + pinctrl-0 = <&serial_0_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + +&blsp1_uart2 { + /* Texas Instruments CC2540T BLE radio */ + pinctrl-0 = <&serial_1_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + +&cryptobam { + status = "okay"; +}; + +&qpic_bam { + status = "okay"; +}; + +&tlmm { + /* + * In addition to the Pins listed below, + * the following GPIOs have "features": + * 39 - out - active low to force HW reset + * 32 - out - active low to reset TPM + * 43 - out - active low to reset BLE radio + * 41 - out - pulse to set warm reset status + * 34 - out - active low to enable PSE port + * 22 - in - active low when 802.3at powered + * 29 - in - active high when DC powered + * 40 - in - active low when reset due to cold HW reset + * 30 - in - active low when USB overcurrent detected + * 35 - in - interrupt line for power monitor chip + * 31 - in - active low when PSE port active + */ + mdio_pins: mdio_pinmux { + mux_1 { + pins = "gpio6"; + function = "mdio"; + bias-pull-up; + }; + mux_2 { + pins = "gpio7"; + function = "mdc"; + bias-pull-up; + }; + }; + + spi_0_pins: spi_0_pinmux { + pin { + function = "blsp_spi0"; + pins = "gpio13", "gpio14", "gpio15"; + drive-strength = <12>; + bias-disable; + }; + pin_cs { + function = "gpio"; + pins = "gpio12", "gpio59"; + drive-strength = <2>; + bias-disable; + output-high; + }; + }; + + i2c_0_pins: i2c_0_pinmux { + mux { + pins = "gpio20", "gpio21"; + function = "blsp_i2c0"; + drive-strength = <4>; + bias-disable; + }; + }; + + serial_0_pins: serial_0_pinmux { + mux { + pins = "gpio16", "gpio17"; + function = "blsp_uart0"; + bias-disable; + }; + }; + + serial_1_pins: serial_1_pinmux { + mux { + pins = "gpio8", "gpio9"; + function = "blsp_uart1"; + bias-disable; + }; + }; + + usb-power { + line-name = "USB-power"; + gpios = <23 GPIO_ACTIVE_HIGH>; + gpio-hog; + output-high; + }; +}; + +&blsp1_spi1 { + pinctrl-0 = <&spi_0_pins>; + pinctrl-names = "default"; + status = "okay"; + cs-gpios = <&tlmm 12 GPIO_ACTIVE_HIGH>, <&tlmm 59 GPIO_ACTIVE_HIGH>; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <24000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + /* + * There is no partition map for the NOR flash + * in the stock firmware. + * + * All partitions here are based on offsets + * found in the U-Boot GPL code and information + * from smem. + */ + + partition@0 { + label = "sbl1"; + reg = <0x0 0x40000>; + read-only; + }; + + partition@40000 { + label = "mibib"; + reg = <0x40000 0x20000>; + read-only; + }; + + partition@60000 { + label = "qsee"; + reg = <0x60000 0x60000>; + read-only; + }; + + partition@c0000 { + label = "cdt"; + reg = <0xc0000 0x10000>; + read-only; + }; + + partition@d0000 { + label = "ddrparams"; + reg = <0xd0000 0x10000>; + read-only; + }; + + partition@e0000 { + label = "appsblenv"; + reg = <0xe0000 0x10000>; + read-only; + }; + + partition@f0000 { + label = "appsbl"; + reg = <0xf0000 0x100000>; + read-only; + }; + + partition@1e0000 { + label = "ART"; + reg = <0x1f0000 0x10000>; + read-only; + }; + + partition@1f0000 { + label = "osss"; + reg = <0x200000 0x170000>; + read-only; + }; + + partition@200000 { + label = "pds"; + reg = <0x370000 0x10000>; + read-only; + }; + + partition@380000 { + label = "apcd"; + reg = <0x380000 0x10000>; + read-only; + }; + + partition@390000 { + label = "mfginfo"; + reg = <0x390000 0x10000>; + read-only; + }; + + partition@3a0000 { + label = "fcache"; + reg = <0x3a0000 0x10000>; + read-only; + }; + + partition@3b0000 { + /* Called osss1 in smem */ + label = "u-boot-env-bak"; + reg = <0x3b0000 0x10000>; + read-only; + }; + + partition@3f0000 { + label = "u-boot-env"; + reg = <0x3c0000 0x40000>; + read-only; + }; + }; + }; + + flash@1 { + status = "okay"; + + compatible = "spi-nand"; + reg = <1>; + spi-max-frequency = <24000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + /* 'aos0' in Aruba firmware */ + label = "aos0"; + reg = <0x0 0x2000000>; + read-only; + }; + + partition@2000000 { + /* 'aos1' in Aruba firmware */ + label = "ubi"; + reg = <0x2000000 0x2000000>; + }; + + partition@4000000 { + label = "aruba-ubifs"; + reg = <0x4000000 0x4000000>; + read-only; + }; + }; + }; +}; + +&usb2_hs_phy { + status = "okay"; +}; + +&wifi0 { + status = "okay"; + qcom,ath10k-calibration-variant = "Aruba-AP-303"; +}; + +&wifi1 { + status = "okay"; + qcom,ath10k-calibration-variant = "Aruba-AP-303"; +}; diff --git a/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4029-ap-365.dts b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4029-ap-365.dts new file mode 100644 index 000000000..988a4421b --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4029-ap-365.dts @@ -0,0 +1,192 @@ +// SPDX-License-Identifier: GPL-2.0-only OR MIT + +#include "qcom-ipq4029-aruba-glenmorangie.dtsi" +#include + +/ { + model = "Aruba AP-365"; + compatible = "aruba,ap-365"; + + aliases { + led-boot = &led_system_green; + led-failsafe = &led_system_red; + led-running = &led_system_green; + led-upgrade = &led_system_red; + }; + + leds { + compatible = "gpio-leds"; + + led_system_red: system_red { + label = "red:system"; + gpios = <&tlmm 46 GPIO_ACTIVE_LOW>; + }; + + led_system_green: system_green { + label = "green:system"; + gpios = <&tlmm 61 GPIO_ACTIVE_LOW>; + }; + + system_amber { + label = "amber:system"; + gpios = <&tlmm 49 GPIO_ACTIVE_LOW>; + }; + }; + + watchdog { + compatible = "linux,wdt-gpio"; + gpios = <&tlmm 41 GPIO_ACTIVE_LOW>; + hw_algo = "toggle"; + hw_margin_ms = <1000>; + always-running; + }; +}; + +&tlmm { + /* + * In addition to the Pins listed below, + * the following GPIOs have "features": + * 39 - out - pulse low to reset watchdog status flipflop + * 40 - out - active high to enable watchdog + * 41 - out - watchdog poke + * 42 - out - active low to reset BLE radio + * 43 - out - active low to reset TPM + * 47 - out - pulse low to reset warm reset status + * 54 - out - active low to force HW reset + * 18 - in - PHY interrupt line + * 45 - in - power monitor interrupt + * 48 - in - active low when cold reset + * 52 - in - active high when watchdog reset + */ + + phy-reset { + line-name = "PHY-reset"; + gpios = <42 GPIO_ACTIVE_HIGH>; + gpio-hog; + output-high; + }; +}; + +&i2c_0 { + power-monitor@40 { + /* No driver */ + compatible = "isl,isl28022"; + reg = <0x40>; + }; + + temperature-sensor@48 { + compatible = "adi,ad7416"; + reg = <0x48>; + }; +}; + +&blsp1_spi1 { + pinctrl-0 = <&spi_0_pins>; + pinctrl-names = "default"; + status = "okay"; + cs-gpios = <&tlmm 12 GPIO_ACTIVE_HIGH>; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <24000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + /* + * There is no partition map for the NOR flash + * in the stock firmware. + * + * All partitions here are based on offsets + * found in the U-Boot GPL code and information + * from smem. + */ + + partition@0 { + label = "sbl1"; + reg = <0x0 0x40000>; + read-only; + }; + + partition@40000 { + label = "mibib"; + reg = <0x40000 0x20000>; + read-only; + }; + + partition@60000 { + label = "qsee"; + reg = <0x60000 0x60000>; + read-only; + }; + + partition@c0000 { + label = "cdt"; + reg = <0xc0000 0x10000>; + read-only; + }; + + partition@d0000 { + label = "ddrparams"; + reg = <0xd0000 0x10000>; + read-only; + }; + + partition@e0000 { + label = "u-boot-env"; + reg = <0xe0000 0x10000>; + }; + + partition@f0000 { + label = "appsbl"; + reg = <0xf0000 0x100000>; + read-only; + }; + + partition@1f0000 { + label = "ART"; + reg = <0x1f0000 0x10000>; + read-only; + }; + + partition@200000 { + label = "osss"; + reg = <0x200000 0x170000>; + read-only; + }; + + partition@370000 { + label = "pds"; + reg = <0x370000 0x10000>; + read-only; + }; + + partition@380000 { + label = "apcd"; + reg = <0x380000 0x10000>; + read-only; + }; + + partition@390000 { + label = "mfginfo"; + reg = <0x390000 0x10000>; + read-only; + }; + + partition@3a0000 { + label = "fcache"; + reg = <0x3a0000 0x10000>; + read-only; + }; + + partition@3b0000 { + label = "osss1"; + reg = <0x3b0000 0x50000>; + read-only; + }; + }; + }; +}; diff --git a/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4029-ap-cig-wf610d.dts b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4029-ap-cig-wf610d.dts new file mode 100755 index 000000000..3f24369f1 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4029-ap-cig-wf610d.dts @@ -0,0 +1,414 @@ +/* Copyright (c) 2015, 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 "qcom-ipq4019.dtsi" +#include +#include +#include + +/ { + model = "Cambridge Industries Group, Ltd. WF-610D"; + compatible = "cig,wf610d", "qcom,ipq4019"; + qcom,board-id = <8 0>; + qcom,msm-id = <0x111 0>; + qcom,pmic-id = <0 0 0 0>; + + memory { + device_type = "memory"; + reg = <0x80000000 0x10000000>; /* 256MB */ + }; + + chosen { + bootargs-append = " clk_ignore_unused"; + }; + + soc { + pinctrl@1000000 { + serial_0_pins: serial0_pinmux { + mux { + pins = "gpio16", "gpio17"; + function = "blsp_uart0"; + bias-disable; + }; + }; + + serial_1_pins: serial1_pinmux { + mux { + pins = "gpio8", "gpio9"; + function = "blsp_uart1"; + bias-disable; + }; + }; + + nand_pins: nand_pins { + + pullups { + pins = "gpio53", "gpio58", + "gpio59"; + function = "qpic"; + bias-pull-up; + }; + + pulldowns { + pins = "gpio54", "gpio55", "gpio56", + "gpio57", "gpio60", "gpio61", + "gpio62", "gpio63", "gpio64", + "gpio65", "gpio66", "gpio67", + "gpio68", "gpio69"; + function = "qpic"; + bias-pull-down; + }; + }; + led_0_pins: led0_pinmux { + mux { + pins = "gpio52", "gpio42", "gpio43", "gpio45", "gpio46", "gpio47", "gpio48", "gpio40", "gpio39", "gpio49"; + function = "gpio"; + drive-strength = <16>; + bias-pull-down; + output-low; + }; + }; + + spi_0_pins: spi_0_pinmux { + pinmux { + function = "blsp_spi0"; + pins = "gpio13", "gpio14", "gpio15"; + }; + pinmux_cs { + function = "gpio"; + pins = "gpio12"; + }; + pinconf { + pins = "gpio13", "gpio14", "gpio15"; + drive-strength = <12>; + bias-disable; + }; + pinconf_cs { + pins = "gpio12"; + drive-strength = <2>; + bias-disable; + output-high; + }; + }; + + i2c_0_pins: i2c_0_pinmux { + pinmux { + function = "blsp_i2c0"; + pins = "gpio10", "gpio11"; + }; + pinconf { + pins = "gpio10", "gpio11"; + drive-strength = <16>; + bias-disable; + }; + }; + mdio_pins: mdio_pinmux { + mux_1 { + pins = "gpio6"; + function = "mdio"; + bias-pull-up; + }; + mux_2 { + pins = "gpio7"; + function = "mdc"; + bias-pull-up; + }; + }; + + }; + + serial@78af000 { + pinctrl-0 = <&serial_0_pins>; + pinctrl-names = "default"; + status = "okay"; + }; + + serial@78b0000 { + pinctrl-0 = <&serial_1_pins>; + pinctrl-names = "default"; + status = "okay"; + }; + + blsp_dma: dma@7884000 { + status = "okay"; + }; + + spi_0: spi@78b5000 { + pinctrl-0 = <&spi_0_pins>; + pinctrl-names = "default"; + status = "okay"; + cs-gpios = <&tlmm 12 GPIO_ACTIVE_HIGH>; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + reg = <0>; + compatible = "jedec,spi-nor"; + linux,modalias = "m25p80", "n25q128a11"; + spi-max-frequency = <24000000>; + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + SBL1@0 { + label = "0:SBL1"; + reg = <0x0 0x40000>; + read-only; + }; + + MIBIB@40000 { + label = "0:MIBIB"; + reg = <0x40000 0x20000>; + read-only; + }; + + QSEE@60000 { + label = "0:QSEE"; + reg = <0x60000 0x60000>; + read-only; + }; + + CDT@c0000 { + label = "0:CDT"; + reg = <0xc0000 0x10000>; + read-only; + }; + + DDRPARAMS@d0000 { + label = "0:DDRPARAMS"; + reg = <0xd0000 0x10000>; + read-only; + }; + + APPSBLENV@e0000 { + label = "0:APPSBLENV"; + reg = <0xe0000 0x10000>; + read-only; + }; + + APPSBL@f0000 { + label = "0:APPSBL"; + reg = <0xf0000 0x80000>; + read-only; + }; + + ART@170000 { + label = "0:ART"; + reg = <0x170000 0x10000>; + read-only; + }; + + firmware@180000 { + compatible = "denx,fit"; + label = "firmware"; + reg = <0x180000 0x1e70000>; + }; + + certificates@1ff0000 { + compatible = "denx,fit"; + label = "certificates"; + reg = <0x1ff0000 0x10000>; + }; + }; + }; + }; + + i2c_0: i2c@78b7000 { /* BLSP1 QUP2 */ + pinctrl-0 = <&i2c_0_pins>; + pinctrl-1 = <&i2c_0_pins>; + pinctrl-names = "i2c_active", "i2c_sleep"; + status = "okay"; + + qca_codec: qca_codec@12 { + compatible = "qca,ipq40xx-codec"; + reg = <0x12>; + status = "disabled"; + }; + + lcd_ts: lcd_ts@40 { + compatible = "qca,gsl1680_ts"; + reg = <0x40>; + status = "disabled"; + }; + }; + + + + cryptobam: dma@8e04000 { + status = "okay"; + }; + + crypto@8e3a000 { + status = "okay"; + }; + + gpio_keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + linux,code = ; + gpios = <&tlmm 50 GPIO_ACTIVE_LOW>; + linux,input-type = <1>; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + pinctrl-0 = <&led_0_pins>; + + wf6203_green_power { + gpios = <&tlmm 52 0>; + label = "wf6203:green:power"; + default-state = "off"; + }; + wf6203_yellow_eth0 { + gpios = <&tlmm 42 0>; + label = "wf6203:yellow:eth0"; + default-state = "off"; + }; + wf6203_green_eth0 { + gpios = <&tlmm 43 GPIO_ACTIVE_LOW>; + label = "wf6203:green:eth0"; + default-state = "off"; + }; + wf6203_yellow_eth1 { + gpios = <&tlmm 45 0>; + label = "wf6203:yellow:eth1"; + default-state = "off"; + }; + wf6203_green_eth1 { + gpios = <&tlmm 46 GPIO_ACTIVE_LOW>; + label = "wf6203:green:eth1"; + default-state = "off"; + }; + wf6203_yellow_eth2 { + gpios = <&tlmm 47 0>; + label = "wf6203:yellow:eth2"; + default-state = "off"; + }; + wf6203_green_eth2 { + gpios = <&tlmm 48 GPIO_ACTIVE_LOW>; + label = "wf6203:green:eth2"; + default-state = "off"; + }; + wf6203_green_wifi2g { + gpios = <&tlmm 40 0>; + label = "wf6203:green:wifi2g"; + default-state = "off"; + }; + wf6203_green_wifi5g { + gpios = <&tlmm 39 0>; + label = "wf6203:green:wifi5g"; + default-state = "off"; + }; + wf6203_green_status { + gpios = <&tlmm 49 0>; + label = "wf6203:green:status"; + default-state = "off"; + }; + }; + + + watchdog@b017000 { + timeout-sec = <60>; + status = "okay"; + }; + + qpic_bam: dma@7984000 { + status = "okay"; + }; + + nand: qpic-nand@79b0000 { + pinctrl-0 = <&nand_pins>; + pinctrl-names = "default"; + status = "okay"; + }; + + mdio@90000 { + pinctrl-0 = <&mdio_pins>; + pinctrl-names = "default"; + phy-reset-gpio = <&tlmm 18 0>; + status = "okay"; + bias-disable; + }; + + ess-switch@c000000 { + switch_lan_bmp = <0x3e>; /* lan port bitmap */ + switch_wan_bmp = <1>; /* wan port bitmap */ + status = "okay"; + }; + + ess-psgmii@98000 { + status = "okay"; + }; + + edma@c080000 { + status = "okay"; + }; + + usb3_ss_phy: ssphy@9a000 { + status = "okay"; + }; + + usb3_hs_phy: hsphy@a6000 { + status = "okay"; + }; + + usb3: usb3@8af8800 { + status = "okay"; + }; + + usb2_hs_phy: hsphy@a8000 { + status = "okay"; + }; + + usb2: usb2@60f8800 { + status = "okay"; + }; + + ext_wtd { + compatible = "linux,wdt-gpio"; + gpios = <&tlmm 41 GPIO_ACTIVE_LOW>; + hw_algo = "toggle"; + hw_margin_ms = <1000>; + always-running; + }; + + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; + qcom,wifi_glb_cfg = ; + }; + + tcsr@1957000 { + compatible = "qcom,tcsr"; + reg = <0x1957000 0x100>; + qcom,wifi_noc_memtype_m0_m2 = ; + }; + + wifi0: wifi@a000000 { + qcom,ath10k-calibration-variant = "CIG WF_610D"; + status = "okay"; + }; + + wifi1: wifi@a800000 { + qcom,ath10k-calibration-variant = "CIG WF_610D"; + status = "okay"; + }; + }; + +}; diff --git a/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4029-aruba-glenmorangie.dtsi b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4029-aruba-glenmorangie.dtsi new file mode 100644 index 000000000..9d0823f3e --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4029-aruba-glenmorangie.dtsi @@ -0,0 +1,251 @@ +// SPDX-License-Identifier: GPL-2.0-only OR MIT + +#include "qcom-ipq4019.dtsi" +#include +#include +#include + +/ { + memory { + device_type = "memory"; + reg = <0x80000000 0x10000000>; + }; + + soc { + rng@22000 { + status = "okay"; + }; + + mdio@90000 { + status = "okay"; + pinctrl-0 = <&mdio_pins>; + pinctrl-names = "default"; + + /delete-node/ ethernet-phy@0; + /delete-node/ ethernet-phy@1; + /delete-node/ ethernet-phy@2; + /delete-node/ ethernet-phy@3; + /delete-node/ ethernet-phy@4; + /delete-node/ psgmii-phy@5; + + ethernet-phy@5 { + reg = <0x5>; + }; + }; + + counter@4a1000 { + compatible = "qcom,qca-gcnt"; + reg = <0x4a1000 0x4>; + }; + + ess_tcsr@1953000 { + compatible = "qcom,tcsr"; + reg = <0x1953000 0x1000>; + qcom,ess-interface-select = ; + }; + + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; + qcom,wifi_glb_cfg = ; + }; + + tcsr@1957000 { + compatible = "qcom,tcsr"; + reg = <0x1957000 0x100>; + qcom,wifi_noc_memtype_m0_m2 = ; + }; + + crypto@8e3a000 { + status = "okay"; + }; + + watchdog@b017000 { + status = "okay"; + }; + + ess-switch@c000000 { + switch_mac_mode = <0x3>; /* mac mode for RGMII RMII */ + switch_lan_bmp = <0x0>; /* lan port bitmap */ + switch_wan_bmp = <0x10>; /* wan port bitmap */ + }; + + edma@c080000 { + qcom,single-phy; + qcom,num_gmac = <1>; + phy-mode = "rgmii-id"; + status = "okay"; + }; + + i2c_0: i2c@78b7000 { + pinctrl-0 = <&i2c_0_pins>; + pinctrl-names = "default"; + status = "okay"; + + tpm@29 { + /* No Driver */ + compatible = "atmel,at97sc3203"; + reg = <0x29>; + read-only; + }; + }; + }; + + keys { + compatible = "gpio-keys"; + + reset { + label = "Reset button"; + gpios = <&tlmm 50 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; +}; + +&blsp_dma { + status = "okay"; +}; + +&blsp1_uart1 { + /* Texas Instruments CC2540T BLE radio */ + pinctrl-0 = <&serial_0_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + +&blsp1_uart2 { + pinctrl-0 = <&serial_1_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + +&cryptobam { + status = "okay"; +}; + +&gmac0 { + qcom,phy_mdio_addr = <5>; + qcom,poll_required = <1>; + vlan_tag = <0 0x20>; +}; + +&qpic_bam { + status = "okay"; +}; + +&tlmm { + mdio_pins: mdio_pinmux { + mux_1 { + pins = "gpio6"; + function = "mdio"; + bias-pull-up; + }; + mux_2 { + pins = "gpio7"; + function = "mdc"; + bias-pull-up; + }; + }; + + nand_pins: nand_pins { + pullups { + pins = "gpio53", "gpio58", "gpio59"; + function = "qpic"; + bias-pull-up; + }; + + pulldowns { + pins = "gpio54", "gpio55", "gpio56", + "gpio57", "gpio60", "gpio61", + "gpio62", "gpio63", "gpio64", + "gpio65", "gpio66", "gpio67", + "gpio68", "gpio69"; + function = "qpic"; + bias-pull-down; + }; + }; + + spi_0_pins: spi_0_pinmux { + pin { + function = "blsp_spi0"; + pins = "gpio13", "gpio14", "gpio15"; + drive-strength = <12>; + bias-disable; + }; + pin_cs { + function = "gpio"; + pins = "gpio12"; + drive-strength = <2>; + bias-disable; + output-high; + }; + }; + + i2c_0_pins: i2c_0_pinmux { + mux { + pins = "gpio10", "gpio11"; + function = "blsp_i2c0"; + drive-strength = <4>; + bias-disable; + }; + }; + + serial_0_pins: serial_0_pinmux { + mux { + pins = "gpio16", "gpio17"; + function = "blsp_uart0"; + bias-disable; + }; + }; + + serial_1_pins: serial_1_pinmux { + mux { + pins = "gpio8", "gpio9"; + function = "blsp_uart1"; + bias-disable; + }; + }; +}; + +&nand { + pinctrl-0 = <&nand_pins>; + pinctrl-names = "default"; + status = "okay"; + + nand@0 { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + /* 'aos0' in Aruba firmware */ + label = "aos0"; + reg = <0x0 0x2000000>; + read-only; + }; + + partition@2000000 { + /* 'aos1' in Aruba firmware */ + label = "ubi"; + reg = <0x2000000 0x2000000>; + }; + + partition@4000000 { + label = "aruba-ubifs"; + reg = <0x4000000 0x4000000>; + read-only; + }; + }; + }; +}; + +&wifi0 { + status = "okay"; + qcom,ath10k-calibration-variant = "Aruba-AP-303"; +}; + +&wifi1 { + status = "okay"; + qcom,ath10k-calibration-variant = "Aruba-AP-303"; +}; diff --git a/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4029-gl-b1300.dts b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4029-gl-b1300.dts new file mode 100644 index 000000000..a735d8e3a --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4029-gl-b1300.dts @@ -0,0 +1,280 @@ +/* Copyright (c) 2015, 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 "qcom-ipq4019.dtsi" +#include +#include +#include + +/ { + model = "GL.iNet GL-B1300"; + compatible = "glinet,gl-b1300"; + + aliases { + led-boot = &power; + led-failsafe = &power; + led-running = &power; + led-upgrade = &power; + }; + + memory { + device_type = "memory"; + reg = <0x80000000 0x10000000>; + }; + + soc { + rng@22000 { + status = "okay"; + }; + + mdio@90000 { + status = "okay"; + }; + + ess-psgmii@98000 { + status = "okay"; + }; + + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; + qcom,wifi_glb_cfg = ; + }; + + tcsr@194b000 { + /* select hostmode */ + compatible = "qcom,tcsr"; + reg = <0x194b000 0x100>; + qcom,usb-hsphy-mode-select = ; + status = "okay"; + }; + + ess_tcsr@1953000 { + compatible = "qcom,tcsr"; + reg = <0x1953000 0x1000>; + qcom,ess-interface-select = ; + }; + + tcsr@1957000 { + compatible = "qcom,tcsr"; + reg = <0x1957000 0x100>; + qcom,wifi_noc_memtype_m0_m2 = ; + }; + + usb2@60f8800 { + status = "okay"; + }; + + usb3@8af8800 { + status = "okay"; + }; + + crypto@8e3a000 { + status = "okay"; + }; + + watchdog@b017000 { + status = "okay"; + }; + + ess-switch@c000000 { + status = "okay"; + switch_lan_bmp = <0x18>; + switch_wan_bmp = <0x20>; + }; + + edma@c080000 { + status = "okay"; + }; + }; + + keys { + compatible = "gpio-keys"; + + wps { + label = "wps"; + gpios = <&tlmm 5 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + + reset { + label = "reset"; + gpios = <&tlmm 63 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + leds { + compatible = "gpio-leds"; + + power: power { + label = "green:power"; + gpios = <&tlmm 4 GPIO_ACTIVE_HIGH>; + default-state = "on"; + }; + + mesh { + label = "green:mesh"; + gpios = <&tlmm 3 GPIO_ACTIVE_HIGH>; + }; + + wlan { + label = "green:wlan"; + gpios = <&tlmm 2 GPIO_ACTIVE_HIGH>; + }; + }; +}; + +&blsp_dma { + status = "okay"; +}; + +&cryptobam { + status = "okay"; +}; + +&blsp1_spi1 { + pinctrl-0 = <&spi_0_pins>; + pinctrl-names = "default"; + status = "okay"; + cs-gpios = <&tlmm 54 GPIO_ACTIVE_HIGH>; + + mx25l25635f@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <24000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + SBL1@0 { + label = "SBL1"; + reg = <0x0 0x40000>; + read-only; + }; + + MIBIB@40000 { + label = "MIBIB"; + reg = <0x40000 0x20000>; + read-only; + }; + + QSEE@60000 { + label = "QSEE"; + reg = <0x60000 0x60000>; + read-only; + }; + + CDT@c0000 { + label = "CDT"; + reg = <0xc0000 0x10000>; + read-only; + }; + + DDRPARAMS@d0000 { + label = "DDRPARAMS"; + reg = <0xd0000 0x10000>; + read-only; + }; + + APPSBLENV@e0000 { + label = "APPSBLENV"; + reg = <0xe0000 0x10000>; + read-only; + }; + + APPSBL@f0000 { + label = "APPSBL"; + reg = <0xf0000 0x80000>; + read-only; + }; + + ART@170000 { + label = "ART"; + reg = <0x170000 0x10000>; + read-only; + }; + + firmware@180000 { + compatible = "denx,fit"; + label = "firmware"; + reg = <0x180000 0x1e80000>; + }; + }; + }; +}; + +&blsp1_uart1 { + pinctrl-0 = <&serial_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + +&tlmm { + serial_pins: serial_pinmux { + mux { + pins = "gpio60", "gpio61"; + function = "blsp_uart0"; + bias-disable; + }; + }; + + spi_0_pins: spi_0_pinmux { + pinmux { + function = "blsp_spi0"; + pins = "gpio55", "gpio56", "gpio57"; + }; + pinmux_cs { + function = "gpio"; + pins = "gpio54"; + }; + pinconf { + pins = "gpio55", "gpio56", "gpio57"; + drive-strength = <12>; + bias-disable; + }; + pinconf_cs { + pins = "gpio54"; + drive-strength = <2>; + bias-disable; + output-high; + }; + }; +}; + +&usb2_hs_phy { + status = "okay"; +}; + +&usb3_hs_phy { + status = "okay"; +}; + +&usb3_ss_phy { + status = "okay"; +}; + +&wifi0 { + status = "okay"; + qcom,ath10k-calibration-variant = "GL-B1300"; +}; + +&wifi1 { + status = "okay"; + qcom,ath10k-calibration-variant = "GL-B1300"; +}; diff --git a/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4029-gl-s1300.dts b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4029-gl-s1300.dts new file mode 100644 index 000000000..fa859b73a --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4029-gl-s1300.dts @@ -0,0 +1,356 @@ +// SPDX-License-Identifier: GPL-2.0-only OR MIT + +#include "qcom-ipq4019.dtsi" +#include +#include +#include + +/ { + model = "GL.iNet GL-S1300"; + compatible = "glinet,gl-s1300"; + + aliases { + led-boot = &led_power; + led-failsafe = &led_power; + led-running = &led_power; + led-upgrade = &led_power; + }; + + memory { + device_type = "memory"; + reg = <0x80000000 0x10000000>; + }; + + soc { + rng@22000 { + status = "okay"; + }; + + mdio@90000 { + status = "okay"; + }; + + ess-psgmii@98000 { + status = "okay"; + }; + + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; + qcom,wifi_glb_cfg = ; + }; + + tcsr@194b000 { + /* select hostmode */ + compatible = "qcom,tcsr"; + reg = <0x194b000 0x100>; + qcom,usb-hsphy-mode-select = ; + status = "okay"; + }; + + ess_tcsr@1953000 { + compatible = "qcom,tcsr"; + reg = <0x1953000 0x1000>; + qcom,ess-interface-select = ; + }; + + tcsr@1957000 { + compatible = "qcom,tcsr"; + reg = <0x1957000 0x100>; + qcom,wifi_noc_memtype_m0_m2 = ; + }; + + usb2@60f8800 { + status = "okay"; + }; + + usb3@8af8800 { + status = "okay"; + }; + + crypto@8e3a000 { + status = "okay"; + }; + + watchdog@b017000 { + status = "okay"; + }; + + ess-switch@c000000 { + status = "okay"; + switch_lan_bmp = <0x18>; + switch_wan_bmp = <0x20>; + }; + + edma@c080000 { + status = "okay"; + }; + }; + + keys { + compatible = "gpio-keys"; + + wps { + label = "wps"; + gpios = <&tlmm 53 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + + reset { + label = "reset"; + gpios = <&tlmm 18 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + leds { + compatible = "gpio-leds"; + + led_power: power { + label = "green:power"; + gpios = <&tlmm 57 GPIO_ACTIVE_HIGH>; + default-state = "on"; + }; + + mesh { + label = "green:mesh"; + gpios = <&tlmm 59 GPIO_ACTIVE_HIGH>; + }; + + wlan { + label = "green:wlan"; + gpios = <&tlmm 60 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "phy0tpt"; + }; + }; +}; + +&vqmmc { + status = "okay"; +}; + +&sdhci { + status = "okay"; + pinctrl-0 = <&sd_pins>; + pinctrl-names = "default"; + cd-gpios = <&tlmm 22 GPIO_ACTIVE_LOW>; + vqmmc-supply = <&vqmmc>; +}; + +&blsp_dma { + status = "okay"; +}; + +&cryptobam { + status = "okay"; +}; + +&blsp1_spi1 { + pinctrl-0 = <&spi_0_pins>; + pinctrl-names = "default"; + status = "okay"; + cs-gpios = <&tlmm 12 GPIO_ACTIVE_HIGH>; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <24000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + SBL1@0 { + label = "SBL1"; + reg = <0x0 0x40000>; + read-only; + }; + + MIBIB@40000 { + label = "MIBIB"; + reg = <0x40000 0x20000>; + read-only; + }; + + QSEE@60000 { + label = "QSEE"; + reg = <0x60000 0x60000>; + read-only; + }; + + CDT@c0000 { + label = "CDT"; + reg = <0xc0000 0x10000>; + read-only; + }; + + DDRPARAMS@d0000 { + label = "DDRPARAMS"; + reg = <0xd0000 0x10000>; + read-only; + }; + + APPSBLENV@e0000 { + label = "APPSBLENV"; + reg = <0xe0000 0x10000>; + read-only; + }; + + APPSBL@f0000 { + label = "APPSBL"; + reg = <0xf0000 0x80000>; + read-only; + }; + + ART@170000 { + label = "ART"; + reg = <0x170000 0x10000>; + read-only; + }; + + firmware@180000 { + compatible = "denx,fit"; + label = "firmware"; + reg = <0x180000 0xe80000>; + }; + }; + }; +}; + +&blsp1_spi2 { + pinctrl-0 = <&spi_1_pins>; + pinctrl-names = "default"; + status = "okay"; + + spidev1: spi@0 { + compatible = "siliconlabs,si3210"; + reg = <0>; + spi-max-frequency = <24000000>; + }; +}; + +&blsp1_uart1 { + pinctrl-0 = <&serial_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + +&blsp1_uart2 { + pinctrl-0 = <&serial_1_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + +&tlmm { + serial_pins: serial_pinmux { + mux { + pins = "gpio16", "gpio17"; + function = "blsp_uart0"; + bias-disable; + }; + }; + + serial_1_pins: serial1_pinmux { + mux { + pins = "gpio8", "gpio9", + "gpio10", "gpio11"; + function = "blsp_uart1"; + bias-disable; + }; + }; + + spi_0_pins: spi_0_pinmux { + pinmux { + function = "blsp_spi0"; + pins = "gpio13", "gpio14", "gpio15"; + }; + pinmux_cs { + function = "gpio"; + pins = "gpio12"; + }; + pinconf { + pins = "gpio13", "gpio14", "gpio15"; + drive-strength = <12>; + bias-disable; + }; + pinconf_cs { + pins = "gpio12"; + drive-strength = <2>; + bias-disable; + output-high; + }; + }; + + spi_1_pins: spi_1_pinmux { + mux { + pins = "gpio44", "gpio46", "gpio47"; + function = "blsp_spi1"; + bias-disable; + }; + host_int { + pins = "gpio42"; + function = "gpio"; + input; + }; + cs { + pins = "gpio45"; + function = "gpio"; + bias-pull-up; + }; + wake { + pins = "gpio40"; + function = "gpio"; + output-high; + }; + reset { + pins = "gpio49"; + function = "gpio"; + output-high; + }; + }; + + sd_pins: sd_pins { + pinmux { + function = "sdio"; + pins = "gpio23", "gpio24", "gpio25", "gpio26", + "gpio28", "gpio29", "gpio30", "gpio31"; + drive-strength = <10>; + }; + + pinmux_sd_clk { + function = "sdio"; + pins = "gpio27"; + drive-strength = <16>; + }; + + pinmux_sd7 { + function = "sdio"; + pins = "gpio32"; + drive-strength = <10>; + bias-disable; + }; + }; +}; + +&usb2_hs_phy { + status = "okay"; +}; + +&usb3_hs_phy { + status = "okay"; +}; + +&usb3_ss_phy { + status = "okay"; +}; + +&wifi0 { + status = "okay"; + qcom,ath10k-calibration-variant = "GL-S1300"; +}; + +&wifi1 { + status = "okay"; + qcom,ath10k-calibration-variant = "GL-S1300"; +}; diff --git a/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4029-mr33.dts b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4029-mr33.dts new file mode 100644 index 000000000..36a01e505 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4029-mr33.dts @@ -0,0 +1,400 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Device Tree Source for Meraki MR33 (Stinkbug) + * + * Copyright (C) 2017 Chris Blake + * Copyright (C) 2017 Christian Lamparter + * + * Based on Cisco Meraki DTS from GPL release r25-linux-3.14-20170427 + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without + * any warranty of any kind, whether express or implied. + */ + +#include "qcom-ipq4019.dtsi" +#include +#include +#include + +/ { + model = "Meraki MR33 Access Point"; + compatible = "meraki,mr33"; + + aliases { + led-boot = &status_green; + led-failsafe = &status_red; + led-running = &status_green; + led-upgrade = &power_orange; + }; + + /* Do we really need this defined? */ + memory { + device_type = "memory"; + reg = <0x80000000 0x10000000>; + }; + + soc { + rng@22000 { + status = "okay"; + }; + + mdio@90000 { + status = "okay"; + pinctrl-0 = <&mdio_pins>; + pinctrl-names = "default"; + }; + + /* It is a 56-bit counter that supplies the count to the ARM arch + timers and without upstream driver */ + counter@4a1000 { + compatible = "qcom,qca-gcnt"; + reg = <0x4a1000 0x4>; + }; + + ess_tcsr@1953000 { + compatible = "qcom,tcsr"; + reg = <0x1953000 0x1000>; + qcom,ess-interface-select = ; + }; + + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; + qcom,wifi_glb_cfg = ; + }; + + tcsr@1957000 { + compatible = "qcom,tcsr"; + reg = <0x1957000 0x100>; + qcom,wifi_noc_memtype_m0_m2 = ; + }; + + serial@78b0000 { + pinctrl-0 = <&serial_1_pins>; + pinctrl-names = "default"; + status = "okay"; + + bluetooth { + compatible = "ti,cc2650"; + enable-gpios = <&tlmm 12 GPIO_ACTIVE_LOW>; + }; + }; + + crypto@8e3a000 { + status = "okay"; + }; + + watchdog@b017000 { + status = "okay"; + }; + + ess-switch@c000000 { + switch_mac_mode = <0x3>; /* mac mode for RGMII RMII */ + switch_lan_bmp = <0x0>; /* lan port bitmap */ + switch_wan_bmp = <0x10>; /* wan port bitmap */ + }; + + edma@c080000 { + qcom,single-phy; + qcom,num_gmac = <1>; + phy-mode = "rgmii-rxid"; + status = "okay"; + }; + }; + + keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + gpios = <&tlmm 18 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + leds { + compatible = "gpio-leds"; + + power_orange: power { + label = "orange:power"; + gpios = <&tlmm 49 GPIO_ACTIVE_LOW>; + panic-indicator; + }; + }; +}; + +&blsp_dma { + status = "okay"; +}; + +&blsp1_uart1 { + pinctrl-0 = <&serial_0_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + +&cryptobam { + status = "okay"; +}; + +&gmac0 { + qcom,phy_mdio_addr = <1>; + qcom,poll_required = <1>; + vlan_tag = <0 0x20>; +}; + +&blsp1_i2c3 { + pinctrl-0 = <&i2c_0_pins>; + pinctrl-names = "default"; + status = "okay"; + at24@50 { + compatible = "atmel,24c64"; + pagesize = <32>; + reg = <0x50>; + read-only; /* This holds our MAC & Meraki board-data */ + }; +}; + +&blsp1_i2c4 { + pinctrl-0 = <&i2c_1_pins>; + pinctrl-names = "default"; + status = "okay"; + + led-controller@30 { + compatible = "ti,lp5562"; + reg = <0x30>; + clock-mode = /bits/8 <2>; + enable-gpio = <&tlmm 48 GPIO_ACTIVE_HIGH>; + + /* RGB led */ + status_red: chan0 { + chan-name = "red:status"; + led-cur = /bits/ 8 <0x20>; + max-cur = /bits/ 8 <0x60>; + }; + + status_green: chan1 { + chan-name = "green:status"; + led-cur = /bits/ 8 <0x20>; + max-cur = /bits/ 8 <0x60>; + }; + + chan2 { + chan-name = "blue:status"; + led-cur = /bits/ 8 <0x20>; + max-cur = /bits/ 8 <0x60>; + }; + + chan3 { + chan-name = "white:status"; + led-cur = /bits/ 8 <0x20>; + max-cur = /bits/ 8 <0x60>; + }; + }; +}; + +&nand { + pinctrl-0 = <&nand_pins>; + pinctrl-names = "default"; + status = "okay"; + + nand@0 { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "sbl1"; + reg = <0x00000000 0x00100000>; + read-only; + }; + partition@100000 { + label = "mibib"; + reg = <0x00100000 0x00100000>; + read-only; + }; + partition@200000 { + label = "bootconfig"; + reg = <0x00200000 0x00100000>; + read-only; + }; + partition@300000 { + label = "qsee"; + reg = <0x00300000 0x00100000>; + read-only; + }; + partition@400000 { + label = "qsee_alt"; + reg = <0x00400000 0x00100000>; + read-only; + }; + partition@500000 { + label = "cdt"; + reg = <0x00500000 0x00080000>; + read-only; + }; + partition@580000 { + label = "cdt_alt"; + reg = <0x00580000 0x00080000>; + read-only; + }; + partition@600000 { + label = "ddrparams"; + reg = <0x00600000 0x00080000>; + read-only; + }; + partition@700000 { + label = "u-boot"; + reg = <0x00700000 0x00200000>; + read-only; + }; + partition@900000 { + label = "u-boot-backup"; + reg = <0x00900000 0x00200000>; + read-only; + }; + partition@b00000 { + label = "ART"; + reg = <0x00b00000 0x00080000>; + read-only; + }; + partition@c00000 { + label = "ubi"; + reg = <0x00c00000 0x07000000>; + /* + * Do not try to allocate the remaining + * 4 MiB to this ubi partition. It will + * confuse the u-boot and it might not + * find the kernel partition anymore. + */ + }; + }; + }; +}; + +&pcie0 { + status = "okay"; + perst-gpio = <&tlmm 38 GPIO_ACTIVE_LOW>; + wake-gpio = <&tlmm 50 GPIO_ACTIVE_LOW>; + + bridge@0,0 { + reg = <0x00000000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + ranges; + + wifi2: wifi@1,0 { + compatible = "qcom,ath10k"; + status = "okay"; + reg = <0x00010000 0 0 0 0>; + }; + }; +}; + +&qpic_bam { + status = "okay"; +}; + +&tlmm { + /* + * GPIO43 should be 0/1 whenever the unit is + * powered through PoE or AC-Adapter. + * That said, playing with this seems to + * reset the AP. + */ + + mdio_pins: mdio_pinmux { + mux_1 { + pins = "gpio6"; + function = "mdio"; + bias-pull-up; + }; + mux_2 { + pins = "gpio7"; + function = "mdc"; + bias-pull-up; + }; + }; + + serial_0_pins: serial_pinmux { + mux { + pins = "gpio16", "gpio17"; + function = "blsp_uart0"; + bias-disable; + }; + }; + + serial_1_pins: serial1_pinmux { + mux { + /* We use the i2c-0 pins for serial_1 */ + pins = "gpio8", "gpio9"; + function = "blsp_uart1"; + bias-disable; + }; + }; + + i2c_0_pins: i2c_0_pinmux { + pinmux { + function = "blsp_i2c0"; + pins = "gpio20", "gpio21"; + }; + pinconf { + pins = "gpio20", "gpio21"; + drive-strength = <16>; + bias-disable; + }; + }; + + i2c_1_pins: i2c_1_pinmux { + pinmux { + function = "blsp_i2c1"; + pins = "gpio34", "gpio35"; + }; + pinconf { + pins = "gpio34", "gpio35"; + drive-strength = <16>; + bias-disable; + }; + }; + + nand_pins: nand_pins { + /* + * There are 18 pins. 15 pins are common between LCD and NAND. + * The QPIC controller arbitrates between LCD and NAND. Of the + * remaining 4, 2 are for NAND and 2 are for LCD exclusively. + * + * The meraki source hints that the bluetooth module claims + * pin 52 as well. But sadly, there's no data whenever this + * is a NAND or LCD exclusive pin or not. + */ + + pullups { + pins = "gpio52", "gpio53", "gpio58", + "gpio59"; + function = "qpic"; + bias-pull-up; + }; + + pulldowns { + pins = "gpio54", "gpio55", "gpio56", + "gpio57", "gpio60", "gpio61", + "gpio62", "gpio63", "gpio64", + "gpio65", "gpio66", "gpio67", + "gpio68", "gpio69"; + function = "qpic"; + bias-pull-down; + }; + }; +}; + +&wifi0 { + status = "okay"; + qcom,ath10k-calibration-variant = "Meraki-MR33"; +}; + +&wifi1 { + status = "okay"; + qcom,ath10k-calibration-variant = "Meraki-MR33"; +}; diff --git a/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq40x9-dr40x9.dts b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq40x9-dr40x9.dts new file mode 100644 index 000000000..34630959e --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/files/arch/arm/boot/dts/qcom-ipq40x9-dr40x9.dts @@ -0,0 +1,387 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "qcom-ipq4019.dtsi" +#include +#include +#include + +/ { + model = "Wallys DR40X9"; + compatible = "wallys,dr40x9"; + + chosen { + bootargs-append = " ubi.mtd=ubi root=/dev/ubiblock0_1"; + }; + + soc { + rng@22000 { + status = "okay"; + }; + + mdio@90000 { + status = "okay"; + + pinctrl-0 = <&mdio_pins>; + pinctrl-names = "default"; + reset-gpios = <&tlmm 41 GPIO_ACTIVE_LOW>; + reset-delay-us = <2000>; + }; + + ess-psgmii@98000 { + status = "okay"; + }; + + counter@4a1000 { + compatible = "qcom,qca-gcnt"; + reg = <0x4a1000 0x4>; + }; + + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; + qcom,wifi_glb_cfg = ; + }; + + tcsr@194b000 { + status = "okay"; + + /* select hostmode */ + compatible = "qcom,tcsr"; + reg = <0x194b000 0x100>; + qcom,usb-hsphy-mode-select = ; + }; + + ess_tcsr@1953000 { + compatible = "qcom,tcsr"; + reg = <0x1953000 0x1000>; + qcom,ess-interface-select = ; + }; + + tcsr@1957000 { + compatible = "qcom,tcsr"; + reg = <0x1957000 0x100>; + qcom,wifi_noc_memtype_m0_m2 = ; + }; + + usb2: usb2@60f8800 { + status = "okay"; + }; + + usb3: usb3@8af8800 { + status = "okay"; + }; + + crypto@8e3a000 { + status = "okay"; + }; + + watchdog@b017000 { + status = "okay"; + }; + + ess-switch@c000000 { + status = "okay"; + }; + + edma@c080000 { + status = "okay"; + }; + }; + + keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + gpios = <&tlmm 18 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + leds { + compatible = "gpio-leds"; + + wlan2g { + label = "dr4029:green:wlan2g"; + gpios = <&tlmm 32 GPIO_ACTIVE_LOW>; + linux,default-trigger = "phy0tpt"; + }; + + wlan5g { + label = "dr4029:green:wlan5g"; + gpios = <&tlmm 50 GPIO_ACTIVE_LOW>; + linux,default-trigger = "phy1tpt"; + }; + + wlan2g-strength { + label = "dr4029:green:wlan2g-strength"; + gpios = <&tlmm 36 GPIO_ACTIVE_LOW>; + }; + + wlan5g-strength { + label = "dr4029:green:wlan5g-strength"; + gpios = <&tlmm 39 GPIO_ACTIVE_LOW>; + }; + }; +}; + +&tlmm { + mdio_pins: mdio_pinmux { + mux_1 { + pins = "gpio6"; + function = "mdio"; + bias-pull-up; + }; + mux_2 { + pins = "gpio7"; + function = "mdc"; + bias-pull-up; + }; + }; + + serial0_pins: serial0_pinmux { + mux { + pins = "gpio16", "gpio17"; + function = "blsp_uart0"; + bias-disable; + }; + }; + + serial1_pins: serial1_pinmux { + mux { + pins = "gpio8", "gpio9"; + function = "blsp_uart1"; + bias-disable; + }; + }; + + spi_0_pins: spi_0_pinmux { + pinmux { + function = "blsp_spi0"; + pins = "gpio13", "gpio14", "gpio15"; + drive-strength = <12>; + bias-disable; + }; + pinmux_cs { + function = "gpio"; + pins = "gpio12"; + drive-strength = <2>; + bias-disable; + output-high; + }; + }; + + nand_pins: nand_pins { + pullups { + pins = "gpio52", "gpio53", "gpio58", "gpio59"; + function = "qpic"; + bias-pull-up; + }; + + pulldowns { + pins = "gpio54", "gpio55", "gpio56", "gpio57", + "gpio60", "gpio62", "gpio63", "gpio64", + "gpio65", "gpio66", "gpio67", "gpio68", + "gpio69"; + function = "qpic"; + bias-pull-down; + }; + }; + + sd_pins: sd_pins { + pinmux { + function = "sdio"; + pins = "gpio23", "gpio24", "gpio25", "gpio26", + "gpio28", "gpio29", "gpio30", "gpio31"; + drive-strength = <10>; + }; + pinmux_sd_clk { + function = "sdio"; + pins = "gpio27"; + drive-strength = <16>; + }; + pinmux_sd7 { + function = "sdio"; + pins = "gpio32"; + drive-strength = <10>; + bias-disable; + }; + }; +}; + +&blsp_dma { + status = "okay"; +}; + +&blsp1_spi1 { + status = "okay"; + + pinctrl-0 = <&spi_0_pins>; + pinctrl-names = "default"; + + cs-gpios = <&tlmm 12 GPIO_ACTIVE_HIGH>; + + flash@0 { + compatible = "jedec,spi-nor"; + spi-max-frequency = <24000000>; + reg = <0>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition0@0 { + label = "0:SBL1"; + reg = <0x00000000 0x00040000>; + read-only; + }; + + partition1@40000 { + label = "0:MIBIB"; + reg = <0x00040000 0x00020000>; + read-only; + }; + + partition2@60000 { + label = "0:QSEE"; + reg = <0x00060000 0x00060000>; + read-only; + }; + + partition3@c0000 { + label = "0:CDT"; + reg = <0x000c0000 0x00010000>; + read-only; + }; + + partition4@d0000 { + label = "0:DDRPARAMS"; + reg = <0x000d0000 0x00010000>; + read-only; + }; + + partition5@e0000 { + label = "0:APPSBLENV"; /* uboot env */ + reg = <0x000e0000 0x00010000>; + read-only; + }; + + partition6@f0000 { + label = "0:APPSBL"; /* uboot */ + reg = <0x000f0000 0x00080000>; + read-only; + }; + + partition7@170000 { + label = "0:ART"; + reg = <0x00170000 0x00010000>; + read-only; + }; + }; + }; +}; + +&qpic_bam { + status = "okay"; +}; + +&nand { + status = "okay"; + + pinctrl-0 = <&nand_pins>; + pinctrl-names = "default"; + + nand@0 { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "ubi"; + reg = <0x00000000 0x04000000>; + }; + }; + }; +}; + +&blsp1_uart1 { + status = "okay"; + + pinctrl-0 = <&serial0_pins>; + pinctrl-names = "default"; +}; + +&blsp1_uart2 { + status = "okay"; + + pinctrl-0 = <&serial1_pins>; + pinctrl-names = "default"; +}; + +&cryptobam { + status = "okay"; +}; + +&pcie0 { + status = "okay"; + + perst-gpio = <&tlmm 38 GPIO_ACTIVE_LOW>; + wake-gpio = <&tlmm 40 GPIO_ACTIVE_LOW>; + + /* Unpolulated slot */ + bridge@0,0 { + reg = <0x00000000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + ranges; + }; +}; + +&vqmmc { + status = "okay"; +}; + +&sdhci { + pinctrl-0 = <&sd_pins>; + pinctrl-names = "default"; + cd-gpios = <&tlmm 22 GPIO_ACTIVE_LOW>; + vqmmc-supply = <&vqmmc>; + status = "okay"; +}; + +ðphy4 { + qcom,fiber-enable; +}; + +&gmac0 { + qcom,phy_mdio_addr = <3>; + qcom,poll_required = <1>; + qcom,forced_speed = <1000>; + qcom,forced_duplex = <1>; +}; + +&wifi0 { + status = "okay"; + + qcom,ath10k-calibration-variant = "Wallys-DR40X9"; +}; + +&wifi1 { + status = "okay"; + + qcom,ath10k-calibration-variant = "Wallys-DR40X9"; +}; + +&usb3_ss_phy { + status = "okay"; +}; + +&usb3_hs_phy { + status = "okay"; +}; + +&usb2_hs_phy { + status = "okay"; +}; diff --git a/feeds/ipq40xx/ipq40xx/files/drivers/net/ethernet/qualcomm/essedma/Makefile b/feeds/ipq40xx/ipq40xx/files/drivers/net/ethernet/qualcomm/essedma/Makefile new file mode 100644 index 000000000..4e6cd6505 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/files/drivers/net/ethernet/qualcomm/essedma/Makefile @@ -0,0 +1,9 @@ +# +## Makefile for the Qualcomm Atheros ethernet edma driver +# + + +obj-$(CONFIG_ESSEDMA) += essedma.o + +essedma-objs := edma_axi.o edma.o edma_ethtool.o + diff --git a/feeds/ipq40xx/ipq40xx/files/drivers/net/ethernet/qualcomm/essedma/edma.c b/feeds/ipq40xx/ipq40xx/files/drivers/net/ethernet/qualcomm/essedma/edma.c new file mode 100644 index 000000000..80db1f0ac --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/files/drivers/net/ethernet/qualcomm/essedma/edma.c @@ -0,0 +1,2177 @@ +/* + * Copyright (c) 2014 - 2016, The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all copies. + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include "ess_edma.h" +#include "edma.h" + +extern struct net_device *edma_netdev[EDMA_MAX_PORTID_SUPPORTED]; +bool edma_stp_rstp; +u16 edma_ath_eth_type; + +/* edma_skb_priority_offset() + * get edma skb priority + */ +static unsigned int edma_skb_priority_offset(struct sk_buff *skb) +{ + return (skb->priority >> 2) & 1; +} + +/* edma_alloc_tx_ring() + * Allocate Tx descriptors ring + */ +static int edma_alloc_tx_ring(struct edma_common_info *edma_cinfo, + struct edma_tx_desc_ring *etdr) +{ + struct platform_device *pdev = edma_cinfo->pdev; + + /* Initialize ring */ + etdr->size = sizeof(struct edma_sw_desc) * etdr->count; + etdr->sw_next_to_fill = 0; + etdr->sw_next_to_clean = 0; + + /* Allocate SW descriptors */ + etdr->sw_desc = vzalloc(etdr->size); + if (!etdr->sw_desc) { + dev_err(&pdev->dev, "buffer alloc of tx ring failed=%p", etdr); + return -ENOMEM; + } + + /* Allocate HW descriptors */ + etdr->hw_desc = dma_alloc_coherent(&pdev->dev, etdr->size, &etdr->dma, + GFP_KERNEL); + if (!etdr->hw_desc) { + dev_err(&pdev->dev, "descriptor allocation for tx ring failed"); + vfree(etdr->sw_desc); + return -ENOMEM; + } + + return 0; +} + +/* edma_free_tx_ring() + * Free tx rings allocated by edma_alloc_tx_rings + */ +static void edma_free_tx_ring(struct edma_common_info *edma_cinfo, + struct edma_tx_desc_ring *etdr) +{ + struct platform_device *pdev = edma_cinfo->pdev; + + if (likely(etdr->dma)) + dma_free_coherent(&pdev->dev, etdr->size, etdr->hw_desc, + etdr->dma); + + vfree(etdr->sw_desc); + etdr->sw_desc = NULL; +} + +/* edma_alloc_rx_ring() + * allocate rx descriptor ring + */ +static int edma_alloc_rx_ring(struct edma_common_info *edma_cinfo, + struct edma_rfd_desc_ring *erxd) +{ + struct platform_device *pdev = edma_cinfo->pdev; + + erxd->size = sizeof(struct edma_sw_desc) * erxd->count; + erxd->sw_next_to_fill = 0; + erxd->sw_next_to_clean = 0; + + /* Allocate SW descriptors */ + erxd->sw_desc = vzalloc(erxd->size); + if (!erxd->sw_desc) + return -ENOMEM; + + /* Alloc HW descriptors */ + erxd->hw_desc = dma_alloc_coherent(&pdev->dev, erxd->size, &erxd->dma, + GFP_KERNEL); + if (!erxd->hw_desc) { + vfree(erxd->sw_desc); + return -ENOMEM; + } + + /* Initialize pending_fill */ + erxd->pending_fill = 0; + + return 0; +} + +/* edma_free_rx_ring() + * Free rx ring allocated by alloc_rx_ring + */ +static void edma_free_rx_ring(struct edma_common_info *edma_cinfo, + struct edma_rfd_desc_ring *rxdr) +{ + struct platform_device *pdev = edma_cinfo->pdev; + + if (likely(rxdr->dma)) + dma_free_coherent(&pdev->dev, rxdr->size, rxdr->hw_desc, + rxdr->dma); + + vfree(rxdr->sw_desc); + rxdr->sw_desc = NULL; +} + +/* edma_configure_tx() + * Configure transmission control data + */ +static void edma_configure_tx(struct edma_common_info *edma_cinfo) +{ + u32 txq_ctrl_data; + + txq_ctrl_data = (EDMA_TPD_BURST << EDMA_TXQ_NUM_TPD_BURST_SHIFT); + txq_ctrl_data |= EDMA_TXQ_CTRL_TPD_BURST_EN; + txq_ctrl_data |= (EDMA_TXF_BURST << EDMA_TXQ_TXF_BURST_NUM_SHIFT); + edma_write_reg(EDMA_REG_TXQ_CTRL, txq_ctrl_data); +} + + +/* edma_configure_rx() + * configure reception control data + */ +static void edma_configure_rx(struct edma_common_info *edma_cinfo) +{ + struct edma_hw *hw = &edma_cinfo->hw; + u32 rss_type, rx_desc1, rxq_ctrl_data; + + /* Set RSS type */ + rss_type = hw->rss_type; + edma_write_reg(EDMA_REG_RSS_TYPE, rss_type); + + /* Set RFD burst number */ + rx_desc1 = (EDMA_RFD_BURST << EDMA_RXQ_RFD_BURST_NUM_SHIFT); + + /* Set RFD prefetch threshold */ + rx_desc1 |= (EDMA_RFD_THR << EDMA_RXQ_RFD_PF_THRESH_SHIFT); + + /* Set RFD in host ring low threshold to generte interrupt */ + rx_desc1 |= (EDMA_RFD_LTHR << EDMA_RXQ_RFD_LOW_THRESH_SHIFT); + edma_write_reg(EDMA_REG_RX_DESC1, rx_desc1); + + /* Set Rx FIFO threshold to start to DMA data to host */ + rxq_ctrl_data = EDMA_FIFO_THRESH_128_BYTE; + + /* Set RX remove vlan bit */ + rxq_ctrl_data |= EDMA_RXQ_CTRL_RMV_VLAN; + + edma_write_reg(EDMA_REG_RXQ_CTRL, rxq_ctrl_data); +} + +/* edma_alloc_rx_buf() + * does skb allocation for the received packets. + */ +static int edma_alloc_rx_buf(struct edma_common_info + *edma_cinfo, + struct edma_rfd_desc_ring *erdr, + int cleaned_count, int queue_id) +{ + struct platform_device *pdev = edma_cinfo->pdev; + struct edma_rx_free_desc *rx_desc; + struct edma_sw_desc *sw_desc; + struct sk_buff *skb; + unsigned int i; + u16 prod_idx, length; + u32 reg_data; + + if (cleaned_count > erdr->count) + cleaned_count = erdr->count - 1; + + i = erdr->sw_next_to_fill; + + while (cleaned_count) { + sw_desc = &erdr->sw_desc[i]; + length = edma_cinfo->rx_head_buffer_len; + + if (sw_desc->flags & EDMA_SW_DESC_FLAG_SKB_REUSE) { + skb = sw_desc->skb; + + /* Clear REUSE Flag */ + sw_desc->flags &= ~EDMA_SW_DESC_FLAG_SKB_REUSE; + } else { + /* alloc skb */ + skb = netdev_alloc_skb_ip_align(edma_netdev[0], length); + if (!skb) { + /* Better luck next round */ + break; + } + } + + if (edma_cinfo->page_mode) { + struct page *pg = alloc_page(GFP_ATOMIC); + + if (!pg) { + dev_kfree_skb_any(skb); + break; + } + + sw_desc->dma = dma_map_page(&pdev->dev, pg, 0, + edma_cinfo->rx_page_buffer_len, + DMA_FROM_DEVICE); + if (dma_mapping_error(&pdev->dev, + sw_desc->dma)) { + __free_page(pg); + dev_kfree_skb_any(skb); + break; + } + + skb_fill_page_desc(skb, 0, pg, 0, + edma_cinfo->rx_page_buffer_len); + sw_desc->flags = EDMA_SW_DESC_FLAG_SKB_FRAG; + sw_desc->length = edma_cinfo->rx_page_buffer_len; + } else { + sw_desc->dma = dma_map_single(&pdev->dev, skb->data, + length, DMA_FROM_DEVICE); + if (dma_mapping_error(&pdev->dev, + sw_desc->dma)) { + dev_kfree_skb_any(skb); + break; + } + + sw_desc->flags = EDMA_SW_DESC_FLAG_SKB_HEAD; + sw_desc->length = length; + } + + /* Update the buffer info */ + sw_desc->skb = skb; + rx_desc = (&((struct edma_rx_free_desc *)(erdr->hw_desc))[i]); + rx_desc->buffer_addr = cpu_to_le64(sw_desc->dma); + if (++i == erdr->count) + i = 0; + cleaned_count--; + } + + erdr->sw_next_to_fill = i; + + if (i == 0) + prod_idx = erdr->count - 1; + else + prod_idx = i - 1; + + /* Update the producer index */ + edma_read_reg(EDMA_REG_RFD_IDX_Q(queue_id), ®_data); + reg_data &= ~EDMA_RFD_PROD_IDX_BITS; + reg_data |= prod_idx; + edma_write_reg(EDMA_REG_RFD_IDX_Q(queue_id), reg_data); + + /* If we couldn't allocate all the buffers + * we increment the alloc failure counters + */ + if (cleaned_count) + edma_cinfo->edma_ethstats.rx_alloc_fail_ctr++; + + return cleaned_count; +} + +/* edma_init_desc() + * update descriptor ring size, buffer and producer/consumer index + */ +static void edma_init_desc(struct edma_common_info *edma_cinfo) +{ + struct edma_rfd_desc_ring *rfd_ring; + struct edma_tx_desc_ring *etdr; + int i = 0, j = 0; + u32 data = 0; + u16 hw_cons_idx = 0; + + /* Set the base address of every TPD ring. */ + for (i = 0; i < edma_cinfo->num_tx_queues; i++) { + etdr = edma_cinfo->tpd_ring[i]; + + /* Update descriptor ring base address */ + edma_write_reg(EDMA_REG_TPD_BASE_ADDR_Q(i), (u32)etdr->dma); + edma_read_reg(EDMA_REG_TPD_IDX_Q(i), &data); + + /* Calculate hardware consumer index */ + hw_cons_idx = (data >> EDMA_TPD_CONS_IDX_SHIFT) & 0xffff; + etdr->sw_next_to_fill = hw_cons_idx; + etdr->sw_next_to_clean = hw_cons_idx; + data &= ~(EDMA_TPD_PROD_IDX_MASK << EDMA_TPD_PROD_IDX_SHIFT); + data |= hw_cons_idx; + + /* update producer index */ + edma_write_reg(EDMA_REG_TPD_IDX_Q(i), data); + + /* update SW consumer index register */ + edma_write_reg(EDMA_REG_TX_SW_CONS_IDX_Q(i), hw_cons_idx); + + /* Set TPD ring size */ + edma_write_reg(EDMA_REG_TPD_RING_SIZE, + edma_cinfo->tx_ring_count & + EDMA_TPD_RING_SIZE_MASK); + } + + for (i = 0, j = 0; i < edma_cinfo->num_rx_queues; i++) { + rfd_ring = edma_cinfo->rfd_ring[j]; + /* Update Receive Free descriptor ring base address */ + edma_write_reg(EDMA_REG_RFD_BASE_ADDR_Q(j), + (u32)(rfd_ring->dma)); + j += ((edma_cinfo->num_rx_queues == 4) ? 2 : 1); + } + + data = edma_cinfo->rx_head_buffer_len; + if (edma_cinfo->page_mode) + data = edma_cinfo->rx_page_buffer_len; + + data &= EDMA_RX_BUF_SIZE_MASK; + data <<= EDMA_RX_BUF_SIZE_SHIFT; + + /* Update RFD ring size and RX buffer size */ + data |= (edma_cinfo->rx_ring_count & EDMA_RFD_RING_SIZE_MASK) + << EDMA_RFD_RING_SIZE_SHIFT; + + edma_write_reg(EDMA_REG_RX_DESC0, data); + + /* Disable TX FIFO low watermark and high watermark */ + edma_write_reg(EDMA_REG_TXF_WATER_MARK, 0); + + /* Load all of base address above */ + edma_read_reg(EDMA_REG_TX_SRAM_PART, &data); + data |= 1 << EDMA_LOAD_PTR_SHIFT; + edma_write_reg(EDMA_REG_TX_SRAM_PART, data); +} + +/* edma_receive_checksum + * Api to check checksum on receive packets + */ +static void edma_receive_checksum(struct edma_rx_return_desc *rd, + struct sk_buff *skb) +{ + skb_checksum_none_assert(skb); + + /* check the RRD IP/L4 checksum bit to see if + * its set, which in turn indicates checksum + * failure. + */ + if (rd->rrd6 & EDMA_RRD_CSUM_FAIL_MASK) + return; + + skb->ip_summed = CHECKSUM_UNNECESSARY; +} + +/* edma_clean_rfd() + * clean up rx resourcers on error + */ +static void edma_clean_rfd(struct edma_rfd_desc_ring *erdr, u16 index) +{ + struct edma_rx_free_desc *rx_desc; + struct edma_sw_desc *sw_desc; + + rx_desc = (&((struct edma_rx_free_desc *)(erdr->hw_desc))[index]); + sw_desc = &erdr->sw_desc[index]; + if (sw_desc->skb) { + dev_kfree_skb_any(sw_desc->skb); + sw_desc->skb = NULL; + } + + memset(rx_desc, 0, sizeof(struct edma_rx_free_desc)); +} + +/* edma_rx_complete_fraglist() + * Complete Rx processing for fraglist skbs + */ +static void edma_rx_complete_stp_rstp(struct sk_buff *skb, int port_id, struct edma_rx_return_desc *rd) +{ + int i; + u32 priority; + u16 port_type; + u8 mac_addr[EDMA_ETH_HDR_LEN]; + + port_type = (rd->rrd1 >> EDMA_RRD_PORT_TYPE_SHIFT) + & EDMA_RRD_PORT_TYPE_MASK; + /* if port type is 0x4, then only proceed with + * other stp/rstp calculation + */ + if (port_type == EDMA_RX_ATH_HDR_RSTP_PORT_TYPE) { + u8 bpdu_mac[6] = {0x01, 0x80, 0xc2, 0x00, 0x00, 0x00}; + + /* calculate the frame priority */ + priority = (rd->rrd1 >> EDMA_RRD_PRIORITY_SHIFT) + & EDMA_RRD_PRIORITY_MASK; + + for (i = 0; i < EDMA_ETH_HDR_LEN; i++) + mac_addr[i] = skb->data[i]; + + /* Check if destination mac addr is bpdu addr */ + if (!memcmp(mac_addr, bpdu_mac, 6)) { + /* destination mac address is BPDU + * destination mac address, then add + * atheros header to the packet. + */ + u16 athr_hdr = (EDMA_RX_ATH_HDR_VERSION << EDMA_RX_ATH_HDR_VERSION_SHIFT) | + (priority << EDMA_RX_ATH_HDR_PRIORITY_SHIFT) | + (EDMA_RX_ATH_HDR_RSTP_PORT_TYPE << EDMA_RX_ATH_PORT_TYPE_SHIFT) | port_id; + skb_push(skb, 4); + memcpy(skb->data, mac_addr, EDMA_ETH_HDR_LEN); + *(uint16_t *)&skb->data[12] = htons(edma_ath_eth_type); + *(uint16_t *)&skb->data[14] = htons(athr_hdr); + } + } +} + +/* + * edma_rx_complete_fraglist() + * Complete Rx processing for fraglist skbs + */ +static int edma_rx_complete_fraglist(struct sk_buff *skb, u16 num_rfds, u16 length, u32 sw_next_to_clean, + u16 *cleaned_count, struct edma_rfd_desc_ring *erdr, struct edma_common_info *edma_cinfo) +{ + struct platform_device *pdev = edma_cinfo->pdev; + struct edma_hw *hw = &edma_cinfo->hw; + struct sk_buff *skb_temp; + struct edma_sw_desc *sw_desc; + int i; + u16 size_remaining; + + skb->data_len = 0; + skb->tail += (hw->rx_head_buff_size - 16); + skb->len = skb->truesize = length; + size_remaining = length - (hw->rx_head_buff_size - 16); + + /* clean-up all related sw_descs */ + for (i = 1; i < num_rfds; i++) { + struct sk_buff *skb_prev; + sw_desc = &erdr->sw_desc[sw_next_to_clean]; + skb_temp = sw_desc->skb; + + dma_unmap_single(&pdev->dev, sw_desc->dma, + sw_desc->length, DMA_FROM_DEVICE); + + if (size_remaining < hw->rx_head_buff_size) + skb_put(skb_temp, size_remaining); + else + skb_put(skb_temp, hw->rx_head_buff_size); + + /* + * If we are processing the first rfd, we link + * skb->frag_list to the skb corresponding to the + * first RFD + */ + if (i == 1) + skb_shinfo(skb)->frag_list = skb_temp; + else + skb_prev->next = skb_temp; + skb_prev = skb_temp; + skb_temp->next = NULL; + + skb->data_len += skb_temp->len; + size_remaining -= skb_temp->len; + + /* Increment SW index */ + sw_next_to_clean = (sw_next_to_clean + 1) & (erdr->count - 1); + (*cleaned_count)++; + } + + return sw_next_to_clean; +} + +/* edma_rx_complete_paged() + * Complete Rx processing for paged skbs + */ +static int edma_rx_complete_paged(struct sk_buff *skb, u16 num_rfds, u16 length, u32 sw_next_to_clean, + u16 *cleaned_count, struct edma_rfd_desc_ring *erdr, struct edma_common_info *edma_cinfo) +{ + struct platform_device *pdev = edma_cinfo->pdev; + struct sk_buff *skb_temp; + struct edma_sw_desc *sw_desc; + int i; + u16 size_remaining; + + skb_frag_t *frag = &skb_shinfo(skb)->frags[0]; + + /* Setup skbuff fields */ + skb->len = length; + + if (likely(num_rfds <= 1)) { + skb->data_len = length; + skb->truesize += edma_cinfo->rx_page_buffer_len; + skb_fill_page_desc(skb, 0, skb_frag_page(frag), + 16, length); + } else { + skb_frag_size_sub(frag, 16); + skb->data_len = skb_frag_size(frag); + skb->truesize += edma_cinfo->rx_page_buffer_len; + size_remaining = length - skb_frag_size(frag); + + skb_fill_page_desc(skb, 0, skb_frag_page(frag), + 16, skb_frag_size(frag)); + + /* clean-up all related sw_descs */ + for (i = 1; i < num_rfds; i++) { + sw_desc = &erdr->sw_desc[sw_next_to_clean]; + skb_temp = sw_desc->skb; + frag = &skb_shinfo(skb_temp)->frags[0]; + dma_unmap_page(&pdev->dev, sw_desc->dma, + sw_desc->length, DMA_FROM_DEVICE); + + if (size_remaining < edma_cinfo->rx_page_buffer_len) + skb_frag_size_set(frag, size_remaining); + + skb_fill_page_desc(skb, i, skb_frag_page(frag), + 0, skb_frag_size(frag)); + + skb_shinfo(skb_temp)->nr_frags = 0; + dev_kfree_skb_any(skb_temp); + + skb->data_len += skb_frag_size(frag); + skb->truesize += edma_cinfo->rx_page_buffer_len; + size_remaining -= skb_frag_size(frag); + + /* Increment SW index */ + sw_next_to_clean = (sw_next_to_clean + 1) & (erdr->count - 1); + (*cleaned_count)++; + } + } + + return sw_next_to_clean; +} + +/* + * edma_rx_complete() + * Main api called from the poll function to process rx packets. + */ +static u16 edma_rx_complete(struct edma_common_info *edma_cinfo, + int *work_done, int work_to_do, int queue_id, + struct napi_struct *napi) +{ + struct platform_device *pdev = edma_cinfo->pdev; + struct edma_rfd_desc_ring *erdr = edma_cinfo->rfd_ring[queue_id]; + struct net_device *netdev; + struct edma_adapter *adapter; + struct edma_sw_desc *sw_desc; + struct sk_buff *skb; + struct edma_rx_return_desc *rd; + u16 hash_type, rrd[8], cleaned_count = 0, length = 0, num_rfds = 1, + sw_next_to_clean, hw_next_to_clean = 0, vlan = 0, ret_count = 0; + u32 data = 0; + u8 *vaddr; + int port_id, i, drop_count = 0; + u32 priority; + u16 count = erdr->count, rfd_avail; + u8 queue_to_rxid[8] = {0, 0, 1, 1, 2, 2, 3, 3}; + + cleaned_count = erdr->pending_fill; + sw_next_to_clean = erdr->sw_next_to_clean; + + edma_read_reg(EDMA_REG_RFD_IDX_Q(queue_id), &data); + hw_next_to_clean = (data >> EDMA_RFD_CONS_IDX_SHIFT) & + EDMA_RFD_CONS_IDX_MASK; + + do { + while (sw_next_to_clean != hw_next_to_clean) { + if (!work_to_do) + break; + + sw_desc = &erdr->sw_desc[sw_next_to_clean]; + skb = sw_desc->skb; + + /* Unmap the allocated buffer */ + if (likely(sw_desc->flags & EDMA_SW_DESC_FLAG_SKB_HEAD)) + dma_unmap_single(&pdev->dev, sw_desc->dma, + sw_desc->length, DMA_FROM_DEVICE); + else + dma_unmap_page(&pdev->dev, sw_desc->dma, + sw_desc->length, DMA_FROM_DEVICE); + + /* Get RRD */ + if (edma_cinfo->page_mode) { + vaddr = kmap_atomic(skb_frag_page(&skb_shinfo(skb)->frags[0])); + memcpy((uint8_t *)&rrd[0], vaddr, 16); + rd = (struct edma_rx_return_desc *)rrd; + kunmap_atomic(vaddr); + } else { + rd = (struct edma_rx_return_desc *)skb->data; + } + + /* Check if RRD is valid */ + if (!(rd->rrd7 & EDMA_RRD_DESC_VALID)) { + edma_clean_rfd(erdr, sw_next_to_clean); + sw_next_to_clean = (sw_next_to_clean + 1) & + (erdr->count - 1); + cleaned_count++; + continue; + } + + /* Get the number of RFDs from RRD */ + num_rfds = rd->rrd1 & EDMA_RRD_NUM_RFD_MASK; + + /* Get Rx port ID from switch */ + port_id = (rd->rrd1 >> EDMA_PORT_ID_SHIFT) & EDMA_PORT_ID_MASK; + if ((!port_id) || (port_id > EDMA_MAX_PORTID_SUPPORTED)) { + dev_err(&pdev->dev, "Invalid RRD source port bit set"); + for (i = 0; i < num_rfds; i++) { + edma_clean_rfd(erdr, sw_next_to_clean); + sw_next_to_clean = (sw_next_to_clean + 1) & (erdr->count - 1); + cleaned_count++; + } + continue; + } + + /* check if we have a sink for the data we receive. + * If the interface isn't setup, we have to drop the + * incoming data for now. + */ + netdev = edma_cinfo->portid_netdev_lookup_tbl[port_id]; + if (!netdev) { + edma_clean_rfd(erdr, sw_next_to_clean); + sw_next_to_clean = (sw_next_to_clean + 1) & + (erdr->count - 1); + cleaned_count++; + continue; + } + adapter = netdev_priv(netdev); + + /* This code is added to handle a usecase where high + * priority stream and a low priority stream are + * received simultaneously on DUT. The problem occurs + * if one of the Rx rings is full and the corresponding + * core is busy with other stuff. This causes ESS CPU + * port to backpressure all incoming traffic including + * high priority one. We monitor free descriptor count + * on each CPU and whenever it reaches threshold (< 80), + * we drop all low priority traffic and let only high + * priotiy traffic pass through. We can hence avoid + * ESS CPU port to send backpressure on high priroity + * stream. + */ + priority = (rd->rrd1 >> EDMA_RRD_PRIORITY_SHIFT) + & EDMA_RRD_PRIORITY_MASK; + if (likely(!priority && !edma_cinfo->page_mode && (num_rfds <= 1))) { + rfd_avail = (count + sw_next_to_clean - hw_next_to_clean - 1) & (count - 1); + if (rfd_avail < EDMA_RFD_AVAIL_THR) { + sw_desc->flags = EDMA_SW_DESC_FLAG_SKB_REUSE; + sw_next_to_clean = (sw_next_to_clean + 1) & (erdr->count - 1); + adapter->stats.rx_dropped++; + cleaned_count++; + drop_count++; + if (drop_count == 3) { + work_to_do--; + (*work_done)++; + drop_count = 0; + } + if (cleaned_count >= EDMA_RX_BUFFER_WRITE) { + /* If buffer clean count reaches 16, we replenish HW buffers. */ + ret_count = edma_alloc_rx_buf(edma_cinfo, erdr, cleaned_count, queue_id); + edma_write_reg(EDMA_REG_RX_SW_CONS_IDX_Q(queue_id), + sw_next_to_clean); + cleaned_count = ret_count; + erdr->pending_fill = ret_count; + } + continue; + } + } + + work_to_do--; + (*work_done)++; + + /* Increment SW index */ + sw_next_to_clean = (sw_next_to_clean + 1) & + (erdr->count - 1); + + cleaned_count++; + + /* Get the packet size and allocate buffer */ + length = rd->rrd6 & EDMA_RRD_PKT_SIZE_MASK; + + if (edma_cinfo->page_mode) { + /* paged skb */ + sw_next_to_clean = edma_rx_complete_paged(skb, num_rfds, length, sw_next_to_clean, &cleaned_count, erdr, edma_cinfo); + if (!pskb_may_pull(skb, ETH_HLEN)) { + dev_kfree_skb_any(skb); + continue; + } + } else { + /* single or fraglist skb */ + + /* Addition of 16 bytes is required, as in the packet + * first 16 bytes are rrd descriptors, so actual data + * starts from an offset of 16. + */ + skb_reserve(skb, 16); + if (likely((num_rfds <= 1) || !edma_cinfo->fraglist_mode)) { + skb_put(skb, length); + } else { + sw_next_to_clean = edma_rx_complete_fraglist(skb, num_rfds, length, sw_next_to_clean, &cleaned_count, erdr, edma_cinfo); + } + } + + if (edma_stp_rstp) { + edma_rx_complete_stp_rstp(skb, port_id, rd); + } + + skb->protocol = eth_type_trans(skb, netdev); + + /* Record Rx queue for RFS/RPS and fill flow hash from HW */ + skb_record_rx_queue(skb, queue_to_rxid[queue_id]); + if (netdev->features & NETIF_F_RXHASH) { + hash_type = (rd->rrd5 >> EDMA_HASH_TYPE_SHIFT); + if ((hash_type > EDMA_HASH_TYPE_START) && (hash_type < EDMA_HASH_TYPE_END)) + skb_set_hash(skb, rd->rrd2, PKT_HASH_TYPE_L4); + } + +#ifdef CONFIG_NF_FLOW_COOKIE + skb->flow_cookie = rd->rrd3 & EDMA_RRD_FLOW_COOKIE_MASK; +#endif + edma_receive_checksum(rd, skb); + + /* Process VLAN HW acceleration indication provided by HW */ + if (unlikely(adapter->default_vlan_tag != rd->rrd4)) { + vlan = rd->rrd4; + if (likely(rd->rrd7 & EDMA_RRD_CVLAN)) + __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlan); + else if (rd->rrd1 & EDMA_RRD_SVLAN) + __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021AD), vlan); + } + + /* Update rx statistics */ + adapter->stats.rx_packets++; + adapter->stats.rx_bytes += length; + + /* Check if we reached refill threshold */ + if (cleaned_count >= EDMA_RX_BUFFER_WRITE) { + ret_count = edma_alloc_rx_buf(edma_cinfo, erdr, cleaned_count, queue_id); + edma_write_reg(EDMA_REG_RX_SW_CONS_IDX_Q(queue_id), + sw_next_to_clean); + cleaned_count = ret_count; + erdr->pending_fill = ret_count; + } + + /* At this point skb should go to stack */ + napi_gro_receive(napi, skb); + } + + /* Check if we still have NAPI budget */ + if (!work_to_do) + break; + + /* Read index once again since we still have NAPI budget */ + edma_read_reg(EDMA_REG_RFD_IDX_Q(queue_id), &data); + hw_next_to_clean = (data >> EDMA_RFD_CONS_IDX_SHIFT) & + EDMA_RFD_CONS_IDX_MASK; + } while (hw_next_to_clean != sw_next_to_clean); + + erdr->sw_next_to_clean = sw_next_to_clean; + + /* Refill here in case refill threshold wasn't reached */ + if (likely(cleaned_count)) { + ret_count = edma_alloc_rx_buf(edma_cinfo, erdr, cleaned_count, queue_id); + erdr->pending_fill = ret_count; + if (ret_count) { + if (net_ratelimit()) + dev_dbg(&pdev->dev, "Not all buffers was reallocated"); + } + + edma_write_reg(EDMA_REG_RX_SW_CONS_IDX_Q(queue_id), + erdr->sw_next_to_clean); + } + + return erdr->pending_fill; +} + +/* edma_delete_rfs_filter() + * Remove RFS filter from switch + */ +static int edma_delete_rfs_filter(struct edma_adapter *adapter, + struct edma_rfs_filter_node *filter_node) +{ + int res = -1; + + struct flow_keys *keys = &filter_node->keys; + + if (likely(adapter->set_rfs_rule)) + res = (*adapter->set_rfs_rule)(adapter->netdev, + flow_get_u32_src(keys), flow_get_u32_dst(keys), + keys->ports.src, keys->ports.dst, + keys->basic.ip_proto, filter_node->rq_id, 0); + + return res; +} + +/* edma_add_rfs_filter() + * Add RFS filter to switch + */ +static int edma_add_rfs_filter(struct edma_adapter *adapter, + struct flow_keys *keys, u16 rq, + struct edma_rfs_filter_node *filter_node) +{ + int res = -1; + + struct flow_keys *dest_keys = &filter_node->keys; + + memcpy(dest_keys, &filter_node->keys, sizeof(*dest_keys)); +/* + dest_keys->control = keys->control; + dest_keys->basic = keys->basic; + dest_keys->addrs = keys->addrs; + dest_keys->ports = keys->ports; + dest_keys.ip_proto = keys->ip_proto; +*/ + /* Call callback registered by ESS driver */ + if (likely(adapter->set_rfs_rule)) + res = (*adapter->set_rfs_rule)(adapter->netdev, flow_get_u32_src(keys), + flow_get_u32_dst(keys), keys->ports.src, keys->ports.dst, + keys->basic.ip_proto, rq, 1); + + return res; +} + +/* edma_rfs_key_search() + * Look for existing RFS entry + */ +static struct edma_rfs_filter_node *edma_rfs_key_search(struct hlist_head *h, + struct flow_keys *key) +{ + struct edma_rfs_filter_node *p; + + hlist_for_each_entry(p, h, node) + if (flow_get_u32_src(&p->keys) == flow_get_u32_src(key) && + flow_get_u32_dst(&p->keys) == flow_get_u32_dst(key) && + p->keys.ports.src == key->ports.src && + p->keys.ports.dst == key->ports.dst && + p->keys.basic.ip_proto == key->basic.ip_proto) + return p; + return NULL; +} + +/* edma_initialise_rfs_flow_table() + * Initialise EDMA RFS flow table + */ +static void edma_initialise_rfs_flow_table(struct edma_adapter *adapter) +{ + int i; + + spin_lock_init(&adapter->rfs.rfs_ftab_lock); + + /* Initialize EDMA flow hash table */ + for (i = 0; i < EDMA_RFS_FLOW_ENTRIES; i++) + INIT_HLIST_HEAD(&adapter->rfs.hlist_head[i]); + + adapter->rfs.max_num_filter = EDMA_RFS_FLOW_ENTRIES; + adapter->rfs.filter_available = adapter->rfs.max_num_filter; + adapter->rfs.hashtoclean = 0; + + /* Add timer to get periodic RFS updates from OS */ + timer_setup(&adapter->rfs.expire_rfs, edma_flow_may_expire, 0); + mod_timer(&adapter->rfs.expire_rfs, jiffies + HZ / 4); +} + +/* edma_free_rfs_flow_table() + * Free EDMA RFS flow table + */ +static void edma_free_rfs_flow_table(struct edma_adapter *adapter) +{ + int i; + + /* Remove sync timer */ + del_timer_sync(&adapter->rfs.expire_rfs); + spin_lock_bh(&adapter->rfs.rfs_ftab_lock); + + /* Free EDMA RFS table entries */ + adapter->rfs.filter_available = 0; + + /* Clean-up EDMA flow hash table */ + for (i = 0; i < EDMA_RFS_FLOW_ENTRIES; i++) { + struct hlist_head *hhead; + struct hlist_node *tmp; + struct edma_rfs_filter_node *filter_node; + int res; + + hhead = &adapter->rfs.hlist_head[i]; + hlist_for_each_entry_safe(filter_node, tmp, hhead, node) { + res = edma_delete_rfs_filter(adapter, filter_node); + if (res < 0) + dev_warn(&adapter->netdev->dev, + "EDMA going down but RFS entry %d not allowed to be flushed by Switch", + filter_node->flow_id); + hlist_del(&filter_node->node); + kfree(filter_node); + } + } + spin_unlock_bh(&adapter->rfs.rfs_ftab_lock); +} + +/* edma_tx_unmap_and_free() + * clean TX buffer + */ +static inline void edma_tx_unmap_and_free(struct platform_device *pdev, + struct edma_sw_desc *sw_desc) +{ + struct sk_buff *skb = sw_desc->skb; + + if (likely((sw_desc->flags & EDMA_SW_DESC_FLAG_SKB_HEAD) || + (sw_desc->flags & EDMA_SW_DESC_FLAG_SKB_FRAGLIST))) + /* unmap_single for skb head area */ + dma_unmap_single(&pdev->dev, sw_desc->dma, + sw_desc->length, DMA_TO_DEVICE); + else if (sw_desc->flags & EDMA_SW_DESC_FLAG_SKB_FRAG) + /* unmap page for paged fragments */ + dma_unmap_page(&pdev->dev, sw_desc->dma, + sw_desc->length, DMA_TO_DEVICE); + + if (likely(sw_desc->flags & EDMA_SW_DESC_FLAG_LAST)) + dev_kfree_skb_any(skb); + + sw_desc->flags = 0; +} + +/* edma_tx_complete() + * Used to clean tx queues and update hardware and consumer index + */ +static void edma_tx_complete(struct edma_common_info *edma_cinfo, int queue_id) +{ + struct edma_tx_desc_ring *etdr = edma_cinfo->tpd_ring[queue_id]; + struct edma_sw_desc *sw_desc; + struct platform_device *pdev = edma_cinfo->pdev; + int i; + + u16 sw_next_to_clean = etdr->sw_next_to_clean; + u16 hw_next_to_clean; + u32 data = 0; + + edma_read_reg(EDMA_REG_TPD_IDX_Q(queue_id), &data); + hw_next_to_clean = (data >> EDMA_TPD_CONS_IDX_SHIFT) & EDMA_TPD_CONS_IDX_MASK; + + /* clean the buffer here */ + while (sw_next_to_clean != hw_next_to_clean) { + sw_desc = &etdr->sw_desc[sw_next_to_clean]; + edma_tx_unmap_and_free(pdev, sw_desc); + sw_next_to_clean = (sw_next_to_clean + 1) & (etdr->count - 1); + } + + etdr->sw_next_to_clean = sw_next_to_clean; + + /* update the TPD consumer index register */ + edma_write_reg(EDMA_REG_TX_SW_CONS_IDX_Q(queue_id), sw_next_to_clean); + + /* Wake the queue if queue is stopped and netdev link is up */ + for (i = 0; i < EDMA_MAX_NETDEV_PER_QUEUE && etdr->nq[i] ; i++) { + if (netif_tx_queue_stopped(etdr->nq[i])) { + if ((etdr->netdev[i]) && netif_carrier_ok(etdr->netdev[i])) + netif_tx_wake_queue(etdr->nq[i]); + } + } +} + +/* edma_get_tx_buffer() + * Get sw_desc corresponding to the TPD + */ +static struct edma_sw_desc *edma_get_tx_buffer(struct edma_common_info *edma_cinfo, + struct edma_tx_desc *tpd, int queue_id) +{ + struct edma_tx_desc_ring *etdr = edma_cinfo->tpd_ring[queue_id]; + return &etdr->sw_desc[tpd - (struct edma_tx_desc *)etdr->hw_desc]; +} + +/* edma_get_next_tpd() + * Return a TPD descriptor for transfer + */ +static struct edma_tx_desc *edma_get_next_tpd(struct edma_common_info *edma_cinfo, + int queue_id) +{ + struct edma_tx_desc_ring *etdr = edma_cinfo->tpd_ring[queue_id]; + u16 sw_next_to_fill = etdr->sw_next_to_fill; + struct edma_tx_desc *tpd_desc = + (&((struct edma_tx_desc *)(etdr->hw_desc))[sw_next_to_fill]); + + etdr->sw_next_to_fill = (etdr->sw_next_to_fill + 1) & (etdr->count - 1); + + return tpd_desc; +} + +/* edma_tpd_available() + * Check number of free TPDs + */ +static inline u16 edma_tpd_available(struct edma_common_info *edma_cinfo, + int queue_id) +{ + struct edma_tx_desc_ring *etdr = edma_cinfo->tpd_ring[queue_id]; + + u16 sw_next_to_fill; + u16 sw_next_to_clean; + u16 count = 0; + + sw_next_to_clean = etdr->sw_next_to_clean; + sw_next_to_fill = etdr->sw_next_to_fill; + + if (likely(sw_next_to_clean <= sw_next_to_fill)) + count = etdr->count; + + return count + sw_next_to_clean - sw_next_to_fill - 1; +} + +/* edma_tx_queue_get() + * Get the starting number of the queue + */ +static inline int edma_tx_queue_get(struct edma_adapter *adapter, + struct sk_buff *skb, int txq_id) +{ + /* skb->priority is used as an index to skb priority table + * and based on packet priority, correspong queue is assigned. + */ + return adapter->tx_start_offset[txq_id] + edma_skb_priority_offset(skb); +} + +/* edma_tx_update_hw_idx() + * update the producer index for the ring transmitted + */ +static void edma_tx_update_hw_idx(struct edma_common_info *edma_cinfo, + struct sk_buff *skb, int queue_id) +{ + struct edma_tx_desc_ring *etdr = edma_cinfo->tpd_ring[queue_id]; + u32 tpd_idx_data; + + /* Read and update the producer index */ + edma_read_reg(EDMA_REG_TPD_IDX_Q(queue_id), &tpd_idx_data); + tpd_idx_data &= ~EDMA_TPD_PROD_IDX_BITS; + tpd_idx_data |= (etdr->sw_next_to_fill & EDMA_TPD_PROD_IDX_MASK) + << EDMA_TPD_PROD_IDX_SHIFT; + + edma_write_reg(EDMA_REG_TPD_IDX_Q(queue_id), tpd_idx_data); +} + +/* edma_rollback_tx() + * Function to retrieve tx resources in case of error + */ +static void edma_rollback_tx(struct edma_adapter *adapter, + struct edma_tx_desc *start_tpd, int queue_id) +{ + struct edma_tx_desc_ring *etdr = adapter->edma_cinfo->tpd_ring[queue_id]; + struct edma_sw_desc *sw_desc; + struct edma_tx_desc *tpd = NULL; + u16 start_index, index; + + start_index = start_tpd - (struct edma_tx_desc *)(etdr->hw_desc); + + index = start_index; + while (index != etdr->sw_next_to_fill) { + tpd = (&((struct edma_tx_desc *)(etdr->hw_desc))[index]); + sw_desc = &etdr->sw_desc[index]; + edma_tx_unmap_and_free(adapter->pdev, sw_desc); + memset(tpd, 0, sizeof(struct edma_tx_desc)); + if (++index == etdr->count) + index = 0; + } + etdr->sw_next_to_fill = start_index; +} + +/* edma_tx_map_and_fill() + * gets called from edma_xmit_frame + * + * This is where the dma of the buffer to be transmitted + * gets mapped + */ +static int edma_tx_map_and_fill(struct edma_common_info *edma_cinfo, + struct edma_adapter *adapter, struct sk_buff *skb, int queue_id, + unsigned int flags_transmit, u16 from_cpu, u16 dp_bitmap, + bool packet_is_rstp, int nr_frags) +{ + struct edma_sw_desc *sw_desc = NULL; + struct platform_device *pdev = edma_cinfo->pdev; + struct edma_tx_desc *tpd = NULL, *start_tpd = NULL; + struct sk_buff *iter_skb; + int i = 0; + u32 word1 = 0, word3 = 0, lso_word1 = 0, svlan_tag = 0; + u16 buf_len, lso_desc_len = 0; + + /* It should either be a nr_frags skb or fraglist skb but not both */ + BUG_ON(nr_frags && skb_has_frag_list(skb)); + + if (skb_is_gso(skb)) { + /* TODO: What additional checks need to be performed here */ + if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4) { + lso_word1 |= EDMA_TPD_IPV4_EN; + ip_hdr(skb)->check = 0; + tcp_hdr(skb)->check = ~csum_tcpudp_magic(ip_hdr(skb)->saddr, + ip_hdr(skb)->daddr, 0, IPPROTO_TCP, 0); + } else if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6) { + lso_word1 |= EDMA_TPD_LSO_V2_EN; + ipv6_hdr(skb)->payload_len = 0; + tcp_hdr(skb)->check = ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr, + &ipv6_hdr(skb)->daddr, 0, IPPROTO_TCP, 0); + } else + return -EINVAL; + + lso_word1 |= EDMA_TPD_LSO_EN | ((skb_shinfo(skb)->gso_size & EDMA_TPD_MSS_MASK) << EDMA_TPD_MSS_SHIFT) | + (skb_transport_offset(skb) << EDMA_TPD_HDR_SHIFT); + } else if (flags_transmit & EDMA_HW_CHECKSUM) { + u8 css, cso; + cso = skb_checksum_start_offset(skb); + css = cso + skb->csum_offset; + + word1 |= (EDMA_TPD_CUSTOM_CSUM_EN); + word1 |= (cso >> 1) << EDMA_TPD_HDR_SHIFT; + word1 |= ((css >> 1) << EDMA_TPD_CUSTOM_CSUM_SHIFT); + } + + if (skb->protocol == htons(ETH_P_PPP_SES)) + word1 |= EDMA_TPD_PPPOE_EN; + + if (flags_transmit & EDMA_VLAN_TX_TAG_INSERT_FLAG) { + switch(skb->vlan_proto) { + case htons(ETH_P_8021Q): + word3 |= (1 << EDMA_TX_INS_CVLAN); + word3 |= skb_vlan_tag_get(skb) << EDMA_TX_CVLAN_TAG_SHIFT; + break; + case htons(ETH_P_8021AD): + word1 |= (1 << EDMA_TX_INS_SVLAN); + svlan_tag = skb_vlan_tag_get(skb) << EDMA_TX_SVLAN_TAG_SHIFT; + break; + default: + dev_err(&pdev->dev, "no ctag or stag present\n"); + goto vlan_tag_error; + } + } else if (flags_transmit & EDMA_VLAN_TX_TAG_INSERT_DEFAULT_FLAG) { + word3 |= (1 << EDMA_TX_INS_CVLAN); + word3 |= (adapter->default_vlan_tag) << EDMA_TX_CVLAN_TAG_SHIFT; + } + + if (packet_is_rstp) { + word3 |= dp_bitmap << EDMA_TPD_PORT_BITMAP_SHIFT; + word3 |= from_cpu << EDMA_TPD_FROM_CPU_SHIFT; + } else { + word3 |= adapter->dp_bitmap << EDMA_TPD_PORT_BITMAP_SHIFT; + } + + buf_len = skb_headlen(skb); + + if (lso_word1) { + if (lso_word1 & EDMA_TPD_LSO_V2_EN) { + + /* IPv6 LSOv2 descriptor */ + start_tpd = tpd = edma_get_next_tpd(edma_cinfo, queue_id); + sw_desc = edma_get_tx_buffer(edma_cinfo, tpd, queue_id); + sw_desc->flags |= EDMA_SW_DESC_FLAG_SKB_NONE; + + /* LSOv2 descriptor overrides addr field to pass length */ + tpd->addr = cpu_to_le16(skb->len); + tpd->svlan_tag = svlan_tag; + tpd->word1 = word1 | lso_word1; + tpd->word3 = word3; + } + + tpd = edma_get_next_tpd(edma_cinfo, queue_id); + if (!start_tpd) + start_tpd = tpd; + sw_desc = edma_get_tx_buffer(edma_cinfo, tpd, queue_id); + + /* The last buffer info contain the skb address, + * so skb will be freed after unmap + */ + sw_desc->length = lso_desc_len; + sw_desc->flags |= EDMA_SW_DESC_FLAG_SKB_HEAD; + + sw_desc->dma = dma_map_single(&adapter->pdev->dev, + skb->data, buf_len, DMA_TO_DEVICE); + if (dma_mapping_error(&pdev->dev, sw_desc->dma)) + goto dma_error; + + tpd->addr = cpu_to_le32(sw_desc->dma); + tpd->len = cpu_to_le16(buf_len); + + tpd->svlan_tag = svlan_tag; + tpd->word1 = word1 | lso_word1; + tpd->word3 = word3; + + /* The last buffer info contain the skb address, + * so it will be freed after unmap + */ + sw_desc->length = lso_desc_len; + sw_desc->flags |= EDMA_SW_DESC_FLAG_SKB_HEAD; + + buf_len = 0; + } + + if (likely(buf_len)) { + + /* TODO Do not dequeue descriptor if there is a potential error */ + tpd = edma_get_next_tpd(edma_cinfo, queue_id); + + if (!start_tpd) + start_tpd = tpd; + + sw_desc = edma_get_tx_buffer(edma_cinfo, tpd, queue_id); + + /* The last buffer info contain the skb address, + * so it will be free after unmap + */ + sw_desc->length = buf_len; + sw_desc->flags |= EDMA_SW_DESC_FLAG_SKB_HEAD; + sw_desc->dma = dma_map_single(&adapter->pdev->dev, + skb->data, buf_len, DMA_TO_DEVICE); + if (dma_mapping_error(&pdev->dev, sw_desc->dma)) + goto dma_error; + + tpd->addr = cpu_to_le32(sw_desc->dma); + tpd->len = cpu_to_le16(buf_len); + + tpd->svlan_tag = svlan_tag; + tpd->word1 = word1 | lso_word1; + tpd->word3 = word3; + } + + /* Walk through all paged fragments */ + while (nr_frags--) { + skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; + buf_len = skb_frag_size(frag); + tpd = edma_get_next_tpd(edma_cinfo, queue_id); + sw_desc = edma_get_tx_buffer(edma_cinfo, tpd, queue_id); + sw_desc->length = buf_len; + sw_desc->flags |= EDMA_SW_DESC_FLAG_SKB_FRAG; + + sw_desc->dma = skb_frag_dma_map(&pdev->dev, frag, 0, buf_len, DMA_TO_DEVICE); + + if (dma_mapping_error(NULL, sw_desc->dma)) + goto dma_error; + + tpd->addr = cpu_to_le32(sw_desc->dma); + tpd->len = cpu_to_le16(buf_len); + + tpd->svlan_tag = svlan_tag; + tpd->word1 = word1 | lso_word1; + tpd->word3 = word3; + i++; + } + + /* Walk through all fraglist skbs */ + skb_walk_frags(skb, iter_skb) { + buf_len = iter_skb->len; + tpd = edma_get_next_tpd(edma_cinfo, queue_id); + sw_desc = edma_get_tx_buffer(edma_cinfo, tpd, queue_id); + sw_desc->length = buf_len; + sw_desc->dma = dma_map_single(&adapter->pdev->dev, + iter_skb->data, buf_len, DMA_TO_DEVICE); + + if (dma_mapping_error(NULL, sw_desc->dma)) + goto dma_error; + + tpd->addr = cpu_to_le32(sw_desc->dma); + tpd->len = cpu_to_le16(buf_len); + tpd->svlan_tag = svlan_tag; + tpd->word1 = word1 | lso_word1; + tpd->word3 = word3; + sw_desc->flags |= EDMA_SW_DESC_FLAG_SKB_FRAGLIST; + } + + if (tpd) + tpd->word1 |= 1 << EDMA_TPD_EOP_SHIFT; + + sw_desc->skb = skb; + sw_desc->flags |= EDMA_SW_DESC_FLAG_LAST; + + return 0; + +dma_error: + edma_rollback_tx(adapter, start_tpd, queue_id); + dev_err(&pdev->dev, "TX DMA map failed\n"); +vlan_tag_error: + return -ENOMEM; +} + +/* edma_check_link() + * check Link status + */ +static int edma_check_link(struct edma_adapter *adapter) +{ + struct phy_device *phydev = adapter->phydev; + + if (!(adapter->poll_required)) + return __EDMA_LINKUP; + + if (phydev->link) + return __EDMA_LINKUP; + + return __EDMA_LINKDOWN; +} + +/* edma_adjust_link() + * check for edma link status + */ +void edma_adjust_link(struct net_device *netdev) +{ + int status; + struct edma_adapter *adapter = netdev_priv(netdev); + struct phy_device *phydev = adapter->phydev; + + if (!test_bit(__EDMA_UP, &adapter->state_flags)) + return; + + status = edma_check_link(adapter); + + if (status == __EDMA_LINKUP && adapter->link_state == __EDMA_LINKDOWN) { + phy_print_status(phydev); + adapter->link_state = __EDMA_LINKUP; + if (adapter->edma_cinfo->is_single_phy) { + ess_set_port_status_speed(adapter->edma_cinfo, phydev, + ffs(adapter->dp_bitmap) - 1); + } + netif_carrier_on(netdev); + if (netif_running(netdev)) + netif_tx_wake_all_queues(netdev); + } else if (status == __EDMA_LINKDOWN && adapter->link_state == __EDMA_LINKUP) { + phy_print_status(phydev); + adapter->link_state = __EDMA_LINKDOWN; + netif_carrier_off(netdev); + netif_tx_stop_all_queues(netdev); + } +} + +/* edma_get_stats() + * Statistics api used to retreive the tx/rx statistics + */ +struct net_device_stats *edma_get_stats(struct net_device *netdev) +{ + struct edma_adapter *adapter = netdev_priv(netdev); + + return &adapter->stats; +} + +/* edma_xmit() + * Main api to be called by the core for packet transmission + */ +netdev_tx_t edma_xmit(struct sk_buff *skb, + struct net_device *net_dev) +{ + struct edma_adapter *adapter = netdev_priv(net_dev); + struct edma_common_info *edma_cinfo = adapter->edma_cinfo; + struct edma_tx_desc_ring *etdr; + u16 from_cpu, dp_bitmap, txq_id; + int ret, nr_frags = 0, num_tpds_needed = 1, queue_id; + unsigned int flags_transmit = 0; + bool packet_is_rstp = false; + struct netdev_queue *nq = NULL; + + if (skb_shinfo(skb)->nr_frags) { + nr_frags = skb_shinfo(skb)->nr_frags; + num_tpds_needed += nr_frags; + } else if (skb_has_frag_list(skb)) { + struct sk_buff *iter_skb; + + skb_walk_frags(skb, iter_skb) + num_tpds_needed++; + } + + if (num_tpds_needed > EDMA_MAX_SKB_FRAGS) { + dev_err(&net_dev->dev, + "skb received with fragments %d which is more than %lu", + num_tpds_needed, EDMA_MAX_SKB_FRAGS); + dev_kfree_skb_any(skb); + adapter->stats.tx_errors++; + return NETDEV_TX_OK; + } + + if (edma_stp_rstp) { + u16 ath_hdr, ath_eth_type; + u8 mac_addr[EDMA_ETH_HDR_LEN]; + ath_eth_type = ntohs(*(uint16_t *)&skb->data[12]); + if (ath_eth_type == edma_ath_eth_type) { + packet_is_rstp = true; + ath_hdr = htons(*(uint16_t *)&skb->data[14]); + dp_bitmap = ath_hdr & EDMA_TX_ATH_HDR_PORT_BITMAP_MASK; + from_cpu = (ath_hdr & EDMA_TX_ATH_HDR_FROM_CPU_MASK) >> EDMA_TX_ATH_HDR_FROM_CPU_SHIFT; + memcpy(mac_addr, skb->data, EDMA_ETH_HDR_LEN); + + skb_pull(skb, 4); + + memcpy(skb->data, mac_addr, EDMA_ETH_HDR_LEN); + } + } + + /* this will be one of the 4 TX queues exposed to linux kernel */ + txq_id = skb_get_queue_mapping(skb); + queue_id = edma_tx_queue_get(adapter, skb, txq_id); + etdr = edma_cinfo->tpd_ring[queue_id]; + nq = netdev_get_tx_queue(net_dev, txq_id); + + local_bh_disable(); + /* Tx is not handled in bottom half context. Hence, we need to protect + * Tx from tasks and bottom half + */ + + if (num_tpds_needed > edma_tpd_available(edma_cinfo, queue_id)) { + /* not enough descriptor, just stop queue */ + netif_tx_stop_queue(nq); + local_bh_enable(); + dev_dbg(&net_dev->dev, "Not enough descriptors available"); + edma_cinfo->edma_ethstats.tx_desc_error++; + return NETDEV_TX_BUSY; + } + + /* Check and mark VLAN tag offload */ + if (unlikely(skb_vlan_tag_present(skb))) + flags_transmit |= EDMA_VLAN_TX_TAG_INSERT_FLAG; + else if (!adapter->edma_cinfo->is_single_phy && adapter->default_vlan_tag) + flags_transmit |= EDMA_VLAN_TX_TAG_INSERT_DEFAULT_FLAG; + + /* Check and mark checksum offload */ + if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) + flags_transmit |= EDMA_HW_CHECKSUM; + + /* Map and fill descriptor for Tx */ + ret = edma_tx_map_and_fill(edma_cinfo, adapter, skb, queue_id, + flags_transmit, from_cpu, dp_bitmap, packet_is_rstp, nr_frags); + if (ret) { + dev_kfree_skb_any(skb); + adapter->stats.tx_errors++; + goto netdev_okay; + } + + /* Update SW producer index */ + edma_tx_update_hw_idx(edma_cinfo, skb, queue_id); + + /* update tx statistics */ + adapter->stats.tx_packets++; + adapter->stats.tx_bytes += skb->len; + +netdev_okay: + local_bh_enable(); + return NETDEV_TX_OK; +} + +/* + * edma_flow_may_expire() + * Timer function called periodically to delete the node + */ +void edma_flow_may_expire(struct timer_list *t) +{ + struct edma_rfs_flow_table *table = from_timer(table, t, expire_rfs); + struct edma_adapter *adapter = + container_of(table, typeof(*adapter), rfs); + int j; + + spin_lock_bh(&adapter->rfs.rfs_ftab_lock); + for (j = 0; j < EDMA_RFS_EXPIRE_COUNT_PER_CALL; j++) { + struct hlist_head *hhead; + struct hlist_node *tmp; + struct edma_rfs_filter_node *n; + bool res; + + hhead = &adapter->rfs.hlist_head[adapter->rfs.hashtoclean++]; + hlist_for_each_entry_safe(n, tmp, hhead, node) { + res = rps_may_expire_flow(adapter->netdev, n->rq_id, + n->flow_id, n->filter_id); + if (res) { + int ret; + ret = edma_delete_rfs_filter(adapter, n); + if (ret < 0) + dev_dbg(&adapter->netdev->dev, + "RFS entry %d not allowed to be flushed by Switch", + n->flow_id); + else { + hlist_del(&n->node); + kfree(n); + adapter->rfs.filter_available++; + } + } + } + } + + adapter->rfs.hashtoclean = adapter->rfs.hashtoclean & (EDMA_RFS_FLOW_ENTRIES - 1); + spin_unlock_bh(&adapter->rfs.rfs_ftab_lock); + mod_timer(&adapter->rfs.expire_rfs, jiffies + HZ / 4); +} + +/* edma_rx_flow_steer() + * Called by core to to steer the flow to CPU + */ +int edma_rx_flow_steer(struct net_device *dev, const struct sk_buff *skb, + u16 rxq, u32 flow_id) +{ + struct flow_keys keys; + struct edma_rfs_filter_node *filter_node; + struct edma_adapter *adapter = netdev_priv(dev); + u16 hash_tblid; + int res; + + if (skb->protocol == htons(ETH_P_IPV6)) { + dev_err(&adapter->pdev->dev, "IPv6 not supported\n"); + res = -EINVAL; + goto no_protocol_err; + } + + /* Dissect flow parameters + * We only support IPv4 + TCP/UDP + */ + res = skb_flow_dissect_flow_keys(skb, &keys, 0); + if (!((keys.basic.ip_proto == IPPROTO_TCP) || (keys.basic.ip_proto == IPPROTO_UDP))) { + res = -EPROTONOSUPPORT; + goto no_protocol_err; + } + + /* Check if table entry exists */ + hash_tblid = skb_get_hash_raw(skb) & EDMA_RFS_FLOW_ENTRIES_MASK; + + spin_lock_bh(&adapter->rfs.rfs_ftab_lock); + filter_node = edma_rfs_key_search(&adapter->rfs.hlist_head[hash_tblid], &keys); + + if (filter_node) { + if (rxq == filter_node->rq_id) { + res = -EEXIST; + goto out; + } else { + res = edma_delete_rfs_filter(adapter, filter_node); + if (res < 0) + dev_warn(&adapter->netdev->dev, + "Cannot steer flow %d to different queue", + filter_node->flow_id); + else { + adapter->rfs.filter_available++; + res = edma_add_rfs_filter(adapter, &keys, rxq, filter_node); + if (res < 0) { + dev_warn(&adapter->netdev->dev, + "Cannot steer flow %d to different queue", + filter_node->flow_id); + } else { + adapter->rfs.filter_available--; + filter_node->rq_id = rxq; + filter_node->filter_id = res; + } + } + } + } else { + if (adapter->rfs.filter_available == 0) { + res = -EBUSY; + goto out; + } + + filter_node = kmalloc(sizeof(*filter_node), GFP_ATOMIC); + if (!filter_node) { + res = -ENOMEM; + goto out; + } + + res = edma_add_rfs_filter(adapter, &keys, rxq, filter_node); + if (res < 0) { + kfree(filter_node); + goto out; + } + + adapter->rfs.filter_available--; + filter_node->rq_id = rxq; + filter_node->filter_id = res; + filter_node->flow_id = flow_id; + filter_node->keys = keys; + INIT_HLIST_NODE(&filter_node->node); + hlist_add_head(&filter_node->node, &adapter->rfs.hlist_head[hash_tblid]); + } + +out: + spin_unlock_bh(&adapter->rfs.rfs_ftab_lock); +no_protocol_err: + return res; +} + +/* edma_register_rfs_filter() + * Add RFS filter callback + */ +int edma_register_rfs_filter(struct net_device *netdev, + set_rfs_filter_callback_t set_filter) +{ + struct edma_adapter *adapter = netdev_priv(netdev); + + spin_lock_bh(&adapter->rfs.rfs_ftab_lock); + + if (adapter->set_rfs_rule) { + spin_unlock_bh(&adapter->rfs.rfs_ftab_lock); + return -1; + } + + adapter->set_rfs_rule = set_filter; + spin_unlock_bh(&adapter->rfs.rfs_ftab_lock); + + return 0; +} + +/* edma_alloc_tx_rings() + * Allocate rx rings + */ +int edma_alloc_tx_rings(struct edma_common_info *edma_cinfo) +{ + struct platform_device *pdev = edma_cinfo->pdev; + int i, err = 0; + + for (i = 0; i < edma_cinfo->num_tx_queues; i++) { + err = edma_alloc_tx_ring(edma_cinfo, edma_cinfo->tpd_ring[i]); + if (err) { + dev_err(&pdev->dev, "Tx Queue alloc %u failed\n", i); + return err; + } + } + + return 0; +} + +/* edma_free_tx_rings() + * Free tx rings + */ +void edma_free_tx_rings(struct edma_common_info *edma_cinfo) +{ + int i; + + for (i = 0; i < edma_cinfo->num_tx_queues; i++) + edma_free_tx_ring(edma_cinfo, edma_cinfo->tpd_ring[i]); +} + +/* edma_free_tx_resources() + * Free buffers associated with tx rings + */ +void edma_free_tx_resources(struct edma_common_info *edma_cinfo) +{ + struct edma_tx_desc_ring *etdr; + struct edma_sw_desc *sw_desc; + struct platform_device *pdev = edma_cinfo->pdev; + int i, j; + + for (i = 0; i < edma_cinfo->num_tx_queues; i++) { + etdr = edma_cinfo->tpd_ring[i]; + for (j = 0; j < EDMA_TX_RING_SIZE; j++) { + sw_desc = &etdr->sw_desc[j]; + if (sw_desc->flags & (EDMA_SW_DESC_FLAG_SKB_HEAD | + EDMA_SW_DESC_FLAG_SKB_FRAG | EDMA_SW_DESC_FLAG_SKB_FRAGLIST)) + edma_tx_unmap_and_free(pdev, sw_desc); + } + } +} + +/* edma_alloc_rx_rings() + * Allocate rx rings + */ +int edma_alloc_rx_rings(struct edma_common_info *edma_cinfo) +{ + struct platform_device *pdev = edma_cinfo->pdev; + int i, j, err = 0; + + for (i = 0, j = 0; i < edma_cinfo->num_rx_queues; i++) { + err = edma_alloc_rx_ring(edma_cinfo, edma_cinfo->rfd_ring[j]); + if (err) { + dev_err(&pdev->dev, "Rx Queue alloc%u failed\n", i); + return err; + } + j += ((edma_cinfo->num_rx_queues == 4) ? 2 : 1); + } + + return 0; +} + +/* edma_free_rx_rings() + * free rx rings + */ +void edma_free_rx_rings(struct edma_common_info *edma_cinfo) +{ + int i, j; + + for (i = 0, j = 0; i < edma_cinfo->num_rx_queues; i++) { + edma_free_rx_ring(edma_cinfo, edma_cinfo->rfd_ring[j]); + j += ((edma_cinfo->num_rx_queues == 4) ? 2 : 1); + } +} + +/* edma_free_queues() + * Free the queues allocaated + */ +void edma_free_queues(struct edma_common_info *edma_cinfo) +{ + int i , j; + + for (i = 0; i < edma_cinfo->num_tx_queues; i++) { + if (edma_cinfo->tpd_ring[i]) + kfree(edma_cinfo->tpd_ring[i]); + edma_cinfo->tpd_ring[i] = NULL; + } + + for (i = 0, j = 0; i < edma_cinfo->num_rx_queues; i++) { + if (edma_cinfo->rfd_ring[j]) + kfree(edma_cinfo->rfd_ring[j]); + edma_cinfo->rfd_ring[j] = NULL; + j += ((edma_cinfo->num_rx_queues == 4) ? 2 : 1); + } + + edma_cinfo->num_rx_queues = 0; + edma_cinfo->num_tx_queues = 0; + + return; +} + +/* edma_free_rx_resources() + * Free buffers associated with tx rings + */ +void edma_free_rx_resources(struct edma_common_info *edma_cinfo) +{ + struct edma_rfd_desc_ring *erdr; + struct edma_sw_desc *sw_desc; + struct platform_device *pdev = edma_cinfo->pdev; + int i, j, k; + + for (i = 0, k = 0; i < edma_cinfo->num_rx_queues; i++) { + erdr = edma_cinfo->rfd_ring[k]; + for (j = 0; j < EDMA_RX_RING_SIZE; j++) { + sw_desc = &erdr->sw_desc[j]; + if (likely(sw_desc->flags & EDMA_SW_DESC_FLAG_SKB_HEAD)) { + dma_unmap_single(&pdev->dev, sw_desc->dma, + sw_desc->length, DMA_FROM_DEVICE); + edma_clean_rfd(erdr, j); + } else if ((sw_desc->flags & EDMA_SW_DESC_FLAG_SKB_FRAG)) { + dma_unmap_page(&pdev->dev, sw_desc->dma, + sw_desc->length, DMA_FROM_DEVICE); + edma_clean_rfd(erdr, j); + } + } + k += ((edma_cinfo->num_rx_queues == 4) ? 2 : 1); + + } +} + +/* edma_alloc_queues_tx() + * Allocate memory for all rings + */ +int edma_alloc_queues_tx(struct edma_common_info *edma_cinfo) +{ + int i; + + for (i = 0; i < edma_cinfo->num_tx_queues; i++) { + struct edma_tx_desc_ring *etdr; + etdr = kzalloc(sizeof(struct edma_tx_desc_ring), GFP_KERNEL); + if (!etdr) + goto err; + etdr->count = edma_cinfo->tx_ring_count; + edma_cinfo->tpd_ring[i] = etdr; + } + + return 0; +err: + edma_free_queues(edma_cinfo); + return -1; +} + +/* edma_alloc_queues_rx() + * Allocate memory for all rings + */ +int edma_alloc_queues_rx(struct edma_common_info *edma_cinfo) +{ + int i, j; + + for (i = 0, j = 0; i < edma_cinfo->num_rx_queues; i++) { + struct edma_rfd_desc_ring *rfd_ring; + rfd_ring = kzalloc(sizeof(struct edma_rfd_desc_ring), + GFP_KERNEL); + if (!rfd_ring) + goto err; + rfd_ring->count = edma_cinfo->rx_ring_count; + edma_cinfo->rfd_ring[j] = rfd_ring; + j += ((edma_cinfo->num_rx_queues == 4) ? 2 : 1); + } + return 0; +err: + edma_free_queues(edma_cinfo); + return -1; +} + +/* edma_clear_irq_status() + * Clear interrupt status + */ +void edma_clear_irq_status() +{ + edma_write_reg(EDMA_REG_RX_ISR, 0xff); + edma_write_reg(EDMA_REG_TX_ISR, 0xffff); + edma_write_reg(EDMA_REG_MISC_ISR, 0x1fff); + edma_write_reg(EDMA_REG_WOL_ISR, 0x1); +}; + +/* edma_configure() + * Configure skb, edma interrupts and control register. + */ +int edma_configure(struct edma_common_info *edma_cinfo) +{ + struct edma_hw *hw = &edma_cinfo->hw; + u32 intr_modrt_data; + u32 intr_ctrl_data = 0; + int i, j, ret_count; + + edma_read_reg(EDMA_REG_INTR_CTRL, &intr_ctrl_data); + intr_ctrl_data &= ~(1 << EDMA_INTR_SW_IDX_W_TYP_SHIFT); + intr_ctrl_data |= hw->intr_sw_idx_w << EDMA_INTR_SW_IDX_W_TYP_SHIFT; + edma_write_reg(EDMA_REG_INTR_CTRL, intr_ctrl_data); + + edma_clear_irq_status(); + + /* Clear any WOL status */ + edma_write_reg(EDMA_REG_WOL_CTRL, 0); + intr_modrt_data = (EDMA_TX_IMT << EDMA_IRQ_MODRT_TX_TIMER_SHIFT); + intr_modrt_data |= (EDMA_RX_IMT << EDMA_IRQ_MODRT_RX_TIMER_SHIFT); + edma_write_reg(EDMA_REG_IRQ_MODRT_TIMER_INIT, intr_modrt_data); + edma_configure_tx(edma_cinfo); + edma_configure_rx(edma_cinfo); + + /* Allocate the RX buffer */ + for (i = 0, j = 0; i < edma_cinfo->num_rx_queues; i++) { + struct edma_rfd_desc_ring *ring = edma_cinfo->rfd_ring[j]; + ret_count = edma_alloc_rx_buf(edma_cinfo, ring, ring->count, j); + if (ret_count) { + dev_dbg(&edma_cinfo->pdev->dev, "not all rx buffers allocated\n"); + } + j += ((edma_cinfo->num_rx_queues == 4) ? 2 : 1); + } + + /* Configure descriptor Ring */ + edma_init_desc(edma_cinfo); + return 0; +} + +/* edma_irq_enable() + * Enable default interrupt generation settings + */ +void edma_irq_enable(struct edma_common_info *edma_cinfo) +{ + struct edma_hw *hw = &edma_cinfo->hw; + int i, j; + + edma_write_reg(EDMA_REG_RX_ISR, 0xff); + for (i = 0, j = 0; i < edma_cinfo->num_rx_queues; i++) { + edma_write_reg(EDMA_REG_RX_INT_MASK_Q(j), hw->rx_intr_mask); + j += ((edma_cinfo->num_rx_queues == 4) ? 2 : 1); + } + edma_write_reg(EDMA_REG_TX_ISR, 0xffff); + for (i = 0; i < edma_cinfo->num_tx_queues; i++) + edma_write_reg(EDMA_REG_TX_INT_MASK_Q(i), hw->tx_intr_mask); +} + +/* edma_irq_disable() + * Disable Interrupt + */ +void edma_irq_disable(struct edma_common_info *edma_cinfo) +{ + int i; + + for (i = 0; i < EDMA_MAX_RECEIVE_QUEUE; i++) + edma_write_reg(EDMA_REG_RX_INT_MASK_Q(i), 0x0); + + for (i = 0; i < EDMA_MAX_TRANSMIT_QUEUE; i++) + edma_write_reg(EDMA_REG_TX_INT_MASK_Q(i), 0x0); + edma_write_reg(EDMA_REG_MISC_IMR, 0); + edma_write_reg(EDMA_REG_WOL_IMR, 0); +} + +/* edma_free_irqs() + * Free All IRQs + */ +void edma_free_irqs(struct edma_adapter *adapter) +{ + struct edma_common_info *edma_cinfo = adapter->edma_cinfo; + int i, j; + int k = ((edma_cinfo->num_rx_queues == 4) ? 1 : 2); + + for (i = 0; i < CONFIG_NR_CPUS; i++) { + for (j = edma_cinfo->edma_percpu_info[i].tx_start; j < (edma_cinfo->edma_percpu_info[i].tx_start + 4); j++) + free_irq(edma_cinfo->tx_irq[j], &edma_cinfo->edma_percpu_info[i]); + + for (j = edma_cinfo->edma_percpu_info[i].rx_start; j < (edma_cinfo->edma_percpu_info[i].rx_start + k); j++) + free_irq(edma_cinfo->rx_irq[j], &edma_cinfo->edma_percpu_info[i]); + } +} + +/* edma_enable_rx_ctrl() + * Enable RX queue control + */ +void edma_enable_rx_ctrl(struct edma_hw *hw) +{ + u32 data; + + edma_read_reg(EDMA_REG_RXQ_CTRL, &data); + data |= EDMA_RXQ_CTRL_EN; + edma_write_reg(EDMA_REG_RXQ_CTRL, data); +} + + +/* edma_enable_tx_ctrl() + * Enable TX queue control + */ +void edma_enable_tx_ctrl(struct edma_hw *hw) +{ + u32 data; + + edma_read_reg(EDMA_REG_TXQ_CTRL, &data); + data |= EDMA_TXQ_CTRL_TXQ_EN; + edma_write_reg(EDMA_REG_TXQ_CTRL, data); +} + +/* edma_stop_rx_tx() + * Disable RX/TQ Queue control + */ +void edma_stop_rx_tx(struct edma_hw *hw) +{ + u32 data; + + edma_read_reg(EDMA_REG_RXQ_CTRL, &data); + data &= ~EDMA_RXQ_CTRL_EN; + edma_write_reg(EDMA_REG_RXQ_CTRL, data); + edma_read_reg(EDMA_REG_TXQ_CTRL, &data); + data &= ~EDMA_TXQ_CTRL_TXQ_EN; + edma_write_reg(EDMA_REG_TXQ_CTRL, data); +} + +/* edma_reset() + * Reset the EDMA + */ +int edma_reset(struct edma_common_info *edma_cinfo) +{ + struct edma_hw *hw = &edma_cinfo->hw; + + edma_irq_disable(edma_cinfo); + + edma_clear_irq_status(); + + edma_stop_rx_tx(hw); + + return 0; +} + +/* edma_fill_netdev() + * Fill netdev for each etdr + */ +int edma_fill_netdev(struct edma_common_info *edma_cinfo, int queue_id, + int dev, int txq_id) +{ + struct edma_tx_desc_ring *etdr; + int i = 0; + + etdr = edma_cinfo->tpd_ring[queue_id]; + + while (etdr->netdev[i]) + i++; + + if (i >= EDMA_MAX_NETDEV_PER_QUEUE) + return -1; + + /* Populate the netdev associated with the tpd ring */ + etdr->netdev[i] = edma_netdev[dev]; + etdr->nq[i] = netdev_get_tx_queue(edma_netdev[dev], txq_id); + + return 0; +} + +/* edma_set_mac() + * Change the Ethernet Address of the NIC + */ +int edma_set_mac_addr(struct net_device *netdev, void *p) +{ + struct sockaddr *addr = p; + + if (!is_valid_ether_addr(addr->sa_data)) + return -EINVAL; + + if (netif_running(netdev)) + return -EBUSY; + + memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); + return 0; +} + +/* edma_set_stp_rstp() + * set stp/rstp + */ +void edma_set_stp_rstp(bool rstp) +{ + edma_stp_rstp = rstp; +} + +/* edma_assign_ath_hdr_type() + * assign atheros header eth type + */ +void edma_assign_ath_hdr_type(int eth_type) +{ + edma_ath_eth_type = eth_type & EDMA_ETH_TYPE_MASK; +} + +/* edma_get_default_vlan_tag() + * Used by other modules to get the default vlan tag + */ +int edma_get_default_vlan_tag(struct net_device *netdev) +{ + struct edma_adapter *adapter = netdev_priv(netdev); + + if (adapter->default_vlan_tag) + return adapter->default_vlan_tag; + + return 0; +} + +/* edma_open() + * gets called when netdevice is up, start the queue. + */ +int edma_open(struct net_device *netdev) +{ + struct edma_adapter *adapter = netdev_priv(netdev); + struct platform_device *pdev = adapter->edma_cinfo->pdev; + + netif_tx_start_all_queues(netdev); + edma_initialise_rfs_flow_table(adapter); + set_bit(__EDMA_UP, &adapter->state_flags); + + /* if Link polling is enabled, in our case enabled for WAN, then + * do a phy start, else always set link as UP + */ + if (adapter->poll_required) { + if (!IS_ERR(adapter->phydev)) { + /* AR40xx calibration will leave the PHY in unwanted state, + * so a soft reset is required before phy_start() + */ + genphy_soft_reset(adapter->phydev); + phy_start(adapter->phydev); + phy_start_aneg(adapter->phydev); + adapter->link_state = __EDMA_LINKDOWN; + } else { + dev_dbg(&pdev->dev, "Invalid PHY device for a link polled interface\n"); + } + } else { + adapter->link_state = __EDMA_LINKUP; + netif_carrier_on(netdev); + } + + return 0; +} + + +/* edma_close() + * gets called when netdevice is down, stops the queue. + */ +int edma_close(struct net_device *netdev) +{ + struct edma_adapter *adapter = netdev_priv(netdev); + + edma_free_rfs_flow_table(adapter); + netif_carrier_off(netdev); + netif_tx_stop_all_queues(netdev); + + if (adapter->poll_required) { + if (!IS_ERR(adapter->phydev)) + phy_stop(adapter->phydev); + } + + adapter->link_state = __EDMA_LINKDOWN; + + /* Set GMAC state to UP before link state is checked + */ + clear_bit(__EDMA_UP, &adapter->state_flags); + + return 0; +} + +/* edma_poll + * polling function that gets called when the napi gets scheduled. + * + * Main sequence of task performed in this api + * is clear irq status -> clear_tx_irq -> clean_rx_irq-> + * enable interrupts. + */ +int edma_poll(struct napi_struct *napi, int budget) +{ + struct edma_per_cpu_queues_info *edma_percpu_info = container_of(napi, + struct edma_per_cpu_queues_info, napi); + struct edma_common_info *edma_cinfo = edma_percpu_info->edma_cinfo; + u32 reg_data; + u32 shadow_rx_status, shadow_tx_status; + int queue_id; + int i, work_done = 0; + u16 rx_pending_fill; + + /* Store the Rx/Tx status by ANDing it with + * appropriate CPU RX?TX mask + */ + edma_read_reg(EDMA_REG_RX_ISR, ®_data); + edma_percpu_info->rx_status |= reg_data & edma_percpu_info->rx_mask; + shadow_rx_status = edma_percpu_info->rx_status; + edma_read_reg(EDMA_REG_TX_ISR, ®_data); + edma_percpu_info->tx_status |= reg_data & edma_percpu_info->tx_mask; + shadow_tx_status = edma_percpu_info->tx_status; + + /* Every core will have a start, which will be computed + * in probe and stored in edma_percpu_info->tx_start variable. + * We will shift the status bit by tx_start to obtain + * status bits for the core on which the current processing + * is happening. Since, there are 4 tx queues per core, + * we will run the loop till we get the correct queue to clear. + */ + while (edma_percpu_info->tx_status) { + queue_id = ffs(edma_percpu_info->tx_status) - 1; + edma_tx_complete(edma_cinfo, queue_id); + edma_percpu_info->tx_status &= ~(1 << queue_id); + } + + /* Every core will have a start, which will be computed + * in probe and stored in edma_percpu_info->tx_start variable. + * We will shift the status bit by tx_start to obtain + * status bits for the core on which the current processing + * is happening. Since, there are 4 tx queues per core, we + * will run the loop till we get the correct queue to clear. + */ + while (edma_percpu_info->rx_status) { + queue_id = ffs(edma_percpu_info->rx_status) - 1; + rx_pending_fill = edma_rx_complete(edma_cinfo, &work_done, + budget, queue_id, napi); + + if (likely(work_done < budget)) { + if (rx_pending_fill) { + /* reschedule poll() to refill rx buffer deficit */ + work_done = budget; + break; + } + edma_percpu_info->rx_status &= ~(1 << queue_id); + } else { + break; + } + } + + /* Clear the status register, to avoid the interrupts to + * reoccur.This clearing of interrupt status register is + * done here as writing to status register only takes place + * once the producer/consumer index has been updated to + * reflect that the packet transmission/reception went fine. + */ + edma_write_reg(EDMA_REG_RX_ISR, shadow_rx_status); + edma_write_reg(EDMA_REG_TX_ISR, shadow_tx_status); + + /* If budget not fully consumed, exit the polling mode */ + if (likely(work_done < budget)) { + napi_complete(napi); + + /* re-enable the interrupts */ + for (i = 0; i < edma_cinfo->num_rxq_per_core; i++) + edma_write_reg(EDMA_REG_RX_INT_MASK_Q(edma_percpu_info->rx_start + i), 0x1); + for (i = 0; i < edma_cinfo->num_txq_per_core; i++) + edma_write_reg(EDMA_REG_TX_INT_MASK_Q(edma_percpu_info->tx_start + i), 0x1); + } + + return work_done; +} + +/* edma interrupt() + * interrupt handler + */ +irqreturn_t edma_interrupt(int irq, void *dev) +{ + struct edma_per_cpu_queues_info *edma_percpu_info = (struct edma_per_cpu_queues_info *) dev; + struct edma_common_info *edma_cinfo = edma_percpu_info->edma_cinfo; + int i; + + /* Unmask the TX/RX interrupt register */ + for (i = 0; i < edma_cinfo->num_rxq_per_core; i++) + edma_write_reg(EDMA_REG_RX_INT_MASK_Q(edma_percpu_info->rx_start + i), 0x0); + + for (i = 0; i < edma_cinfo->num_txq_per_core; i++) + edma_write_reg(EDMA_REG_TX_INT_MASK_Q(edma_percpu_info->tx_start + i), 0x0); + + napi_schedule(&edma_percpu_info->napi); + + return IRQ_HANDLED; +} diff --git a/feeds/ipq40xx/ipq40xx/files/drivers/net/ethernet/qualcomm/essedma/edma.h b/feeds/ipq40xx/ipq40xx/files/drivers/net/ethernet/qualcomm/essedma/edma.h new file mode 100644 index 000000000..015e5f502 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/files/drivers/net/ethernet/qualcomm/essedma/edma.h @@ -0,0 +1,455 @@ +/* + * Copyright (c) 2014 - 2016, 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 _EDMA_H_ +#define _EDMA_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ess_edma.h" + +#define EDMA_CPU_CORES_SUPPORTED 4 +#define EDMA_MAX_PORTID_SUPPORTED 5 +#define EDMA_MAX_VLAN_SUPPORTED EDMA_MAX_PORTID_SUPPORTED +#define EDMA_MAX_PORTID_BITMAP_INDEX (EDMA_MAX_PORTID_SUPPORTED + 1) +#define EDMA_MAX_PORTID_BITMAP_SUPPORTED 0x1f /* 0001_1111 = 0x1f */ +#define EDMA_MAX_NETDEV_PER_QUEUE 4 /* 3 Netdev per queue, 1 space for indexing */ + +#define EDMA_MAX_RECEIVE_QUEUE 8 +#define EDMA_MAX_TRANSMIT_QUEUE 16 + +/* WAN/LAN adapter number */ +#define EDMA_WAN 0 +#define EDMA_LAN 1 + +/* VLAN tag */ +#define EDMA_LAN_DEFAULT_VLAN 1 +#define EDMA_WAN_DEFAULT_VLAN 2 + +#define EDMA_DEFAULT_GROUP1_VLAN 1 +#define EDMA_DEFAULT_GROUP2_VLAN 2 +#define EDMA_DEFAULT_GROUP3_VLAN 3 +#define EDMA_DEFAULT_GROUP4_VLAN 4 +#define EDMA_DEFAULT_GROUP5_VLAN 5 + +/* Queues exposed to linux kernel */ +#define EDMA_NETDEV_TX_QUEUE 4 +#define EDMA_NETDEV_RX_QUEUE 4 + +/* Number of queues per core */ +#define EDMA_NUM_TXQ_PER_CORE 4 +#define EDMA_NUM_RXQ_PER_CORE 2 + +#define EDMA_TPD_EOP_SHIFT 31 + +#define EDMA_PORT_ID_SHIFT 12 +#define EDMA_PORT_ID_MASK 0x7 + +/* tpd word 3 bit 18-28 */ +#define EDMA_TPD_PORT_BITMAP_SHIFT 18 + +#define EDMA_TPD_FROM_CPU_SHIFT 25 + +#define EDMA_FROM_CPU_MASK 0x80 +#define EDMA_SKB_PRIORITY_MASK 0x38 + +/* TX/RX descriptor ring count */ +/* should be a power of 2 */ +#define EDMA_RX_RING_SIZE 128 +#define EDMA_TX_RING_SIZE 128 + +/* Flags used in paged/non paged mode */ +#define EDMA_RX_HEAD_BUFF_SIZE_JUMBO 256 +#define EDMA_RX_HEAD_BUFF_SIZE 1540 + +/* MAX frame size supported by switch */ +#define EDMA_MAX_JUMBO_FRAME_SIZE 9216 + +/* Configurations */ +#define EDMA_INTR_CLEAR_TYPE 0 +#define EDMA_INTR_SW_IDX_W_TYPE 0 +#define EDMA_FIFO_THRESH_TYPE 0 +#define EDMA_RSS_TYPE 0 +#define EDMA_RX_IMT 0x0020 +#define EDMA_TX_IMT 0x0050 +#define EDMA_TPD_BURST 5 +#define EDMA_TXF_BURST 0x100 +#define EDMA_RFD_BURST 8 +#define EDMA_RFD_THR 16 +#define EDMA_RFD_LTHR 0 + +/* RX/TX per CPU based mask/shift */ +#define EDMA_TX_PER_CPU_MASK 0xF +#define EDMA_RX_PER_CPU_MASK 0x3 +#define EDMA_TX_PER_CPU_MASK_SHIFT 0x2 +#define EDMA_RX_PER_CPU_MASK_SHIFT 0x1 +#define EDMA_TX_CPU_START_SHIFT 0x2 +#define EDMA_RX_CPU_START_SHIFT 0x1 + +/* FLags used in transmit direction */ +#define EDMA_HW_CHECKSUM 0x00000001 +#define EDMA_VLAN_TX_TAG_INSERT_FLAG 0x00000002 +#define EDMA_VLAN_TX_TAG_INSERT_DEFAULT_FLAG 0x00000004 + +#define EDMA_SW_DESC_FLAG_LAST 0x1 +#define EDMA_SW_DESC_FLAG_SKB_HEAD 0x2 +#define EDMA_SW_DESC_FLAG_SKB_FRAG 0x4 +#define EDMA_SW_DESC_FLAG_SKB_FRAGLIST 0x8 +#define EDMA_SW_DESC_FLAG_SKB_NONE 0x10 +#define EDMA_SW_DESC_FLAG_SKB_REUSE 0x20 + + +#define EDMA_MAX_SKB_FRAGS (MAX_SKB_FRAGS + 1) + +/* Ethtool specific list of EDMA supported features */ +#define EDMA_SUPPORTED_FEATURES (SUPPORTED_10baseT_Half \ + | SUPPORTED_10baseT_Full \ + | SUPPORTED_100baseT_Half \ + | SUPPORTED_100baseT_Full \ + | SUPPORTED_1000baseT_Full) + +/* Recevie side atheros Header */ +#define EDMA_RX_ATH_HDR_VERSION 0x2 +#define EDMA_RX_ATH_HDR_VERSION_SHIFT 14 +#define EDMA_RX_ATH_HDR_PRIORITY_SHIFT 11 +#define EDMA_RX_ATH_PORT_TYPE_SHIFT 6 +#define EDMA_RX_ATH_HDR_RSTP_PORT_TYPE 0x4 + +/* Transmit side atheros Header */ +#define EDMA_TX_ATH_HDR_PORT_BITMAP_MASK 0x7F +#define EDMA_TX_ATH_HDR_FROM_CPU_MASK 0x80 +#define EDMA_TX_ATH_HDR_FROM_CPU_SHIFT 7 + +#define EDMA_TXQ_START_CORE0 8 +#define EDMA_TXQ_START_CORE1 12 +#define EDMA_TXQ_START_CORE2 0 +#define EDMA_TXQ_START_CORE3 4 + +#define EDMA_TXQ_IRQ_MASK_CORE0 0x0F00 +#define EDMA_TXQ_IRQ_MASK_CORE1 0xF000 +#define EDMA_TXQ_IRQ_MASK_CORE2 0x000F +#define EDMA_TXQ_IRQ_MASK_CORE3 0x00F0 + +#define EDMA_ETH_HDR_LEN 12 +#define EDMA_ETH_TYPE_MASK 0xFFFF + +#define EDMA_RX_BUFFER_WRITE 16 +#define EDMA_RFD_AVAIL_THR 80 + +#define EDMA_GMAC_NO_MDIO_PHY PHY_MAX_ADDR + +extern int ssdk_rfs_ipct_rule_set(__be32 ip_src, __be32 ip_dst, + __be16 sport, __be16 dport, + uint8_t proto, u16 loadbalance, bool action); +struct edma_ethtool_statistics { + u32 tx_q0_pkt; + u32 tx_q1_pkt; + u32 tx_q2_pkt; + u32 tx_q3_pkt; + u32 tx_q4_pkt; + u32 tx_q5_pkt; + u32 tx_q6_pkt; + u32 tx_q7_pkt; + u32 tx_q8_pkt; + u32 tx_q9_pkt; + u32 tx_q10_pkt; + u32 tx_q11_pkt; + u32 tx_q12_pkt; + u32 tx_q13_pkt; + u32 tx_q14_pkt; + u32 tx_q15_pkt; + u32 tx_q0_byte; + u32 tx_q1_byte; + u32 tx_q2_byte; + u32 tx_q3_byte; + u32 tx_q4_byte; + u32 tx_q5_byte; + u32 tx_q6_byte; + u32 tx_q7_byte; + u32 tx_q8_byte; + u32 tx_q9_byte; + u32 tx_q10_byte; + u32 tx_q11_byte; + u32 tx_q12_byte; + u32 tx_q13_byte; + u32 tx_q14_byte; + u32 tx_q15_byte; + u32 rx_q0_pkt; + u32 rx_q1_pkt; + u32 rx_q2_pkt; + u32 rx_q3_pkt; + u32 rx_q4_pkt; + u32 rx_q5_pkt; + u32 rx_q6_pkt; + u32 rx_q7_pkt; + u32 rx_q0_byte; + u32 rx_q1_byte; + u32 rx_q2_byte; + u32 rx_q3_byte; + u32 rx_q4_byte; + u32 rx_q5_byte; + u32 rx_q6_byte; + u32 rx_q7_byte; + u32 tx_desc_error; + u32 rx_alloc_fail_ctr; +}; + +struct edma_mdio_data { + struct mii_bus *mii_bus; + void __iomem *membase; + int phy_irq[PHY_MAX_ADDR]; +}; + +/* EDMA LINK state */ +enum edma_link_state { + __EDMA_LINKUP, /* Indicate link is UP */ + __EDMA_LINKDOWN /* Indicate link is down */ +}; + +/* EDMA GMAC state */ +enum edma_gmac_state { + __EDMA_UP /* use to indicate GMAC is up */ +}; + +/* edma transmit descriptor */ +struct edma_tx_desc { + __le16 len; /* full packet including CRC */ + __le16 svlan_tag; /* vlan tag */ + __le32 word1; /* byte 4-7 */ + __le32 addr; /* address of buffer */ + __le32 word3; /* byte 12 */ +}; + +/* edma receive return descriptor */ +struct edma_rx_return_desc { + u16 rrd0; + u16 rrd1; + u16 rrd2; + u16 rrd3; + u16 rrd4; + u16 rrd5; + u16 rrd6; + u16 rrd7; +}; + +/* RFD descriptor */ +struct edma_rx_free_desc { + __le32 buffer_addr; /* buffer address */ +}; + +/* edma hw specific data */ +struct edma_hw { + u32 __iomem *hw_addr; /* inner register address */ + struct edma_adapter *adapter; /* netdevice adapter */ + u32 rx_intr_mask; /*rx interrupt mask */ + u32 tx_intr_mask; /* tx interrupt nask */ + u32 misc_intr_mask; /* misc interrupt mask */ + u32 wol_intr_mask; /* wake on lan interrupt mask */ + bool intr_clear_type; /* interrupt clear */ + bool intr_sw_idx_w; /* interrupt software index */ + u32 rx_head_buff_size; /* Rx buffer size */ + u8 rss_type; /* rss protocol type */ +}; + +/* edma_sw_desc stores software descriptor + * SW descriptor has 1:1 map with HW descriptor + */ +struct edma_sw_desc { + struct sk_buff *skb; + dma_addr_t dma; /* dma address */ + u16 length; /* Tx/Rx buffer length */ + u32 flags; +}; + +/* per core related information */ +struct edma_per_cpu_queues_info { + struct napi_struct napi; /* napi associated with the core */ + u32 tx_mask; /* tx interrupt mask */ + u32 rx_mask; /* rx interrupt mask */ + u32 tx_status; /* tx interrupt status */ + u32 rx_status; /* rx interrupt status */ + u32 tx_start; /* tx queue start */ + u32 rx_start; /* rx queue start */ + struct edma_common_info *edma_cinfo; /* edma common info */ +}; + +/* edma specific common info */ +struct edma_common_info { + struct edma_tx_desc_ring *tpd_ring[16]; /* 16 Tx queues */ + struct edma_rfd_desc_ring *rfd_ring[8]; /* 8 Rx queues */ + struct platform_device *pdev; /* device structure */ + struct net_device *netdev[EDMA_MAX_PORTID_SUPPORTED]; + struct net_device *portid_netdev_lookup_tbl[EDMA_MAX_PORTID_BITMAP_INDEX]; + struct ctl_table_header *edma_ctl_table_hdr; + int num_gmac; + struct edma_ethtool_statistics edma_ethstats; /* ethtool stats */ + int num_rx_queues; /* number of rx queue */ + u32 num_tx_queues; /* number of tx queue */ + u32 tx_irq[16]; /* number of tx irq */ + u32 rx_irq[8]; /* number of rx irq */ + u32 from_cpu; /* from CPU TPD field */ + u32 num_rxq_per_core; /* Rx queues per core */ + u32 num_txq_per_core; /* Tx queues per core */ + u16 tx_ring_count; /* Tx ring count */ + u16 rx_ring_count; /* Rx ring*/ + u16 rx_head_buffer_len; /* rx buffer length */ + u16 rx_page_buffer_len; /* rx buffer length */ + u32 page_mode; /* Jumbo frame supported flag */ + u32 fraglist_mode; /* fraglist supported flag */ + struct edma_hw hw; /* edma hw specific structure */ + struct edma_per_cpu_queues_info edma_percpu_info[CONFIG_NR_CPUS]; /* per cpu information */ + spinlock_t stats_lock; /* protect edma stats area for updation */ + struct timer_list edma_stats_timer; + bool is_single_phy; + void __iomem *ess_hw_addr; + struct clk *ess_clk; +}; + +/* transimit packet descriptor (tpd) ring */ +struct edma_tx_desc_ring { + struct netdev_queue *nq[EDMA_MAX_NETDEV_PER_QUEUE]; /* Linux queue index */ + struct net_device *netdev[EDMA_MAX_NETDEV_PER_QUEUE]; + /* Array of netdevs associated with the tpd ring */ + void *hw_desc; /* descriptor ring virtual address */ + struct edma_sw_desc *sw_desc; /* buffer associated with ring */ + int netdev_bmp; /* Bitmap for per-ring netdevs */ + u32 size; /* descriptor ring length in bytes */ + u16 count; /* number of descriptors in the ring */ + dma_addr_t dma; /* descriptor ring physical address */ + u16 sw_next_to_fill; /* next Tx descriptor to fill */ + u16 sw_next_to_clean; /* next Tx descriptor to clean */ +}; + +/* receive free descriptor (rfd) ring */ +struct edma_rfd_desc_ring { + void *hw_desc; /* descriptor ring virtual address */ + struct edma_sw_desc *sw_desc; /* buffer associated with ring */ + u16 size; /* bytes allocated to sw_desc */ + u16 count; /* number of descriptors in the ring */ + dma_addr_t dma; /* descriptor ring physical address */ + u16 sw_next_to_fill; /* next descriptor to fill */ + u16 sw_next_to_clean; /* next descriptor to clean */ + u16 pending_fill; /* fill pending from previous iteration */ +}; + +/* edma_rfs_flter_node - rfs filter node in hash table */ +struct edma_rfs_filter_node { + struct flow_keys keys; + u32 flow_id; /* flow_id of filter provided by kernel */ + u16 filter_id; /* filter id of filter returned by adaptor */ + u16 rq_id; /* desired rq index */ + struct hlist_node node; /* edma rfs list node */ +}; + +/* edma_rfs_flow_tbl - rfs flow table */ +struct edma_rfs_flow_table { + u16 max_num_filter; /* Maximum number of filters edma supports */ + u16 hashtoclean; /* hash table index to clean next */ + int filter_available; /* Number of free filters available */ + struct hlist_head hlist_head[EDMA_RFS_FLOW_ENTRIES]; + spinlock_t rfs_ftab_lock; + struct timer_list expire_rfs; /* timer function for edma_rps_may_expire_flow */ +}; + +/* EDMA net device structure */ +struct edma_adapter { + struct net_device *netdev; /* netdevice */ + struct platform_device *pdev; /* platform device */ + struct edma_common_info *edma_cinfo; /* edma common info */ + struct phy_device *phydev; /* Phy device */ + struct edma_rfs_flow_table rfs; /* edma rfs flow table */ + struct net_device_stats stats; /* netdev statistics */ + set_rfs_filter_callback_t set_rfs_rule; + u32 flags;/* status flags */ + unsigned long state_flags; /* GMAC up/down flags */ + u32 forced_speed; /* link force speed */ + u32 forced_duplex; /* link force duplex */ + u32 link_state; /* phy link state */ + u32 phy_mdio_addr; /* PHY device address on MII interface */ + u32 poll_required; /* check if link polling is required */ + u32 tx_start_offset[CONFIG_NR_CPUS]; /* tx queue start */ + u32 default_vlan_tag; /* vlan tag */ + u32 dp_bitmap; + uint8_t phy_id[MII_BUS_ID_SIZE + 3]; +}; + +int edma_alloc_queues_tx(struct edma_common_info *edma_cinfo); +int edma_alloc_queues_rx(struct edma_common_info *edma_cinfo); +int edma_open(struct net_device *netdev); +int edma_close(struct net_device *netdev); +void edma_free_tx_resources(struct edma_common_info *edma_c_info); +void edma_free_rx_resources(struct edma_common_info *edma_c_info); +int edma_alloc_tx_rings(struct edma_common_info *edma_cinfo); +int edma_alloc_rx_rings(struct edma_common_info *edma_cinfo); +void edma_free_tx_rings(struct edma_common_info *edma_cinfo); +void edma_free_rx_rings(struct edma_common_info *edma_cinfo); +void edma_free_queues(struct edma_common_info *edma_cinfo); +void edma_irq_disable(struct edma_common_info *edma_cinfo); +int edma_reset(struct edma_common_info *edma_cinfo); +int edma_poll(struct napi_struct *napi, int budget); +netdev_tx_t edma_xmit(struct sk_buff *skb, + struct net_device *netdev); +int edma_configure(struct edma_common_info *edma_cinfo); +void edma_irq_enable(struct edma_common_info *edma_cinfo); +void edma_enable_tx_ctrl(struct edma_hw *hw); +void edma_enable_rx_ctrl(struct edma_hw *hw); +void edma_stop_rx_tx(struct edma_hw *hw); +void edma_free_irqs(struct edma_adapter *adapter); +irqreturn_t edma_interrupt(int irq, void *dev); +void edma_write_reg(u16 reg_addr, u32 reg_value); +void edma_read_reg(u16 reg_addr, volatile u32 *reg_value); +struct net_device_stats *edma_get_stats(struct net_device *netdev); +int edma_set_mac_addr(struct net_device *netdev, void *p); +int edma_rx_flow_steer(struct net_device *dev, const struct sk_buff *skb, + u16 rxq, u32 flow_id); +int edma_register_rfs_filter(struct net_device *netdev, + set_rfs_filter_callback_t set_filter); +void edma_flow_may_expire(struct timer_list *t); +void edma_set_ethtool_ops(struct net_device *netdev); +void edma_set_stp_rstp(bool tag); +void edma_assign_ath_hdr_type(int tag); +int edma_get_default_vlan_tag(struct net_device *netdev); +void edma_adjust_link(struct net_device *netdev); +int edma_fill_netdev(struct edma_common_info *edma_cinfo, int qid, int num, int txq_id); +void edma_read_append_stats(struct edma_common_info *edma_cinfo); +void edma_change_tx_coalesce(int usecs); +void edma_change_rx_coalesce(int usecs); +void edma_get_tx_rx_coalesce(u32 *reg_val); +void edma_clear_irq_status(void); +void ess_set_port_status_speed(struct edma_common_info *edma_cinfo, + struct phy_device *phydev, uint8_t port_id); +#endif /* _EDMA_H_ */ diff --git a/feeds/ipq40xx/ipq40xx/files/drivers/net/ethernet/qualcomm/essedma/edma_axi.c b/feeds/ipq40xx/ipq40xx/files/drivers/net/ethernet/qualcomm/essedma/edma_axi.c new file mode 100644 index 000000000..9dc38bcfc --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/files/drivers/net/ethernet/qualcomm/essedma/edma_axi.c @@ -0,0 +1,1351 @@ +/* + * Copyright (c) 2014 - 2016, The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all copies. + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "edma.h" +#include "ess_edma.h" + +/* Weight round robin and virtual QID mask */ +#define EDMA_WRR_VID_SCTL_MASK 0xffff + +/* Weight round robin and virtual QID shift */ +#define EDMA_WRR_VID_SCTL_SHIFT 16 + +char edma_axi_driver_name[] = "ess_edma"; +static const u32 default_msg = NETIF_MSG_DRV | NETIF_MSG_PROBE | + NETIF_MSG_LINK | NETIF_MSG_TIMER | NETIF_MSG_IFDOWN | NETIF_MSG_IFUP; + +static u32 edma_hw_addr; + +char edma_tx_irq[16][64]; +char edma_rx_irq[8][64]; +struct net_device *edma_netdev[EDMA_MAX_PORTID_SUPPORTED]; +static u16 tx_start[4] = {EDMA_TXQ_START_CORE0, EDMA_TXQ_START_CORE1, + EDMA_TXQ_START_CORE2, EDMA_TXQ_START_CORE3}; +static u32 tx_mask[4] = {EDMA_TXQ_IRQ_MASK_CORE0, EDMA_TXQ_IRQ_MASK_CORE1, + EDMA_TXQ_IRQ_MASK_CORE2, EDMA_TXQ_IRQ_MASK_CORE3}; + +static u32 edma_default_ltag __read_mostly = EDMA_LAN_DEFAULT_VLAN; +static u32 edma_default_wtag __read_mostly = EDMA_WAN_DEFAULT_VLAN; +static u32 edma_default_group1_vtag __read_mostly = EDMA_DEFAULT_GROUP1_VLAN; +static u32 edma_default_group2_vtag __read_mostly = EDMA_DEFAULT_GROUP2_VLAN; +static u32 edma_default_group3_vtag __read_mostly = EDMA_DEFAULT_GROUP3_VLAN; +static u32 edma_default_group4_vtag __read_mostly = EDMA_DEFAULT_GROUP4_VLAN; +static u32 edma_default_group5_vtag __read_mostly = EDMA_DEFAULT_GROUP5_VLAN; +static u32 edma_rss_idt_val = EDMA_RSS_IDT_VALUE; +static u32 edma_rss_idt_idx; + +static int edma_weight_assigned_to_q __read_mostly; +static int edma_queue_to_virtual_q __read_mostly; +static bool edma_enable_rstp __read_mostly; +static int edma_athr_hdr_eth_type __read_mostly; + +static int page_mode; +module_param(page_mode, int, 0); +MODULE_PARM_DESC(page_mode, "enable page mode"); + +static int overwrite_mode; +module_param(overwrite_mode, int, 0); +MODULE_PARM_DESC(overwrite_mode, "overwrite default page_mode setting"); + +static int jumbo_mru = EDMA_RX_HEAD_BUFF_SIZE; +module_param(jumbo_mru, int, 0); +MODULE_PARM_DESC(jumbo_mru, "enable fraglist support"); + +static int num_rxq = 4; +module_param(num_rxq, int, 0); +MODULE_PARM_DESC(num_rxq, "change the number of rx queues"); + +void edma_write_reg(u16 reg_addr, u32 reg_value) +{ + writel(reg_value, ((void __iomem *)(edma_hw_addr + reg_addr))); +} + +void edma_read_reg(u16 reg_addr, volatile u32 *reg_value) +{ + *reg_value = readl((void __iomem *)(edma_hw_addr + reg_addr)); +} + +static void ess_write_reg(struct edma_common_info *edma, u16 reg_addr, u32 reg_value) +{ + writel(reg_value, ((void __iomem *) + ((unsigned long)edma->ess_hw_addr + reg_addr))); +} + +static void ess_read_reg(struct edma_common_info *edma, u16 reg_addr, + volatile u32 *reg_value) +{ + *reg_value = readl((void __iomem *) + ((unsigned long)edma->ess_hw_addr + reg_addr)); +} + +static int ess_reset(struct edma_common_info *edma) +{ + struct device_node *switch_node = NULL; + struct reset_control *ess_rst; + u32 regval; + + switch_node = of_find_node_by_name(NULL, "ess-switch"); + if (!switch_node) { + pr_err("switch-node not found\n"); + return -EINVAL; + } + + ess_rst = of_reset_control_get(switch_node, "ess_rst"); + of_node_put(switch_node); + + if (IS_ERR(ess_rst)) { + pr_err("failed to find ess_rst!\n"); + return -ENOENT; + } + + reset_control_assert(ess_rst); + msleep(10); + reset_control_deassert(ess_rst); + msleep(100); + reset_control_put(ess_rst); + + /* Enable only port 5 <--> port 0 + * bits 0:6 bitmap of ports it can fwd to */ +#define SET_PORT_BMP(r,v) \ + ess_read_reg(edma, r, ®val); \ + ess_write_reg(edma, r, ((regval & ~0x3F) | v)); + + SET_PORT_BMP(ESS_PORT0_LOOKUP_CTRL,0x20); + SET_PORT_BMP(ESS_PORT1_LOOKUP_CTRL,0x00); + SET_PORT_BMP(ESS_PORT2_LOOKUP_CTRL,0x00); + SET_PORT_BMP(ESS_PORT3_LOOKUP_CTRL,0x00); + SET_PORT_BMP(ESS_PORT4_LOOKUP_CTRL,0x00); + SET_PORT_BMP(ESS_PORT5_LOOKUP_CTRL,0x01); + ess_write_reg(edma, ESS_RGMII_CTRL, 0x400); + ess_write_reg(edma, ESS_PORT0_STATUS, ESS_PORT_1G_FDX); + ess_write_reg(edma, ESS_PORT5_STATUS, ESS_PORT_1G_FDX); + ess_write_reg(edma, ESS_PORT0_HEADER_CTRL, 0); +#undef SET_PORT_BMP + + /* forward multicast and broadcast frames to CPU */ + ess_write_reg(edma, ESS_FWD_CTRL1, + (ESS_PORTS_ALL << ESS_FWD_CTRL1_UC_FLOOD_S) | + (ESS_PORTS_ALL << ESS_FWD_CTRL1_MC_FLOOD_S) | + (ESS_PORTS_ALL << ESS_FWD_CTRL1_BC_FLOOD_S)); + + return 0; +} + +void ess_set_port_status_speed(struct edma_common_info *edma, + struct phy_device *phydev, uint8_t port_id) +{ + uint16_t reg_off = ESS_PORT0_STATUS + (4 * port_id); + uint32_t reg_val = 0; + + ess_read_reg(edma, reg_off, ®_val); + + /* reset the speed bits [0:1] */ + reg_val &= ~ESS_PORT_STATUS_SPEED_INV; + + /* set the new speed */ + switch(phydev->speed) { + case SPEED_1000: reg_val |= ESS_PORT_STATUS_SPEED_1000; break; + case SPEED_100: reg_val |= ESS_PORT_STATUS_SPEED_100; break; + case SPEED_10: reg_val |= ESS_PORT_STATUS_SPEED_10; break; + default: reg_val |= ESS_PORT_STATUS_SPEED_INV; break; + } + + /* check full/half duplex */ + if (phydev->duplex) { + reg_val |= ESS_PORT_STATUS_DUPLEX_MODE; + } else { + reg_val &= ~ESS_PORT_STATUS_DUPLEX_MODE; + } + + ess_write_reg(edma, reg_off, reg_val); +} + +/* edma_change_tx_coalesce() + * change tx interrupt moderation timer + */ +void edma_change_tx_coalesce(int usecs) +{ + u32 reg_value; + + /* Here, we right shift the value from the user by 1, this is + * done because IMT resolution timer is 2usecs. 1 count + * of this register corresponds to 2 usecs. + */ + edma_read_reg(EDMA_REG_IRQ_MODRT_TIMER_INIT, ®_value); + reg_value = ((reg_value & 0xffff) | ((usecs >> 1) << 16)); + edma_write_reg(EDMA_REG_IRQ_MODRT_TIMER_INIT, reg_value); +} + +/* edma_change_rx_coalesce() + * change rx interrupt moderation timer + */ +void edma_change_rx_coalesce(int usecs) +{ + u32 reg_value; + + /* Here, we right shift the value from the user by 1, this is + * done because IMT resolution timer is 2usecs. 1 count + * of this register corresponds to 2 usecs. + */ + edma_read_reg(EDMA_REG_IRQ_MODRT_TIMER_INIT, ®_value); + reg_value = ((reg_value & 0xffff0000) | (usecs >> 1)); + edma_write_reg(EDMA_REG_IRQ_MODRT_TIMER_INIT, reg_value); +} + +/* edma_get_tx_rx_coalesce() + * Get tx/rx interrupt moderation value + */ +void edma_get_tx_rx_coalesce(u32 *reg_val) +{ + edma_read_reg(EDMA_REG_IRQ_MODRT_TIMER_INIT, reg_val); +} + +void edma_read_append_stats(struct edma_common_info *edma_cinfo) +{ + uint32_t *p; + int i; + u32 stat; + + spin_lock_bh(&edma_cinfo->stats_lock); + p = (uint32_t *)&(edma_cinfo->edma_ethstats); + + for (i = 0; i < EDMA_MAX_TRANSMIT_QUEUE; i++) { + edma_read_reg(EDMA_REG_TX_STAT_PKT_Q(i), &stat); + *p += stat; + p++; + } + + for (i = 0; i < EDMA_MAX_TRANSMIT_QUEUE; i++) { + edma_read_reg(EDMA_REG_TX_STAT_BYTE_Q(i), &stat); + *p += stat; + p++; + } + + for (i = 0; i < EDMA_MAX_RECEIVE_QUEUE; i++) { + edma_read_reg(EDMA_REG_RX_STAT_PKT_Q(i), &stat); + *p += stat; + p++; + } + + for (i = 0; i < EDMA_MAX_RECEIVE_QUEUE; i++) { + edma_read_reg(EDMA_REG_RX_STAT_BYTE_Q(i), &stat); + *p += stat; + p++; + } + + spin_unlock_bh(&edma_cinfo->stats_lock); +} + +static void edma_statistics_timer(struct timer_list *t) +{ + struct edma_common_info *edma_cinfo = + from_timer(edma_cinfo, t, edma_stats_timer); + + edma_read_append_stats(edma_cinfo); + + mod_timer(&edma_cinfo->edma_stats_timer, jiffies + 1*HZ); +} + +static int edma_enable_stp_rstp(struct ctl_table *table, int write, + void __user *buffer, size_t *lenp, + loff_t *ppos) +{ + int ret; + + ret = proc_dointvec(table, write, buffer, lenp, ppos); + if (write) + edma_set_stp_rstp(edma_enable_rstp); + + return ret; +} + +static int edma_ath_hdr_eth_type(struct ctl_table *table, int write, + void __user *buffer, size_t *lenp, + loff_t *ppos) +{ + int ret; + + ret = proc_dointvec(table, write, buffer, lenp, ppos); + if (write) + edma_assign_ath_hdr_type(edma_athr_hdr_eth_type); + + return ret; +} + +static int edma_change_default_lan_vlan(struct ctl_table *table, int write, + void __user *buffer, size_t *lenp, + loff_t *ppos) +{ + struct edma_adapter *adapter; + int ret; + + if (!edma_netdev[1]) { + pr_err("Netdevice for default_lan does not exist\n"); + return -1; + } + + adapter = netdev_priv(edma_netdev[1]); + + ret = proc_dointvec(table, write, buffer, lenp, ppos); + + if (write) + adapter->default_vlan_tag = edma_default_ltag; + + return ret; +} + +static int edma_change_default_wan_vlan(struct ctl_table *table, int write, + void __user *buffer, size_t *lenp, + loff_t *ppos) +{ + struct edma_adapter *adapter; + int ret; + + if (!edma_netdev[0]) { + pr_err("Netdevice for default_wan does not exist\n"); + return -1; + } + + adapter = netdev_priv(edma_netdev[0]); + + ret = proc_dointvec(table, write, buffer, lenp, ppos); + + if (write) + adapter->default_vlan_tag = edma_default_wtag; + + return ret; +} + +static int edma_change_group1_vtag(struct ctl_table *table, int write, + void __user *buffer, size_t *lenp, + loff_t *ppos) +{ + struct edma_adapter *adapter; + struct edma_common_info *edma_cinfo; + int ret; + + if (!edma_netdev[0]) { + pr_err("Netdevice for Group 1 does not exist\n"); + return -1; + } + + adapter = netdev_priv(edma_netdev[0]); + edma_cinfo = adapter->edma_cinfo; + + ret = proc_dointvec(table, write, buffer, lenp, ppos); + + if (write) + adapter->default_vlan_tag = edma_default_group1_vtag; + + return ret; +} + +static int edma_change_group2_vtag(struct ctl_table *table, int write, + void __user *buffer, size_t *lenp, + loff_t *ppos) +{ + struct edma_adapter *adapter; + struct edma_common_info *edma_cinfo; + int ret; + + if (!edma_netdev[1]) { + pr_err("Netdevice for Group 2 does not exist\n"); + return -1; + } + + adapter = netdev_priv(edma_netdev[1]); + edma_cinfo = adapter->edma_cinfo; + + ret = proc_dointvec(table, write, buffer, lenp, ppos); + + if (write) + adapter->default_vlan_tag = edma_default_group2_vtag; + + return ret; +} + +static int edma_change_group3_vtag(struct ctl_table *table, int write, + void __user *buffer, size_t *lenp, + loff_t *ppos) +{ + struct edma_adapter *adapter; + struct edma_common_info *edma_cinfo; + int ret; + + if (!edma_netdev[2]) { + pr_err("Netdevice for Group 3 does not exist\n"); + return -1; + } + + adapter = netdev_priv(edma_netdev[2]); + edma_cinfo = adapter->edma_cinfo; + + ret = proc_dointvec(table, write, buffer, lenp, ppos); + + if (write) + adapter->default_vlan_tag = edma_default_group3_vtag; + + return ret; +} + +static int edma_change_group4_vtag(struct ctl_table *table, int write, + void __user *buffer, size_t *lenp, + loff_t *ppos) +{ + struct edma_adapter *adapter; + struct edma_common_info *edma_cinfo; + int ret; + + if (!edma_netdev[3]) { + pr_err("Netdevice for Group 4 does not exist\n"); + return -1; + } + + adapter = netdev_priv(edma_netdev[3]); + edma_cinfo = adapter->edma_cinfo; + + ret = proc_dointvec(table, write, buffer, lenp, ppos); + + if (write) + adapter->default_vlan_tag = edma_default_group4_vtag; + + return ret; +} + +static int edma_change_group5_vtag(struct ctl_table *table, int write, + void __user *buffer, size_t *lenp, + loff_t *ppos) +{ + struct edma_adapter *adapter; + struct edma_common_info *edma_cinfo; + int ret; + + if (!edma_netdev[4]) { + pr_err("Netdevice for Group 5 does not exist\n"); + return -1; + } + + adapter = netdev_priv(edma_netdev[4]); + edma_cinfo = adapter->edma_cinfo; + + ret = proc_dointvec(table, write, buffer, lenp, ppos); + + if (write) + adapter->default_vlan_tag = edma_default_group5_vtag; + + return ret; +} + +static int edma_set_rss_idt_value(struct ctl_table *table, int write, + void __user *buffer, size_t *lenp, + loff_t *ppos) +{ + int ret; + + ret = proc_dointvec(table, write, buffer, lenp, ppos); + if (write && !ret) + edma_write_reg(EDMA_REG_RSS_IDT(edma_rss_idt_idx), + edma_rss_idt_val); + return ret; +} + +static int edma_set_rss_idt_idx(struct ctl_table *table, int write, + void __user *buffer, size_t *lenp, + loff_t *ppos) +{ + int ret; + u32 old_value = edma_rss_idt_idx; + + ret = proc_dointvec(table, write, buffer, lenp, ppos); + if (!write || ret) + return ret; + + if (edma_rss_idt_idx >= EDMA_NUM_IDT) { + pr_err("Invalid RSS indirection table index %d\n", + edma_rss_idt_idx); + edma_rss_idt_idx = old_value; + return -EINVAL; + } + return ret; +} + +static int edma_weight_assigned_to_queues(struct ctl_table *table, int write, + void __user *buffer, size_t *lenp, + loff_t *ppos) +{ + int ret, queue_id, weight; + u32 reg_data, data, reg_addr; + + ret = proc_dointvec(table, write, buffer, lenp, ppos); + if (write) { + queue_id = edma_weight_assigned_to_q & EDMA_WRR_VID_SCTL_MASK; + if (queue_id < 0 || queue_id > 15) { + pr_err("queue_id not within desired range\n"); + return -EINVAL; + } + + weight = edma_weight_assigned_to_q >> EDMA_WRR_VID_SCTL_SHIFT; + if (weight < 0 || weight > 0xF) { + pr_err("queue_id not within desired range\n"); + return -EINVAL; + } + + data = weight << EDMA_WRR_SHIFT(queue_id); + + reg_addr = EDMA_REG_WRR_CTRL_Q0_Q3 + (queue_id & ~0x3); + edma_read_reg(reg_addr, ®_data); + reg_data &= ~(1 << EDMA_WRR_SHIFT(queue_id)); + edma_write_reg(reg_addr, data | reg_data); + } + + return ret; +} + +static int edma_queue_to_virtual_queue_map(struct ctl_table *table, int write, + void __user *buffer, size_t *lenp, + loff_t *ppos) +{ + int ret, queue_id, virtual_qid; + u32 reg_data, data, reg_addr; + + ret = proc_dointvec(table, write, buffer, lenp, ppos); + if (write) { + queue_id = edma_queue_to_virtual_q & EDMA_WRR_VID_SCTL_MASK; + if (queue_id < 0 || queue_id > 15) { + pr_err("queue_id not within desired range\n"); + return -EINVAL; + } + + virtual_qid = edma_queue_to_virtual_q >> + EDMA_WRR_VID_SCTL_SHIFT; + if (virtual_qid < 0 || virtual_qid > 8) { + pr_err("queue_id not within desired range\n"); + return -EINVAL; + } + + data = virtual_qid << EDMA_VQ_ID_SHIFT(queue_id); + + reg_addr = EDMA_REG_VQ_CTRL0 + (queue_id & ~0x3); + edma_read_reg(reg_addr, ®_data); + reg_data &= ~(1 << EDMA_VQ_ID_SHIFT(queue_id)); + edma_write_reg(reg_addr, data | reg_data); + } + + return ret; +} + +static struct ctl_table edma_table[] = { + { + .procname = "default_lan_tag", + .data = &edma_default_ltag, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = edma_change_default_lan_vlan + }, + { + .procname = "default_wan_tag", + .data = &edma_default_wtag, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = edma_change_default_wan_vlan + }, + { + .procname = "weight_assigned_to_queues", + .data = &edma_weight_assigned_to_q, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = edma_weight_assigned_to_queues + }, + { + .procname = "queue_to_virtual_queue_map", + .data = &edma_queue_to_virtual_q, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = edma_queue_to_virtual_queue_map + }, + { + .procname = "enable_stp_rstp", + .data = &edma_enable_rstp, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = edma_enable_stp_rstp + }, + { + .procname = "athr_hdr_eth_type", + .data = &edma_athr_hdr_eth_type, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = edma_ath_hdr_eth_type + }, + { + .procname = "default_group1_vlan_tag", + .data = &edma_default_group1_vtag, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = edma_change_group1_vtag + }, + { + .procname = "default_group2_vlan_tag", + .data = &edma_default_group2_vtag, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = edma_change_group2_vtag + }, + { + .procname = "default_group3_vlan_tag", + .data = &edma_default_group3_vtag, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = edma_change_group3_vtag + }, + { + .procname = "default_group4_vlan_tag", + .data = &edma_default_group4_vtag, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = edma_change_group4_vtag + }, + { + .procname = "default_group5_vlan_tag", + .data = &edma_default_group5_vtag, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = edma_change_group5_vtag + }, + { + .procname = "edma_rss_idt_value", + .data = &edma_rss_idt_val, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = edma_set_rss_idt_value + }, + { + .procname = "edma_rss_idt_idx", + .data = &edma_rss_idt_idx, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = edma_set_rss_idt_idx + }, + {} +}; + +static int ess_parse(struct edma_common_info *edma) +{ + struct device_node *switch_node; + int ret = -EINVAL; + + switch_node = of_find_node_by_name(NULL, "ess-switch"); + if (!switch_node) { + pr_err("cannot find ess-switch node\n"); + goto out; + } + + edma->ess_hw_addr = of_io_request_and_map(switch_node, + 0, KBUILD_MODNAME); + if (!edma->ess_hw_addr) { + pr_err("%s ioremap fail.", __func__); + goto out; + } + + edma->ess_clk = of_clk_get_by_name(switch_node, "ess_clk"); + ret = clk_prepare_enable(edma->ess_clk); +out: + of_node_put(switch_node); + return ret; +} + +/* edma_axi_netdev_ops + * Describe the operations supported by registered netdevices + * + * static const struct net_device_ops edma_axi_netdev_ops = { + * .ndo_open = edma_open, + * .ndo_stop = edma_close, + * .ndo_start_xmit = edma_xmit_frame, + * .ndo_set_mac_address = edma_set_mac_addr, + * } + */ +static const struct net_device_ops edma_axi_netdev_ops = { + .ndo_open = edma_open, + .ndo_stop = edma_close, + .ndo_start_xmit = edma_xmit, + .ndo_set_mac_address = edma_set_mac_addr, +#ifdef CONFIG_RFS_ACCEL + .ndo_rx_flow_steer = edma_rx_flow_steer, + .ndo_register_rfs_filter = edma_register_rfs_filter, + .ndo_get_default_vlan_tag = edma_get_default_vlan_tag, +#endif + .ndo_get_stats = edma_get_stats, +}; + +/* edma_axi_probe() + * Initialise an adapter identified by a platform_device structure. + * + * The OS initialization, configuring of the adapter private structure, + * and a hardware reset occur in the probe. + */ +static int edma_axi_probe(struct platform_device *pdev) +{ + struct edma_common_info *edma_cinfo; + struct edma_hw *hw; + struct edma_adapter *adapter[EDMA_MAX_PORTID_SUPPORTED]; + struct resource *res; + struct device_node *np = pdev->dev.of_node; + struct device_node *pnp; + struct device_node *mdio_node = NULL; + struct mii_bus *miibus = NULL; + int i, j, k, err = 0; + int portid_bmp; + int idx = 0, idx_mac = 0; + + if (CONFIG_NR_CPUS != EDMA_CPU_CORES_SUPPORTED) { + dev_err(&pdev->dev, "Invalid CPU Cores\n"); + return -EINVAL; + } + + if ((num_rxq != 4) && (num_rxq != 8)) { + dev_err(&pdev->dev, "Invalid RX queue, edma probe failed\n"); + return -EINVAL; + } + edma_cinfo = kzalloc(sizeof(struct edma_common_info), GFP_KERNEL); + if (!edma_cinfo) { + err = -ENOMEM; + goto err_alloc; + } + + edma_cinfo->pdev = pdev; + + of_property_read_u32(np, "qcom,num_gmac", &edma_cinfo->num_gmac); + if (edma_cinfo->num_gmac > EDMA_MAX_PORTID_SUPPORTED) { + pr_err("Invalid DTSI Entry for qcom,num_gmac\n"); + err = -EINVAL; + goto err_cinfo; + } + + /* Initialize the netdev array before allocation + * to avoid double free + */ + for (i = 0 ; i < edma_cinfo->num_gmac ; i++) + edma_netdev[i] = NULL; + + for (i = 0 ; i < edma_cinfo->num_gmac ; i++) { + edma_netdev[i] = alloc_etherdev_mqs(sizeof(struct edma_adapter), + EDMA_NETDEV_TX_QUEUE, EDMA_NETDEV_RX_QUEUE); + + if (!edma_netdev[i]) { + dev_err(&pdev->dev, + "net device alloc fails for index=%d\n", i); + err = -ENODEV; + goto err_ioremap; + } + + SET_NETDEV_DEV(edma_netdev[i], &pdev->dev); + platform_set_drvdata(pdev, edma_netdev[i]); + edma_cinfo->netdev[i] = edma_netdev[i]; + } + + /* Fill ring details */ + edma_cinfo->num_tx_queues = EDMA_MAX_TRANSMIT_QUEUE; + edma_cinfo->num_txq_per_core = (EDMA_MAX_TRANSMIT_QUEUE / 4); + edma_cinfo->tx_ring_count = EDMA_TX_RING_SIZE; + + /* Update num rx queues based on module parameter */ + edma_cinfo->num_rx_queues = num_rxq; + edma_cinfo->num_rxq_per_core = ((num_rxq == 4) ? 1 : 2); + + edma_cinfo->rx_ring_count = EDMA_RX_RING_SIZE; + + hw = &edma_cinfo->hw; + + /* Fill HW defaults */ + hw->tx_intr_mask = EDMA_TX_IMR_NORMAL_MASK; + hw->rx_intr_mask = EDMA_RX_IMR_NORMAL_MASK; + + of_property_read_u32(np, "qcom,page-mode", &edma_cinfo->page_mode); + of_property_read_u32(np, "qcom,rx_head_buf_size", + &hw->rx_head_buff_size); + + if (overwrite_mode) { + dev_info(&pdev->dev, "page mode overwritten"); + edma_cinfo->page_mode = page_mode; + } + + if (jumbo_mru) + edma_cinfo->fraglist_mode = 1; + + if (edma_cinfo->page_mode) + hw->rx_head_buff_size = EDMA_RX_HEAD_BUFF_SIZE_JUMBO; + else if (edma_cinfo->fraglist_mode) + hw->rx_head_buff_size = jumbo_mru; + else if (!hw->rx_head_buff_size) + hw->rx_head_buff_size = EDMA_RX_HEAD_BUFF_SIZE; + + hw->misc_intr_mask = 0; + hw->wol_intr_mask = 0; + + hw->intr_clear_type = EDMA_INTR_CLEAR_TYPE; + hw->intr_sw_idx_w = EDMA_INTR_SW_IDX_W_TYPE; + + /* configure RSS type to the different protocol that can be + * supported + */ + hw->rss_type = EDMA_RSS_TYPE_IPV4TCP | EDMA_RSS_TYPE_IPV6_TCP | + EDMA_RSS_TYPE_IPV4_UDP | EDMA_RSS_TYPE_IPV6UDP | + EDMA_RSS_TYPE_IPV4 | EDMA_RSS_TYPE_IPV6; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + + edma_cinfo->hw.hw_addr = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(edma_cinfo->hw.hw_addr)) { + err = PTR_ERR(edma_cinfo->hw.hw_addr); + goto err_ioremap; + } + + edma_hw_addr = (u32)edma_cinfo->hw.hw_addr; + + /* Parse tx queue interrupt number from device tree */ + for (i = 0; i < edma_cinfo->num_tx_queues; i++) + edma_cinfo->tx_irq[i] = platform_get_irq(pdev, i); + + /* Parse rx queue interrupt number from device tree + * Here we are setting j to point to the point where we + * left tx interrupt parsing(i.e 16) and run run the loop + * from 0 to 7 to parse rx interrupt number. + */ + for (i = 0, j = edma_cinfo->num_tx_queues, k = 0; + i < edma_cinfo->num_rx_queues; i++) { + edma_cinfo->rx_irq[k] = platform_get_irq(pdev, j); + k += ((num_rxq == 4) ? 2 : 1); + j += ((num_rxq == 4) ? 2 : 1); + } + + edma_cinfo->rx_head_buffer_len = edma_cinfo->hw.rx_head_buff_size; + edma_cinfo->rx_page_buffer_len = PAGE_SIZE; + + err = edma_alloc_queues_tx(edma_cinfo); + if (err) { + dev_err(&pdev->dev, "Allocation of TX queue failed\n"); + goto err_tx_qinit; + } + + err = edma_alloc_queues_rx(edma_cinfo); + if (err) { + dev_err(&pdev->dev, "Allocation of RX queue failed\n"); + goto err_rx_qinit; + } + + err = edma_alloc_tx_rings(edma_cinfo); + if (err) { + dev_err(&pdev->dev, "Allocation of TX resources failed\n"); + goto err_tx_rinit; + } + + err = edma_alloc_rx_rings(edma_cinfo); + if (err) { + dev_err(&pdev->dev, "Allocation of RX resources failed\n"); + goto err_rx_rinit; + } + + /* Initialize netdev and netdev bitmap for transmit descriptor rings */ + for (i = 0; i < edma_cinfo->num_tx_queues; i++) { + struct edma_tx_desc_ring *etdr = edma_cinfo->tpd_ring[i]; + int j; + + etdr->netdev_bmp = 0; + for (j = 0; j < EDMA_MAX_NETDEV_PER_QUEUE; j++) { + etdr->netdev[j] = NULL; + etdr->nq[j] = NULL; + } + } + + if (of_property_read_bool(np, "qcom,mdio_supported")) { + mdio_node = of_find_compatible_node(NULL, NULL, + "qcom,ipq4019-mdio"); + if (!mdio_node) { + dev_err(&pdev->dev, "cannot find mdio node by phandle"); + err = -EIO; + goto err_mdiobus_init_fail; + } + + miibus = of_mdio_find_bus(mdio_node); + if (!miibus) + return -EINVAL; + } + + if (of_property_read_bool(np, "qcom,single-phy") && + edma_cinfo->num_gmac == 1) { + err = ess_parse(edma_cinfo); + if (!err) + err = ess_reset(edma_cinfo); + if (err) + goto err_single_phy_init; + else + edma_cinfo->is_single_phy = true; + } + + for_each_available_child_of_node(np, pnp) { + const char *mac_addr; + + /* this check is needed if parent and daughter dts have + * different number of gmac nodes + */ + if (idx_mac == edma_cinfo->num_gmac) { + of_node_put(np); + break; + } + + mac_addr = of_get_mac_address(pnp); + if (!IS_ERR(mac_addr)) + memcpy(edma_netdev[idx_mac]->dev_addr, mac_addr, ETH_ALEN); + + idx_mac++; + } + + /* Populate the adapter structure register the netdevice */ + for (i = 0; i < edma_cinfo->num_gmac; i++) { + int k, m; + + adapter[i] = netdev_priv(edma_netdev[i]); + adapter[i]->netdev = edma_netdev[i]; + adapter[i]->pdev = pdev; + for (j = 0; j < CONFIG_NR_CPUS; j++) { + m = i % 2; + adapter[i]->tx_start_offset[j] = + ((j << EDMA_TX_CPU_START_SHIFT) + (m << 1)); + /* Share the queues with available net-devices. + * For instance , with 5 net-devices + * eth0/eth2/eth4 will share q0,q1,q4,q5,q8,q9,q12,q13 + * and eth1/eth3 will get the remaining. + */ + for (k = adapter[i]->tx_start_offset[j]; k < + (adapter[i]->tx_start_offset[j] + 2); k++) { + if (edma_fill_netdev(edma_cinfo, k, i, j)) { + pr_err("Netdev overflow Error\n"); + goto err_register; + } + } + } + + adapter[i]->edma_cinfo = edma_cinfo; + edma_netdev[i]->netdev_ops = &edma_axi_netdev_ops; + edma_netdev[i]->max_mtu = 9000; + edma_netdev[i]->features = NETIF_F_HW_CSUM | NETIF_F_RXCSUM + | NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_SG | + NETIF_F_TSO | NETIF_F_GRO; + edma_netdev[i]->hw_features = NETIF_F_HW_CSUM | NETIF_F_RXCSUM | + NETIF_F_HW_VLAN_CTAG_RX + | NETIF_F_SG | NETIF_F_TSO | NETIF_F_GRO; + edma_netdev[i]->vlan_features = NETIF_F_HW_CSUM | NETIF_F_SG | + NETIF_F_TSO | NETIF_F_GRO; + edma_netdev[i]->wanted_features = NETIF_F_HW_CSUM | NETIF_F_SG | + NETIF_F_TSO | NETIF_F_GRO; + + if (of_property_read_bool(np, "qcom,single-phy") && edma_cinfo->num_gmac == 1) + edma_netdev[i]->features |= NETIF_F_HW_VLAN_CTAG_TX; + +#ifdef CONFIG_RFS_ACCEL + edma_netdev[i]->features |= NETIF_F_NTUPLE; + edma_netdev[i]->hw_features |= NETIF_F_NTUPLE; + edma_netdev[i]->vlan_features |= NETIF_F_NTUPLE; + edma_netdev[i]->wanted_features |= NETIF_F_NTUPLE; + if (of_property_read_bool(np, "qcom,single-phy") && edma_cinfo->num_gmac == 1) { + edma_netdev[i]->features |= NETIF_F_RXHASH; + edma_netdev[i]->hw_features |= NETIF_F_RXHASH; + edma_netdev[i]->vlan_features |= NETIF_F_RXHASH; + edma_netdev[i]->wanted_features |= NETIF_F_RXHASH; + } +#endif + edma_set_ethtool_ops(edma_netdev[i]); + + /* This just fill in some default MAC address + */ + if (!is_valid_ether_addr(edma_netdev[i]->dev_addr)) { + random_ether_addr(edma_netdev[i]->dev_addr); + pr_info("EDMA using MAC@ - using"); + pr_info("%02x:%02x:%02x:%02x:%02x:%02x\n", + *(edma_netdev[i]->dev_addr), + *(edma_netdev[i]->dev_addr + 1), + *(edma_netdev[i]->dev_addr + 2), + *(edma_netdev[i]->dev_addr + 3), + *(edma_netdev[i]->dev_addr + 4), + *(edma_netdev[i]->dev_addr + 5)); + } + + err = register_netdev(edma_netdev[i]); + if (err) + goto err_register; + + /* carrier off reporting is important to + * ethtool even BEFORE open + */ + netif_carrier_off(edma_netdev[i]); + + /* Allocate reverse irq cpu mapping structure for + * receive queues + */ +#ifdef CONFIG_RFS_ACCEL + edma_netdev[i]->rx_cpu_rmap = + alloc_irq_cpu_rmap(EDMA_NETDEV_RX_QUEUE); + if (!edma_netdev[i]->rx_cpu_rmap) { + err = -ENOMEM; + goto err_rmap_alloc_fail; + } +#endif + } + + for (i = 0; i < EDMA_MAX_PORTID_BITMAP_INDEX; i++) + edma_cinfo->portid_netdev_lookup_tbl[i] = NULL; + + for_each_available_child_of_node(np, pnp) { + const uint32_t *vlan_tag = NULL; + int len; + + /* this check is needed if parent and daughter dts have + * different number of gmac nodes + */ + if (idx == edma_cinfo->num_gmac) + break; + + /* Populate port-id to netdev lookup table */ + vlan_tag = of_get_property(pnp, "vlan_tag", &len); + if (!vlan_tag) { + pr_err("Vlan tag parsing Failed.\n"); + goto err_rmap_alloc_fail; + } + + adapter[idx]->default_vlan_tag = of_read_number(vlan_tag, 1); + vlan_tag++; + portid_bmp = of_read_number(vlan_tag, 1); + adapter[idx]->dp_bitmap = portid_bmp; + + portid_bmp = portid_bmp >> 1; /* We ignore CPU Port bit 0 */ + while (portid_bmp) { + int port_bit = ffs(portid_bmp); + + if (port_bit > EDMA_MAX_PORTID_SUPPORTED) + goto err_rmap_alloc_fail; + edma_cinfo->portid_netdev_lookup_tbl[port_bit] = + edma_netdev[idx]; + portid_bmp &= ~(1 << (port_bit - 1)); + } + + if (!of_property_read_u32(pnp, "qcom,poll_required", + &adapter[idx]->poll_required)) { + if (adapter[idx]->poll_required) { + of_property_read_u32(pnp, "qcom,phy_mdio_addr", + &adapter[idx]->phy_mdio_addr); + of_property_read_u32(pnp, "qcom,forced_speed", + &adapter[idx]->forced_speed); + of_property_read_u32(pnp, "qcom,forced_duplex", + &adapter[idx]->forced_duplex); + + /* create a phyid using MDIO bus id + * and MDIO bus address + */ + snprintf(adapter[idx]->phy_id, + MII_BUS_ID_SIZE + 3, PHY_ID_FMT, + miibus->id, + adapter[idx]->phy_mdio_addr); + } + } else { + adapter[idx]->poll_required = 0; + adapter[idx]->forced_speed = SPEED_1000; + adapter[idx]->forced_duplex = DUPLEX_FULL; + } + + idx++; + } + + edma_cinfo->edma_ctl_table_hdr = register_net_sysctl(&init_net, + "net/edma", + edma_table); + if (!edma_cinfo->edma_ctl_table_hdr) { + dev_err(&pdev->dev, "edma sysctl table hdr not registered\n"); + goto err_unregister_sysctl_tbl; + } + + /* Disable all 16 Tx and 8 rx irqs */ + edma_irq_disable(edma_cinfo); + + err = edma_reset(edma_cinfo); + if (err) { + err = -EIO; + goto err_reset; + } + + /* populate per_core_info, do a napi_Add, request 16 TX irqs, + * 8 RX irqs, do a napi enable + */ + for (i = 0; i < CONFIG_NR_CPUS; i++) { + u8 rx_start; + + edma_cinfo->edma_percpu_info[i].napi.state = 0; + + netif_napi_add(edma_netdev[0], + &edma_cinfo->edma_percpu_info[i].napi, + edma_poll, 64); + napi_enable(&edma_cinfo->edma_percpu_info[i].napi); + edma_cinfo->edma_percpu_info[i].tx_mask = tx_mask[i]; + edma_cinfo->edma_percpu_info[i].rx_mask = EDMA_RX_PER_CPU_MASK + << (i << EDMA_RX_PER_CPU_MASK_SHIFT); + edma_cinfo->edma_percpu_info[i].tx_start = tx_start[i]; + edma_cinfo->edma_percpu_info[i].rx_start = + i << EDMA_RX_CPU_START_SHIFT; + rx_start = i << EDMA_RX_CPU_START_SHIFT; + edma_cinfo->edma_percpu_info[i].tx_status = 0; + edma_cinfo->edma_percpu_info[i].rx_status = 0; + edma_cinfo->edma_percpu_info[i].edma_cinfo = edma_cinfo; + + /* Request irq per core */ + for (j = edma_cinfo->edma_percpu_info[i].tx_start; + j < tx_start[i] + 4; j++) { + sprintf(&edma_tx_irq[j][0], "edma_eth_tx%d", j); + err = request_irq(edma_cinfo->tx_irq[j], + edma_interrupt, + 0, + &edma_tx_irq[j][0], + &edma_cinfo->edma_percpu_info[i]); + if (err) + goto err_reset; + } + + for (j = edma_cinfo->edma_percpu_info[i].rx_start; + j < (rx_start + + ((edma_cinfo->num_rx_queues == 4) ? 1 : 2)); + j++) { + sprintf(&edma_rx_irq[j][0], "edma_eth_rx%d", j); + err = request_irq(edma_cinfo->rx_irq[j], + edma_interrupt, + 0, + &edma_rx_irq[j][0], + &edma_cinfo->edma_percpu_info[i]); + if (err) + goto err_reset; + } + +#ifdef CONFIG_RFS_ACCEL + for (j = edma_cinfo->edma_percpu_info[i].rx_start; + j < rx_start + 2; j += 2) { + err = irq_cpu_rmap_add(edma_netdev[0]->rx_cpu_rmap, + edma_cinfo->rx_irq[j]); + if (err) + goto err_rmap_add_fail; + } +#endif + } + + /* Used to clear interrupt status, allocate rx buffer, + * configure edma descriptors registers + */ + err = edma_configure(edma_cinfo); + if (err) { + err = -EIO; + goto err_configure; + } + + /* Configure RSS indirection table. + * 128 hash will be configured in the following + * pattern: hash{0,1,2,3} = {Q0,Q2,Q4,Q6} respectively + * and so on + */ + for (i = 0; i < EDMA_NUM_IDT; i++) + edma_write_reg(EDMA_REG_RSS_IDT(i), EDMA_RSS_IDT_VALUE); + + /* Configure load balance mapping table. + * 4 table entry will be configured according to the + * following pattern: load_balance{0,1,2,3} = {Q0,Q1,Q3,Q4} + * respectively. + */ + edma_write_reg(EDMA_REG_LB_RING, EDMA_LB_REG_VALUE); + + /* Configure Virtual queue for Tx rings + * User can also change this value runtime through + * a sysctl + */ + edma_write_reg(EDMA_REG_VQ_CTRL0, EDMA_VQ_REG_VALUE); + edma_write_reg(EDMA_REG_VQ_CTRL1, EDMA_VQ_REG_VALUE); + + /* Configure Max AXI Burst write size to 128 bytes*/ + edma_write_reg(EDMA_REG_AXIW_CTRL_MAXWRSIZE, + EDMA_AXIW_MAXWRSIZE_VALUE); + + /* Enable All 16 tx and 8 rx irq mask */ + edma_irq_enable(edma_cinfo); + edma_enable_tx_ctrl(&edma_cinfo->hw); + edma_enable_rx_ctrl(&edma_cinfo->hw); + + for (i = 0; i < edma_cinfo->num_gmac; i++) { + if (adapter[i]->poll_required) { + int phy_mode = of_get_phy_mode(np); + + if (phy_mode < 0) + phy_mode = PHY_INTERFACE_MODE_SGMII; + adapter[i]->phydev = + phy_connect(edma_netdev[i], + (const char *)adapter[i]->phy_id, + &edma_adjust_link, + phy_mode); + if (IS_ERR(adapter[i]->phydev)) { + dev_dbg(&pdev->dev, "PHY attach FAIL"); + err = -EIO; + goto edma_phy_attach_fail; + } else { + linkmode_set_bit(ETHTOOL_LINK_MODE_Pause_BIT, + adapter[i]->phydev->advertising); + linkmode_set_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, + adapter[i]->phydev->advertising); + linkmode_set_bit(ETHTOOL_LINK_MODE_Pause_BIT, + adapter[i]->phydev->supported); + linkmode_set_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, + adapter[i]->phydev->supported); + } + } else { + adapter[i]->phydev = NULL; + } + } + + spin_lock_init(&edma_cinfo->stats_lock); + + timer_setup(&edma_cinfo->edma_stats_timer, edma_statistics_timer, 0); + mod_timer(&edma_cinfo->edma_stats_timer, jiffies + 1*HZ); + + return 0; + +edma_phy_attach_fail: + miibus = NULL; +err_configure: +#ifdef CONFIG_RFS_ACCEL + for (i = 0; i < edma_cinfo->num_gmac; i++) { + free_irq_cpu_rmap(adapter[i]->netdev->rx_cpu_rmap); + adapter[i]->netdev->rx_cpu_rmap = NULL; + } +#endif +err_rmap_add_fail: + edma_free_irqs(adapter[0]); + for (i = 0; i < CONFIG_NR_CPUS; i++) + napi_disable(&edma_cinfo->edma_percpu_info[i].napi); +err_reset: +err_unregister_sysctl_tbl: +err_rmap_alloc_fail: + for (i = 0; i < edma_cinfo->num_gmac; i++) + unregister_netdev(edma_netdev[i]); +err_register: +err_single_phy_init: + iounmap(edma_cinfo->ess_hw_addr); + clk_disable_unprepare(edma_cinfo->ess_clk); +err_mdiobus_init_fail: + edma_free_rx_rings(edma_cinfo); +err_rx_rinit: + edma_free_tx_rings(edma_cinfo); +err_tx_rinit: + edma_free_queues(edma_cinfo); +err_rx_qinit: +err_tx_qinit: + iounmap(edma_cinfo->hw.hw_addr); +err_ioremap: + for (i = 0; i < edma_cinfo->num_gmac; i++) { + if (edma_netdev[i]) + free_netdev(edma_netdev[i]); + } +err_cinfo: + kfree(edma_cinfo); +err_alloc: + return err; +} + +/* edma_axi_remove() + * Device Removal Routine + * + * edma_axi_remove is called by the platform subsystem to alert the driver + * that it should release a platform device. + */ +static int edma_axi_remove(struct platform_device *pdev) +{ + struct edma_adapter *adapter = netdev_priv(edma_netdev[0]); + struct edma_common_info *edma_cinfo = adapter->edma_cinfo; + struct edma_hw *hw = &edma_cinfo->hw; + int i; + + for (i = 0; i < edma_cinfo->num_gmac; i++) + unregister_netdev(edma_netdev[i]); + + edma_stop_rx_tx(hw); + for (i = 0; i < CONFIG_NR_CPUS; i++) + napi_disable(&edma_cinfo->edma_percpu_info[i].napi); + + edma_irq_disable(edma_cinfo); + edma_write_reg(EDMA_REG_RX_ISR, 0xff); + edma_write_reg(EDMA_REG_TX_ISR, 0xffff); +#ifdef CONFIG_RFS_ACCEL + for (i = 0; i < edma_cinfo->num_gmac; i++) { + free_irq_cpu_rmap(edma_netdev[i]->rx_cpu_rmap); + edma_netdev[i]->rx_cpu_rmap = NULL; + } +#endif + + for (i = 0; i < edma_cinfo->num_gmac; i++) { + struct edma_adapter *adapter = netdev_priv(edma_netdev[i]); + + if (adapter->phydev) + phy_disconnect(adapter->phydev); + } + + del_timer_sync(&edma_cinfo->edma_stats_timer); + edma_free_irqs(adapter); + unregister_net_sysctl_table(edma_cinfo->edma_ctl_table_hdr); + iounmap(edma_cinfo->ess_hw_addr); + clk_disable_unprepare(edma_cinfo->ess_clk); + edma_free_tx_resources(edma_cinfo); + edma_free_rx_resources(edma_cinfo); + edma_free_tx_rings(edma_cinfo); + edma_free_rx_rings(edma_cinfo); + edma_free_queues(edma_cinfo); + for (i = 0; i < edma_cinfo->num_gmac; i++) + free_netdev(edma_netdev[i]); + + kfree(edma_cinfo); + + return 0; +} + +static const struct of_device_id edma_of_mtable[] = { + {.compatible = "qcom,ess-edma" }, + {} +}; +MODULE_DEVICE_TABLE(of, edma_of_mtable); + +static struct platform_driver edma_axi_driver = { + .driver = { + .name = edma_axi_driver_name, + .of_match_table = edma_of_mtable, + }, + .probe = edma_axi_probe, + .remove = edma_axi_remove, +}; + +module_platform_driver(edma_axi_driver); + +MODULE_AUTHOR("Qualcomm Atheros Inc"); +MODULE_DESCRIPTION("QCA ESS EDMA driver"); +MODULE_LICENSE("GPL"); diff --git a/feeds/ipq40xx/ipq40xx/files/drivers/net/ethernet/qualcomm/essedma/edma_ethtool.c b/feeds/ipq40xx/ipq40xx/files/drivers/net/ethernet/qualcomm/essedma/edma_ethtool.c new file mode 100644 index 000000000..ac5cb5096 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/files/drivers/net/ethernet/qualcomm/essedma/edma_ethtool.c @@ -0,0 +1,334 @@ +/* + * Copyright (c) 2015 - 2016, The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all copies. + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include "edma.h" + +struct edma_ethtool_stats { + uint8_t stat_string[ETH_GSTRING_LEN]; + uint32_t stat_offset; +}; + +#define EDMA_STAT(m) offsetof(struct edma_ethtool_statistics, m) +#define DRVINFO_LEN 32 + +/* Array of strings describing statistics + */ +static const struct edma_ethtool_stats edma_gstrings_stats[] = { + {"tx_q0_pkt", EDMA_STAT(tx_q0_pkt)}, + {"tx_q1_pkt", EDMA_STAT(tx_q1_pkt)}, + {"tx_q2_pkt", EDMA_STAT(tx_q2_pkt)}, + {"tx_q3_pkt", EDMA_STAT(tx_q3_pkt)}, + {"tx_q4_pkt", EDMA_STAT(tx_q4_pkt)}, + {"tx_q5_pkt", EDMA_STAT(tx_q5_pkt)}, + {"tx_q6_pkt", EDMA_STAT(tx_q6_pkt)}, + {"tx_q7_pkt", EDMA_STAT(tx_q7_pkt)}, + {"tx_q8_pkt", EDMA_STAT(tx_q8_pkt)}, + {"tx_q9_pkt", EDMA_STAT(tx_q9_pkt)}, + {"tx_q10_pkt", EDMA_STAT(tx_q10_pkt)}, + {"tx_q11_pkt", EDMA_STAT(tx_q11_pkt)}, + {"tx_q12_pkt", EDMA_STAT(tx_q12_pkt)}, + {"tx_q13_pkt", EDMA_STAT(tx_q13_pkt)}, + {"tx_q14_pkt", EDMA_STAT(tx_q14_pkt)}, + {"tx_q15_pkt", EDMA_STAT(tx_q15_pkt)}, + {"tx_q0_byte", EDMA_STAT(tx_q0_byte)}, + {"tx_q1_byte", EDMA_STAT(tx_q1_byte)}, + {"tx_q2_byte", EDMA_STAT(tx_q2_byte)}, + {"tx_q3_byte", EDMA_STAT(tx_q3_byte)}, + {"tx_q4_byte", EDMA_STAT(tx_q4_byte)}, + {"tx_q5_byte", EDMA_STAT(tx_q5_byte)}, + {"tx_q6_byte", EDMA_STAT(tx_q6_byte)}, + {"tx_q7_byte", EDMA_STAT(tx_q7_byte)}, + {"tx_q8_byte", EDMA_STAT(tx_q8_byte)}, + {"tx_q9_byte", EDMA_STAT(tx_q9_byte)}, + {"tx_q10_byte", EDMA_STAT(tx_q10_byte)}, + {"tx_q11_byte", EDMA_STAT(tx_q11_byte)}, + {"tx_q12_byte", EDMA_STAT(tx_q12_byte)}, + {"tx_q13_byte", EDMA_STAT(tx_q13_byte)}, + {"tx_q14_byte", EDMA_STAT(tx_q14_byte)}, + {"tx_q15_byte", EDMA_STAT(tx_q15_byte)}, + {"rx_q0_pkt", EDMA_STAT(rx_q0_pkt)}, + {"rx_q1_pkt", EDMA_STAT(rx_q1_pkt)}, + {"rx_q2_pkt", EDMA_STAT(rx_q2_pkt)}, + {"rx_q3_pkt", EDMA_STAT(rx_q3_pkt)}, + {"rx_q4_pkt", EDMA_STAT(rx_q4_pkt)}, + {"rx_q5_pkt", EDMA_STAT(rx_q5_pkt)}, + {"rx_q6_pkt", EDMA_STAT(rx_q6_pkt)}, + {"rx_q7_pkt", EDMA_STAT(rx_q7_pkt)}, + {"rx_q0_byte", EDMA_STAT(rx_q0_byte)}, + {"rx_q1_byte", EDMA_STAT(rx_q1_byte)}, + {"rx_q2_byte", EDMA_STAT(rx_q2_byte)}, + {"rx_q3_byte", EDMA_STAT(rx_q3_byte)}, + {"rx_q4_byte", EDMA_STAT(rx_q4_byte)}, + {"rx_q5_byte", EDMA_STAT(rx_q5_byte)}, + {"rx_q6_byte", EDMA_STAT(rx_q6_byte)}, + {"rx_q7_byte", EDMA_STAT(rx_q7_byte)}, + {"tx_desc_error", EDMA_STAT(tx_desc_error)}, + {"rx_alloc_fail_ctr", EDMA_STAT(rx_alloc_fail_ctr)}, +}; + +#define EDMA_STATS_LEN ARRAY_SIZE(edma_gstrings_stats) + +/* edma_get_strset_count() + * Get strset count + */ +static int edma_get_strset_count(struct net_device *netdev, + int sset) +{ + switch (sset) { + case ETH_SS_STATS: + return EDMA_STATS_LEN; + default: + netdev_dbg(netdev, "%s: Invalid string set", __func__); + return -EOPNOTSUPP; + } +} + + +/* edma_get_strings() + * get stats string + */ +static void edma_get_strings(struct net_device *netdev, uint32_t stringset, + uint8_t *data) +{ + uint8_t *p = data; + uint32_t i; + + switch (stringset) { + case ETH_SS_STATS: + for (i = 0; i < EDMA_STATS_LEN; i++) { + memcpy(p, edma_gstrings_stats[i].stat_string, + min((size_t)ETH_GSTRING_LEN, + strlen(edma_gstrings_stats[i].stat_string) + + 1)); + p += ETH_GSTRING_LEN; + } + break; + } +} + +/* edma_get_ethtool_stats() + * Get ethtool statistics + */ +static void edma_get_ethtool_stats(struct net_device *netdev, + struct ethtool_stats *stats, uint64_t *data) +{ + struct edma_adapter *adapter = netdev_priv(netdev); + struct edma_common_info *edma_cinfo = adapter->edma_cinfo; + int i; + uint8_t *p = NULL; + + edma_read_append_stats(edma_cinfo); + + for(i = 0; i < EDMA_STATS_LEN; i++) { + p = (uint8_t *)&(edma_cinfo->edma_ethstats) + + edma_gstrings_stats[i].stat_offset; + data[i] = *(uint32_t *)p; + } +} + +/* edma_get_drvinfo() + * get edma driver info + */ +static void edma_get_drvinfo(struct net_device *dev, + struct ethtool_drvinfo *info) +{ + strlcpy(info->driver, "ess_edma", DRVINFO_LEN); + strlcpy(info->bus_info, "axi", ETHTOOL_BUSINFO_LEN); +} + +/* edma_nway_reset() + * Reset the phy, if available. + */ +static int edma_nway_reset(struct net_device *netdev) +{ + return -EINVAL; +} + +/* edma_get_wol() + * get wake on lan info + */ +static void edma_get_wol(struct net_device *netdev, + struct ethtool_wolinfo *wol) +{ + wol->supported = 0; + wol->wolopts = 0; +} + +/* edma_get_msglevel() + * get message level. + */ +static uint32_t edma_get_msglevel(struct net_device *netdev) +{ + return 0; +} + +/* edma_get_settings() + * Get edma settings + */ +static int edma_get_settings(struct net_device *netdev, + struct ethtool_link_ksettings *cmd) +{ + struct edma_adapter *adapter = netdev_priv(netdev); + + if (adapter->poll_required) { + if ((adapter->forced_speed != SPEED_UNKNOWN) + && !(adapter->poll_required)) + return -EPERM; + + phy_ethtool_ksettings_get(adapter->phydev, cmd); + if (linkmode_test_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, adapter->phydev->advertising)) + cmd->base.port = PORT_FIBRE; + else + cmd->base.port = PORT_TP; + } else { + /* If the speed/duplex for this GMAC is forced and we + * are not polling for link state changes, return the + * values as specified by platform. This will be true + * for GMACs connected to switch, and interfaces that + * do not use a PHY. + */ + if (!(adapter->poll_required)) { + if (adapter->forced_speed != SPEED_UNKNOWN) { + /* set speed and duplex */ + cmd->base.speed = SPEED_1000; + cmd->base.duplex = DUPLEX_FULL; + + /* Populate capabilities advertised by self */ + linkmode_zero(cmd->link_modes.advertising); + cmd->base.autoneg = 0; + cmd->base.port = PORT_TP; + cmd->base.transceiver = XCVR_EXTERNAL; + } else { + /* non link polled and non + * forced speed/duplex interface + */ + return -EIO; + } + } + } + + return 0; +} + +/* edma_set_settings() + * Set EDMA settings + */ +static int edma_set_settings(struct net_device *netdev, + const struct ethtool_link_ksettings *cmd) +{ + struct edma_adapter *adapter = netdev_priv(netdev); + + if ((adapter->forced_speed != SPEED_UNKNOWN) && + !adapter->poll_required) + return -EPERM; + + return phy_ethtool_ksettings_set(adapter->phydev, cmd); +} + +/* edma_get_coalesce + * get interrupt mitigation + */ +static int edma_get_coalesce(struct net_device *netdev, + struct ethtool_coalesce *ec) +{ + u32 reg_val; + + edma_get_tx_rx_coalesce(®_val); + + /* We read the Interrupt Moderation Timer(IMT) register value, + * use lower 16 bit for rx and higher 16 bit for Tx. We do a + * left shift by 1, because IMT resolution timer is 2usecs. + * Hence the value given by the register is multiplied by 2 to + * get the actual time in usecs. + */ + ec->tx_coalesce_usecs = (((reg_val >> 16) & 0xffff) << 1); + ec->rx_coalesce_usecs = ((reg_val & 0xffff) << 1); + + return 0; +} + +/* edma_set_coalesce + * set interrupt mitigation + */ +static int edma_set_coalesce(struct net_device *netdev, + struct ethtool_coalesce *ec) +{ + if (ec->tx_coalesce_usecs) + edma_change_tx_coalesce(ec->tx_coalesce_usecs); + if (ec->rx_coalesce_usecs) + edma_change_rx_coalesce(ec->rx_coalesce_usecs); + + return 0; +} + +/* edma_set_priv_flags() + * Set EDMA private flags + */ +static int edma_set_priv_flags(struct net_device *netdev, u32 flags) +{ + return 0; +} + +/* edma_get_priv_flags() + * get edma driver flags + */ +static u32 edma_get_priv_flags(struct net_device *netdev) +{ + return 0; +} + +/* edma_get_ringparam() + * get ring size + */ +static void edma_get_ringparam(struct net_device *netdev, + struct ethtool_ringparam *ring) +{ + struct edma_adapter *adapter = netdev_priv(netdev); + struct edma_common_info *edma_cinfo = adapter->edma_cinfo; + + ring->tx_max_pending = edma_cinfo->tx_ring_count; + ring->rx_max_pending = edma_cinfo->rx_ring_count; +} + +/* Ethtool operations + */ +static const struct ethtool_ops edma_ethtool_ops = { + .get_drvinfo = &edma_get_drvinfo, + .get_link = ðtool_op_get_link, + .get_msglevel = &edma_get_msglevel, + .nway_reset = &edma_nway_reset, + .get_wol = &edma_get_wol, + .get_link_ksettings = &edma_get_settings, + .set_link_ksettings = &edma_set_settings, + .get_strings = &edma_get_strings, + .get_sset_count = &edma_get_strset_count, + .get_ethtool_stats = &edma_get_ethtool_stats, + .get_coalesce = &edma_get_coalesce, + .set_coalesce = &edma_set_coalesce, + .get_priv_flags = edma_get_priv_flags, + .set_priv_flags = edma_set_priv_flags, + .get_ringparam = edma_get_ringparam, +}; + +/* edma_set_ethtool_ops + * Set ethtool operations + */ +void edma_set_ethtool_ops(struct net_device *netdev) +{ + netdev->ethtool_ops = &edma_ethtool_ops; +} diff --git a/feeds/ipq40xx/ipq40xx/files/drivers/net/ethernet/qualcomm/essedma/ess_edma.h b/feeds/ipq40xx/ipq40xx/files/drivers/net/ethernet/qualcomm/essedma/ess_edma.h new file mode 100644 index 000000000..021be98a3 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/files/drivers/net/ethernet/qualcomm/essedma/ess_edma.h @@ -0,0 +1,389 @@ +/* + * Copyright (c) 2014 - 2016, 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 _ESS_EDMA_H_ +#define _ESS_EDMA_H_ + +#include + +struct edma_adapter; +struct edma_hw; + +/* register definition */ +#define EDMA_REG_MAS_CTRL 0x0 +#define EDMA_REG_TIMEOUT_CTRL 0x004 +#define EDMA_REG_DBG0 0x008 +#define EDMA_REG_DBG1 0x00C +#define EDMA_REG_SW_CTRL0 0x100 +#define EDMA_REG_SW_CTRL1 0x104 + +/* Interrupt Status Register */ +#define EDMA_REG_RX_ISR 0x200 +#define EDMA_REG_TX_ISR 0x208 +#define EDMA_REG_MISC_ISR 0x210 +#define EDMA_REG_WOL_ISR 0x218 + +#define EDMA_MISC_ISR_RX_URG_Q(x) (1 << x) + +#define EDMA_MISC_ISR_AXIR_TIMEOUT 0x00000100 +#define EDMA_MISC_ISR_AXIR_ERR 0x00000200 +#define EDMA_MISC_ISR_TXF_DEAD 0x00000400 +#define EDMA_MISC_ISR_AXIW_ERR 0x00000800 +#define EDMA_MISC_ISR_AXIW_TIMEOUT 0x00001000 + +#define EDMA_WOL_ISR 0x00000001 + +/* Interrupt Mask Register */ +#define EDMA_REG_MISC_IMR 0x214 +#define EDMA_REG_WOL_IMR 0x218 + +#define EDMA_RX_IMR_NORMAL_MASK 0x1 +#define EDMA_TX_IMR_NORMAL_MASK 0x1 +#define EDMA_MISC_IMR_NORMAL_MASK 0x80001FFF +#define EDMA_WOL_IMR_NORMAL_MASK 0x1 + +/* Edma receive consumer index */ +#define EDMA_REG_RX_SW_CONS_IDX_Q(x) (0x220 + ((x) << 2)) /* x is the queue id */ +/* Edma transmit consumer index */ +#define EDMA_REG_TX_SW_CONS_IDX_Q(x) (0x240 + ((x) << 2)) /* x is the queue id */ + +/* IRQ Moderator Initial Timer Register */ +#define EDMA_REG_IRQ_MODRT_TIMER_INIT 0x280 +#define EDMA_IRQ_MODRT_TIMER_MASK 0xFFFF +#define EDMA_IRQ_MODRT_RX_TIMER_SHIFT 0 +#define EDMA_IRQ_MODRT_TX_TIMER_SHIFT 16 + +/* Interrupt Control Register */ +#define EDMA_REG_INTR_CTRL 0x284 +#define EDMA_INTR_CLR_TYP_SHIFT 0 +#define EDMA_INTR_SW_IDX_W_TYP_SHIFT 1 +#define EDMA_INTR_CLEAR_TYPE_W1 0 +#define EDMA_INTR_CLEAR_TYPE_R 1 + +/* RX Interrupt Mask Register */ +#define EDMA_REG_RX_INT_MASK_Q(x) (0x300 + ((x) << 2)) /* x = queue id */ + +/* TX Interrupt mask register */ +#define EDMA_REG_TX_INT_MASK_Q(x) (0x340 + ((x) << 2)) /* x = queue id */ + +/* Load Ptr Register + * Software sets this bit after the initialization of the head and tail + */ +#define EDMA_REG_TX_SRAM_PART 0x400 +#define EDMA_LOAD_PTR_SHIFT 16 + +/* TXQ Control Register */ +#define EDMA_REG_TXQ_CTRL 0x404 +#define EDMA_TXQ_CTRL_IP_OPTION_EN 0x10 +#define EDMA_TXQ_CTRL_TXQ_EN 0x20 +#define EDMA_TXQ_CTRL_ENH_MODE 0x40 +#define EDMA_TXQ_CTRL_LS_8023_EN 0x80 +#define EDMA_TXQ_CTRL_TPD_BURST_EN 0x100 +#define EDMA_TXQ_CTRL_LSO_BREAK_EN 0x200 +#define EDMA_TXQ_NUM_TPD_BURST_MASK 0xF +#define EDMA_TXQ_TXF_BURST_NUM_MASK 0xFFFF +#define EDMA_TXQ_NUM_TPD_BURST_SHIFT 0 +#define EDMA_TXQ_TXF_BURST_NUM_SHIFT 16 + +#define EDMA_REG_TXF_WATER_MARK 0x408 /* In 8-bytes */ +#define EDMA_TXF_WATER_MARK_MASK 0x0FFF +#define EDMA_TXF_LOW_WATER_MARK_SHIFT 0 +#define EDMA_TXF_HIGH_WATER_MARK_SHIFT 16 +#define EDMA_TXQ_CTRL_BURST_MODE_EN 0x80000000 + +/* WRR Control Register */ +#define EDMA_REG_WRR_CTRL_Q0_Q3 0x40c +#define EDMA_REG_WRR_CTRL_Q4_Q7 0x410 +#define EDMA_REG_WRR_CTRL_Q8_Q11 0x414 +#define EDMA_REG_WRR_CTRL_Q12_Q15 0x418 + +/* Weight round robin(WRR), it takes queue as input, and computes + * starting bits where we need to write the weight for a particular + * queue + */ +#define EDMA_WRR_SHIFT(x) (((x) * 5) % 20) + +/* Tx Descriptor Control Register */ +#define EDMA_REG_TPD_RING_SIZE 0x41C +#define EDMA_TPD_RING_SIZE_SHIFT 0 +#define EDMA_TPD_RING_SIZE_MASK 0xFFFF + +/* Transmit descriptor base address */ +#define EDMA_REG_TPD_BASE_ADDR_Q(x) (0x420 + ((x) << 2)) /* x = queue id */ + +/* TPD Index Register */ +#define EDMA_REG_TPD_IDX_Q(x) (0x460 + ((x) << 2)) /* x = queue id */ + +#define EDMA_TPD_PROD_IDX_BITS 0x0000FFFF +#define EDMA_TPD_CONS_IDX_BITS 0xFFFF0000 +#define EDMA_TPD_PROD_IDX_MASK 0xFFFF +#define EDMA_TPD_CONS_IDX_MASK 0xFFFF +#define EDMA_TPD_PROD_IDX_SHIFT 0 +#define EDMA_TPD_CONS_IDX_SHIFT 16 + +/* TX Virtual Queue Mapping Control Register */ +#define EDMA_REG_VQ_CTRL0 0x4A0 +#define EDMA_REG_VQ_CTRL1 0x4A4 + +/* Virtual QID shift, it takes queue as input, and computes + * Virtual QID position in virtual qid control register + */ +#define EDMA_VQ_ID_SHIFT(i) (((i) * 3) % 24) + +/* Virtual Queue Default Value */ +#define EDMA_VQ_REG_VALUE 0x240240 + +/* Tx side Port Interface Control Register */ +#define EDMA_REG_PORT_CTRL 0x4A8 +#define EDMA_PAD_EN_SHIFT 15 + +/* Tx side VLAN Configuration Register */ +#define EDMA_REG_VLAN_CFG 0x4AC + +#define EDMA_TX_CVLAN 16 +#define EDMA_TX_INS_CVLAN 17 +#define EDMA_TX_CVLAN_TAG_SHIFT 0 + +#define EDMA_TX_SVLAN 14 +#define EDMA_TX_INS_SVLAN 15 +#define EDMA_TX_SVLAN_TAG_SHIFT 16 + +/* Tx Queue Packet Statistic Register */ +#define EDMA_REG_TX_STAT_PKT_Q(x) (0x700 + ((x) << 3)) /* x = queue id */ + +#define EDMA_TX_STAT_PKT_MASK 0xFFFFFF + +/* Tx Queue Byte Statistic Register */ +#define EDMA_REG_TX_STAT_BYTE_Q(x) (0x704 + ((x) << 3)) /* x = queue id */ + +/* Load Balance Based Ring Offset Register */ +#define EDMA_REG_LB_RING 0x800 +#define EDMA_LB_RING_ENTRY_MASK 0xff +#define EDMA_LB_RING_ID_MASK 0x7 +#define EDMA_LB_RING_PROFILE_ID_MASK 0x3 +#define EDMA_LB_RING_ENTRY_BIT_OFFSET 8 +#define EDMA_LB_RING_ID_OFFSET 0 +#define EDMA_LB_RING_PROFILE_ID_OFFSET 3 +#define EDMA_LB_REG_VALUE 0x6040200 + +/* Load Balance Priority Mapping Register */ +#define EDMA_REG_LB_PRI_START 0x804 +#define EDMA_REG_LB_PRI_END 0x810 +#define EDMA_LB_PRI_REG_INC 4 +#define EDMA_LB_PRI_ENTRY_BIT_OFFSET 4 +#define EDMA_LB_PRI_ENTRY_MASK 0xf + +/* RSS Priority Mapping Register */ +#define EDMA_REG_RSS_PRI 0x820 +#define EDMA_RSS_PRI_ENTRY_MASK 0xf +#define EDMA_RSS_RING_ID_MASK 0x7 +#define EDMA_RSS_PRI_ENTRY_BIT_OFFSET 4 + +/* RSS Indirection Register */ +#define EDMA_REG_RSS_IDT(x) (0x840 + ((x) << 2)) /* x = No. of indirection table */ +#define EDMA_NUM_IDT 16 +#define EDMA_RSS_IDT_VALUE 0x64206420 + +/* Default RSS Ring Register */ +#define EDMA_REG_DEF_RSS 0x890 +#define EDMA_DEF_RSS_MASK 0x7 + +/* RSS Hash Function Type Register */ +#define EDMA_REG_RSS_TYPE 0x894 +#define EDMA_RSS_TYPE_NONE 0x01 +#define EDMA_RSS_TYPE_IPV4TCP 0x02 +#define EDMA_RSS_TYPE_IPV6_TCP 0x04 +#define EDMA_RSS_TYPE_IPV4_UDP 0x08 +#define EDMA_RSS_TYPE_IPV6UDP 0x10 +#define EDMA_RSS_TYPE_IPV4 0x20 +#define EDMA_RSS_TYPE_IPV6 0x40 +#define EDMA_RSS_HASH_MODE_MASK 0x7f + +#define EDMA_REG_RSS_HASH_VALUE 0x8C0 + +#define EDMA_REG_RSS_TYPE_RESULT 0x8C4 + +#define EDMA_HASH_TYPE_START 0 +#define EDMA_HASH_TYPE_END 5 +#define EDMA_HASH_TYPE_SHIFT 12 + +#define EDMA_RFS_FLOW_ENTRIES 1024 +#define EDMA_RFS_FLOW_ENTRIES_MASK (EDMA_RFS_FLOW_ENTRIES - 1) +#define EDMA_RFS_EXPIRE_COUNT_PER_CALL 128 + +/* RFD Base Address Register */ +#define EDMA_REG_RFD_BASE_ADDR_Q(x) (0x950 + ((x) << 2)) /* x = queue id */ + +/* RFD Index Register */ +#define EDMA_REG_RFD_IDX_Q(x) (0x9B0 + ((x) << 2)) + +#define EDMA_RFD_PROD_IDX_BITS 0x00000FFF +#define EDMA_RFD_CONS_IDX_BITS 0x0FFF0000 +#define EDMA_RFD_PROD_IDX_MASK 0xFFF +#define EDMA_RFD_CONS_IDX_MASK 0xFFF +#define EDMA_RFD_PROD_IDX_SHIFT 0 +#define EDMA_RFD_CONS_IDX_SHIFT 16 + +/* Rx Descriptor Control Register */ +#define EDMA_REG_RX_DESC0 0xA10 +#define EDMA_RFD_RING_SIZE_MASK 0xFFF +#define EDMA_RX_BUF_SIZE_MASK 0xFFFF +#define EDMA_RFD_RING_SIZE_SHIFT 0 +#define EDMA_RX_BUF_SIZE_SHIFT 16 + +#define EDMA_REG_RX_DESC1 0xA14 +#define EDMA_RXQ_RFD_BURST_NUM_MASK 0x3F +#define EDMA_RXQ_RFD_PF_THRESH_MASK 0x1F +#define EDMA_RXQ_RFD_LOW_THRESH_MASK 0xFFF +#define EDMA_RXQ_RFD_BURST_NUM_SHIFT 0 +#define EDMA_RXQ_RFD_PF_THRESH_SHIFT 8 +#define EDMA_RXQ_RFD_LOW_THRESH_SHIFT 16 + +/* RXQ Control Register */ +#define EDMA_REG_RXQ_CTRL 0xA18 +#define EDMA_FIFO_THRESH_TYPE_SHIF 0 +#define EDMA_FIFO_THRESH_128_BYTE 0x0 +#define EDMA_FIFO_THRESH_64_BYTE 0x1 +#define EDMA_RXQ_CTRL_RMV_VLAN 0x00000002 +#define EDMA_RXQ_CTRL_EN 0x0000FF00 + +/* AXI Burst Size Config */ +#define EDMA_REG_AXIW_CTRL_MAXWRSIZE 0xA1C +#define EDMA_AXIW_MAXWRSIZE_VALUE 0x0 + +/* Rx Statistics Register */ +#define EDMA_REG_RX_STAT_BYTE_Q(x) (0xA30 + ((x) << 2)) /* x = queue id */ +#define EDMA_REG_RX_STAT_PKT_Q(x) (0xA50 + ((x) << 2)) /* x = queue id */ + +/* WoL Pattern Length Register */ +#define EDMA_REG_WOL_PATTERN_LEN0 0xC00 +#define EDMA_WOL_PT_LEN_MASK 0xFF +#define EDMA_WOL_PT0_LEN_SHIFT 0 +#define EDMA_WOL_PT1_LEN_SHIFT 8 +#define EDMA_WOL_PT2_LEN_SHIFT 16 +#define EDMA_WOL_PT3_LEN_SHIFT 24 + +#define EDMA_REG_WOL_PATTERN_LEN1 0xC04 +#define EDMA_WOL_PT4_LEN_SHIFT 0 +#define EDMA_WOL_PT5_LEN_SHIFT 8 +#define EDMA_WOL_PT6_LEN_SHIFT 16 + +/* WoL Control Register */ +#define EDMA_REG_WOL_CTRL 0xC08 +#define EDMA_WOL_WK_EN 0x00000001 +#define EDMA_WOL_MG_EN 0x00000002 +#define EDMA_WOL_PT0_EN 0x00000004 +#define EDMA_WOL_PT1_EN 0x00000008 +#define EDMA_WOL_PT2_EN 0x00000010 +#define EDMA_WOL_PT3_EN 0x00000020 +#define EDMA_WOL_PT4_EN 0x00000040 +#define EDMA_WOL_PT5_EN 0x00000080 +#define EDMA_WOL_PT6_EN 0x00000100 + +/* MAC Control Register */ +#define EDMA_REG_MAC_CTRL0 0xC20 +#define EDMA_REG_MAC_CTRL1 0xC24 + +/* WoL Pattern Register */ +#define EDMA_REG_WOL_PATTERN_START 0x5000 +#define EDMA_PATTERN_PART_REG_OFFSET 0x40 + + +/* TX descriptor fields */ +#define EDMA_TPD_HDR_SHIFT 0 +#define EDMA_TPD_PPPOE_EN 0x00000100 +#define EDMA_TPD_IP_CSUM_EN 0x00000200 +#define EDMA_TPD_TCP_CSUM_EN 0x0000400 +#define EDMA_TPD_UDP_CSUM_EN 0x00000800 +#define EDMA_TPD_CUSTOM_CSUM_EN 0x00000C00 +#define EDMA_TPD_LSO_EN 0x00001000 +#define EDMA_TPD_LSO_V2_EN 0x00002000 +#define EDMA_TPD_IPV4_EN 0x00010000 +#define EDMA_TPD_MSS_MASK 0x1FFF +#define EDMA_TPD_MSS_SHIFT 18 +#define EDMA_TPD_CUSTOM_CSUM_SHIFT 18 + +/* RRD descriptor fields */ +#define EDMA_RRD_NUM_RFD_MASK 0x000F +#define EDMA_RRD_SVLAN 0x8000 +#define EDMA_RRD_FLOW_COOKIE_MASK 0x07FF; + +#define EDMA_RRD_PKT_SIZE_MASK 0x3FFF +#define EDMA_RRD_CSUM_FAIL_MASK 0xC000 +#define EDMA_RRD_CVLAN 0x0001 +#define EDMA_RRD_DESC_VALID 0x8000 + +#define EDMA_RRD_PRIORITY_SHIFT 4 +#define EDMA_RRD_PRIORITY_MASK 0x7 +#define EDMA_RRD_PORT_TYPE_SHIFT 7 +#define EDMA_RRD_PORT_TYPE_MASK 0x1F + +#define ESS_RGMII_CTRL 0x0004 + +/* Port status registers */ +#define ESS_PORT0_STATUS 0x007C +#define ESS_PORT1_STATUS 0x0080 +#define ESS_PORT2_STATUS 0x0084 +#define ESS_PORT3_STATUS 0x0088 +#define ESS_PORT4_STATUS 0x008C +#define ESS_PORT5_STATUS 0x0090 + +#define ESS_PORT_STATUS_HDX_FLOW_CTL 0x80 +#define ESS_PORT_STATUS_DUPLEX_MODE 0x40 +#define ESS_PORT_STATUS_RX_FLOW_EN 0x20 +#define ESS_PORT_STATUS_TX_FLOW_EN 0x10 +#define ESS_PORT_STATUS_RX_MAC_EN 0x08 +#define ESS_PORT_STATUS_TX_MAC_EN 0x04 +#define ESS_PORT_STATUS_SPEED_INV 0x03 +#define ESS_PORT_STATUS_SPEED_1000 0x02 +#define ESS_PORT_STATUS_SPEED_100 0x01 +#define ESS_PORT_STATUS_SPEED_10 0x00 + +#define ESS_PORT_1G_FDX (ESS_PORT_STATUS_DUPLEX_MODE | ESS_PORT_STATUS_RX_FLOW_EN | \ + ESS_PORT_STATUS_TX_FLOW_EN | ESS_PORT_STATUS_RX_MAC_EN | \ + ESS_PORT_STATUS_TX_MAC_EN | ESS_PORT_STATUS_SPEED_1000) + +#define PHY_STATUS_REG 0x11 +#define PHY_STATUS_SPEED 0xC000 +#define PHY_STATUS_SPEED_SHIFT 14 +#define PHY_STATUS_DUPLEX 0x2000 +#define PHY_STATUS_DUPLEX_SHIFT 13 +#define PHY_STATUS_SPEED_DUPLEX_RESOLVED 0x0800 +#define PHY_STATUS_CARRIER 0x0400 +#define PHY_STATUS_CARRIER_SHIFT 10 + +/* Port lookup control registers */ +#define ESS_PORT0_LOOKUP_CTRL 0x0660 +#define ESS_PORT1_LOOKUP_CTRL 0x066C +#define ESS_PORT2_LOOKUP_CTRL 0x0678 +#define ESS_PORT3_LOOKUP_CTRL 0x0684 +#define ESS_PORT4_LOOKUP_CTRL 0x0690 +#define ESS_PORT5_LOOKUP_CTRL 0x069C + +#define ESS_PORT0_HEADER_CTRL 0x009C + +#define ESS_PORTS_ALL 0x3f + +#define ESS_FWD_CTRL1 0x0624 +#define ESS_FWD_CTRL1_UC_FLOOD BITS(0, 7) +#define ESS_FWD_CTRL1_UC_FLOOD_S 0 +#define ESS_FWD_CTRL1_MC_FLOOD BITS(8, 7) +#define ESS_FWD_CTRL1_MC_FLOOD_S 8 +#define ESS_FWD_CTRL1_BC_FLOOD BITS(16, 7) +#define ESS_FWD_CTRL1_BC_FLOOD_S 16 +#define ESS_FWD_CTRL1_IGMP BITS(24, 7) +#define ESS_FWD_CTRL1_IGMP_S 24 + +#endif /* _ESS_EDMA_H_ */ diff --git a/feeds/ipq40xx/ipq40xx/files/drivers/net/phy/ar40xx.c b/feeds/ipq40xx/ipq40xx/files/drivers/net/phy/ar40xx.c new file mode 100644 index 000000000..9758f013f --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/files/drivers/net/phy/ar40xx.c @@ -0,0 +1,1909 @@ +/* + * Copyright (c) 2016, The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all copies. + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ar40xx.h" + +static struct ar40xx_priv *ar40xx_priv; + +#define MIB_DESC(_s , _o, _n) \ + { \ + .size = (_s), \ + .offset = (_o), \ + .name = (_n), \ + } + +static const struct ar40xx_mib_desc ar40xx_mibs[] = { + MIB_DESC(1, AR40XX_STATS_RXBROAD, "RxBroad"), + MIB_DESC(1, AR40XX_STATS_RXPAUSE, "RxPause"), + MIB_DESC(1, AR40XX_STATS_RXMULTI, "RxMulti"), + MIB_DESC(1, AR40XX_STATS_RXFCSERR, "RxFcsErr"), + MIB_DESC(1, AR40XX_STATS_RXALIGNERR, "RxAlignErr"), + MIB_DESC(1, AR40XX_STATS_RXRUNT, "RxRunt"), + MIB_DESC(1, AR40XX_STATS_RXFRAGMENT, "RxFragment"), + MIB_DESC(1, AR40XX_STATS_RX64BYTE, "Rx64Byte"), + MIB_DESC(1, AR40XX_STATS_RX128BYTE, "Rx128Byte"), + MIB_DESC(1, AR40XX_STATS_RX256BYTE, "Rx256Byte"), + MIB_DESC(1, AR40XX_STATS_RX512BYTE, "Rx512Byte"), + MIB_DESC(1, AR40XX_STATS_RX1024BYTE, "Rx1024Byte"), + MIB_DESC(1, AR40XX_STATS_RX1518BYTE, "Rx1518Byte"), + MIB_DESC(1, AR40XX_STATS_RXMAXBYTE, "RxMaxByte"), + MIB_DESC(1, AR40XX_STATS_RXTOOLONG, "RxTooLong"), + MIB_DESC(2, AR40XX_STATS_RXGOODBYTE, "RxGoodByte"), + MIB_DESC(2, AR40XX_STATS_RXBADBYTE, "RxBadByte"), + MIB_DESC(1, AR40XX_STATS_RXOVERFLOW, "RxOverFlow"), + MIB_DESC(1, AR40XX_STATS_FILTERED, "Filtered"), + MIB_DESC(1, AR40XX_STATS_TXBROAD, "TxBroad"), + MIB_DESC(1, AR40XX_STATS_TXPAUSE, "TxPause"), + MIB_DESC(1, AR40XX_STATS_TXMULTI, "TxMulti"), + MIB_DESC(1, AR40XX_STATS_TXUNDERRUN, "TxUnderRun"), + MIB_DESC(1, AR40XX_STATS_TX64BYTE, "Tx64Byte"), + MIB_DESC(1, AR40XX_STATS_TX128BYTE, "Tx128Byte"), + MIB_DESC(1, AR40XX_STATS_TX256BYTE, "Tx256Byte"), + MIB_DESC(1, AR40XX_STATS_TX512BYTE, "Tx512Byte"), + MIB_DESC(1, AR40XX_STATS_TX1024BYTE, "Tx1024Byte"), + MIB_DESC(1, AR40XX_STATS_TX1518BYTE, "Tx1518Byte"), + MIB_DESC(1, AR40XX_STATS_TXMAXBYTE, "TxMaxByte"), + MIB_DESC(1, AR40XX_STATS_TXOVERSIZE, "TxOverSize"), + MIB_DESC(2, AR40XX_STATS_TXBYTE, "TxByte"), + MIB_DESC(1, AR40XX_STATS_TXCOLLISION, "TxCollision"), + MIB_DESC(1, AR40XX_STATS_TXABORTCOL, "TxAbortCol"), + MIB_DESC(1, AR40XX_STATS_TXMULTICOL, "TxMultiCol"), + MIB_DESC(1, AR40XX_STATS_TXSINGLECOL, "TxSingleCol"), + MIB_DESC(1, AR40XX_STATS_TXEXCDEFER, "TxExcDefer"), + MIB_DESC(1, AR40XX_STATS_TXDEFER, "TxDefer"), + MIB_DESC(1, AR40XX_STATS_TXLATECOL, "TxLateCol"), +}; + +static u32 +ar40xx_read(struct ar40xx_priv *priv, int reg) +{ + return readl(priv->hw_addr + reg); +} + +static u32 +ar40xx_psgmii_read(struct ar40xx_priv *priv, int reg) +{ + return readl(priv->psgmii_hw_addr + reg); +} + +static void +ar40xx_write(struct ar40xx_priv *priv, int reg, u32 val) +{ + writel(val, priv->hw_addr + reg); +} + +static u32 +ar40xx_rmw(struct ar40xx_priv *priv, int reg, u32 mask, u32 val) +{ + u32 ret; + + ret = ar40xx_read(priv, reg); + ret &= ~mask; + ret |= val; + ar40xx_write(priv, reg, ret); + return ret; +} + +static void +ar40xx_psgmii_write(struct ar40xx_priv *priv, int reg, u32 val) +{ + writel(val, priv->psgmii_hw_addr + reg); +} + +static void +ar40xx_phy_dbg_write(struct ar40xx_priv *priv, int phy_addr, + u16 dbg_addr, u16 dbg_data) +{ + struct mii_bus *bus = priv->mii_bus; + + mutex_lock(&bus->mdio_lock); + bus->write(bus, phy_addr, AR40XX_MII_ATH_DBG_ADDR, dbg_addr); + bus->write(bus, phy_addr, AR40XX_MII_ATH_DBG_DATA, dbg_data); + mutex_unlock(&bus->mdio_lock); +} + +static void +ar40xx_phy_dbg_read(struct ar40xx_priv *priv, int phy_addr, + u16 dbg_addr, u16 *dbg_data) +{ + struct mii_bus *bus = priv->mii_bus; + + mutex_lock(&bus->mdio_lock); + bus->write(bus, phy_addr, AR40XX_MII_ATH_DBG_ADDR, dbg_addr); + *dbg_data = bus->read(bus, phy_addr, AR40XX_MII_ATH_DBG_DATA); + mutex_unlock(&bus->mdio_lock); +} + +static void +ar40xx_phy_mmd_write(struct ar40xx_priv *priv, u32 phy_id, + u16 mmd_num, u16 reg_id, u16 reg_val) +{ + struct mii_bus *bus = priv->mii_bus; + + mutex_lock(&bus->mdio_lock); + bus->write(bus, phy_id, + AR40XX_MII_ATH_MMD_ADDR, mmd_num); + bus->write(bus, phy_id, + AR40XX_MII_ATH_MMD_DATA, reg_id); + bus->write(bus, phy_id, + AR40XX_MII_ATH_MMD_ADDR, + 0x4000 | mmd_num); + bus->write(bus, phy_id, + AR40XX_MII_ATH_MMD_DATA, reg_val); + mutex_unlock(&bus->mdio_lock); +} + +static u16 +ar40xx_phy_mmd_read(struct ar40xx_priv *priv, u32 phy_id, + u16 mmd_num, u16 reg_id) +{ + u16 value; + struct mii_bus *bus = priv->mii_bus; + + mutex_lock(&bus->mdio_lock); + bus->write(bus, phy_id, + AR40XX_MII_ATH_MMD_ADDR, mmd_num); + bus->write(bus, phy_id, + AR40XX_MII_ATH_MMD_DATA, reg_id); + bus->write(bus, phy_id, + AR40XX_MII_ATH_MMD_ADDR, + 0x4000 | mmd_num); + value = bus->read(bus, phy_id, AR40XX_MII_ATH_MMD_DATA); + mutex_unlock(&bus->mdio_lock); + return value; +} + +/* Start of swconfig support */ + +static void +ar40xx_phy_poll_reset(struct ar40xx_priv *priv) +{ + u32 i, in_reset, retries = 500; + struct mii_bus *bus = priv->mii_bus; + + /* Assume RESET was recently issued to some or all of the phys */ + in_reset = GENMASK(AR40XX_NUM_PHYS - 1, 0); + + while (retries--) { + /* 1ms should be plenty of time. + * 802.3 spec allows for a max wait time of 500ms + */ + usleep_range(1000, 2000); + + for (i = 0; i < AR40XX_NUM_PHYS; i++) { + int val; + + /* skip devices which have completed reset */ + if (!(in_reset & BIT(i))) + continue; + + val = mdiobus_read(bus, i, MII_BMCR); + if (val < 0) + continue; + + /* mark when phy is no longer in reset state */ + if (!(val & BMCR_RESET)) + in_reset &= ~BIT(i); + } + + if (!in_reset) + return; + } + + dev_warn(&bus->dev, "Failed to reset all phys! (in_reset: 0x%x)\n", + in_reset); +} + +static void +ar40xx_phy_init(struct ar40xx_priv *priv) +{ + int i; + struct mii_bus *bus; + u16 val; + + bus = priv->mii_bus; + for (i = 0; i < AR40XX_NUM_PORTS - 1; i++) { + ar40xx_phy_dbg_read(priv, i, AR40XX_PHY_DEBUG_0, &val); + val &= ~AR40XX_PHY_MANU_CTRL_EN; + ar40xx_phy_dbg_write(priv, i, AR40XX_PHY_DEBUG_0, val); + mdiobus_write(bus, i, + MII_ADVERTISE, ADVERTISE_ALL | + ADVERTISE_PAUSE_CAP | + ADVERTISE_PAUSE_ASYM); + mdiobus_write(bus, i, MII_CTRL1000, ADVERTISE_1000FULL); + mdiobus_write(bus, i, MII_BMCR, BMCR_RESET | BMCR_ANENABLE); + } + + ar40xx_phy_poll_reset(priv); +} + +static void +ar40xx_port_phy_linkdown(struct ar40xx_priv *priv) +{ + struct mii_bus *bus; + int i; + u16 val; + + bus = priv->mii_bus; + for (i = 0; i < AR40XX_NUM_PORTS - 1; i++) { + mdiobus_write(bus, i, MII_CTRL1000, 0); + mdiobus_write(bus, i, MII_ADVERTISE, 0); + mdiobus_write(bus, i, MII_BMCR, BMCR_RESET | BMCR_ANENABLE); + ar40xx_phy_dbg_read(priv, i, AR40XX_PHY_DEBUG_0, &val); + val |= AR40XX_PHY_MANU_CTRL_EN; + ar40xx_phy_dbg_write(priv, i, AR40XX_PHY_DEBUG_0, val); + /* disable transmit */ + ar40xx_phy_dbg_read(priv, i, AR40XX_PHY_DEBUG_2, &val); + val &= 0xf00f; + ar40xx_phy_dbg_write(priv, i, AR40XX_PHY_DEBUG_2, val); + } +} + +static void +ar40xx_set_mirror_regs(struct ar40xx_priv *priv) +{ + int port; + + /* reset all mirror registers */ + ar40xx_rmw(priv, AR40XX_REG_FWD_CTRL0, + AR40XX_FWD_CTRL0_MIRROR_PORT, + (0xF << AR40XX_FWD_CTRL0_MIRROR_PORT_S)); + for (port = 0; port < AR40XX_NUM_PORTS; port++) { + ar40xx_rmw(priv, AR40XX_REG_PORT_LOOKUP(port), + AR40XX_PORT_LOOKUP_ING_MIRROR_EN, 0); + + ar40xx_rmw(priv, AR40XX_REG_PORT_HOL_CTRL1(port), + AR40XX_PORT_HOL_CTRL1_EG_MIRROR_EN, 0); + } + + /* now enable mirroring if necessary */ + if (priv->source_port >= AR40XX_NUM_PORTS || + priv->monitor_port >= AR40XX_NUM_PORTS || + priv->source_port == priv->monitor_port) { + return; + } + + ar40xx_rmw(priv, AR40XX_REG_FWD_CTRL0, + AR40XX_FWD_CTRL0_MIRROR_PORT, + (priv->monitor_port << AR40XX_FWD_CTRL0_MIRROR_PORT_S)); + + if (priv->mirror_rx) + ar40xx_rmw(priv, AR40XX_REG_PORT_LOOKUP(priv->source_port), 0, + AR40XX_PORT_LOOKUP_ING_MIRROR_EN); + + if (priv->mirror_tx) + ar40xx_rmw(priv, AR40XX_REG_PORT_HOL_CTRL1(priv->source_port), + 0, AR40XX_PORT_HOL_CTRL1_EG_MIRROR_EN); +} + +static int +ar40xx_sw_get_ports(struct switch_dev *dev, struct switch_val *val) +{ + struct ar40xx_priv *priv = swdev_to_ar40xx(dev); + u8 ports = priv->vlan_table[val->port_vlan]; + int i; + + val->len = 0; + for (i = 0; i < dev->ports; i++) { + struct switch_port *p; + + if (!(ports & BIT(i))) + continue; + + p = &val->value.ports[val->len++]; + p->id = i; + if ((priv->vlan_tagged & BIT(i)) || + (priv->pvid[i] != val->port_vlan)) + p->flags = BIT(SWITCH_PORT_FLAG_TAGGED); + else + p->flags = 0; + } + return 0; +} + +static int +ar40xx_sw_set_ports(struct switch_dev *dev, struct switch_val *val) +{ + struct ar40xx_priv *priv = swdev_to_ar40xx(dev); + u8 *vt = &priv->vlan_table[val->port_vlan]; + int i; + + *vt = 0; + for (i = 0; i < val->len; i++) { + struct switch_port *p = &val->value.ports[i]; + + if (p->flags & BIT(SWITCH_PORT_FLAG_TAGGED)) { + if (val->port_vlan == priv->pvid[p->id]) + priv->vlan_tagged |= BIT(p->id); + } else { + priv->vlan_tagged &= ~BIT(p->id); + priv->pvid[p->id] = val->port_vlan; + } + + *vt |= BIT(p->id); + } + return 0; +} + +static int +ar40xx_reg_wait(struct ar40xx_priv *priv, u32 reg, u32 mask, u32 val, + unsigned timeout) +{ + int i; + + for (i = 0; i < timeout; i++) { + u32 t; + + t = ar40xx_read(priv, reg); + if ((t & mask) == val) + return 0; + + usleep_range(1000, 2000); + } + + return -ETIMEDOUT; +} + +static int +ar40xx_mib_op(struct ar40xx_priv *priv, u32 op) +{ + int ret; + + lockdep_assert_held(&priv->mib_lock); + + /* Capture the hardware statistics for all ports */ + ar40xx_rmw(priv, AR40XX_REG_MIB_FUNC, + AR40XX_MIB_FUNC, (op << AR40XX_MIB_FUNC_S)); + + /* Wait for the capturing to complete. */ + ret = ar40xx_reg_wait(priv, AR40XX_REG_MIB_FUNC, + AR40XX_MIB_BUSY, 0, 10); + + return ret; +} + +static void +ar40xx_mib_fetch_port_stat(struct ar40xx_priv *priv, int port, bool flush) +{ + unsigned int base; + u64 *mib_stats; + int i; + u32 num_mibs = ARRAY_SIZE(ar40xx_mibs); + + WARN_ON(port >= priv->dev.ports); + + lockdep_assert_held(&priv->mib_lock); + + base = AR40XX_REG_PORT_STATS_START + + AR40XX_REG_PORT_STATS_LEN * port; + + mib_stats = &priv->mib_stats[port * num_mibs]; + if (flush) { + u32 len; + + len = num_mibs * sizeof(*mib_stats); + memset(mib_stats, 0, len); + return; + } + for (i = 0; i < num_mibs; i++) { + const struct ar40xx_mib_desc *mib; + u64 t; + + mib = &ar40xx_mibs[i]; + t = ar40xx_read(priv, base + mib->offset); + if (mib->size == 2) { + u64 hi; + + hi = ar40xx_read(priv, base + mib->offset + 4); + t |= hi << 32; + } + + mib_stats[i] += t; + } +} + +static int +ar40xx_mib_capture(struct ar40xx_priv *priv) +{ + return ar40xx_mib_op(priv, AR40XX_MIB_FUNC_CAPTURE); +} + +static int +ar40xx_mib_flush(struct ar40xx_priv *priv) +{ + return ar40xx_mib_op(priv, AR40XX_MIB_FUNC_FLUSH); +} + +static int +ar40xx_sw_set_reset_mibs(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct ar40xx_priv *priv = swdev_to_ar40xx(dev); + unsigned int len; + int ret; + u32 num_mibs = ARRAY_SIZE(ar40xx_mibs); + + mutex_lock(&priv->mib_lock); + + len = priv->dev.ports * num_mibs * sizeof(*priv->mib_stats); + memset(priv->mib_stats, 0, len); + ret = ar40xx_mib_flush(priv); + + mutex_unlock(&priv->mib_lock); + return ret; +} + +static int +ar40xx_sw_set_vlan(struct switch_dev *dev, const struct switch_attr *attr, + struct switch_val *val) +{ + struct ar40xx_priv *priv = swdev_to_ar40xx(dev); + + priv->vlan = !!val->value.i; + return 0; +} + +static int +ar40xx_sw_get_vlan(struct switch_dev *dev, const struct switch_attr *attr, + struct switch_val *val) +{ + struct ar40xx_priv *priv = swdev_to_ar40xx(dev); + + val->value.i = priv->vlan; + return 0; +} + +static int +ar40xx_sw_set_mirror_rx_enable(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct ar40xx_priv *priv = swdev_to_ar40xx(dev); + + mutex_lock(&priv->reg_mutex); + priv->mirror_rx = !!val->value.i; + ar40xx_set_mirror_regs(priv); + mutex_unlock(&priv->reg_mutex); + + return 0; +} + +static int +ar40xx_sw_get_mirror_rx_enable(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct ar40xx_priv *priv = swdev_to_ar40xx(dev); + + mutex_lock(&priv->reg_mutex); + val->value.i = priv->mirror_rx; + mutex_unlock(&priv->reg_mutex); + return 0; +} + +static int +ar40xx_sw_set_mirror_tx_enable(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct ar40xx_priv *priv = swdev_to_ar40xx(dev); + + mutex_lock(&priv->reg_mutex); + priv->mirror_tx = !!val->value.i; + ar40xx_set_mirror_regs(priv); + mutex_unlock(&priv->reg_mutex); + + return 0; +} + +static int +ar40xx_sw_get_mirror_tx_enable(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct ar40xx_priv *priv = swdev_to_ar40xx(dev); + + mutex_lock(&priv->reg_mutex); + val->value.i = priv->mirror_tx; + mutex_unlock(&priv->reg_mutex); + return 0; +} + +static int +ar40xx_sw_set_mirror_monitor_port(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct ar40xx_priv *priv = swdev_to_ar40xx(dev); + + mutex_lock(&priv->reg_mutex); + priv->monitor_port = val->value.i; + ar40xx_set_mirror_regs(priv); + mutex_unlock(&priv->reg_mutex); + + return 0; +} + +static int +ar40xx_sw_get_mirror_monitor_port(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct ar40xx_priv *priv = swdev_to_ar40xx(dev); + + mutex_lock(&priv->reg_mutex); + val->value.i = priv->monitor_port; + mutex_unlock(&priv->reg_mutex); + return 0; +} + +static int +ar40xx_sw_set_mirror_source_port(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct ar40xx_priv *priv = swdev_to_ar40xx(dev); + + mutex_lock(&priv->reg_mutex); + priv->source_port = val->value.i; + ar40xx_set_mirror_regs(priv); + mutex_unlock(&priv->reg_mutex); + + return 0; +} + +static int +ar40xx_sw_get_mirror_source_port(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct ar40xx_priv *priv = swdev_to_ar40xx(dev); + + mutex_lock(&priv->reg_mutex); + val->value.i = priv->source_port; + mutex_unlock(&priv->reg_mutex); + return 0; +} + +static int +ar40xx_sw_set_linkdown(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct ar40xx_priv *priv = swdev_to_ar40xx(dev); + + if (val->value.i == 1) + ar40xx_port_phy_linkdown(priv); + else + ar40xx_phy_init(priv); + + return 0; +} + +static int +ar40xx_sw_set_port_reset_mib(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct ar40xx_priv *priv = swdev_to_ar40xx(dev); + int port; + int ret; + + port = val->port_vlan; + if (port >= dev->ports) + return -EINVAL; + + mutex_lock(&priv->mib_lock); + ret = ar40xx_mib_capture(priv); + if (ret) + goto unlock; + + ar40xx_mib_fetch_port_stat(priv, port, true); + +unlock: + mutex_unlock(&priv->mib_lock); + return ret; +} + +static int +ar40xx_sw_get_port_mib(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct ar40xx_priv *priv = swdev_to_ar40xx(dev); + u64 *mib_stats; + int port; + int ret; + char *buf = priv->buf; + int i, len = 0; + u32 num_mibs = ARRAY_SIZE(ar40xx_mibs); + + port = val->port_vlan; + if (port >= dev->ports) + return -EINVAL; + + mutex_lock(&priv->mib_lock); + ret = ar40xx_mib_capture(priv); + if (ret) + goto unlock; + + ar40xx_mib_fetch_port_stat(priv, port, false); + + len += snprintf(buf + len, sizeof(priv->buf) - len, + "Port %d MIB counters\n", + port); + + mib_stats = &priv->mib_stats[port * num_mibs]; + for (i = 0; i < num_mibs; i++) + len += snprintf(buf + len, sizeof(priv->buf) - len, + "%-12s: %llu\n", + ar40xx_mibs[i].name, + mib_stats[i]); + + val->value.s = buf; + val->len = len; + +unlock: + mutex_unlock(&priv->mib_lock); + return ret; +} + +static int +ar40xx_sw_set_vid(struct switch_dev *dev, const struct switch_attr *attr, + struct switch_val *val) +{ + struct ar40xx_priv *priv = swdev_to_ar40xx(dev); + + priv->vlan_id[val->port_vlan] = val->value.i; + return 0; +} + +static int +ar40xx_sw_get_vid(struct switch_dev *dev, const struct switch_attr *attr, + struct switch_val *val) +{ + struct ar40xx_priv *priv = swdev_to_ar40xx(dev); + + val->value.i = priv->vlan_id[val->port_vlan]; + return 0; +} + +static int +ar40xx_sw_get_pvid(struct switch_dev *dev, int port, int *vlan) +{ + struct ar40xx_priv *priv = swdev_to_ar40xx(dev); + *vlan = priv->pvid[port]; + return 0; +} + +static int +ar40xx_sw_set_pvid(struct switch_dev *dev, int port, int vlan) +{ + struct ar40xx_priv *priv = swdev_to_ar40xx(dev); + + /* make sure no invalid PVIDs get set */ + if (vlan >= dev->vlans) + return -EINVAL; + + priv->pvid[port] = vlan; + return 0; +} + +static void +ar40xx_read_port_link(struct ar40xx_priv *priv, int port, + struct switch_port_link *link) +{ + u32 status; + u32 speed; + + memset(link, 0, sizeof(*link)); + + status = ar40xx_read(priv, AR40XX_REG_PORT_STATUS(port)); + + link->aneg = !!(status & AR40XX_PORT_AUTO_LINK_EN); + if (link->aneg || (port != AR40XX_PORT_CPU)) + link->link = !!(status & AR40XX_PORT_STATUS_LINK_UP); + else + link->link = true; + + if (!link->link) + return; + + link->duplex = !!(status & AR40XX_PORT_DUPLEX); + link->tx_flow = !!(status & AR40XX_PORT_STATUS_TXFLOW); + link->rx_flow = !!(status & AR40XX_PORT_STATUS_RXFLOW); + + speed = (status & AR40XX_PORT_SPEED) >> + AR40XX_PORT_STATUS_SPEED_S; + + switch (speed) { + case AR40XX_PORT_SPEED_10M: + link->speed = SWITCH_PORT_SPEED_10; + break; + case AR40XX_PORT_SPEED_100M: + link->speed = SWITCH_PORT_SPEED_100; + break; + case AR40XX_PORT_SPEED_1000M: + link->speed = SWITCH_PORT_SPEED_1000; + break; + default: + link->speed = SWITCH_PORT_SPEED_UNKNOWN; + break; + } +} + +static int +ar40xx_sw_get_port_link(struct switch_dev *dev, int port, + struct switch_port_link *link) +{ + struct ar40xx_priv *priv = swdev_to_ar40xx(dev); + + ar40xx_read_port_link(priv, port, link); + return 0; +} + +static const struct switch_attr ar40xx_sw_attr_globals[] = { + { + .type = SWITCH_TYPE_INT, + .name = "enable_vlan", + .description = "Enable VLAN mode", + .set = ar40xx_sw_set_vlan, + .get = ar40xx_sw_get_vlan, + .max = 1 + }, + { + .type = SWITCH_TYPE_NOVAL, + .name = "reset_mibs", + .description = "Reset all MIB counters", + .set = ar40xx_sw_set_reset_mibs, + }, + { + .type = SWITCH_TYPE_INT, + .name = "enable_mirror_rx", + .description = "Enable mirroring of RX packets", + .set = ar40xx_sw_set_mirror_rx_enable, + .get = ar40xx_sw_get_mirror_rx_enable, + .max = 1 + }, + { + .type = SWITCH_TYPE_INT, + .name = "enable_mirror_tx", + .description = "Enable mirroring of TX packets", + .set = ar40xx_sw_set_mirror_tx_enable, + .get = ar40xx_sw_get_mirror_tx_enable, + .max = 1 + }, + { + .type = SWITCH_TYPE_INT, + .name = "mirror_monitor_port", + .description = "Mirror monitor port", + .set = ar40xx_sw_set_mirror_monitor_port, + .get = ar40xx_sw_get_mirror_monitor_port, + .max = AR40XX_NUM_PORTS - 1 + }, + { + .type = SWITCH_TYPE_INT, + .name = "mirror_source_port", + .description = "Mirror source port", + .set = ar40xx_sw_set_mirror_source_port, + .get = ar40xx_sw_get_mirror_source_port, + .max = AR40XX_NUM_PORTS - 1 + }, + { + .type = SWITCH_TYPE_INT, + .name = "linkdown", + .description = "Link down all the PHYs", + .set = ar40xx_sw_set_linkdown, + .max = 1 + }, +}; + +static const struct switch_attr ar40xx_sw_attr_port[] = { + { + .type = SWITCH_TYPE_NOVAL, + .name = "reset_mib", + .description = "Reset single port MIB counters", + .set = ar40xx_sw_set_port_reset_mib, + }, + { + .type = SWITCH_TYPE_STRING, + .name = "mib", + .description = "Get port's MIB counters", + .set = NULL, + .get = ar40xx_sw_get_port_mib, + }, +}; + +const struct switch_attr ar40xx_sw_attr_vlan[] = { + { + .type = SWITCH_TYPE_INT, + .name = "vid", + .description = "VLAN ID (0-4094)", + .set = ar40xx_sw_set_vid, + .get = ar40xx_sw_get_vid, + .max = 4094, + }, +}; + +/* End of swconfig support */ + +static int +ar40xx_wait_bit(struct ar40xx_priv *priv, int reg, u32 mask, u32 val) +{ + int timeout = 20; + u32 t; + + while (1) { + t = ar40xx_read(priv, reg); + if ((t & mask) == val) + return 0; + + if (timeout-- <= 0) + break; + + usleep_range(10, 20); + } + + pr_err("ar40xx: timeout for reg %08x: %08x & %08x != %08x\n", + (unsigned int)reg, t, mask, val); + return -ETIMEDOUT; +} + +static int +ar40xx_atu_flush(struct ar40xx_priv *priv) +{ + int ret; + + ret = ar40xx_wait_bit(priv, AR40XX_REG_ATU_FUNC, + AR40XX_ATU_FUNC_BUSY, 0); + if (!ret) + ar40xx_write(priv, AR40XX_REG_ATU_FUNC, + AR40XX_ATU_FUNC_OP_FLUSH | + AR40XX_ATU_FUNC_BUSY); + + return ret; +} + +static void +ar40xx_ess_reset(struct ar40xx_priv *priv) +{ + reset_control_assert(priv->ess_rst); + mdelay(10); + reset_control_deassert(priv->ess_rst); + /* Waiting for all inner tables init done. + * It cost 5~10ms. + */ + mdelay(10); + + pr_info("ESS reset ok!\n"); +} + +/* Start of psgmii self test */ + +static void +ar40xx_malibu_psgmii_ess_reset(struct ar40xx_priv *priv) +{ + u32 n; + struct mii_bus *bus = priv->mii_bus; + /* reset phy psgmii */ + /* fix phy psgmii RX 20bit */ + mdiobus_write(bus, 5, 0x0, 0x005b); + /* reset phy psgmii */ + mdiobus_write(bus, 5, 0x0, 0x001b); + /* release reset phy psgmii */ + mdiobus_write(bus, 5, 0x0, 0x005b); + + for (n = 0; n < AR40XX_PSGMII_CALB_NUM; n++) { + u16 status; + + status = ar40xx_phy_mmd_read(priv, 5, 1, 0x28); + if (status & BIT(0)) + break; + /* Polling interval to check PSGMII PLL in malibu is ready + * the worst time is 8.67ms + * for 25MHz reference clock + * [512+(128+2048)*49]*80ns+100us + */ + mdelay(2); + } + + /*check malibu psgmii calibration done end..*/ + + /*freeze phy psgmii RX CDR*/ + mdiobus_write(bus, 5, 0x1a, 0x2230); + + ar40xx_ess_reset(priv); + + /*check psgmii calibration done start*/ + for (n = 0; n < AR40XX_PSGMII_CALB_NUM; n++) { + u32 status; + + status = ar40xx_psgmii_read(priv, 0xa0); + if (status & BIT(0)) + break; + /* Polling interval to check PSGMII PLL in ESS is ready */ + mdelay(2); + } + + /* check dakota psgmii calibration done end..*/ + + /* relesae phy psgmii RX CDR */ + mdiobus_write(bus, 5, 0x1a, 0x3230); + /* release phy psgmii RX 20bit */ + mdiobus_write(bus, 5, 0x0, 0x005f); +} + +static void +ar40xx_psgmii_single_phy_testing(struct ar40xx_priv *priv, int phy) +{ + int j; + u32 tx_ok, tx_error; + u32 rx_ok, rx_error; + u32 tx_ok_high16; + u32 rx_ok_high16; + u32 tx_all_ok, rx_all_ok; + struct mii_bus *bus = priv->mii_bus; + + mdiobus_write(bus, phy, 0x0, 0x9000); + mdiobus_write(bus, phy, 0x0, 0x4140); + + for (j = 0; j < AR40XX_PSGMII_CALB_NUM; j++) { + u16 status; + + status = mdiobus_read(bus, phy, 0x11); + if (status & AR40XX_PHY_SPEC_STATUS_LINK) + break; + /* the polling interval to check if the PHY link up or not + * maxwait_timer: 750 ms +/-10 ms + * minwait_timer : 1 us +/- 0.1us + * time resides in minwait_timer ~ maxwait_timer + * see IEEE 802.3 section 40.4.5.2 + */ + mdelay(8); + } + + /* enable check */ + ar40xx_phy_mmd_write(priv, phy, 7, 0x8029, 0x0000); + ar40xx_phy_mmd_write(priv, phy, 7, 0x8029, 0x0003); + + /* start traffic */ + ar40xx_phy_mmd_write(priv, phy, 7, 0x8020, 0xa000); + /* wait for all traffic end + * 4096(pkt num)*1524(size)*8ns(125MHz)=49.9ms + */ + mdelay(50); + + /* check counter */ + tx_ok = ar40xx_phy_mmd_read(priv, phy, 7, 0x802e); + tx_ok_high16 = ar40xx_phy_mmd_read(priv, phy, 7, 0x802d); + tx_error = ar40xx_phy_mmd_read(priv, phy, 7, 0x802f); + rx_ok = ar40xx_phy_mmd_read(priv, phy, 7, 0x802b); + rx_ok_high16 = ar40xx_phy_mmd_read(priv, phy, 7, 0x802a); + rx_error = ar40xx_phy_mmd_read(priv, phy, 7, 0x802c); + tx_all_ok = tx_ok + (tx_ok_high16 << 16); + rx_all_ok = rx_ok + (rx_ok_high16 << 16); + if (tx_all_ok == 0x1000 && tx_error == 0) { + /* success */ + priv->phy_t_status &= (~BIT(phy)); + } else { + pr_info("PHY %d single test PSGMII issue happen!\n", phy); + priv->phy_t_status |= BIT(phy); + } + + mdiobus_write(bus, phy, 0x0, 0x1840); +} + +static void +ar40xx_psgmii_all_phy_testing(struct ar40xx_priv *priv) +{ + int phy, j; + struct mii_bus *bus = priv->mii_bus; + + mdiobus_write(bus, 0x1f, 0x0, 0x9000); + mdiobus_write(bus, 0x1f, 0x0, 0x4140); + + for (j = 0; j < AR40XX_PSGMII_CALB_NUM; j++) { + for (phy = 0; phy < AR40XX_NUM_PORTS - 1; phy++) { + u16 status; + + status = mdiobus_read(bus, phy, 0x11); + if (!(status & BIT(10))) + break; + } + + if (phy >= (AR40XX_NUM_PORTS - 1)) + break; + /* The polling interva to check if the PHY link up or not */ + mdelay(8); + } + /* enable check */ + ar40xx_phy_mmd_write(priv, 0x1f, 7, 0x8029, 0x0000); + ar40xx_phy_mmd_write(priv, 0x1f, 7, 0x8029, 0x0003); + + /* start traffic */ + ar40xx_phy_mmd_write(priv, 0x1f, 7, 0x8020, 0xa000); + /* wait for all traffic end + * 4096(pkt num)*1524(size)*8ns(125MHz)=49.9ms + */ + mdelay(50); + + for (phy = 0; phy < AR40XX_NUM_PORTS - 1; phy++) { + u32 tx_ok, tx_error; + u32 rx_ok, rx_error; + u32 tx_ok_high16; + u32 rx_ok_high16; + u32 tx_all_ok, rx_all_ok; + + /* check counter */ + tx_ok = ar40xx_phy_mmd_read(priv, phy, 7, 0x802e); + tx_ok_high16 = ar40xx_phy_mmd_read(priv, phy, 7, 0x802d); + tx_error = ar40xx_phy_mmd_read(priv, phy, 7, 0x802f); + rx_ok = ar40xx_phy_mmd_read(priv, phy, 7, 0x802b); + rx_ok_high16 = ar40xx_phy_mmd_read(priv, phy, 7, 0x802a); + rx_error = ar40xx_phy_mmd_read(priv, phy, 7, 0x802c); + tx_all_ok = tx_ok + (tx_ok_high16<<16); + rx_all_ok = rx_ok + (rx_ok_high16<<16); + if (tx_all_ok == 0x1000 && tx_error == 0) { + /* success */ + priv->phy_t_status &= ~BIT(phy + 8); + } else { + pr_info("PHY%d test see issue!\n", phy); + priv->phy_t_status |= BIT(phy + 8); + } + } + + pr_debug("PHY all test 0x%x \r\n", priv->phy_t_status); +} + +void +ar40xx_psgmii_self_test(struct ar40xx_priv *priv) +{ + u32 i, phy; + struct mii_bus *bus = priv->mii_bus; + + ar40xx_malibu_psgmii_ess_reset(priv); + + /* switch to access MII reg for copper */ + mdiobus_write(bus, 4, 0x1f, 0x8500); + for (phy = 0; phy < AR40XX_NUM_PORTS - 1; phy++) { + /*enable phy mdio broadcast write*/ + ar40xx_phy_mmd_write(priv, phy, 7, 0x8028, 0x801f); + } + /* force no link by power down */ + mdiobus_write(bus, 0x1f, 0x0, 0x1840); + /*packet number*/ + ar40xx_phy_mmd_write(priv, 0x1f, 7, 0x8021, 0x1000); + ar40xx_phy_mmd_write(priv, 0x1f, 7, 0x8062, 0x05e0); + + /*fix mdi status */ + mdiobus_write(bus, 0x1f, 0x10, 0x6800); + for (i = 0; i < AR40XX_PSGMII_CALB_NUM; i++) { + priv->phy_t_status = 0; + + for (phy = 0; phy < AR40XX_NUM_PORTS - 1; phy++) { + ar40xx_rmw(priv, AR40XX_REG_PORT_LOOKUP(phy + 1), + AR40XX_PORT_LOOKUP_LOOPBACK, + AR40XX_PORT_LOOKUP_LOOPBACK); + } + + for (phy = 0; phy < AR40XX_NUM_PORTS - 1; phy++) + ar40xx_psgmii_single_phy_testing(priv, phy); + + ar40xx_psgmii_all_phy_testing(priv); + + if (priv->phy_t_status) + ar40xx_malibu_psgmii_ess_reset(priv); + else + break; + } + + if (i >= AR40XX_PSGMII_CALB_NUM) + pr_info("PSGMII cannot recover\n"); + else + pr_debug("PSGMII recovered after %d times reset\n", i); + + /* configuration recover */ + /* packet number */ + ar40xx_phy_mmd_write(priv, 0x1f, 7, 0x8021, 0x0); + /* disable check */ + ar40xx_phy_mmd_write(priv, 0x1f, 7, 0x8029, 0x0); + /* disable traffic */ + ar40xx_phy_mmd_write(priv, 0x1f, 7, 0x8020, 0x0); +} + +void +ar40xx_psgmii_self_test_clean(struct ar40xx_priv *priv) +{ + int phy; + struct mii_bus *bus = priv->mii_bus; + + /* disable phy internal loopback */ + mdiobus_write(bus, 0x1f, 0x10, 0x6860); + mdiobus_write(bus, 0x1f, 0x0, 0x9040); + + for (phy = 0; phy < AR40XX_NUM_PORTS - 1; phy++) { + /* disable mac loop back */ + ar40xx_rmw(priv, AR40XX_REG_PORT_LOOKUP(phy + 1), + AR40XX_PORT_LOOKUP_LOOPBACK, 0); + /* disable phy mdio broadcast write */ + ar40xx_phy_mmd_write(priv, phy, 7, 0x8028, 0x001f); + } + + /* clear fdb entry */ + ar40xx_atu_flush(priv); +} + +/* End of psgmii self test */ + +static void +ar40xx_mac_mode_init(struct ar40xx_priv *priv, u32 mode) +{ + if (mode == PORT_WRAPPER_PSGMII) { + ar40xx_psgmii_write(priv, AR40XX_PSGMII_MODE_CONTROL, 0x2200); + ar40xx_psgmii_write(priv, AR40XX_PSGMIIPHY_TX_CONTROL, 0x8380); + } +} + +static +int ar40xx_cpuport_setup(struct ar40xx_priv *priv) +{ + u32 t; + + t = AR40XX_PORT_STATUS_TXFLOW | + AR40XX_PORT_STATUS_RXFLOW | + AR40XX_PORT_TXHALF_FLOW | + AR40XX_PORT_DUPLEX | + AR40XX_PORT_SPEED_1000M; + ar40xx_write(priv, AR40XX_REG_PORT_STATUS(0), t); + usleep_range(10, 20); + + t |= AR40XX_PORT_TX_EN | + AR40XX_PORT_RX_EN; + ar40xx_write(priv, AR40XX_REG_PORT_STATUS(0), t); + + return 0; +} + +static void +ar40xx_init_port(struct ar40xx_priv *priv, int port) +{ + u32 t; + + ar40xx_rmw(priv, AR40XX_REG_PORT_STATUS(port), + AR40XX_PORT_AUTO_LINK_EN, 0); + + /* CPU port is setting headers to limit output ports */ + if (port == 0) + ar40xx_write(priv, AR40XX_REG_PORT_HEADER(port), 0x8); + else + ar40xx_write(priv, AR40XX_REG_PORT_HEADER(port), 0); + + ar40xx_write(priv, AR40XX_REG_PORT_VLAN0(port), 0); + + t = AR40XX_PORT_VLAN1_OUT_MODE_UNTOUCH << AR40XX_PORT_VLAN1_OUT_MODE_S; + ar40xx_write(priv, AR40XX_REG_PORT_VLAN1(port), t); + + t = AR40XX_PORT_LOOKUP_LEARN; + t |= AR40XX_PORT_STATE_FORWARD << AR40XX_PORT_LOOKUP_STATE_S; + ar40xx_write(priv, AR40XX_REG_PORT_LOOKUP(port), t); +} + +void +ar40xx_init_globals(struct ar40xx_priv *priv) +{ + u32 t; + + /* enable CPU port and disable mirror port */ + t = AR40XX_FWD_CTRL0_CPU_PORT_EN | + AR40XX_FWD_CTRL0_MIRROR_PORT; + ar40xx_write(priv, AR40XX_REG_FWD_CTRL0, t); + + /* forward multicast and broadcast frames to CPU */ + t = (AR40XX_PORTS_ALL << AR40XX_FWD_CTRL1_UC_FLOOD_S) | + (AR40XX_PORTS_ALL << AR40XX_FWD_CTRL1_MC_FLOOD_S) | + (AR40XX_PORTS_ALL << AR40XX_FWD_CTRL1_BC_FLOOD_S); + ar40xx_write(priv, AR40XX_REG_FWD_CTRL1, t); + + /* enable jumbo frames */ + ar40xx_rmw(priv, AR40XX_REG_MAX_FRAME_SIZE, + AR40XX_MAX_FRAME_SIZE_MTU, 9018 + 8 + 2); + + /* Enable MIB counters */ + ar40xx_rmw(priv, AR40XX_REG_MODULE_EN, 0, + AR40XX_MODULE_EN_MIB); + + /* Disable AZ */ + ar40xx_write(priv, AR40XX_REG_EEE_CTRL, 0); + + /* set flowctrl thershold for cpu port */ + t = (AR40XX_PORT0_FC_THRESH_ON_DFLT << 16) | + AR40XX_PORT0_FC_THRESH_OFF_DFLT; + ar40xx_write(priv, AR40XX_REG_PORT_FLOWCTRL_THRESH(0), t); + + /* set service tag to 802.1q */ + t = ETH_P_8021Q | AR40XX_ESS_SERVICE_TAG_STAG; + ar40xx_write(priv, AR40XX_ESS_SERVICE_TAG, t); +} + +static int +ar40xx_hw_init(struct ar40xx_priv *priv) +{ + u32 i; + + ar40xx_ess_reset(priv); + + if (!priv->mii_bus) + return -1; + + ar40xx_psgmii_self_test(priv); + ar40xx_psgmii_self_test_clean(priv); + + ar40xx_mac_mode_init(priv, priv->mac_mode); + + for (i = 0; i < priv->dev.ports; i++) + ar40xx_init_port(priv, i); + + ar40xx_init_globals(priv); + + return 0; +} + +/* Start of qm error WAR */ + +static +int ar40xx_force_1g_full(struct ar40xx_priv *priv, u32 port_id) +{ + u32 reg; + + if (port_id < 0 || port_id > 6) + return -1; + + reg = AR40XX_REG_PORT_STATUS(port_id); + return ar40xx_rmw(priv, reg, AR40XX_PORT_SPEED, + (AR40XX_PORT_SPEED_1000M | AR40XX_PORT_DUPLEX)); +} + +static +int ar40xx_get_qm_status(struct ar40xx_priv *priv, + u32 port_id, u32 *qm_buffer_err) +{ + u32 reg; + u32 qm_val; + + if (port_id < 1 || port_id > 5) { + *qm_buffer_err = 0; + return -1; + } + + if (port_id < 4) { + reg = AR40XX_REG_QM_PORT0_3_QNUM; + ar40xx_write(priv, AR40XX_REG_QM_DEBUG_ADDR, reg); + qm_val = ar40xx_read(priv, AR40XX_REG_QM_DEBUG_VALUE); + /* every 8 bits for each port */ + *qm_buffer_err = (qm_val >> (port_id * 8)) & 0xFF; + } else { + reg = AR40XX_REG_QM_PORT4_6_QNUM; + ar40xx_write(priv, AR40XX_REG_QM_DEBUG_ADDR, reg); + qm_val = ar40xx_read(priv, AR40XX_REG_QM_DEBUG_VALUE); + /* every 8 bits for each port */ + *qm_buffer_err = (qm_val >> ((port_id-4) * 8)) & 0xFF; + } + + return 0; +} + +static void +ar40xx_sw_mac_polling_task(struct ar40xx_priv *priv) +{ + static int task_count; + u32 i; + u32 reg, value; + u32 link, speed, duplex; + u32 qm_buffer_err; + u16 port_phy_status[AR40XX_NUM_PORTS]; + static u32 qm_err_cnt[AR40XX_NUM_PORTS] = {0, 0, 0, 0, 0, 0}; + static u32 link_cnt[AR40XX_NUM_PORTS] = {0, 0, 0, 0, 0, 0}; + struct mii_bus *bus = NULL; + + if (!priv || !priv->mii_bus) + return; + + bus = priv->mii_bus; + + ++task_count; + + for (i = 1; i < AR40XX_NUM_PORTS; ++i) { + port_phy_status[i] = + mdiobus_read(bus, i-1, AR40XX_PHY_SPEC_STATUS); + speed = link = duplex = port_phy_status[i]; + speed &= AR40XX_PHY_SPEC_STATUS_SPEED; + speed >>= 14; + link &= AR40XX_PHY_SPEC_STATUS_LINK; + link >>= 10; + duplex &= AR40XX_PHY_SPEC_STATUS_DUPLEX; + duplex >>= 13; + + if (link != priv->ar40xx_port_old_link[i]) { + ++link_cnt[i]; + /* Up --> Down */ + if ((priv->ar40xx_port_old_link[i] == + AR40XX_PORT_LINK_UP) && + (link == AR40XX_PORT_LINK_DOWN)) { + /* LINK_EN disable(MAC force mode)*/ + reg = AR40XX_REG_PORT_STATUS(i); + ar40xx_rmw(priv, reg, + AR40XX_PORT_AUTO_LINK_EN, 0); + + /* Check queue buffer */ + qm_err_cnt[i] = 0; + ar40xx_get_qm_status(priv, i, &qm_buffer_err); + if (qm_buffer_err) { + priv->ar40xx_port_qm_buf[i] = + AR40XX_QM_NOT_EMPTY; + } else { + u16 phy_val = 0; + + priv->ar40xx_port_qm_buf[i] = + AR40XX_QM_EMPTY; + ar40xx_force_1g_full(priv, i); + /* Ref:QCA8337 Datasheet,Clearing + * MENU_CTRL_EN prevents phy to + * stuck in 100BT mode when + * bringing up the link + */ + ar40xx_phy_dbg_read(priv, i-1, + AR40XX_PHY_DEBUG_0, + &phy_val); + phy_val &= (~AR40XX_PHY_MANU_CTRL_EN); + ar40xx_phy_dbg_write(priv, i-1, + AR40XX_PHY_DEBUG_0, + phy_val); + } + priv->ar40xx_port_old_link[i] = link; + } else if ((priv->ar40xx_port_old_link[i] == + AR40XX_PORT_LINK_DOWN) && + (link == AR40XX_PORT_LINK_UP)) { + /* Down --> Up */ + if (priv->port_link_up[i] < 1) { + ++priv->port_link_up[i]; + } else { + /* Change port status */ + reg = AR40XX_REG_PORT_STATUS(i); + value = ar40xx_read(priv, reg); + priv->port_link_up[i] = 0; + + value &= ~(AR40XX_PORT_DUPLEX | + AR40XX_PORT_SPEED); + value |= speed | (duplex ? BIT(6) : 0); + ar40xx_write(priv, reg, value); + /* clock switch need such time + * to avoid glitch + */ + usleep_range(100, 200); + + value |= AR40XX_PORT_AUTO_LINK_EN; + ar40xx_write(priv, reg, value); + /* HW need such time to make sure link + * stable before enable MAC + */ + usleep_range(100, 200); + + if (speed == AR40XX_PORT_SPEED_100M) { + u16 phy_val = 0; + /* Enable @100M, if down to 10M + * clock will change smoothly + */ + ar40xx_phy_dbg_read(priv, i-1, + 0, + &phy_val); + phy_val |= + AR40XX_PHY_MANU_CTRL_EN; + ar40xx_phy_dbg_write(priv, i-1, + 0, + phy_val); + } + priv->ar40xx_port_old_link[i] = link; + } + } + } + + if (priv->ar40xx_port_qm_buf[i] == AR40XX_QM_NOT_EMPTY) { + /* Check QM */ + ar40xx_get_qm_status(priv, i, &qm_buffer_err); + if (qm_buffer_err) { + ++qm_err_cnt[i]; + } else { + priv->ar40xx_port_qm_buf[i] = + AR40XX_QM_EMPTY; + qm_err_cnt[i] = 0; + ar40xx_force_1g_full(priv, i); + } + } + } +} + +static void +ar40xx_qm_err_check_work_task(struct work_struct *work) +{ + struct ar40xx_priv *priv = container_of(work, struct ar40xx_priv, + qm_dwork.work); + + mutex_lock(&priv->qm_lock); + + ar40xx_sw_mac_polling_task(priv); + + mutex_unlock(&priv->qm_lock); + + schedule_delayed_work(&priv->qm_dwork, + msecs_to_jiffies(AR40XX_QM_WORK_DELAY)); +} + +static int +ar40xx_qm_err_check_work_start(struct ar40xx_priv *priv) +{ + mutex_init(&priv->qm_lock); + + INIT_DELAYED_WORK(&priv->qm_dwork, ar40xx_qm_err_check_work_task); + + schedule_delayed_work(&priv->qm_dwork, + msecs_to_jiffies(AR40XX_QM_WORK_DELAY)); + + return 0; +} + +/* End of qm error WAR */ + +static int +ar40xx_vlan_init(struct ar40xx_priv *priv) +{ + int port; + unsigned long bmp; + + /* By default Enable VLAN */ + priv->vlan = 1; + priv->vlan_table[AR40XX_LAN_VLAN] = priv->cpu_bmp | priv->lan_bmp; + priv->vlan_table[AR40XX_WAN_VLAN] = priv->cpu_bmp | priv->wan_bmp; + priv->vlan_tagged = priv->cpu_bmp; + bmp = priv->lan_bmp; + for_each_set_bit(port, &bmp, AR40XX_NUM_PORTS) + priv->pvid[port] = AR40XX_LAN_VLAN; + + bmp = priv->wan_bmp; + for_each_set_bit(port, &bmp, AR40XX_NUM_PORTS) + priv->pvid[port] = AR40XX_WAN_VLAN; + + return 0; +} + +static void +ar40xx_mib_work_func(struct work_struct *work) +{ + struct ar40xx_priv *priv; + int err; + + priv = container_of(work, struct ar40xx_priv, mib_work.work); + + mutex_lock(&priv->mib_lock); + + err = ar40xx_mib_capture(priv); + if (err) + goto next_port; + + ar40xx_mib_fetch_port_stat(priv, priv->mib_next_port, false); + +next_port: + priv->mib_next_port++; + if (priv->mib_next_port >= priv->dev.ports) + priv->mib_next_port = 0; + + mutex_unlock(&priv->mib_lock); + + schedule_delayed_work(&priv->mib_work, + msecs_to_jiffies(AR40XX_MIB_WORK_DELAY)); +} + +static void +ar40xx_setup_port(struct ar40xx_priv *priv, int port, u32 members) +{ + u32 t; + u32 egress, ingress; + u32 pvid = priv->vlan_id[priv->pvid[port]]; + + if (priv->vlan) { + if (priv->vlan_tagged & BIT(port)) + egress = AR40XX_PORT_VLAN1_OUT_MODE_TAG; + else + egress = AR40XX_PORT_VLAN1_OUT_MODE_UNMOD; + + ingress = AR40XX_IN_SECURE; + } else { + egress = AR40XX_PORT_VLAN1_OUT_MODE_UNTOUCH; + ingress = AR40XX_IN_PORT_ONLY; + } + + t = pvid << AR40XX_PORT_VLAN0_DEF_SVID_S; + t |= pvid << AR40XX_PORT_VLAN0_DEF_CVID_S; + ar40xx_write(priv, AR40XX_REG_PORT_VLAN0(port), t); + + t = egress << AR40XX_PORT_VLAN1_OUT_MODE_S; + + /* set CPU port to core port */ + if (port == 0) + t |= AR40XX_PORT_VLAN1_CORE_PORT; + + if (priv->vlan_tagged & BIT(port)) + t |= AR40XX_PORT_VLAN1_PORT_VLAN_PROP; + else + t |= AR40XX_PORT_VLAN1_PORT_TLS_MODE; + + ar40xx_write(priv, AR40XX_REG_PORT_VLAN1(port), t); + + t = members; + t |= AR40XX_PORT_LOOKUP_LEARN; + t |= ingress << AR40XX_PORT_LOOKUP_IN_MODE_S; + t |= AR40XX_PORT_STATE_FORWARD << AR40XX_PORT_LOOKUP_STATE_S; + ar40xx_write(priv, AR40XX_REG_PORT_LOOKUP(port), t); +} + +static void +ar40xx_vtu_op(struct ar40xx_priv *priv, u32 op, u32 val) +{ + if (ar40xx_wait_bit(priv, AR40XX_REG_VTU_FUNC1, + AR40XX_VTU_FUNC1_BUSY, 0)) + return; + + if ((op & AR40XX_VTU_FUNC1_OP) == AR40XX_VTU_FUNC1_OP_LOAD) + ar40xx_write(priv, AR40XX_REG_VTU_FUNC0, val); + + op |= AR40XX_VTU_FUNC1_BUSY; + ar40xx_write(priv, AR40XX_REG_VTU_FUNC1, op); +} + +static void +ar40xx_vtu_load_vlan(struct ar40xx_priv *priv, u32 vid, u32 port_mask) +{ + u32 op; + u32 val; + int i; + + op = AR40XX_VTU_FUNC1_OP_LOAD | (vid << AR40XX_VTU_FUNC1_VID_S); + val = AR40XX_VTU_FUNC0_VALID | AR40XX_VTU_FUNC0_IVL; + for (i = 0; i < AR40XX_NUM_PORTS; i++) { + u32 mode; + + if ((port_mask & BIT(i)) == 0) + mode = AR40XX_VTU_FUNC0_EG_MODE_NOT; + else if (priv->vlan == 0) + mode = AR40XX_VTU_FUNC0_EG_MODE_KEEP; + else if ((priv->vlan_tagged & BIT(i)) || + (priv->vlan_id[priv->pvid[i]] != vid)) + mode = AR40XX_VTU_FUNC0_EG_MODE_TAG; + else + mode = AR40XX_VTU_FUNC0_EG_MODE_UNTAG; + + val |= mode << AR40XX_VTU_FUNC0_EG_MODE_S(i); + } + ar40xx_vtu_op(priv, op, val); +} + +static void +ar40xx_vtu_flush(struct ar40xx_priv *priv) +{ + ar40xx_vtu_op(priv, AR40XX_VTU_FUNC1_OP_FLUSH, 0); +} + +static int +ar40xx_sw_hw_apply(struct switch_dev *dev) +{ + struct ar40xx_priv *priv = swdev_to_ar40xx(dev); + u8 portmask[AR40XX_NUM_PORTS]; + int i, j; + + mutex_lock(&priv->reg_mutex); + /* flush all vlan entries */ + ar40xx_vtu_flush(priv); + + memset(portmask, 0, sizeof(portmask)); + if (priv->vlan) { + for (j = 0; j < AR40XX_MAX_VLANS; j++) { + u8 vp = priv->vlan_table[j]; + + if (!vp) + continue; + + for (i = 0; i < dev->ports; i++) { + u8 mask = BIT(i); + + if (vp & mask) + portmask[i] |= vp & ~mask; + } + + ar40xx_vtu_load_vlan(priv, priv->vlan_id[j], + priv->vlan_table[j]); + } + } else { + /* 8021q vlan disabled */ + for (i = 0; i < dev->ports; i++) { + if (i == AR40XX_PORT_CPU) + continue; + + portmask[i] = BIT(AR40XX_PORT_CPU); + portmask[AR40XX_PORT_CPU] |= BIT(i); + } + } + + /* update the port destination mask registers and tag settings */ + for (i = 0; i < dev->ports; i++) + ar40xx_setup_port(priv, i, portmask[i]); + + ar40xx_set_mirror_regs(priv); + + mutex_unlock(&priv->reg_mutex); + return 0; +} + +static int +ar40xx_sw_reset_switch(struct switch_dev *dev) +{ + struct ar40xx_priv *priv = swdev_to_ar40xx(dev); + int i, rv; + + mutex_lock(&priv->reg_mutex); + memset(&priv->vlan, 0, sizeof(struct ar40xx_priv) - + offsetof(struct ar40xx_priv, vlan)); + + for (i = 0; i < AR40XX_MAX_VLANS; i++) + priv->vlan_id[i] = i; + + ar40xx_vlan_init(priv); + + priv->mirror_rx = false; + priv->mirror_tx = false; + priv->source_port = 0; + priv->monitor_port = 0; + + mutex_unlock(&priv->reg_mutex); + + rv = ar40xx_sw_hw_apply(dev); + return rv; +} + +static int +ar40xx_start(struct ar40xx_priv *priv) +{ + int ret; + + ret = ar40xx_hw_init(priv); + if (ret) + return ret; + + ret = ar40xx_sw_reset_switch(&priv->dev); + if (ret) + return ret; + + /* at last, setup cpu port */ + ret = ar40xx_cpuport_setup(priv); + if (ret) + return ret; + + schedule_delayed_work(&priv->mib_work, + msecs_to_jiffies(AR40XX_MIB_WORK_DELAY)); + + ar40xx_qm_err_check_work_start(priv); + + return 0; +} + +static const struct switch_dev_ops ar40xx_sw_ops = { + .attr_global = { + .attr = ar40xx_sw_attr_globals, + .n_attr = ARRAY_SIZE(ar40xx_sw_attr_globals), + }, + .attr_port = { + .attr = ar40xx_sw_attr_port, + .n_attr = ARRAY_SIZE(ar40xx_sw_attr_port), + }, + .attr_vlan = { + .attr = ar40xx_sw_attr_vlan, + .n_attr = ARRAY_SIZE(ar40xx_sw_attr_vlan), + }, + .get_port_pvid = ar40xx_sw_get_pvid, + .set_port_pvid = ar40xx_sw_set_pvid, + .get_vlan_ports = ar40xx_sw_get_ports, + .set_vlan_ports = ar40xx_sw_set_ports, + .apply_config = ar40xx_sw_hw_apply, + .reset_switch = ar40xx_sw_reset_switch, + .get_port_link = ar40xx_sw_get_port_link, +}; + +/* Platform driver probe function */ + +static int ar40xx_probe(struct platform_device *pdev) +{ + struct device_node *switch_node; + struct device_node *psgmii_node; + struct device_node *mdio_node; + const __be32 *mac_mode; + struct clk *ess_clk; + struct switch_dev *swdev; + struct ar40xx_priv *priv; + u32 len; + u32 num_mibs; + struct resource psgmii_base = {0}; + struct resource switch_base = {0}; + int ret; + + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + platform_set_drvdata(pdev, priv); + ar40xx_priv = priv; + + switch_node = of_node_get(pdev->dev.of_node); + if (of_address_to_resource(switch_node, 0, &switch_base) != 0) + return -EIO; + + priv->hw_addr = devm_ioremap_resource(&pdev->dev, &switch_base); + if (IS_ERR(priv->hw_addr)) { + dev_err(&pdev->dev, "Failed to ioremap switch_base!\n"); + return PTR_ERR(priv->hw_addr); + } + + /*psgmii dts get*/ + psgmii_node = of_find_node_by_name(NULL, "ess-psgmii"); + if (!psgmii_node) { + dev_err(&pdev->dev, "Failed to find ess-psgmii node!\n"); + return -EINVAL; + } + + if (of_address_to_resource(psgmii_node, 0, &psgmii_base) != 0) + return -EIO; + + priv->psgmii_hw_addr = devm_ioremap_resource(&pdev->dev, &psgmii_base); + if (IS_ERR(priv->psgmii_hw_addr)) { + dev_err(&pdev->dev, "psgmii ioremap fail!\n"); + return PTR_ERR(priv->psgmii_hw_addr); + } + + mac_mode = of_get_property(switch_node, "switch_mac_mode", &len); + if (!mac_mode) { + dev_err(&pdev->dev, "Failed to read switch_mac_mode\n"); + return -EINVAL; + } + priv->mac_mode = be32_to_cpup(mac_mode); + + ess_clk = of_clk_get_by_name(switch_node, "ess_clk"); + if (ess_clk) + clk_prepare_enable(ess_clk); + + priv->ess_rst = devm_reset_control_get(&pdev->dev, "ess_rst"); + if (IS_ERR(priv->ess_rst)) { + dev_err(&pdev->dev, "Failed to get ess_rst control!\n"); + return PTR_ERR(priv->ess_rst); + } + + if (of_property_read_u32(switch_node, "switch_cpu_bmp", + &priv->cpu_bmp) || + of_property_read_u32(switch_node, "switch_lan_bmp", + &priv->lan_bmp) || + of_property_read_u32(switch_node, "switch_wan_bmp", + &priv->wan_bmp)) { + dev_err(&pdev->dev, "Failed to read port properties\n"); + return -EIO; + } + + mutex_init(&priv->reg_mutex); + mutex_init(&priv->mib_lock); + INIT_DELAYED_WORK(&priv->mib_work, ar40xx_mib_work_func); + + /* register switch */ + swdev = &priv->dev; + + mdio_node = of_find_compatible_node(NULL, NULL, "qcom,ipq4019-mdio"); + if (!mdio_node) { + dev_err(&pdev->dev, "Probe failed - Cannot find mdio node by phandle!\n"); + ret = -ENODEV; + goto err_missing_phy; + } + + priv->mii_bus = of_mdio_find_bus(mdio_node); + + if (priv->mii_bus == NULL) { + dev_err(&pdev->dev, "Probe failed - Missing PHYs!\n"); + ret = -ENODEV; + goto err_missing_phy; + } + + swdev->alias = dev_name(&priv->mii_bus->dev); + + swdev->cpu_port = AR40XX_PORT_CPU; + swdev->name = "QCA AR40xx"; + swdev->vlans = AR40XX_MAX_VLANS; + swdev->ports = AR40XX_NUM_PORTS; + swdev->ops = &ar40xx_sw_ops; + ret = register_switch(swdev, NULL); + if (ret < 0) { + dev_err(&pdev->dev, "Switch registration failed!\n"); + return ret; + } + + num_mibs = ARRAY_SIZE(ar40xx_mibs); + len = priv->dev.ports * num_mibs * + sizeof(*priv->mib_stats); + priv->mib_stats = devm_kzalloc(&pdev->dev, len, GFP_KERNEL); + if (!priv->mib_stats) { + ret = -ENOMEM; + goto err_unregister_switch; + } + + ar40xx_start(priv); + + return 0; + +err_unregister_switch: + unregister_switch(&priv->dev); +err_missing_phy: + platform_set_drvdata(pdev, NULL); + return ret; +} + +static int ar40xx_remove(struct platform_device *pdev) +{ + struct ar40xx_priv *priv = platform_get_drvdata(pdev); + + cancel_delayed_work_sync(&priv->qm_dwork); + cancel_delayed_work_sync(&priv->mib_work); + + unregister_switch(&priv->dev); + + return 0; +} + +static const struct of_device_id ar40xx_of_mtable[] = { + {.compatible = "qcom,ess-switch" }, + {} +}; + +struct platform_driver ar40xx_drv = { + .probe = ar40xx_probe, + .remove = ar40xx_remove, + .driver = { + .name = "ar40xx", + .of_match_table = ar40xx_of_mtable, + }, +}; + +module_platform_driver(ar40xx_drv); + +MODULE_DESCRIPTION("IPQ40XX ESS driver"); +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/feeds/ipq40xx/ipq40xx/files/drivers/net/phy/ar40xx.h b/feeds/ipq40xx/ipq40xx/files/drivers/net/phy/ar40xx.h new file mode 100644 index 000000000..7ba40ccf7 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/files/drivers/net/phy/ar40xx.h @@ -0,0 +1,342 @@ +/* + * Copyright (c) 2016, 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 __AR40XX_H +#define __AR40XX_H + +#define AR40XX_MAX_VLANS 128 +#define AR40XX_NUM_PORTS 6 +#define AR40XX_NUM_PHYS 5 + +#define BITS(_s, _n) (((1UL << (_n)) - 1) << _s) + +struct ar40xx_priv { + struct switch_dev dev; + + u8 __iomem *hw_addr; + u8 __iomem *psgmii_hw_addr; + u32 mac_mode; + struct reset_control *ess_rst; + u32 cpu_bmp; + u32 lan_bmp; + u32 wan_bmp; + + struct mii_bus *mii_bus; + struct phy_device *phy; + + /* mutex for qm task */ + struct mutex qm_lock; + struct delayed_work qm_dwork; + u32 port_link_up[AR40XX_NUM_PORTS]; + u32 ar40xx_port_old_link[AR40XX_NUM_PORTS]; + u32 ar40xx_port_qm_buf[AR40XX_NUM_PORTS]; + + u32 phy_t_status; + + /* mutex for switch reg access */ + struct mutex reg_mutex; + + /* mutex for mib task */ + struct mutex mib_lock; + struct delayed_work mib_work; + int mib_next_port; + u64 *mib_stats; + + char buf[2048]; + + /* all fields below will be cleared on reset */ + bool vlan; + u16 vlan_id[AR40XX_MAX_VLANS]; + u8 vlan_table[AR40XX_MAX_VLANS]; + u8 vlan_tagged; + u16 pvid[AR40XX_NUM_PORTS]; + + /* mirror */ + bool mirror_rx; + bool mirror_tx; + int source_port; + int monitor_port; +}; + +#define AR40XX_PORT_LINK_UP 1 +#define AR40XX_PORT_LINK_DOWN 0 +#define AR40XX_QM_NOT_EMPTY 1 +#define AR40XX_QM_EMPTY 0 + +#define AR40XX_LAN_VLAN 1 +#define AR40XX_WAN_VLAN 2 + +enum ar40xx_port_wrapper_cfg { + PORT_WRAPPER_PSGMII = 0, +}; + +struct ar40xx_mib_desc { + u32 size; + u32 offset; + const char *name; +}; + +#define AR40XX_PORT_CPU 0 + +#define AR40XX_PSGMII_MODE_CONTROL 0x1b4 +#define AR40XX_PSGMII_ATHR_CSCO_MODE_25M BIT(0) + +#define AR40XX_PSGMIIPHY_TX_CONTROL 0x288 + +#define AR40XX_MII_ATH_MMD_ADDR 0x0d +#define AR40XX_MII_ATH_MMD_DATA 0x0e +#define AR40XX_MII_ATH_DBG_ADDR 0x1d +#define AR40XX_MII_ATH_DBG_DATA 0x1e + +#define AR40XX_STATS_RXBROAD 0x00 +#define AR40XX_STATS_RXPAUSE 0x04 +#define AR40XX_STATS_RXMULTI 0x08 +#define AR40XX_STATS_RXFCSERR 0x0c +#define AR40XX_STATS_RXALIGNERR 0x10 +#define AR40XX_STATS_RXRUNT 0x14 +#define AR40XX_STATS_RXFRAGMENT 0x18 +#define AR40XX_STATS_RX64BYTE 0x1c +#define AR40XX_STATS_RX128BYTE 0x20 +#define AR40XX_STATS_RX256BYTE 0x24 +#define AR40XX_STATS_RX512BYTE 0x28 +#define AR40XX_STATS_RX1024BYTE 0x2c +#define AR40XX_STATS_RX1518BYTE 0x30 +#define AR40XX_STATS_RXMAXBYTE 0x34 +#define AR40XX_STATS_RXTOOLONG 0x38 +#define AR40XX_STATS_RXGOODBYTE 0x3c +#define AR40XX_STATS_RXBADBYTE 0x44 +#define AR40XX_STATS_RXOVERFLOW 0x4c +#define AR40XX_STATS_FILTERED 0x50 +#define AR40XX_STATS_TXBROAD 0x54 +#define AR40XX_STATS_TXPAUSE 0x58 +#define AR40XX_STATS_TXMULTI 0x5c +#define AR40XX_STATS_TXUNDERRUN 0x60 +#define AR40XX_STATS_TX64BYTE 0x64 +#define AR40XX_STATS_TX128BYTE 0x68 +#define AR40XX_STATS_TX256BYTE 0x6c +#define AR40XX_STATS_TX512BYTE 0x70 +#define AR40XX_STATS_TX1024BYTE 0x74 +#define AR40XX_STATS_TX1518BYTE 0x78 +#define AR40XX_STATS_TXMAXBYTE 0x7c +#define AR40XX_STATS_TXOVERSIZE 0x80 +#define AR40XX_STATS_TXBYTE 0x84 +#define AR40XX_STATS_TXCOLLISION 0x8c +#define AR40XX_STATS_TXABORTCOL 0x90 +#define AR40XX_STATS_TXMULTICOL 0x94 +#define AR40XX_STATS_TXSINGLECOL 0x98 +#define AR40XX_STATS_TXEXCDEFER 0x9c +#define AR40XX_STATS_TXDEFER 0xa0 +#define AR40XX_STATS_TXLATECOL 0xa4 + +#define AR40XX_REG_MODULE_EN 0x030 +#define AR40XX_MODULE_EN_MIB BIT(0) + +#define AR40XX_REG_MIB_FUNC 0x034 +#define AR40XX_MIB_BUSY BIT(17) +#define AR40XX_MIB_CPU_KEEP BIT(20) +#define AR40XX_MIB_FUNC BITS(24, 3) +#define AR40XX_MIB_FUNC_S 24 +#define AR40XX_MIB_FUNC_NO_OP 0x0 +#define AR40XX_MIB_FUNC_FLUSH 0x1 + +#define AR40XX_ESS_SERVICE_TAG 0x48 +#define AR40XX_ESS_SERVICE_TAG_STAG BIT(17) + +#define AR40XX_REG_PORT_STATUS(_i) (0x07c + (_i) * 4) +#define AR40XX_PORT_SPEED BITS(0, 2) +#define AR40XX_PORT_STATUS_SPEED_S 0 +#define AR40XX_PORT_TX_EN BIT(2) +#define AR40XX_PORT_RX_EN BIT(3) +#define AR40XX_PORT_STATUS_TXFLOW BIT(4) +#define AR40XX_PORT_STATUS_RXFLOW BIT(5) +#define AR40XX_PORT_DUPLEX BIT(6) +#define AR40XX_PORT_TXHALF_FLOW BIT(7) +#define AR40XX_PORT_STATUS_LINK_UP BIT(8) +#define AR40XX_PORT_AUTO_LINK_EN BIT(9) +#define AR40XX_PORT_STATUS_FLOW_CONTROL BIT(12) + +#define AR40XX_REG_MAX_FRAME_SIZE 0x078 +#define AR40XX_MAX_FRAME_SIZE_MTU BITS(0, 14) + +#define AR40XX_REG_PORT_HEADER(_i) (0x09c + (_i) * 4) + +#define AR40XX_REG_EEE_CTRL 0x100 +#define AR40XX_EEE_CTRL_DISABLE_PHY(_i) BIT(4 + (_i) * 2) + +#define AR40XX_REG_PORT_VLAN0(_i) (0x420 + (_i) * 0x8) +#define AR40XX_PORT_VLAN0_DEF_SVID BITS(0, 12) +#define AR40XX_PORT_VLAN0_DEF_SVID_S 0 +#define AR40XX_PORT_VLAN0_DEF_CVID BITS(16, 12) +#define AR40XX_PORT_VLAN0_DEF_CVID_S 16 + +#define AR40XX_REG_PORT_VLAN1(_i) (0x424 + (_i) * 0x8) +#define AR40XX_PORT_VLAN1_CORE_PORT BIT(9) +#define AR40XX_PORT_VLAN1_PORT_TLS_MODE BIT(7) +#define AR40XX_PORT_VLAN1_PORT_VLAN_PROP BIT(6) +#define AR40XX_PORT_VLAN1_OUT_MODE BITS(12, 2) +#define AR40XX_PORT_VLAN1_OUT_MODE_S 12 +#define AR40XX_PORT_VLAN1_OUT_MODE_UNMOD 0 +#define AR40XX_PORT_VLAN1_OUT_MODE_UNTAG 1 +#define AR40XX_PORT_VLAN1_OUT_MODE_TAG 2 +#define AR40XX_PORT_VLAN1_OUT_MODE_UNTOUCH 3 + +#define AR40XX_REG_VTU_FUNC0 0x0610 +#define AR40XX_VTU_FUNC0_EG_MODE BITS(4, 14) +#define AR40XX_VTU_FUNC0_EG_MODE_S(_i) (4 + (_i) * 2) +#define AR40XX_VTU_FUNC0_EG_MODE_KEEP 0 +#define AR40XX_VTU_FUNC0_EG_MODE_UNTAG 1 +#define AR40XX_VTU_FUNC0_EG_MODE_TAG 2 +#define AR40XX_VTU_FUNC0_EG_MODE_NOT 3 +#define AR40XX_VTU_FUNC0_IVL BIT(19) +#define AR40XX_VTU_FUNC0_VALID BIT(20) + +#define AR40XX_REG_VTU_FUNC1 0x0614 +#define AR40XX_VTU_FUNC1_OP BITS(0, 3) +#define AR40XX_VTU_FUNC1_OP_NOOP 0 +#define AR40XX_VTU_FUNC1_OP_FLUSH 1 +#define AR40XX_VTU_FUNC1_OP_LOAD 2 +#define AR40XX_VTU_FUNC1_OP_PURGE 3 +#define AR40XX_VTU_FUNC1_OP_REMOVE_PORT 4 +#define AR40XX_VTU_FUNC1_OP_GET_NEXT 5 +#define AR40XX7_VTU_FUNC1_OP_GET_ONE 6 +#define AR40XX_VTU_FUNC1_FULL BIT(4) +#define AR40XX_VTU_FUNC1_PORT BIT(8, 4) +#define AR40XX_VTU_FUNC1_PORT_S 8 +#define AR40XX_VTU_FUNC1_VID BIT(16, 12) +#define AR40XX_VTU_FUNC1_VID_S 16 +#define AR40XX_VTU_FUNC1_BUSY BIT(31) + +#define AR40XX_REG_FWD_CTRL0 0x620 +#define AR40XX_FWD_CTRL0_CPU_PORT_EN BIT(10) +#define AR40XX_FWD_CTRL0_MIRROR_PORT BITS(4, 4) +#define AR40XX_FWD_CTRL0_MIRROR_PORT_S 4 + +#define AR40XX_REG_FWD_CTRL1 0x624 +#define AR40XX_FWD_CTRL1_UC_FLOOD BITS(0, 7) +#define AR40XX_FWD_CTRL1_UC_FLOOD_S 0 +#define AR40XX_FWD_CTRL1_MC_FLOOD BITS(8, 7) +#define AR40XX_FWD_CTRL1_MC_FLOOD_S 8 +#define AR40XX_FWD_CTRL1_BC_FLOOD BITS(16, 7) +#define AR40XX_FWD_CTRL1_BC_FLOOD_S 16 +#define AR40XX_FWD_CTRL1_IGMP BITS(24, 7) +#define AR40XX_FWD_CTRL1_IGMP_S 24 + +#define AR40XX_REG_PORT_LOOKUP(_i) (0x660 + (_i) * 0xc) +#define AR40XX_PORT_LOOKUP_MEMBER BITS(0, 7) +#define AR40XX_PORT_LOOKUP_IN_MODE BITS(8, 2) +#define AR40XX_PORT_LOOKUP_IN_MODE_S 8 +#define AR40XX_PORT_LOOKUP_STATE BITS(16, 3) +#define AR40XX_PORT_LOOKUP_STATE_S 16 +#define AR40XX_PORT_LOOKUP_LEARN BIT(20) +#define AR40XX_PORT_LOOKUP_LOOPBACK BIT(21) +#define AR40XX_PORT_LOOKUP_ING_MIRROR_EN BIT(25) + +#define AR40XX_REG_ATU_FUNC 0x60c +#define AR40XX_ATU_FUNC_OP BITS(0, 4) +#define AR40XX_ATU_FUNC_OP_NOOP 0x0 +#define AR40XX_ATU_FUNC_OP_FLUSH 0x1 +#define AR40XX_ATU_FUNC_OP_LOAD 0x2 +#define AR40XX_ATU_FUNC_OP_PURGE 0x3 +#define AR40XX_ATU_FUNC_OP_FLUSH_LOCKED 0x4 +#define AR40XX_ATU_FUNC_OP_FLUSH_UNICAST 0x5 +#define AR40XX_ATU_FUNC_OP_GET_NEXT 0x6 +#define AR40XX_ATU_FUNC_OP_SEARCH_MAC 0x7 +#define AR40XX_ATU_FUNC_OP_CHANGE_TRUNK 0x8 +#define AR40XX_ATU_FUNC_BUSY BIT(31) + +#define AR40XX_REG_QM_DEBUG_ADDR 0x820 +#define AR40XX_REG_QM_DEBUG_VALUE 0x824 +#define AR40XX_REG_QM_PORT0_3_QNUM 0x1d +#define AR40XX_REG_QM_PORT4_6_QNUM 0x1e + +#define AR40XX_REG_PORT_HOL_CTRL1(_i) (0x974 + (_i) * 0x8) +#define AR40XX_PORT_HOL_CTRL1_EG_MIRROR_EN BIT(16) + +#define AR40XX_REG_PORT_FLOWCTRL_THRESH(_i) (0x9b0 + (_i) * 0x4) +#define AR40XX_PORT0_FC_THRESH_ON_DFLT 0x60 +#define AR40XX_PORT0_FC_THRESH_OFF_DFLT 0x90 + +#define AR40XX_PHY_DEBUG_0 0 +#define AR40XX_PHY_MANU_CTRL_EN BIT(12) + +#define AR40XX_PHY_DEBUG_2 2 + +#define AR40XX_PHY_SPEC_STATUS 0x11 +#define AR40XX_PHY_SPEC_STATUS_LINK BIT(10) +#define AR40XX_PHY_SPEC_STATUS_DUPLEX BIT(13) +#define AR40XX_PHY_SPEC_STATUS_SPEED BITS(14, 2) + +/* port forwarding state */ +enum { + AR40XX_PORT_STATE_DISABLED = 0, + AR40XX_PORT_STATE_BLOCK = 1, + AR40XX_PORT_STATE_LISTEN = 2, + AR40XX_PORT_STATE_LEARN = 3, + AR40XX_PORT_STATE_FORWARD = 4 +}; + +/* ingress 802.1q mode */ +enum { + AR40XX_IN_PORT_ONLY = 0, + AR40XX_IN_PORT_FALLBACK = 1, + AR40XX_IN_VLAN_ONLY = 2, + AR40XX_IN_SECURE = 3 +}; + +/* egress 802.1q mode */ +enum { + AR40XX_OUT_KEEP = 0, + AR40XX_OUT_STRIP_VLAN = 1, + AR40XX_OUT_ADD_VLAN = 2 +}; + +/* port speed */ +enum { + AR40XX_PORT_SPEED_10M = 0, + AR40XX_PORT_SPEED_100M = 1, + AR40XX_PORT_SPEED_1000M = 2, + AR40XX_PORT_SPEED_ERR = 3, +}; + +#define AR40XX_MIB_WORK_DELAY 2000 /* msecs */ + +#define AR40XX_QM_WORK_DELAY 100 + +#define AR40XX_MIB_FUNC_CAPTURE 0x3 + +#define AR40XX_REG_PORT_STATS_START 0x1000 +#define AR40XX_REG_PORT_STATS_LEN 0x100 + +#define AR40XX_PORTS_ALL 0x3f + +#define AR40XX_PSGMII_ID 5 +#define AR40XX_PSGMII_CALB_NUM 100 +#define AR40XX_MALIBU_PSGMII_MODE_CTRL 0x6d +#define AR40XX_MALIBU_PHY_PSGMII_MODE_CTRL_ADJUST_VAL 0x220c +#define AR40XX_MALIBU_PHY_MMD7_DAC_CTRL 0x801a +#define AR40XX_MALIBU_DAC_CTRL_MASK 0x380 +#define AR40XX_MALIBU_DAC_CTRL_VALUE 0x280 +#define AR40XX_MALIBU_PHY_RLP_CTRL 0x805a +#define AR40XX_PSGMII_TX_DRIVER_1_CTRL 0xb +#define AR40XX_MALIBU_PHY_PSGMII_REDUCE_SERDES_TX_AMP 0x8a +#define AR40XX_MALIBU_PHY_LAST_ADDR 4 + +static inline struct ar40xx_priv * +swdev_to_ar40xx(struct switch_dev *swdev) +{ + return container_of(swdev, struct ar40xx_priv, dev); +} + +#endif diff --git a/feeds/ipq40xx/ipq40xx/files/drivers/net/phy/qca807x.c b/feeds/ipq40xx/ipq40xx/files/drivers/net/phy/qca807x.c new file mode 100644 index 000000000..16d7a8045 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/files/drivers/net/phy/qca807x.c @@ -0,0 +1,829 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2020 Sartura Ltd. + * + * Author: Robert Marko + * + * Qualcomm QCA8072 and QCA8075 PHY driver + */ + +#include +#include +#include +#include +#include +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,8,0) +#include +#endif +#include +#include + +#include + +#define PHY_ID_QCA8072 0x004dd0b2 +#define PHY_ID_QCA8075 0x004dd0b1 +#define PHY_ID_QCA807X_PSGMII 0x06820805 + +/* Downshift */ +#define QCA807X_SMARTSPEED_EN BIT(5) +#define QCA807X_SMARTSPEED_RETRY_LIMIT_MASK GENMASK(4, 2) +#define QCA807X_SMARTSPEED_RETRY_LIMIT_DEFAULT 5 +#define QCA807X_SMARTSPEED_RETRY_LIMIT_MIN 2 +#define QCA807X_SMARTSPEED_RETRY_LIMIT_MAX 9 + +/* Cable diagnostic test (CDT) */ +#define QCA807X_CDT 0x16 +#define QCA807X_CDT_ENABLE BIT(15) +#define QCA807X_CDT_ENABLE_INTER_PAIR_SHORT BIT(13) +#define QCA807X_CDT_STATUS BIT(11) +#define QCA807X_CDT_MMD3_STATUS 0x8064 +#define QCA807X_CDT_MDI0_STATUS_MASK GENMASK(15, 12) +#define QCA807X_CDT_MDI1_STATUS_MASK GENMASK(11, 8) +#define QCA807X_CDT_MDI2_STATUS_MASK GENMASK(7, 4) +#define QCA807X_CDT_MDI3_STATUS_MASK GENMASK(3, 0) +#define QCA807X_CDT_RESULTS_INVALID 0x0 +#define QCA807X_CDT_RESULTS_OK 0x1 +#define QCA807X_CDT_RESULTS_OPEN 0x2 +#define QCA807X_CDT_RESULTS_SAME_SHORT 0x3 +#define QCA807X_CDT_RESULTS_CROSS_SHORT_WITH_MDI1_SAME_OK 0x4 +#define QCA807X_CDT_RESULTS_CROSS_SHORT_WITH_MDI2_SAME_OK 0x8 +#define QCA807X_CDT_RESULTS_CROSS_SHORT_WITH_MDI3_SAME_OK 0xc +#define QCA807X_CDT_RESULTS_CROSS_SHORT_WITH_MDI1_SAME_OPEN 0x6 +#define QCA807X_CDT_RESULTS_CROSS_SHORT_WITH_MDI2_SAME_OPEN 0xa +#define QCA807X_CDT_RESULTS_CROSS_SHORT_WITH_MDI3_SAME_OPEN 0xe +#define QCA807X_CDT_RESULTS_CROSS_SHORT_WITH_MDI1_SAME_SHORT 0x7 +#define QCA807X_CDT_RESULTS_CROSS_SHORT_WITH_MDI2_SAME_SHORT 0xb +#define QCA807X_CDT_RESULTS_CROSS_SHORT_WITH_MDI3_SAME_SHORT 0xf +#define QCA807X_CDT_RESULTS_BUSY 0x9 +#define QCA807X_CDT_MMD3_MDI0_LENGTH 0x8065 +#define QCA807X_CDT_MMD3_MDI1_LENGTH 0x8066 +#define QCA807X_CDT_MMD3_MDI2_LENGTH 0x8067 +#define QCA807X_CDT_MMD3_MDI3_LENGTH 0x8068 +#define QCA807X_CDT_SAME_SHORT_LENGTH_MASK GENMASK(15, 8) +#define QCA807X_CDT_CROSS_SHORT_LENGTH_MASK GENMASK(7, 0) + +#define QCA807X_CHIP_CONFIGURATION 0x1f +#define QCA807X_BT_BX_REG_SEL BIT(15) +#define QCA807X_CHIP_CONFIGURATION_MODE_CFG_MASK GENMASK(3, 0) +#define QCA807X_CHIP_CONFIGURATION_MODE_QSGMII_SGMII 4 +#define QCA807X_CHIP_CONFIGURATION_MODE_PSGMII_FIBER 3 +#define QCA807X_CHIP_CONFIGURATION_MODE_PSGMII_ALL_COPPER 0 + +#define QCA807X_MEDIA_SELECT_STATUS 0x1a +#define QCA807X_MEDIA_DETECTED_COPPER BIT(5) +#define QCA807X_MEDIA_DETECTED_1000_BASE_X BIT(4) +#define QCA807X_MEDIA_DETECTED_100_BASE_FX BIT(3) + +#define QCA807X_MMD7_FIBER_MODE_AUTO_DETECTION 0x807e +#define QCA807X_MMD7_FIBER_MODE_AUTO_DETECTION_EN BIT(0) + +#define QCA807X_MMD7_1000BASE_T_POWER_SAVE_PER_CABLE_LENGTH 0x801a +#define QCA807X_CONTROL_DAC_MASK GENMASK(2, 0) + +#define QCA807X_MMD7_LED_100N_1 0x8074 +#define QCA807X_MMD7_LED_100N_2 0x8075 +#define QCA807X_MMD7_LED_1000N_1 0x8076 +#define QCA807X_MMD7_LED_1000N_2 0x8077 +#define QCA807X_LED_TXACT_BLK_EN_2 BIT(10) +#define QCA807X_LED_RXACT_BLK_EN_2 BIT(9) +#define QCA807X_LED_GT_ON_EN_2 BIT(6) +#define QCA807X_LED_HT_ON_EN_2 BIT(5) +#define QCA807X_LED_BT_ON_EN_2 BIT(4) +#define QCA807X_GPIO_FORCE_EN BIT(15) +#define QCA807X_GPIO_FORCE_MODE_MASK GENMASK(14, 13) + +#define QCA807X_INTR_ENABLE 0x12 +#define QCA807X_INTR_STATUS 0x13 +#define QCA807X_INTR_ENABLE_AUTONEG_ERR BIT(15) +#define QCA807X_INTR_ENABLE_SPEED_CHANGED BIT(14) +#define QCA807X_INTR_ENABLE_DUPLEX_CHANGED BIT(13) +#define QCA807X_INTR_ENABLE_LINK_FAIL BIT(11) +#define QCA807X_INTR_ENABLE_LINK_SUCCESS BIT(10) + +#define QCA807X_FUNCTION_CONTROL 0x10 +#define QCA807X_FC_MDI_CROSSOVER_MODE_MASK GENMASK(6, 5) +#define QCA807X_FC_MDI_CROSSOVER_AUTO 3 +#define QCA807X_FC_MDI_CROSSOVER_MANUAL_MDIX 1 +#define QCA807X_FC_MDI_CROSSOVER_MANUAL_MDI 0 + +#define QCA807X_PHY_SPECIFIC_STATUS 0x11 +#define QCA807X_SS_SPEED_AND_DUPLEX_RESOLVED BIT(11) +#define QCA807X_SS_SPEED_MASK GENMASK(15, 14) +#define QCA807X_SS_SPEED_1000 2 +#define QCA807X_SS_SPEED_100 1 +#define QCA807X_SS_SPEED_10 0 +#define QCA807X_SS_DUPLEX BIT(13) +#define QCA807X_SS_MDIX BIT(6) + +/* PSGMII PHY specific */ +#define PSGMII_QSGMII_DRIVE_CONTROL_1 0xb +#define PSGMII_QSGMII_TX_DRIVER_MASK GENMASK(7, 4) +#define PSGMII_MODE_CTRL 0x6d +#define PSGMII_MODE_CTRL_AZ_WORKAROUND_MASK GENMASK(3, 0) +#define PSGMII_MMD3_SERDES_CONTROL 0x805a + +struct qca807x_gpio_priv { + struct phy_device *phy; +}; + +static int qca807x_get_downshift(struct phy_device *phydev, u8 *data) +{ + int val, cnt, enable; + + val = phy_read(phydev, MII_NWAYTEST); + if (val < 0) + return val; + + enable = FIELD_GET(QCA807X_SMARTSPEED_EN, val); + cnt = FIELD_GET(QCA807X_SMARTSPEED_RETRY_LIMIT_MASK, val) + 2; + + *data = enable ? cnt : DOWNSHIFT_DEV_DISABLE; + + return 0; +} + +static int qca807x_set_downshift(struct phy_device *phydev, u8 cnt) +{ + int ret, val; + + if (cnt > QCA807X_SMARTSPEED_RETRY_LIMIT_MAX || + (cnt < QCA807X_SMARTSPEED_RETRY_LIMIT_MIN && cnt != DOWNSHIFT_DEV_DISABLE)) + return -EINVAL; + + if (!cnt) { + ret = phy_clear_bits(phydev, MII_NWAYTEST, QCA807X_SMARTSPEED_EN); + } else { + val = QCA807X_SMARTSPEED_EN; + val |= FIELD_PREP(QCA807X_SMARTSPEED_RETRY_LIMIT_MASK, cnt - 2); + + phy_modify(phydev, MII_NWAYTEST, + QCA807X_SMARTSPEED_EN | + QCA807X_SMARTSPEED_RETRY_LIMIT_MASK, + val); + } + + ret = genphy_soft_reset(phydev); + + return ret; +} + +static int qca807x_get_tunable(struct phy_device *phydev, + struct ethtool_tunable *tuna, void *data) +{ + switch (tuna->id) { + case ETHTOOL_PHY_DOWNSHIFT: + return qca807x_get_downshift(phydev, data); + default: + return -EOPNOTSUPP; + } +} + +static int qca807x_set_tunable(struct phy_device *phydev, + struct ethtool_tunable *tuna, const void *data) +{ + switch (tuna->id) { + case ETHTOOL_PHY_DOWNSHIFT: + return qca807x_set_downshift(phydev, *(const u8 *)data); + default: + return -EOPNOTSUPP; + } +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,8,0) +static bool qca807x_distance_valid(int result) +{ + switch (result) { + case QCA807X_CDT_RESULTS_OPEN: + case QCA807X_CDT_RESULTS_SAME_SHORT: + case QCA807X_CDT_RESULTS_CROSS_SHORT_WITH_MDI1_SAME_OK: + case QCA807X_CDT_RESULTS_CROSS_SHORT_WITH_MDI2_SAME_OK: + case QCA807X_CDT_RESULTS_CROSS_SHORT_WITH_MDI3_SAME_OK: + case QCA807X_CDT_RESULTS_CROSS_SHORT_WITH_MDI1_SAME_OPEN: + case QCA807X_CDT_RESULTS_CROSS_SHORT_WITH_MDI2_SAME_OPEN: + case QCA807X_CDT_RESULTS_CROSS_SHORT_WITH_MDI3_SAME_OPEN: + case QCA807X_CDT_RESULTS_CROSS_SHORT_WITH_MDI1_SAME_SHORT: + case QCA807X_CDT_RESULTS_CROSS_SHORT_WITH_MDI2_SAME_SHORT: + case QCA807X_CDT_RESULTS_CROSS_SHORT_WITH_MDI3_SAME_SHORT: + return true; + } + return false; +} + +static int qca807x_report_length(struct phy_device *phydev, + int pair, int result) +{ + int length; + int ret; + + ret = phy_read_mmd(phydev, MDIO_MMD_PCS, QCA807X_CDT_MMD3_MDI0_LENGTH + pair); + if (ret < 0) + return ret; + + switch (result) { + case ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT: + length = (FIELD_GET(QCA807X_CDT_SAME_SHORT_LENGTH_MASK, ret) * 800) / 10; + break; + case ETHTOOL_A_CABLE_RESULT_CODE_OPEN: + case ETHTOOL_A_CABLE_RESULT_CODE_CROSS_SHORT: + length = (FIELD_GET(QCA807X_CDT_CROSS_SHORT_LENGTH_MASK, ret) * 800) / 10; + break; + } + + ethnl_cable_test_fault_length(phydev, pair, length); + + return 0; +} + +static int qca807x_cable_test_report_trans(int result) +{ + switch (result) { + case QCA807X_CDT_RESULTS_OK: + return ETHTOOL_A_CABLE_RESULT_CODE_OK; + case QCA807X_CDT_RESULTS_OPEN: + return ETHTOOL_A_CABLE_RESULT_CODE_OPEN; + case QCA807X_CDT_RESULTS_SAME_SHORT: + return ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT; + case QCA807X_CDT_RESULTS_CROSS_SHORT_WITH_MDI1_SAME_OK: + case QCA807X_CDT_RESULTS_CROSS_SHORT_WITH_MDI2_SAME_OK: + case QCA807X_CDT_RESULTS_CROSS_SHORT_WITH_MDI3_SAME_OK: + case QCA807X_CDT_RESULTS_CROSS_SHORT_WITH_MDI1_SAME_OPEN: + case QCA807X_CDT_RESULTS_CROSS_SHORT_WITH_MDI2_SAME_OPEN: + case QCA807X_CDT_RESULTS_CROSS_SHORT_WITH_MDI3_SAME_OPEN: + case QCA807X_CDT_RESULTS_CROSS_SHORT_WITH_MDI1_SAME_SHORT: + case QCA807X_CDT_RESULTS_CROSS_SHORT_WITH_MDI2_SAME_SHORT: + case QCA807X_CDT_RESULTS_CROSS_SHORT_WITH_MDI3_SAME_SHORT: + return ETHTOOL_A_CABLE_RESULT_CODE_CROSS_SHORT; + default: + return ETHTOOL_A_CABLE_RESULT_CODE_UNSPEC; + } +} + +static int qca807x_cable_test_report(struct phy_device *phydev) +{ + int pair0, pair1, pair2, pair3; + int ret; + + ret = phy_read_mmd(phydev, MDIO_MMD_PCS, QCA807X_CDT_MMD3_STATUS); + if (ret < 0) + return ret; + + pair0 = FIELD_GET(QCA807X_CDT_MDI0_STATUS_MASK, ret); + pair1 = FIELD_GET(QCA807X_CDT_MDI1_STATUS_MASK, ret); + pair2 = FIELD_GET(QCA807X_CDT_MDI2_STATUS_MASK, ret); + pair3 = FIELD_GET(QCA807X_CDT_MDI3_STATUS_MASK, ret); + + ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_A, + qca807x_cable_test_report_trans(pair0)); + ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_B, + qca807x_cable_test_report_trans(pair1)); + ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_C, + qca807x_cable_test_report_trans(pair2)); + ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_D, + qca807x_cable_test_report_trans(pair3)); + + if (qca807x_distance_valid(pair0)) + qca807x_report_length(phydev, 0, qca807x_cable_test_report_trans(pair0)); + if (qca807x_distance_valid(pair1)) + qca807x_report_length(phydev, 1, qca807x_cable_test_report_trans(pair1)); + if (qca807x_distance_valid(pair2)) + qca807x_report_length(phydev, 2, qca807x_cable_test_report_trans(pair2)); + if (qca807x_distance_valid(pair3)) + qca807x_report_length(phydev, 3, qca807x_cable_test_report_trans(pair3)); + + return 0; +} + +static int qca807x_cable_test_get_status(struct phy_device *phydev, + bool *finished) +{ + int val; + + *finished = false; + + val = phy_read(phydev, QCA807X_CDT); + if (!((val & QCA807X_CDT_ENABLE) && (val & QCA807X_CDT_STATUS))) { + *finished = true; + + return qca807x_cable_test_report(phydev); + } + + return 0; +} + +static int qca807x_cable_test_start(struct phy_device *phydev) +{ + int val, ret; + + val = phy_read(phydev, QCA807X_CDT); + /* Enable inter-pair short check as well */ + val &= ~QCA807X_CDT_ENABLE_INTER_PAIR_SHORT; + val |= QCA807X_CDT_ENABLE; + ret = phy_write(phydev, QCA807X_CDT, val); + + return ret; +} +#endif + +#ifdef CONFIG_GPIOLIB +static int qca807x_gpio_get_direction(struct gpio_chip *gc, unsigned int offset) +{ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,5,0) + return GPIO_LINE_DIRECTION_OUT; +#else + return GPIOF_DIR_OUT; +#endif +} + +static int qca807x_gpio_get_reg(unsigned int offset) +{ + return QCA807X_MMD7_LED_100N_2 + (offset % 2) * 2; +} + +static int qca807x_gpio_get(struct gpio_chip *gc, unsigned int offset) +{ + struct qca807x_gpio_priv *priv = gpiochip_get_data(gc); + int val; + + val = phy_read_mmd(priv->phy, MDIO_MMD_AN, qca807x_gpio_get_reg(offset)); + + return FIELD_GET(QCA807X_GPIO_FORCE_MODE_MASK, val); +} + +static void qca807x_gpio_set(struct gpio_chip *gc, unsigned int offset, int value) +{ + struct qca807x_gpio_priv *priv = gpiochip_get_data(gc); + int val; + + val = phy_read_mmd(priv->phy, MDIO_MMD_AN, qca807x_gpio_get_reg(offset)); + val &= ~QCA807X_GPIO_FORCE_MODE_MASK; + val |= QCA807X_GPIO_FORCE_EN; + val |= FIELD_PREP(QCA807X_GPIO_FORCE_MODE_MASK, value); + + phy_write_mmd(priv->phy, MDIO_MMD_AN, qca807x_gpio_get_reg(offset), val); +} + +static int qca807x_gpio_dir_out(struct gpio_chip *gc, unsigned int offset, int value) +{ + qca807x_gpio_set(gc, offset, value); + + return 0; +} + +static int qca807x_gpio(struct phy_device *phydev) +{ + struct device *dev = &phydev->mdio.dev; + struct qca807x_gpio_priv *priv; + struct gpio_chip *gc; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->phy = phydev; + + gc = devm_kzalloc(dev, sizeof(*gc), GFP_KERNEL); + if (!gc) + return -ENOMEM; + + gc->label = dev_name(dev); + gc->base = -1; + gc->ngpio = 2; + gc->parent = dev; + gc->owner = THIS_MODULE; + gc->can_sleep = true; + gc->get_direction = qca807x_gpio_get_direction; + gc->direction_output = qca807x_gpio_dir_out; + gc->get = qca807x_gpio_get; + gc->set = qca807x_gpio_set; + + return devm_gpiochip_add_data(dev, gc, priv); +} +#endif + +static int qca807x_read_copper_status(struct phy_device *phydev, bool combo_port) +{ + int ss, err, page, old_link = phydev->link; + + /* Only combo port has dual pages */ + if (combo_port) { + /* Check whether copper page is set and set if needed */ + page = phy_read(phydev, QCA807X_CHIP_CONFIGURATION); + if (!(page & QCA807X_BT_BX_REG_SEL)) { + page |= QCA807X_BT_BX_REG_SEL; + phy_write(phydev, QCA807X_CHIP_CONFIGURATION, page); + } + } + + /* Update the link, but return if there was an error */ + err = genphy_update_link(phydev); + if (err) + return err; + + /* why bother the PHY if nothing can have changed */ + if (phydev->autoneg == AUTONEG_ENABLE && old_link && phydev->link) + return 0; + + phydev->speed = SPEED_UNKNOWN; + phydev->duplex = DUPLEX_UNKNOWN; + phydev->pause = 0; + phydev->asym_pause = 0; + + err = genphy_read_lpa(phydev); + if (err < 0) + return err; + + /* Read the QCA807x PHY-Specific Status register copper page, + * which indicates the speed and duplex that the PHY is actually + * using, irrespective of whether we are in autoneg mode or not. + */ + ss = phy_read(phydev, QCA807X_PHY_SPECIFIC_STATUS); + if (ss < 0) + return ss; + + if (ss & QCA807X_SS_SPEED_AND_DUPLEX_RESOLVED) { + int sfc; + + sfc = phy_read(phydev, QCA807X_FUNCTION_CONTROL); + if (sfc < 0) + return sfc; + + switch (FIELD_GET(QCA807X_SS_SPEED_MASK, ss)) { + case QCA807X_SS_SPEED_10: + phydev->speed = SPEED_10; + break; + case QCA807X_SS_SPEED_100: + phydev->speed = SPEED_100; + break; + case QCA807X_SS_SPEED_1000: + phydev->speed = SPEED_1000; + break; + } + if (ss & QCA807X_SS_DUPLEX) + phydev->duplex = DUPLEX_FULL; + else + phydev->duplex = DUPLEX_HALF; + + if (ss & QCA807X_SS_MDIX) + phydev->mdix = ETH_TP_MDI_X; + else + phydev->mdix = ETH_TP_MDI; + + switch (FIELD_GET(QCA807X_FC_MDI_CROSSOVER_MODE_MASK, sfc)) { + case QCA807X_FC_MDI_CROSSOVER_MANUAL_MDI: + phydev->mdix_ctrl = ETH_TP_MDI; + break; + case QCA807X_FC_MDI_CROSSOVER_MANUAL_MDIX: + phydev->mdix_ctrl = ETH_TP_MDI_X; + break; + case QCA807X_FC_MDI_CROSSOVER_AUTO: + phydev->mdix_ctrl = ETH_TP_MDI_AUTO; + break; + } + } + + if (phydev->autoneg == AUTONEG_ENABLE && phydev->autoneg_complete) + phy_resolve_aneg_pause(phydev); + + return 0; +} + +static int qca807x_read_fiber_status(struct phy_device *phydev, bool combo_port) +{ + int ss, err, page, lpa, old_link = phydev->link; + + /* Check whether fiber page is set and set if needed */ + page = phy_read(phydev, QCA807X_CHIP_CONFIGURATION); + if (page & QCA807X_BT_BX_REG_SEL) { + page &= ~QCA807X_BT_BX_REG_SEL; + phy_write(phydev, QCA807X_CHIP_CONFIGURATION, page); + } + + /* Update the link, but return if there was an error */ + err = genphy_update_link(phydev); + if (err) + return err; + + /* why bother the PHY if nothing can have changed */ + if (phydev->autoneg == AUTONEG_ENABLE && old_link && phydev->link) + return 0; + + phydev->speed = SPEED_UNKNOWN; + phydev->duplex = DUPLEX_UNKNOWN; + phydev->pause = 0; + phydev->asym_pause = 0; + + if (phydev->autoneg == AUTONEG_ENABLE && phydev->autoneg_complete) { + lpa = phy_read(phydev, MII_LPA); + if (lpa < 0) + return lpa; + + linkmode_mod_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, + phydev->lp_advertising, lpa & LPA_LPACK); + linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseX_Full_BIT, + phydev->lp_advertising, lpa & LPA_1000XFULL); + linkmode_mod_bit(ETHTOOL_LINK_MODE_Pause_BIT, + phydev->lp_advertising, lpa & LPA_1000XPAUSE); + linkmode_mod_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, + phydev->lp_advertising, + lpa & LPA_1000XPAUSE_ASYM); + + phy_resolve_aneg_linkmode(phydev); + } + + /* Read the QCA807x PHY-Specific Status register fiber page, + * which indicates the speed and duplex that the PHY is actually + * using, irrespective of whether we are in autoneg mode or not. + */ + ss = phy_read(phydev, QCA807X_PHY_SPECIFIC_STATUS); + if (ss < 0) + return ss; + + if (ss & QCA807X_SS_SPEED_AND_DUPLEX_RESOLVED) { + switch (FIELD_GET(QCA807X_SS_SPEED_MASK, ss)) { + case QCA807X_SS_SPEED_100: + phydev->speed = SPEED_100; + break; + case QCA807X_SS_SPEED_1000: + phydev->speed = SPEED_1000; + break; + } + + if (ss & QCA807X_SS_DUPLEX) + phydev->duplex = DUPLEX_FULL; + else + phydev->duplex = DUPLEX_HALF; + } + + return 0; +} + +static int qca807x_read_status(struct phy_device *phydev) +{ + int val; + + /* Check for Combo port */ + if (phy_read(phydev, QCA807X_CHIP_CONFIGURATION)) { + /* Check for fiber mode first */ + if (linkmode_test_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, phydev->supported)) { + /* Check for actual detected media */ + val = phy_read(phydev, QCA807X_MEDIA_SELECT_STATUS); + if (val & QCA807X_MEDIA_DETECTED_COPPER) { + qca807x_read_copper_status(phydev, true); + } else if ((val & QCA807X_MEDIA_DETECTED_1000_BASE_X) || + (val & QCA807X_MEDIA_DETECTED_100_BASE_FX)) { + qca807x_read_fiber_status(phydev, true); + } + } else { + qca807x_read_copper_status(phydev, true); + } + } else { + qca807x_read_copper_status(phydev, false); + } + + return 0; +} + +static int qca807x_config_intr(struct phy_device *phydev) +{ + int ret, val; + + val = phy_read(phydev, QCA807X_INTR_ENABLE); + + if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { + /* Check for combo port as it has fewer interrupts */ + if (phy_read(phydev, QCA807X_CHIP_CONFIGURATION)) { + val |= QCA807X_INTR_ENABLE_SPEED_CHANGED; + val |= QCA807X_INTR_ENABLE_LINK_FAIL; + val |= QCA807X_INTR_ENABLE_LINK_SUCCESS; + } else { + val |= QCA807X_INTR_ENABLE_AUTONEG_ERR; + val |= QCA807X_INTR_ENABLE_SPEED_CHANGED; + val |= QCA807X_INTR_ENABLE_DUPLEX_CHANGED; + val |= QCA807X_INTR_ENABLE_LINK_FAIL; + val |= QCA807X_INTR_ENABLE_LINK_SUCCESS; + } + ret = phy_write(phydev, QCA807X_INTR_ENABLE, val); + } else { + ret = phy_write(phydev, QCA807X_INTR_ENABLE, 0); + } + + return ret; +} + +static int qca807x_ack_intr(struct phy_device *phydev) +{ + int ret; + + ret = phy_read(phydev, QCA807X_INTR_STATUS); + + return (ret < 0) ? ret : 0; +} + +static int qca807x_led_config(struct phy_device *phydev) +{ + struct device_node *node = phydev->mdio.dev.of_node; + bool led_config = false; + int val; + + val = phy_read_mmd(phydev, MDIO_MMD_AN, QCA807X_MMD7_LED_1000N_1); + if (val < 0) + return val; + + if (of_property_read_bool(node, "qcom,single-led-1000")) { + val |= QCA807X_LED_TXACT_BLK_EN_2; + val |= QCA807X_LED_RXACT_BLK_EN_2; + val |= QCA807X_LED_GT_ON_EN_2; + + led_config = true; + } + + if (of_property_read_bool(node, "qcom,single-led-100")) { + val |= QCA807X_LED_HT_ON_EN_2; + + led_config = true; + } + + if (of_property_read_bool(node, "qcom,single-led-10")) { + val |= QCA807X_LED_BT_ON_EN_2; + + led_config = true; + } + + if (led_config) + return phy_write_mmd(phydev, MDIO_MMD_AN, QCA807X_MMD7_LED_1000N_1, val); + else + return 0; +} + +static const struct sfp_upstream_ops qca807x_sfp_ops = { + .attach = phy_sfp_attach, + .detach = phy_sfp_detach, +}; + +static int qca807x_config(struct phy_device *phydev) +{ + struct device_node *node = phydev->mdio.dev.of_node; + int control_dac, ret = 0; + u32 of_control_dac; + + /* Check for Combo port */ + if (phy_read(phydev, QCA807X_CHIP_CONFIGURATION)) { + int fiber_mode_autodect; + int psgmii_serdes; + int chip_config; + + if (of_property_read_bool(node, "qcom,fiber-enable")) { + /* Enable fiber mode autodection (1000Base-X or 100Base-FX) */ + fiber_mode_autodect = phy_read_mmd(phydev, MDIO_MMD_AN, + QCA807X_MMD7_FIBER_MODE_AUTO_DETECTION); + fiber_mode_autodect |= QCA807X_MMD7_FIBER_MODE_AUTO_DETECTION_EN; + phy_write_mmd(phydev, MDIO_MMD_AN, QCA807X_MMD7_FIBER_MODE_AUTO_DETECTION, + fiber_mode_autodect); + + /* Enable 4 copper + combo port mode */ + chip_config = phy_read(phydev, QCA807X_CHIP_CONFIGURATION); + chip_config &= ~QCA807X_CHIP_CONFIGURATION_MODE_CFG_MASK; + chip_config |= FIELD_PREP(QCA807X_CHIP_CONFIGURATION_MODE_CFG_MASK, + QCA807X_CHIP_CONFIGURATION_MODE_PSGMII_FIBER); + phy_write(phydev, QCA807X_CHIP_CONFIGURATION, chip_config); + + linkmode_set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, phydev->supported); + linkmode_set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, phydev->advertising); + } + + /* Prevent PSGMII going into hibernation via PSGMII self test */ + psgmii_serdes = phy_read_mmd(phydev, MDIO_MMD_PCS, PSGMII_MMD3_SERDES_CONTROL); + psgmii_serdes &= ~BIT(1); + ret = phy_write_mmd(phydev, MDIO_MMD_PCS, + PSGMII_MMD3_SERDES_CONTROL, + psgmii_serdes); + } + + if (!of_property_read_u32(node, "qcom,control-dac", &of_control_dac)) { + control_dac = phy_read_mmd(phydev, MDIO_MMD_AN, + QCA807X_MMD7_1000BASE_T_POWER_SAVE_PER_CABLE_LENGTH); + control_dac &= ~QCA807X_CONTROL_DAC_MASK; + control_dac |= FIELD_PREP(QCA807X_CONTROL_DAC_MASK, of_control_dac); + ret = phy_write_mmd(phydev, MDIO_MMD_AN, + QCA807X_MMD7_1000BASE_T_POWER_SAVE_PER_CABLE_LENGTH, + control_dac); + } + + /* Optionally configure LED-s */ + if (IS_ENABLED(CONFIG_GPIOLIB)) { + /* Check whether PHY-s pins are used as GPIO-s */ + if (!of_property_read_bool(node, "gpio-controller")) + ret = qca807x_led_config(phydev); + } else { + ret = qca807x_led_config(phydev); + } + + return ret; +} + +static int qca807x_probe(struct phy_device *phydev) +{ + struct device_node *node = phydev->mdio.dev.of_node; + int ret = 0; + + if (IS_ENABLED(CONFIG_GPIOLIB)) { + /* Do not register a GPIO controller unless flagged for it */ + if (of_property_read_bool(node, "gpio-controller")) + ret = qca807x_gpio(phydev); + } + + /* Attach SFP bus on combo port*/ + if (of_property_read_bool(node, "qcom,fiber-enable")) { + if (phy_read(phydev, QCA807X_CHIP_CONFIGURATION)) + ret = phy_sfp_probe(phydev, &qca807x_sfp_ops); + } + + return ret; +} + +static int qca807x_psgmii_config(struct phy_device *phydev) +{ + struct device_node *node = phydev->mdio.dev.of_node; + int psgmii_az, tx_amp, ret = 0; + u32 tx_driver_strength; + + /* Workaround to enable AZ transmitting ability */ + if (of_property_read_bool(node, "qcom,psgmii-az")) { + psgmii_az = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, PSGMII_MODE_CTRL); + psgmii_az &= ~PSGMII_MODE_CTRL_AZ_WORKAROUND_MASK; + psgmii_az |= FIELD_PREP(PSGMII_MODE_CTRL_AZ_WORKAROUND_MASK, 0xc); + ret = phy_write_mmd(phydev, MDIO_MMD_PMAPMD, PSGMII_MODE_CTRL, psgmii_az); + psgmii_az = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, PSGMII_MODE_CTRL); + } + + /* PSGMII/QSGMII TX amp set to DT defined value instead of default 600mV */ + if (!of_property_read_u32(node, "qcom,tx-driver-strength", &tx_driver_strength)) { + tx_amp = phy_read(phydev, PSGMII_QSGMII_DRIVE_CONTROL_1); + tx_amp &= ~PSGMII_QSGMII_TX_DRIVER_MASK; + tx_amp |= FIELD_PREP(PSGMII_QSGMII_TX_DRIVER_MASK, tx_driver_strength); + ret = phy_write(phydev, PSGMII_QSGMII_DRIVE_CONTROL_1, tx_amp); + } + + return ret; +} + +static struct phy_driver qca807x_drivers[] = { + { + PHY_ID_MATCH_EXACT(PHY_ID_QCA8072), + .name = "Qualcomm QCA8072", +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,8,0) + .flags = PHY_POLL_CABLE_TEST, +#endif + /* PHY_GBIT_FEATURES */ + .probe = qca807x_probe, + .config_init = qca807x_config, + .read_status = qca807x_read_status, + .config_intr = qca807x_config_intr, + .ack_interrupt = qca807x_ack_intr, + .soft_reset = genphy_soft_reset, + .get_tunable = qca807x_get_tunable, + .set_tunable = qca807x_set_tunable, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,8,0) + .cable_test_start = qca807x_cable_test_start, + .cable_test_get_status = qca807x_cable_test_get_status, +#endif + }, + { + PHY_ID_MATCH_EXACT(PHY_ID_QCA8075), + .name = "Qualcomm QCA8075", +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,8,0) + .flags = PHY_POLL_CABLE_TEST, +#endif + /* PHY_GBIT_FEATURES */ + .probe = qca807x_probe, + .config_init = qca807x_config, + .read_status = qca807x_read_status, + .config_intr = qca807x_config_intr, + .ack_interrupt = qca807x_ack_intr, + .soft_reset = genphy_soft_reset, + .get_tunable = qca807x_get_tunable, + .set_tunable = qca807x_set_tunable, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,8,0) + .cable_test_start = qca807x_cable_test_start, + .cable_test_get_status = qca807x_cable_test_get_status, +#endif + }, + { + PHY_ID_MATCH_EXACT(PHY_ID_QCA807X_PSGMII), + .name = "Qualcomm QCA807x PSGMII", + .probe = qca807x_psgmii_config, + }, +}; +module_phy_driver(qca807x_drivers); + +static struct mdio_device_id __maybe_unused qca807x_tbl[] = { + { PHY_ID_MATCH_EXACT(PHY_ID_QCA8072) }, + { PHY_ID_MATCH_EXACT(PHY_ID_QCA8075) }, + { PHY_ID_MATCH_MODEL(PHY_ID_QCA807X_PSGMII) }, + { } +}; + +MODULE_AUTHOR("Robert Marko"); +MODULE_DESCRIPTION("Qualcomm QCA807x PHY driver"); +MODULE_DEVICE_TABLE(mdio, qca807x_tbl); +MODULE_LICENSE("GPL"); diff --git a/feeds/ipq40xx/ipq40xx/generic/target.mk b/feeds/ipq40xx/ipq40xx/generic/target.mk new file mode 100644 index 000000000..f5cb1fb19 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/generic/target.mk @@ -0,0 +1 @@ +BOARDNAME:=Generic diff --git a/feeds/ipq40xx/ipq40xx/image/Makefile b/feeds/ipq40xx/ipq40xx/image/Makefile new file mode 100644 index 000000000..b0cfff4ea --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/image/Makefile @@ -0,0 +1,19 @@ +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/image.mk + +define Device/Default + PROFILES := Default + KERNEL_DEPENDS = $$(wildcard $(DTS_DIR)/$$(DEVICE_DTS).dts) + KERNEL_INITRAMFS_PREFIX := $$(IMG_PREFIX)-$(1)-initramfs + #KERNEL_PREFIX := $$(IMAGE_PREFIX) + KERNEL_LOADADDR := 0x80208000 + DEVICE_DTS = $$(SOC)-$(lastword $(subst _, ,$(1))) + DEVICE_DTS_CONFIG := config@1 + IMAGES := sysupgrade.bin + IMAGE/sysupgrade.bin = sysupgrade-tar | append-metadata + IMAGE/sysupgrade.bin/squashfs := +endef + +include $(SUBTARGET).mk + +$(eval $(call BuildImage)) diff --git a/feeds/ipq40xx/ipq40xx/image/generic.mk b/feeds/ipq40xx/ipq40xx/image/generic.mk new file mode 100644 index 000000000..9da8418a9 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/image/generic.mk @@ -0,0 +1,963 @@ + +DEVICE_VARS += NETGEAR_BOARD_ID NETGEAR_HW_ID +DEVICE_VARS += RAS_BOARD RAS_ROOTFS_SIZE RAS_VERSION +DEVICE_VARS += WRGG_DEVNAME WRGG_SIGNATURE + +define Device/FitImage + KERNEL_SUFFIX := -fit-uImage.itb + KERNEL = kernel-bin | gzip | fit gzip $$(DTS_DIR)/$$(DEVICE_DTS).dtb + KERNEL_NAME := Image +endef + +define Device/FitImageLzma + KERNEL_SUFFIX := -fit-uImage.itb + KERNEL = kernel-bin | lzma | fit lzma $$(DTS_DIR)/$$(DEVICE_DTS).dtb + KERNEL_NAME := Image +endef + +define Device/FitzImage + KERNEL_SUFFIX := -fit-zImage.itb + KERNEL = kernel-bin | fit none $$(DTS_DIR)/$$(DEVICE_DTS).dtb + KERNEL_NAME := zImage +endef + +define Device/UbiFit + KERNEL_IN_UBI := 1 + IMAGES := nand-factory.ubi nand-sysupgrade.bin + IMAGE/nand-factory.ubi := append-ubi + IMAGE/nand-sysupgrade.bin := sysupgrade-tar | append-metadata +endef + +define Device/DniImage + $(call Device/FitzImage) + NETGEAR_BOARD_ID := + NETGEAR_HW_ID := + IMAGES += factory.img + IMAGE/factory.img := append-kernel | pad-offset 64k 64 | append-uImage-fakehdr filesystem | append-rootfs | pad-rootfs | netgear-dni + IMAGE/sysupgrade.bin := append-kernel | pad-offset 64k 64 | append-uImage-fakehdr filesystem | \ + append-rootfs | pad-rootfs | append-metadata | check-size +endef + +define Build/append-rootfshdr + mkimage -A $(LINUX_KARCH) \ + -O linux -T filesystem \ + -C lzma -a $(KERNEL_LOADADDR) -e $(if $(KERNEL_ENTRY),$(KERNEL_ENTRY),$(KERNEL_LOADADDR)) \ + -n root.squashfs -d $(IMAGE_ROOTFS) $@.new + dd if=$@.new bs=64 count=1 >> $(IMAGE_KERNEL) +endef + +define Build/mkmylofw_32m + $(eval device_id=$(word 1,$(1))) + $(eval revision=$(word 2,$(1))) + + let \ + size="$$(stat -c%s $@)" \ + pad="$(subst k,* 1024,$(BLOCKSIZE))" \ + pad="(pad - (size % pad)) % pad" \ + newsize='size + pad'; \ + $(STAGING_DIR_HOST)/bin/mkmylofw \ + -B WPE72 -i 0x11f6:$(device_id):0x11f6:$(device_id) -r $(revision) \ + -s 0x2000000 -p0x180000:$$newsize:al:0x80208000:"OpenWrt":$@ \ + $@.new + @mv $@.new $@ +endef + +define Build/qsdk-ipq-factory-nand-askey + $(TOPDIR)/scripts/mkits-qsdk-ipq-image.sh $@.its\ + askey_kernel $(IMAGE_KERNEL) \ + askey_fs $(IMAGE_ROOTFS) \ + ubifs $@ + PATH=$(LINUX_DIR)/scripts/dtc:$(PATH) mkimage -f $@.its $@.new + @mv $@.new $@ +endef + +define Build/SenaoFW + -$(STAGING_DIR_HOST)/bin/mksenaofw \ + -n $(BOARD_NAME) -r $(VENDOR_ID) -p $(1) \ + -c $(DATECODE) -w $(2) -x $(CW_VER) -t 0 \ + -e $@ \ + -o $@.new + @cp $@.new $@ +endef + +define Build/wrgg-image + mkwrggimg -i $@ \ + -o $@.new \ + -d "$(WRGG_DEVNAME)" \ + -s "$(WRGG_SIGNATURE)" \ + -v "" -m "" -B "" + mv $@.new $@ +endef + +define Device/8dev_habanero-dvk + $(call Device/FitImageLzma) + DEVICE_VENDOR := 8devices + DEVICE_MODEL := Habanero DVK + IMAGE_SIZE := 30976k + SOC := qcom-ipq4019 + DEVICE_PACKAGES := ipq-wifi-8dev_habanero-dvk + IMAGE/sysupgrade.bin := append-kernel | pad-to 64k | append-rootfs | pad-rootfs | append-metadata | check-size +endef +TARGET_DEVICES += 8dev_habanero-dvk + +define Device/8dev_jalapeno-common + $(call Device/FitImage) + $(call Device/UbiFit) + BLOCKSIZE := 128k + PAGESIZE := 2048 + SOC := qcom-ipq4018 +endef + +define Device/8dev_jalapeno + $(call Device/8dev_jalapeno-common) + DEVICE_VENDOR := 8devices + DEVICE_MODEL := Jalapeno +endef +TARGET_DEVICES += 8dev_jalapeno + +define Device/alfa-network_ap120c-ac + $(call Device/FitImage) + $(call Device/UbiFit) + DEVICE_VENDOR := ALFA Network + DEVICE_MODEL := AP120C-AC + SOC := qcom-ipq4018 + DEVICE_PACKAGES := kmod-usb-acm kmod-tpm-i2c-atmel + BLOCKSIZE := 128k + PAGESIZE := 2048 + IMAGE_SIZE := 65536k + IMAGES := nand-factory.bin nand-sysupgrade.bin + IMAGE/nand-factory.bin := append-ubi | qsdk-ipq-factory-nand +endef +TARGET_DEVICES += alfa-network_ap120c-ac + +define Device/aruba_glenmorangie + $(call Device/FitImageLzma) + DEVICE_VENDOR := Aruba + SOC := qcom-ipq4029 + DEVICE_PACKAGES := ipq-wifi-aruba_ap-303 +endef + +define Device/aruba_ap-303 + $(call Device/aruba_glenmorangie) + DEVICE_MODEL := AP-303 +endef +TARGET_DEVICES += aruba_ap-303 + +define Device/aruba_ap-303h + $(call Device/aruba_glenmorangie) + DEVICE_MODEL := AP-303H +endef +TARGET_DEVICES += aruba_ap-303h + +define Device/aruba_ap-365 + $(call Device/aruba_glenmorangie) + DEVICE_MODEL := AP-365 + DEVICE_PACKAGES += kmod-hwmon-ad7418 +endef +TARGET_DEVICES += aruba_ap-365 + +define Device/asus_map-ac2200 + $(call Device/FitImageLzma) + DEVICE_VENDOR := ASUS + DEVICE_MODEL := Lyra (MAP-AC2200) + SOC := qcom-ipq4019 + DEVICE_PACKAGES := ath10k-firmware-qca9888-ct kmod-ath3k +endef +TARGET_DEVICES += asus_map-ac2200 + +define Device/asus_rt-ac58u + $(call Device/FitImageLzma) + DEVICE_VENDOR := ASUS + DEVICE_MODEL := RT-AC58U + SOC := qcom-ipq4018 + BLOCKSIZE := 128k + PAGESIZE := 2048 + DTB_SIZE := 65536 + IMAGE_SIZE := 20439364 + FILESYSTEMS := squashfs +# Someone - in their infinite wisdom - decided to put the firmware +# version in front of the image name \03\00\00\04 => Version 3.0.0.4 +# Since u-boot works with strings we either need another fixup step +# to add a version... or we are very careful not to add '\0' into that +# string and call it a day.... Yeah, we do the latter! + UIMAGE_NAME:=$(shell echo -e '\03\01\01\01RT-AC58U') + DEVICE_PACKAGES := -kmod-ath10k-ct kmod-ath10k-ct-smallbuffers \ + kmod-usb-ledtrig-usbport +endef +TARGET_DEVICES += asus_rt-ac58u + +define Device/avm_fritzbox-4040 + $(call Device/FitImageLzma) + DEVICE_VENDOR := AVM + DEVICE_MODEL := FRITZ!Box 4040 + SOC := qcom-ipq4018 + BOARD_NAME := fritz4040 + IMAGE_SIZE := 29056k + UBOOT_PATH := $(STAGING_DIR_IMAGE)/uboot-fritz4040.bin + UBOOT_PARTITION_SIZE := 524288 + IMAGES += eva.bin + IMAGE/eva.bin := append-uboot | pad-to $$$$(UBOOT_PARTITION_SIZE) | append-kernel | append-rootfs | pad-rootfs + IMAGE/sysupgrade.bin := append-kernel | append-rootfs | pad-rootfs | append-metadata | check-size + DEVICE_PACKAGES := fritz-tffs fritz-caldata +endef +TARGET_DEVICES += avm_fritzbox-4040 + +define Device/avm_fritzbox-7530 + $(call Device/FitImageLzma) + DEVICE_VENDOR := AVM + DEVICE_MODEL := FRITZ!Box 7530 + SOC := qcom-ipq4019 + DEVICE_PACKAGES := fritz-caldata fritz-tffs-nand +endef +TARGET_DEVICES += avm_fritzbox-7530 + +define Device/avm_fritzrepeater-1200 + $(call Device/FitImageLzma) + DEVICE_VENDOR := AVM + DEVICE_MODEL := FRITZ!Repeater 1200 + SOC := qcom-ipq4019 + DEVICE_PACKAGES := fritz-caldata fritz-tffs-nand ipq-wifi-avm_fritzrepeater-1200 +endef +TARGET_DEVICES += avm_fritzrepeater-1200 + +define Device/avm_fritzrepeater-3000 + $(call Device/FitImageLzma) + DEVICE_VENDOR := AVM + DEVICE_MODEL := FRITZ!Repeater 3000 + SOC := qcom-ipq4019 + DEVICE_PACKAGES := ath10k-firmware-qca9984-ct fritz-caldata fritz-tffs-nand +endef +TARGET_DEVICES += avm_fritzrepeater-3000 + +define Device/buffalo_wtr-m2133hp + $(call Device/FitImage) + $(call Device/UbiFit) + DEVICE_VENDOR := Buffalo + DEVICE_MODEL := WTR-M2133HP + SOC := qcom-ipq4019 + DEVICE_PACKAGES := ath10k-firmware-qca9984-ct ipq-wifi-buffalo_wtr-m2133hp + BLOCKSIZE := 128k + PAGESIZE := 2048 +endef +TARGET_DEVICES += buffalo_wtr-m2133hp + +define Device/cellc_rtl30vw + KERNEL_SUFFIX := -fit-uImage.itb + KERNEL_INITRAMFS = kernel-bin | gzip | fit gzip $$(DTS_DIR)/$$(DEVICE_DTS).dtb + KERNEL = kernel-bin | gzip | fit gzip $$(DTS_DIR)/$$(DEVICE_DTS).dtb | uImage lzma | pad-to 2048 + KERNEL_NAME := Image + KERNEL_IN_UBI := + IMAGES := nand-factory.bin nand-sysupgrade.bin + IMAGE/nand-factory.bin := append-rootfshdr | append-ubi | qsdk-ipq-factory-nand-askey + IMAGE/nand-sysupgrade.bin := append-rootfshdr | sysupgrade-tar | append-metadata + DEVICE_VENDOR := Cell C + DEVICE_MODEL := RTL30VW + SOC := qcom-ipq4019 + DEVICE_DTS_CONFIG := config@5 + KERNEL_INSTALL := 1 + KERNEL_SIZE := 4096k + IMAGE_SIZE := 57344k + BLOCKSIZE := 128k + PAGESIZE := 2048 + DEVICE_PACKAGES := kmod-usb-net-qmi-wwan kmod-usb-serial-option uqmi ipq-wifi-cellc_rtl30vw +endef +TARGET_DEVICES += cellc_rtl30vw + +define Device/cilab_meshpoint-one + $(call Device/8dev_jalapeno-common) + DEVICE_VENDOR := Crisis Innovation Lab + DEVICE_MODEL := MeshPoint.One + DEVICE_PACKAGES := kmod-i2c-gpio kmod-iio-bmp280-i2c kmod-hwmon-ina2xx kmod-rtc-pcf2127 +endef +TARGET_DEVICES += cilab_meshpoint-one + +define Device/cig_wf610d + $(call Device/FitImage) + DEVICE_TITLE := CIG WF_610D + DEVICE_DTS := qcom-ipq4029-ap-cig-wf610d + KERNEL_INSTALL := 1 + KERNEL_SIZE := 4048k + BLOCKSIZE := 128k + PAGESIZE := 2048 + DEVICE_PACKAGES := ipq-wifi-cig_wf610d + IMAGES = sysupgrade.bin + IMAGE/sysupgrade.bin := append-kernel | append-rootfs | pad-rootfs | append-metadata +endef +TARGET_DEVICES += cig_wf610d + +define Device/compex_wpj419 + $(call Device/FitImage) + $(call Device/UbiFit) + DEVICE_VENDOR := Compex + DEVICE_MODEL := WPJ419 + SOC := qcom-ipq4019 + DEVICE_DTS_CONFIG := config@12 + KERNEL_INSTALL := 1 + BLOCKSIZE := 128k + PAGESIZE := 2048 + FILESYSTEMS := squashfs +endef +TARGET_DEVICES += compex_wpj419 + +define Device/compex_wpj428 + $(call Device/FitImage) + DEVICE_VENDOR := Compex + DEVICE_MODEL := WPJ428 + SOC := qcom-ipq4028 + DEVICE_DTS_CONFIG := config@4 + BLOCKSIZE := 64k + IMAGE_SIZE := 31232k + KERNEL_SIZE := 4096k + IMAGES += cpximg-6a04.bin + IMAGE/sysupgrade.bin := append-kernel | append-rootfs | pad-rootfs | append-metadata + IMAGE/cpximg-6a04.bin := append-kernel | append-rootfs | pad-rootfs | mkmylofw_32m 0x8A2 3 + DEVICE_PACKAGES := kmod-gpio-beeper +endef +TARGET_DEVICES += compex_wpj428 + +define Device/devolo_magic-2-wifi-next + $(call Device/FitImage) + DEVICE_VENDOR := devolo + DEVICE_MODEL := Magic 2 WiFi next + SOC := qcom-ipq4018 + KERNEL_SIZE := 4096k + + # If the bootloader sees 0xDEADC0DE and this trailer at the 64k boundary of a TFTP image + # it will bootm it, just like we want for the initramfs. + KERNEL_INITRAMFS := kernel-bin | gzip | fit gzip $$(DTS_DIR)/$$(DEVICE_DTS).dtb | pad-to 64k |\ + append-string -e '\xDE\xAD\xC0\xDE{"fl_initramfs":""}\x00' + + IMAGE_SIZE := 26624k + IMAGES := sysupgrade.bin + IMAGE/sysupgrade.bin := append-kernel | append-rootfs | pad-rootfs | append-metadata + DEVICE_PACKAGES := ipq-wifi-devolo_magic-2-wifi-next +endef +TARGET_DEVICES += devolo_magic-2-wifi-next + +define Device/dlink_dap-2610 + $(call Device/FitImageLzma) + DEVICE_VENDOR := D-Link + DEVICE_MODEL := DAP-2610 + SOC := qcom-ipq4018 + DEVICE_DTS_CONFIG := config@ap.dk01.1-c1 + BLOCKSIZE := 64k + WRGG_DEVNAME := /dev/mtdblock/8 + WRGG_SIGNATURE := wapac30_dkbs_dap2610 + IMAGE_SIZE := 14080k + IMAGES += factory.bin + # Bootloader expects a special 160 byte header which is added by + # wrgg-image. + # Factory image size must be larger than 6MB, and size in wrgg header must + # match actual factory image size to be flashable from D-Link http server. + # Bootloader verifies checksum of wrgg image before booting, thus jffs2 + # cannot be part of the wrgg image. This is solved in the factory image by + # having the rootfs at the end of the image (without pad-rootfs). And in + # the sysupgrade image only the kernel is included in the wrgg checksum, + # but this is not flashable from the D-link http server. + # append-rootfs must start on an erase block boundary. + IMAGE/factory.bin := append-kernel | pad-offset 6144k 160 | append-rootfs | wrgg-image | check-size + IMAGE/sysupgrade.bin := append-kernel | wrgg-image | pad-to $$$$(BLOCKSIZE) | append-rootfs | pad-rootfs | check-size | append-metadata + DEVICE_PACKAGES := ipq-wifi-dlink_dap2610 +endef +TARGET_DEVICES += dlink_dap-2610 + +define Device/edgecore_ecw5211 + $(call Device/FitImage) + $(call Device/UbiFit) + DEVICE_VENDOR := Edgecore + DEVICE_MODEL := ECW5211 + SOC := qcom-ipq4018 + BLOCKSIZE := 128k + PAGESIZE := 2048 + DEVICE_DTS_CONFIG := config@ap.dk01.1-c2 + DEVICE_PACKAGES := kmod-tpm-i2c-atmel kmod-usb-acm +endef +TARGET_DEVICES += edgecore_ecw5211 + +define Device/edgecore_spw2ac1200 + $(call Device/FitImage) + $(call Device/UbiFit) + DEVICE_VENDOR := Edgecore + DEVICE_MODEL := SPW2AC1200 + SOC := qcom-ipq4018 + BLOCKSIZE := 128k + PAGESIZE := 2048 + DEVICE_DTS_CONFIG := config@ap.dk01.1-c2 + DEVICE_PACKAGES := kmod-tpm-i2c-atmel kmod-usb-acm uboot-envtools kmod-usb-net kmod-usb-net-cdc-qmi uqmi +endef +TARGET_DEVICES += edgecore_spw2ac1200 + +define Device/edgecore_spw2ac1200-lan-poe + $(call Device/FitImage) + $(call Device/UbiFit) + DEVICE_VENDOR := Edgecore + DEVICE_MODEL := SPW2AC1200 + SOC := qcom-ipq4018 + BLOCKSIZE := 128k + PAGESIZE := 2048 + DEVICE_DTS_CONFIG := config@ap.dk01.1-c2 + DEVICE_PACKAGES := kmod-tpm-i2c-atmel kmod-usb-acm uboot-envtools kmod-usb-net kmod-usb-net-cdc-qmi uqmi +endef +TARGET_DEVICES += edgecore_spw2ac1200-lan-poe + +define Device/edgecore_oap100 + $(call Device/FitImage) + $(call Device/UbiFit) + DEVICE_VENDOR := Edgecore + DEVICE_MODEL := OAP100 + SOC := qcom-ipq4019 + BLOCKSIZE := 128k + PAGESIZE := 2048 + IMAGES := nand-sysupgrade.bin + DEVICE_DTS_CONFIG := config@ap.dk07.1-c1 + DEVICE_PACKAGES := ipq-wifi-edgecore_oap100 kmod-usb-acm kmod-usb-net kmod-usb-net-cdc-qmi uqmi +endef +TARGET_DEVICES += edgecore_oap100 + +define Device/edgecore_oap100e + $(call Device/FitImage) + $(call Device/UbiFit) + DEVICE_VENDOR := Edgecore + DEVICE_MODEL := OAP100e + SOC := qcom-ipq4019 + BLOCKSIZE := 128k + PAGESIZE := 2048 + IMAGES := nand-sysupgrade.bin + DEVICE_DTS_CONFIG := config@ap.dk07.1-c1 + DEVICE_PACKAGES := ipq-wifi-edgecore_oap100 kmod-usb-acm kmod-usb-net kmod-usb-net-cdc-qmi uqmi +endef +TARGET_DEVICES += edgecore_oap100e + +define Device/engenius_eap1300 + $(call Device/FitImage) + DEVICE_VENDOR := EnGenius + DEVICE_MODEL := EAP1300 + DEVICE_DTS_CONFIG := config@4 + BOARD_NAME := eap1300 + SOC := qcom-ipq4018 + KERNEL_SIZE := 5120k + IMAGE_SIZE := 25344k + IMAGE/sysupgrade.bin := append-kernel | append-rootfs | pad-rootfs | append-metadata +endef +TARGET_DEVICES += engenius_eap1300 + +define Device/engenius_eap2200 + $(call Device/FitImage) + $(call Device/UbiFit) + DEVICE_VENDOR := EnGenius + DEVICE_MODEL := EAP2200 + SOC := qcom-ipq4019 + BLOCKSIZE := 128k + PAGESIZE := 2048 + DEVICE_PACKAGES := ath10k-firmware-qca9888-ct ipq-wifi-engenius_eap2200 -kmod-ath10k-ct kmod-ath10k-ct-smallbuffers +endef +TARGET_DEVICES += engenius_eap2200 + +define Device/engenius_emd1 + $(call Device/FitImage) + DEVICE_VENDOR := EnGenius + DEVICE_MODEL := EMD1 + DEVICE_DTS_CONFIG := config@4 + SOC := qcom-ipq4018 + IMAGE_SIZE := 30720k + IMAGES += factory.bin + IMAGE/sysupgrade.bin := append-kernel | append-rootfs | pad-rootfs | append-metadata + IMAGE/factory.bin := qsdk-ipq-factory-nor | check-size + DEVICE_PACKAGES := ipq-wifi-engenius_emd1 +endef +TARGET_DEVICES += engenius_emd1 + +define Device/engenius_emr3500 + $(call Device/FitImage) + DEVICE_VENDOR := EnGenius + DEVICE_MODEL := EMR3500 + DEVICE_DTS_CONFIG := config@4 + SOC := qcom-ipq4018 + KERNEL_SIZE := 4096k + IMAGE_SIZE := 30720k + IMAGES += factory.bin + IMAGE/sysupgrade.bin := append-kernel | append-rootfs | pad-rootfs | append-metadata + IMAGE/factory.bin := qsdk-ipq-factory-nor | check-size + DEVICE_PACKAGES := ipq-wifi-engenius_emr3500 +endef +TARGET_DEVICES += engenius_emr3500 + +define Device/engenius_ens620ext + $(call Device/FitImage) + DEVICE_VENDOR := EnGenius + DEVICE_MODEL := ENS620EXT + SOC := qcom-ipq4018 + DEVICE_DTS_CONFIG := config@4 + BLOCKSIZE := 64k + PAGESIZE := 256 + BOARD_NAME := ENS620EXT + VENDOR_ID := 0x0101 + PRODUCT_ID := 0x79 + PRODUCT_ID_NEW := 0xA4 + DATECODE := 190507 + FW_VER := 3.1.2 + FW_VER_NEW := 3.5.6 + CW_VER := 1.8.99 + IMAGE_SIZE := 21312k + KERNEL_SIZE := 5120k + FILESYSTEMS := squashfs + IMAGES += factory_30.bin factory_35.bin + IMAGE/sysupgrade.bin := append-kernel | append-rootfs | pad-rootfs | check-size | append-metadata + IMAGE/factory_30.bin := append-kernel | pad-to $$$$(KERNEL_SIZE) | append-rootfs | pad-rootfs | check-size | SenaoFW $$$$(PRODUCT_ID) $$$$(FW_VER) + IMAGE/factory_35.bin := qsdk-ipq-factory-nor | check-size | SenaoFW $$$$(PRODUCT_ID_NEW) $$$$(FW_VER_NEW) +endef +TARGET_DEVICES += engenius_ens620ext + +define Device/ezviz_cs-w3-wd1200g-eup + $(call Device/FitImage) + DEVICE_VENDOR := EZVIZ + DEVICE_MODEL := CS-W3-WD1200G + DEVICE_VARIANT := EUP + DEVICE_DTS_CONFIG := config@4 + IMAGE_SIZE := 14848k + SOC := qcom-ipq4018 + IMAGE/sysupgrade.bin := append-kernel | append-rootfs | pad-rootfs | \ + append-metadata + DEVICE_PACKAGES := -kmod-ath10k-ct kmod-ath10k-ct-smallbuffers \ + ipq-wifi-ezviz_cs-w3-wd1200g-eup +endef +TARGET_DEVICES += ezviz_cs-w3-wd1200g-eup + +define Device/glinet_gl-ap1300 + $(call Device/FitImage) + $(call Device/UbiFit) + DEVICE_VENDOR := GL.iNet + DEVICE_MODEL := GL-AP1300 + SOC := qcom-ipq4018 + DEVICE_DTS_CONFIG := config@ap.dk01.1-c2 + BLOCKSIZE := 128k + PAGESIZE := 2048 + IMAGE_SIZE := 131072k + KERNEL_INSTALL := 1 + DEVICE_PACKAGES := ipq-wifi-glinet_gl-ap1300 +endef +TARGET_DEVICES += glinet_gl-ap1300 + +define Device/glinet_gl-b1300 + $(call Device/FitImage) + DEVICE_VENDOR := GL.iNet + DEVICE_MODEL := GL-B1300 + BOARD_NAME := gl-b1300 + SOC := qcom-ipq4029 + KERNEL_SIZE := 4096k + IMAGE_SIZE := 26624k + IMAGE/sysupgrade.bin := append-kernel |append-rootfs | pad-rootfs | append-metadata +endef +TARGET_DEVICES += glinet_gl-b1300 + +define Device/glinet_gl-s1300 + $(call Device/FitImage) + DEVICE_VENDOR := GL.iNet + DEVICE_MODEL := GL-S1300 + SOC := qcom-ipq4029 + KERNEL_SIZE := 4096k + IMAGE_SIZE := 26624k + IMAGES := sysupgrade.bin + IMAGE/sysupgrade.bin := append-kernel | append-rootfs | pad-rootfs | append-metadata + DEVICE_PACKAGES := ipq-wifi-glinet_gl-s1300 kmod-fs-ext4 kmod-mmc kmod-spi-dev +endef +TARGET_DEVICES += glinet_gl-s1300 + +define Device/linksys_ea6350v3 + # The Linksys EA6350v3 has a uboot bootloader that does not + # support either booting lzma kernel images nor booting UBI + # partitions. This uboot, however, supports raw kernel images and + # gzipped images. + # + # As for the time of writing this, the device will boot the kernel + # from a fixed address with a fixed length of 3MiB. Also, the + # device has a hard-coded kernel command line that requieres the + # rootfs and alt_rootfs to be in mtd11 and mtd13 respectively. + # Oh... and the kernel partition overlaps with the rootfs + # partition (the same for alt_kernel and alt_rootfs). + # + # If you are planing re-partitioning the device, you may want to + # keep those details in mind: + # 1. The kernel adresses you should honor are 0x00000000 and + # 0x02800000 respectively. + # 2. The kernel size (plus the dtb) cannot exceed 3.00MiB in size. + # 3. You can use 'zImage', but not a raw 'Image' packed with lzma. + # 4. The kernel command line from uboot is harcoded to boot with + # rootfs either in mtd11 or mtd13. + $(call Device/FitzImage) + DEVICE_VENDOR := Linksys + DEVICE_MODEL := EA6350 + DEVICE_VARIANT := v3 + SOC := qcom-ipq4018 + BLOCKSIZE := 128k + PAGESIZE := 2048 + KERNEL_SIZE := 3072k + IMAGE_SIZE := 37888k + UBINIZE_OPTS := -E 5 + IMAGES += factory.bin + IMAGE/factory.bin := append-kernel | append-uImage-fakehdr filesystem | pad-to $$$$(KERNEL_SIZE) | append-ubi | linksys-image type=EA6350v3 +endef +TARGET_DEVICES += linksys_ea6350v3 + +define Device/linksys_ea8300 + $(call Device/FitzImage) + DEVICE_VENDOR := Linksys + DEVICE_MODEL := EA8300 + SOC := qcom-ipq4019 + KERNEL_SIZE := 3072k + IMAGE_SIZE := 87040k + BLOCKSIZE := 128k + PAGESIZE := 2048 + UBINIZE_OPTS := -E 5 # EOD marks to "hide" factory sig at EOF + IMAGES += factory.bin + IMAGE/factory.bin := append-kernel | pad-to $$$$(KERNEL_SIZE) | append-ubi | linksys-image type=EA8300 + DEVICE_PACKAGES := ath10k-firmware-qca9888-ct ipq-wifi-linksys_ea8300 kmod-usb-ledtrig-usbport +endef +TARGET_DEVICES += linksys_ea8300 + +define Device/linksys_mr8300 + $(call Device/FitzImage) + DEVICE_VENDOR := Linksys + DEVICE_MODEL := MR8300 + SOC := qcom-ipq4019 + KERNEL_SIZE := 3072k + IMAGE_SIZE := 87040k + BLOCKSIZE := 128k + PAGESIZE := 2048 + UBINIZE_OPTS := -E 5 # EOD marks to "hide" factory sig at EOF + IMAGES += factory.bin + IMAGE/factory.bin := append-kernel | pad-to $$$$(KERNEL_SIZE) | append-ubi | linksys-image type=MR8300 + DEVICE_PACKAGES := ath10k-firmware-qca9888-ct ipq-wifi-linksys_mr8300-v0 kmod-usb-ledtrig-usbport +endef +TARGET_DEVICES += linksys_mr8300 + +define Device/luma_wrtq-329acn + $(call Device/FitImage) + DEVICE_VENDOR := Luma Home + DEVICE_MODEL := WRTQ-329ACN + SOC := qcom-ipq4018 + DEVICE_PACKAGES := ipq-wifi-luma_wrtq-329acn kmod-ath3k kmod-eeprom-at24 kmod-i2c-gpio + IMAGE_SIZE := 76632k + BLOCKSIZE := 128k + PAGESIZE := 2048 +endef +TARGET_DEVICES += luma_wrtq-329acn + +define Device/meraki_mr33 + $(call Device/FitImage) + DEVICE_VENDOR := Cisco Meraki + DEVICE_MODEL := MR33 + SOC := qcom-ipq4029 + BLOCKSIZE := 128k + PAGESIZE := 2048 + DEVICE_PACKAGES := -swconfig ath10k-firmware-qca9887-ct +endef +TARGET_DEVICES += meraki_mr33 + +define Device/mobipromo_cm520-79f + $(call Device/FitzImage) + $(call Device/UbiFit) + DEVICE_VENDOR := MobiPromo + DEVICE_MODEL := CM520-79F + SOC := qcom-ipq4019 + BLOCKSIZE := 128k + PAGESIZE := 2048 + DEVICE_PACKAGES := ipq-wifi-mobipromo_cm520-79f kmod-usb-ledtrig-usbport +endef +TARGET_DEVICES += mobipromo_cm520-79f + +define Device/netgear_ex61x0v2 + $(call Device/DniImage) + DEVICE_VENDOR := NETGEAR + DEVICE_DTS_CONFIG := config@4 + NETGEAR_BOARD_ID := EX6150v2series + NETGEAR_HW_ID := 29765285+16+0+128+2x2 + IMAGE_SIZE := 14400k + SOC := qcom-ipq4018 +endef + +define Device/netgear_ex6100v2 + $(call Device/netgear_ex61x0v2) + DEVICE_MODEL := EX6100 + DEVICE_VARIANT := v2 +endef +TARGET_DEVICES += netgear_ex6100v2 + +define Device/netgear_ex6150v2 + $(call Device/netgear_ex61x0v2) + DEVICE_MODEL := EX6150 + DEVICE_VARIANT := v2 +endef +TARGET_DEVICES += netgear_ex6150v2 + +define Device/openmesh_a42 + $(call Device/FitImageLzma) + DEVICE_VENDOR := OpenMesh + DEVICE_MODEL := A42 + SOC := qcom-ipq4018 + DEVICE_DTS_CONFIG := config@om.a42 + BLOCKSIZE := 64k + KERNEL = kernel-bin | lzma | fit lzma $$(DTS_DIR)/$$(DEVICE_DTS).dtb | pad-to $$(BLOCKSIZE) + IMAGE_SIZE := 15616k + IMAGES += factory.bin + IMAGE/factory.bin := append-rootfs | pad-rootfs | openmesh-image ce_type=A42 + IMAGE/sysupgrade.bin/squashfs := append-rootfs | pad-rootfs | sysupgrade-tar rootfs=$$$$@ | append-metadata +endef +TARGET_DEVICES += openmesh_a42 + +define Device/openmesh_a62 + $(call Device/FitImageLzma) + DEVICE_VENDOR := OpenMesh + DEVICE_MODEL := A62 + SOC := qcom-ipq4019 + DEVICE_DTS_CONFIG := config@om.a62 + BLOCKSIZE := 64k + KERNEL = kernel-bin | lzma | fit lzma $$(DTS_DIR)/$$(DEVICE_DTS).dtb | pad-to $$(BLOCKSIZE) + IMAGE_SIZE := 15552k + IMAGES += factory.bin + IMAGE/factory.bin := append-rootfs | pad-rootfs | openmesh-image ce_type=A62 + IMAGE/sysupgrade.bin/squashfs := append-rootfs | pad-rootfs | sysupgrade-tar rootfs=$$$$@ | append-metadata + DEVICE_PACKAGES := ath10k-firmware-qca9888-ct +endef +TARGET_DEVICES += openmesh_a62 + +define Device/plasmacloud_pa1200 + $(call Device/FitImageLzma) + DEVICE_VENDOR := Plasma Cloud + DEVICE_MODEL := PA1200 + SOC := qcom-ipq4018 + DEVICE_DTS_CONFIG := config@pc.pa1200 + BLOCKSIZE := 64k + KERNEL = kernel-bin | lzma | fit lzma $$(DTS_DIR)/$$(DEVICE_DTS).dtb | pad-to $$(BLOCKSIZE) + IMAGE_SIZE := 15616k + IMAGES += factory.bin + IMAGE/factory.bin := append-rootfs | pad-rootfs | openmesh-image ce_type=PA1200 + IMAGE/sysupgrade.bin/squashfs := append-rootfs | pad-rootfs | sysupgrade-tar rootfs=$$$$@ | append-metadata + DEVICE_PACKAGES := ipq-wifi-plasmacloud_pa1200 +endef +TARGET_DEVICES += plasmacloud_pa1200 + +define Device/plasmacloud_pa2200 + $(call Device/FitImageLzma) + DEVICE_VENDOR := Plasma Cloud + DEVICE_MODEL := PA2200 + SOC := qcom-ipq4019 + DEVICE_DTS_CONFIG := config@pc.pa2200 + BLOCKSIZE := 64k + KERNEL = kernel-bin | lzma | fit lzma $$(DTS_DIR)/$$(DEVICE_DTS).dtb | pad-to $$(BLOCKSIZE) + IMAGE_SIZE := 15552k + IMAGES += factory.bin + IMAGE/factory.bin := append-rootfs | pad-rootfs | openmesh-image ce_type=PA2200 + IMAGE/sysupgrade.bin/squashfs := append-rootfs | pad-rootfs | sysupgrade-tar rootfs=$$$$@ | append-metadata + DEVICE_PACKAGES := ath10k-firmware-qca9888-ct ipq-wifi-plasmacloud_pa2200 +endef +TARGET_DEVICES += plasmacloud_pa2200 + +define Device/qcom_ap-dk01.1-c1 + DEVICE_VENDOR := Qualcomm Atheros + DEVICE_MODEL := AP-DK01.1 + DEVICE_VARIANT := C1 + BOARD_NAME := ap-dk01.1-c1 + SOC := qcom-ipq4019 + DEVICE_DTS := qcom-ipq4019-ap.dk01.1-c1 + KERNEL_INSTALL := 1 + KERNEL_SIZE := 4096k + IMAGE_SIZE := 26624k + $(call Device/FitImage) + IMAGE/sysupgrade.bin := append-kernel | pad-to $$$$(KERNEL_SIZE) | append-rootfs | pad-rootfs | append-metadata +endef +TARGET_DEVICES += qcom_ap-dk01.1-c1 + +define Device/qcom_ap-dk04.1-c1 + $(call Device/FitImage) + $(call Device/UbiFit) + DEVICE_VENDOR := Qualcomm Atheros + DEVICE_MODEL := AP-DK04.1 + DEVICE_VARIANT := C1 + SOC := qcom-ipq4019 + DEVICE_DTS := qcom-ipq4019-ap.dk04.1-c1 + KERNEL_INSTALL := 1 + KERNEL_SIZE := 4048k + BLOCKSIZE := 128k + PAGESIZE := 2048 + BOARD_NAME := ap-dk04.1-c1 +endef +TARGET_DEVICES += qcom_ap-dk04.1-c1 + +define Device/qxwlan_e2600ac-c1 + $(call Device/FitImage) + DEVICE_VENDOR := Qxwlan + DEVICE_MODEL := E2600AC + DEVICE_VARIANT := C1 + BOARD_NAME := e2600ac-c1 + SOC := qcom-ipq4019 + KERNEL_SIZE := 4096k + IMAGE_SIZE := 31232k + IMAGE/sysupgrade.bin := append-kernel | append-rootfs | pad-rootfs | append-metadata + DEVICE_PACKAGES := ipq-wifi-qxwlan_e2600ac +endef +TARGET_DEVICES += qxwlan_e2600ac-c1 + +define Device/qxwlan_e2600ac-c2 + $(call Device/FitImage) + $(call Device/UbiFit) + DEVICE_VENDOR := Qxwlan + DEVICE_MODEL := E2600AC + DEVICE_VARIANT := C2 + SOC := qcom-ipq4019 + KERNEL_INSTALL := 1 + BLOCKSIZE := 128k + PAGESIZE := 2048 + DEVICE_PACKAGES := ipq-wifi-qxwlan_e2600ac +endef +TARGET_DEVICES += qxwlan_e2600ac-c2 + +define Device/unielec_u4019-32m + $(call Device/FitImage) + DEVICE_VENDOR := Unielec + DEVICE_MODEL := U4019 + DEVICE_VARIANT := 32M + BOARD_NAME := u4019-32m + SOC := qcom-ipq4019 + KERNEL_SIZE := 4096k + IMAGE_SIZE := 31232k + IMAGE/sysupgrade.bin := append-kernel | append-rootfs | pad-rootfs | append-metadata +endef +TARGET_DEVICES += unielec_u4019-32m + +define Device/zyxel_nbg6617 + $(call Device/FitImageLzma) + DEVICE_VENDOR := ZyXEL + DEVICE_MODEL := NBG6617 + SOC := qcom-ipq4018 + KERNEL_SIZE := 4096k + ROOTFS_SIZE := 24960k + RAS_BOARD := NBG6617 + RAS_ROOTFS_SIZE := 19840k + RAS_VERSION := "$(VERSION_DIST) $(REVISION)" + IMAGE/sysupgrade.bin := append-kernel | append-rootfs | pad-rootfs | append-metadata + IMAGES += factory.bin +# The ZyXEL firmware allows flashing thru the web-gui only when the rootfs is +# at least as large as the one of the initial firmware image (not the current +# one on the device). This only applies to the Web-UI, the bootlaoder ignores +# this minimum-size. However, the larger image can be flashed both ways. + IMAGE/factory.bin := append-rootfs | pad-rootfs | pad-to 64k | check-size $$$$(ROOTFS_SIZE) | zyxel-ras-image separate-kernel + IMAGE/sysupgrade.bin/squashfs := append-rootfs | pad-rootfs | check-size $$$$(ROOTFS_SIZE) | sysupgrade-tar rootfs=$$$$@ | append-metadata + DEVICE_PACKAGES := kmod-usb-ledtrig-usbport +endef +TARGET_DEVICES += zyxel_nbg6617 + +define Device/zyxel_wre6606 + $(call Device/FitImage) + DEVICE_VENDOR := ZyXEL + DEVICE_MODEL := WRE6606 + DEVICE_DTS_CONFIG := config@4 + SOC := qcom-ipq4018 + IMAGE_SIZE := 13184k + IMAGE/sysupgrade.bin := append-kernel | append-rootfs | pad-rootfs | append-metadata | check-size + DEVICE_PACKAGES := -kmod-ath10k-ct kmod-ath10k-ct-smallbuffers +endef +TARGET_DEVICES += zyxel_wre6606 + +define Device/wallys_dr40x9 + $(call Device/FitImage) + $(call Device/UbiFit) + DEVICE_VENDOR := Wallys + DEVICE_MODEL := DR40X9 + SOC := qcom-ipq40x9 + DEVICE_DTS_CONFIG := config@ap.dk07.1-c1 + BLOCKSIZE := 128k + PAGESIZE := 2048 + DEVICE_PACKAGES := ipq-wifi-wallys_dr40x9 +endef +TARGET_DEVICES += wallys_dr40x9 + +define Device/tp-link_ec420_g1 + $(call Device/FitImage) + $(call Device/UbiFit) + DEVICE_TITLE := tp-link EC420 G1 + BOARD_NAME := ec420_g1 + DEVICE_DTS := qcom-ipq4019-tp-link-ec420-g1 + KERNEL_SIZE := 4096k + IMAGE_SIZE := 26624k + BLOCKSIZE := 128k + PAGESIZE := 2048 + SUPPORTED_DEVICES := tp-link,ec420-g1 + DEVICE_PACKAGES := ath10k-firmware-qca9984-ct ipq-wifi-tp-link_ec420-g1 uboot-envtools +endef +TARGET_DEVICES += tp-link_ec420_g1 + +define Device/hfcl_ion4 + $(call Device/FitImage) + $(call Device/UbiFit) + DEVICE_VENDOR := HFCL + DEVICE_MODEL := ION4 + SOC := qcom-ipq4019 + DEVICE_DTS := qcom-ipq4019-hfcl-ion4 + KERNEL_INSTALL := 1 + KERNEL_SIZE := 4048k + BLOCKSIZE := 128k + PAGESIZE := 2048 + BOARD_NAME := hfcl-ion4 + IMAGES := nand-sysupgrade.bin + IMAGE/nand-sysupgrade.bin := sysupgrade-tar | append-metadata + DEVICE_PACKAGES := uboot-envtools +endef +TARGET_DEVICES += hfcl_ion4 + +define Device/um-325ac + DEVICE_VENDOR := Indio Networks + DEVICE_MODEL := UM-325AC + BOARD_NAME := um-325ac + SOC := qcom-ipq4019 + DEVICE_DTS := qcom-ipq4019-um-325ac + KERNEL_INSTALL := 1 + KERNEL_SIZE := 4096k + IMAGE_SIZE := 26624k + $(call Device/FitImage) + IMAGE/sysupgrade.bin := append-kernel | pad-to $$$$(KERNEL_SIZE) | append-rootfs | pad-rootfs | append-metadata +endef +TARGET_DEVICES += um-325ac + +define Device/udaya_a5-id2 + DEVICE_VENDOR := udaya + DEVICE_MODEL := A5-ID2 + SOC := qcom-ipq4018 + DEVICE_DTS := qcom-ipq4018-udaya-a5-id2 + KERNEL_INSTALL := 1 + KERNEL_SIZE := 4096k + IMAGE_SIZE := 26624k + DEVICE_PACKAGES := ipq-wifi-udaya-a5-id2 + $(call Device/FitImage) + IMAGE/sysupgrade.bin := append-kernel | pad-to $$$$(KERNEL_SIZE) | append-rootfs | pad-rootfs | append-metadata +endef +TARGET_DEVICES += udaya_a5-id2 + +define Device/um-550ac + DEVICE_VENDOR := Indio Networks + DEVICE_MODEL := UM-550AC + BOARD_NAME := um-550ac + SOC := qcom-ipq4019 + DEVICE_DTS := qcom-ipq4019-um-550ac + KERNEL_INSTALL := 1 + KERNEL_SIZE := 4096k + IMAGE_SIZE := 26624k + $(call Device/FitImage) + IMAGE/sysupgrade.bin := append-kernel | pad-to $$$$(KERNEL_SIZE) | append-rootfs | pad-rootfs | append-metadata +endef +TARGET_DEVICES += um-550ac + + +define Device/um-510ac-v3 + DEVICE_VENDOR := Indio Networks + DEVICE_MODEL := UM-510AC-V3 + BOARD_NAME := um-510ac-v3 + SOC := qcom-ipq4019 + DEVICE_DTS := qcom-ipq4019-um-510ac-v3 + KERNEL_INSTALL := 1 + KERNEL_SIZE := 4096k + IMAGE_SIZE := 26624k + $(call Device/FitImage) + IMAGE/sysupgrade.bin := append-kernel | pad-to $$$$(KERNEL_SIZE) | append-rootfs | pad-rootfs | append-metadata +endef +TARGET_DEVICES += um-510ac-v3 diff --git a/feeds/ipq40xx/ipq40xx/image/mikrotik.mk b/feeds/ipq40xx/ipq40xx/image/mikrotik.mk new file mode 100644 index 000000000..7c2fa5273 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/image/mikrotik.mk @@ -0,0 +1,28 @@ +define Device/mikrotik_nor + DEVICE_VENDOR := MikroTik + BLOCKSIZE := 64k + IMAGE_SIZE := 16128k + KERNEL_NAME := vmlinux + KERNEL := kernel-bin | append-dtb-elf + IMAGES = sysupgrade.bin + IMAGE/sysupgrade.bin := append-kernel | kernel2minor -s 1024 | \ + pad-to $$$$(BLOCKSIZE) | append-rootfs | pad-rootfs | \ + append-metadata | check-size +endef + +define Device/mikrotik_hap-ac2 + $(call Device/mikrotik_nor) + DEVICE_MODEL := hAP ac2 + SOC := qcom-ipq4018 + DEVICE_PACKAGES := ipq-wifi-mikrotik_hap-ac2 -kmod-ath10k-ct \ + kmod-ath10k-ct-smallbuffers +endef +TARGET_DEVICES += mikrotik_hap-ac2 + +define Device/mikrotik_sxtsq-5-ac + $(call Device/mikrotik_nor) + DEVICE_MODEL := SXTsq 5 ac (RBSXTsqG-5acD) + SOC := qcom-ipq4018 + DEVICE_PACKAGES := ipq-wifi-mikrotik_sxtsq-5-ac rssileds +endef +TARGET_DEVICES += mikrotik_sxtsq-5-ac diff --git a/feeds/ipq40xx/ipq40xx/mikrotik/config-default b/feeds/ipq40xx/ipq40xx/mikrotik/config-default new file mode 100644 index 000000000..147217380 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/mikrotik/config-default @@ -0,0 +1,4 @@ +CONFIG_MIKROTIK=y +CONFIG_MIKROTIK_RB_SYSFS=y +CONFIG_MTD_ROUTERBOOT_PARTS=y +CONFIG_MTD_SPLIT_MINOR_FW=y diff --git a/feeds/ipq40xx/ipq40xx/mikrotik/target.mk b/feeds/ipq40xx/ipq40xx/mikrotik/target.mk new file mode 100644 index 000000000..4530a9098 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/mikrotik/target.mk @@ -0,0 +1,4 @@ +BOARDNAME:=MikroTik +FEATURES += minor +KERNEL_IMAGES:=vmlinux +IMAGES_DIR:=compressed diff --git a/feeds/ipq40xx/ipq40xx/patches-5.4/0001-v5.7-ARM-qcom-Add-support-for-IPQ40xx.patch b/feeds/ipq40xx/ipq40xx/patches-5.4/0001-v5.7-ARM-qcom-Add-support-for-IPQ40xx.patch new file mode 100644 index 000000000..8aa71f360 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/patches-5.4/0001-v5.7-ARM-qcom-Add-support-for-IPQ40xx.patch @@ -0,0 +1,42 @@ +From f125e2d4339dda6937865f975470b29c84714c9b Mon Sep 17 00:00:00 2001 +From: Christian Lamparter +Date: Mon, 6 Jan 2020 14:57:15 +0100 +Subject: [PATCH] ARM: qcom: Add support for IPQ40xx + +Add support for the Qualcomm IPQ40xx SoC in Kconfig. +Also add its appropriate textofs. + +Signed-off-by: Christian Lamparter +Signed-off-by: John Crispin +Tested-by: Robert Marko +Cc: Luka Perkov +Signed-off-by: Arnd Bergmann +--- + arch/arm/Makefile | 1 + + arch/arm/mach-qcom/Kconfig | 5 +++++ + 2 files changed, 6 insertions(+) + +--- a/arch/arm/Makefile ++++ b/arch/arm/Makefile +@@ -152,6 +152,7 @@ textofs-$(CONFIG_PM_H1940) := 0x001 + ifeq ($(CONFIG_ARCH_SA1100),y) + textofs-$(CONFIG_SA1111) := 0x00208000 + endif ++textofs-$(CONFIG_ARCH_IPQ40XX) := 0x00208000 + textofs-$(CONFIG_ARCH_MSM8X60) := 0x00208000 + textofs-$(CONFIG_ARCH_MSM8960) := 0x00208000 + textofs-$(CONFIG_ARCH_MESON) := 0x00208000 +--- a/arch/arm/mach-qcom/Kconfig ++++ b/arch/arm/mach-qcom/Kconfig +@@ -12,6 +12,11 @@ menuconfig ARCH_QCOM + + if ARCH_QCOM + ++config ARCH_IPQ40XX ++ bool "Enable support for IPQ40XX" ++ select CLKSRC_QCOM ++ select HAVE_ARM_ARCH_TIMER ++ + config ARCH_MSM8X60 + bool "Enable support for MSM8X60" + select CLKSRC_QCOM diff --git a/feeds/ipq40xx/ipq40xx/patches-5.4/0002-01-v5.6-regulator-add-IPQ4019-SDHCI-VQMMC-LDO-driver.patch b/feeds/ipq40xx/ipq40xx/patches-5.4/0002-01-v5.6-regulator-add-IPQ4019-SDHCI-VQMMC-LDO-driver.patch new file mode 100644 index 000000000..aaf8c807e --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/patches-5.4/0002-01-v5.6-regulator-add-IPQ4019-SDHCI-VQMMC-LDO-driver.patch @@ -0,0 +1,153 @@ +From 97043d292365ae39d62b54a6d79dff98d048b501 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Wed, 22 Jan 2020 12:44:14 +0100 +Subject: [PATCH] From ebf652b408200504194be32ad0a3f5bb49d6000a Mon Sep 17 + 00:00:00 2001 From: Robert Marko Date: Sun, 12 Jan + 2020 12:30:01 +0100 Subject: [PATCH] regulator: add IPQ4019 SDHCI VQMMC LDO + driver + +This introduces the IPQ4019 VQMMC LDO driver needed for +the SD/EMMC driver I/O level operation. +This will enable introducing SD/EMMC support for the built-in controller. + +Signed-off-by: Mantas Pucka +Signed-off-by: Robert Marko +Link: https://lore.kernel.org/r/20200112113003.11110-1-robert.marko@sartura.hr +Signed-off-by: Mark Brown +--- + drivers/regulator/Kconfig | 7 ++ + drivers/regulator/Makefile | 1 + + drivers/regulator/vqmmc-ipq4019-regulator.c | 101 ++++++++++++++++++++ + 3 files changed, 109 insertions(+) + create mode 100644 drivers/regulator/vqmmc-ipq4019-regulator.c + +--- a/drivers/regulator/Kconfig ++++ b/drivers/regulator/Kconfig +@@ -1077,6 +1077,13 @@ config REGULATOR_VEXPRESS + This driver provides support for voltage regulators available + on the ARM Ltd's Versatile Express platform. + ++config REGULATOR_VQMMC_IPQ4019 ++ tristate "IPQ4019 VQMMC SD LDO regulator support" ++ depends on ARCH_QCOM ++ help ++ This driver provides support for the VQMMC LDO I/0 ++ voltage regulator of the IPQ4019 SD/EMMC controller. ++ + config REGULATOR_WM831X + tristate "Wolfson Microelectronics WM831x PMIC regulators" + depends on MFD_WM831X +--- a/drivers/regulator/Makefile ++++ b/drivers/regulator/Makefile +@@ -132,6 +132,7 @@ obj-$(CONFIG_REGULATOR_TWL4030) += twl-r + obj-$(CONFIG_REGULATOR_UNIPHIER) += uniphier-regulator.o + obj-$(CONFIG_REGULATOR_VCTRL) += vctrl-regulator.o + obj-$(CONFIG_REGULATOR_VEXPRESS) += vexpress-regulator.o ++obj-$(CONFIG_REGULATOR_VQMMC_IPQ4019) += vqmmc-ipq4019-regulator.o + obj-$(CONFIG_REGULATOR_WM831X) += wm831x-dcdc.o + obj-$(CONFIG_REGULATOR_WM831X) += wm831x-isink.o + obj-$(CONFIG_REGULATOR_WM831X) += wm831x-ldo.o +--- /dev/null ++++ b/drivers/regulator/vqmmc-ipq4019-regulator.c +@@ -0,0 +1,101 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++// ++// Copyright (c) 2019 Mantas Pucka ++// Copyright (c) 2019 Robert Marko ++// ++// Driver for IPQ4019 SD/MMC controller's I/O LDO voltage regulator ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static const unsigned int ipq4019_vmmc_voltages[] = { ++ 1500000, 1800000, 2500000, 3000000, ++}; ++ ++static const struct regulator_ops ipq4019_regulator_voltage_ops = { ++ .list_voltage = regulator_list_voltage_table, ++ .map_voltage = regulator_map_voltage_ascend, ++ .get_voltage_sel = regulator_get_voltage_sel_regmap, ++ .set_voltage_sel = regulator_set_voltage_sel_regmap, ++}; ++ ++static const struct regulator_desc vmmc_regulator = { ++ .name = "vmmcq", ++ .ops = &ipq4019_regulator_voltage_ops, ++ .type = REGULATOR_VOLTAGE, ++ .owner = THIS_MODULE, ++ .volt_table = ipq4019_vmmc_voltages, ++ .n_voltages = ARRAY_SIZE(ipq4019_vmmc_voltages), ++ .vsel_reg = 0, ++ .vsel_mask = 0x3, ++}; ++ ++static const struct regmap_config ipq4019_vmmcq_regmap_config = { ++ .reg_bits = 32, ++ .reg_stride = 4, ++ .val_bits = 32, ++}; ++ ++static int ipq4019_regulator_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct regulator_init_data *init_data; ++ struct regulator_config cfg = {}; ++ struct regulator_dev *rdev; ++ struct resource *res; ++ struct regmap *rmap; ++ void __iomem *base; ++ ++ init_data = of_get_regulator_init_data(dev, dev->of_node, ++ &vmmc_regulator); ++ if (!init_data) ++ return -EINVAL; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ base = devm_ioremap_resource(dev, res); ++ if (IS_ERR(base)) ++ return PTR_ERR(base); ++ ++ rmap = devm_regmap_init_mmio(dev, base, &ipq4019_vmmcq_regmap_config); ++ if (IS_ERR(rmap)) ++ return PTR_ERR(rmap); ++ ++ cfg.dev = dev; ++ cfg.init_data = init_data; ++ cfg.of_node = dev->of_node; ++ cfg.regmap = rmap; ++ ++ rdev = devm_regulator_register(dev, &vmmc_regulator, &cfg); ++ if (IS_ERR(rdev)) { ++ dev_err(dev, "Failed to register regulator: %ld\n", ++ PTR_ERR(rdev)); ++ return PTR_ERR(rdev); ++ } ++ platform_set_drvdata(pdev, rdev); ++ ++ return 0; ++} ++ ++static const struct of_device_id regulator_ipq4019_of_match[] = { ++ { .compatible = "qcom,vqmmc-ipq4019-regulator", }, ++ {}, ++}; ++ ++static struct platform_driver ipq4019_regulator_driver = { ++ .probe = ipq4019_regulator_probe, ++ .driver = { ++ .name = "vqmmc-ipq4019-regulator", ++ .of_match_table = of_match_ptr(regulator_ipq4019_of_match), ++ }, ++}; ++module_platform_driver(ipq4019_regulator_driver); ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Mantas Pucka "); ++MODULE_DESCRIPTION("IPQ4019 VQMMC voltage regulator"); diff --git a/feeds/ipq40xx/ipq40xx/patches-5.4/0002-02-v5.5-ARM-dts-qcom-ipq4019-Add-SDHCI-controller-node.patch b/feeds/ipq40xx/ipq40xx/patches-5.4/0002-02-v5.5-ARM-dts-qcom-ipq4019-Add-SDHCI-controller-node.patch new file mode 100644 index 000000000..25fce8daf --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/patches-5.4/0002-02-v5.5-ARM-dts-qcom-ipq4019-Add-SDHCI-controller-node.patch @@ -0,0 +1,36 @@ +From 04b3b72b5b8fdb883bfdc619cb29b03641b1cc6a Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Thu, 15 Aug 2019 19:28:23 +0200 +Subject: [PATCH] ARM: dts: qcom: ipq4019: Add SDHCI controller node + +IPQ4019 has a built in SD/eMMC controller which is supported by the +SDHCI MSM driver, by the "qcom,sdhci-msm-v4" binding. +So lets add the appropriate node for it. + +Signed-off-by: Robert Marko +Signed-off-by: Bjorn Andersson +--- + arch/arm/boot/dts/qcom-ipq4019.dtsi | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +--- a/arch/arm/boot/dts/qcom-ipq4019.dtsi ++++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi +@@ -206,6 +206,18 @@ + interrupts = ; + }; + ++ sdhci: sdhci@7824900 { ++ compatible = "qcom,sdhci-msm-v4"; ++ reg = <0x7824900 0x11c>, <0x7824000 0x800>; ++ interrupts = , ; ++ interrupt-names = "hc_irq", "pwr_irq"; ++ bus-width = <8>; ++ clocks = <&gcc GCC_SDCC1_APPS_CLK>, <&gcc GCC_SDCC1_AHB_CLK>, ++ <&gcc GCC_DCD_XO_CLK>; ++ clock-names = "core", "iface", "xo"; ++ status = "disabled"; ++ }; ++ + blsp_dma: dma@7884000 { + compatible = "qcom,bam-v1.7.0"; + reg = <0x07884000 0x23000>; diff --git a/feeds/ipq40xx/ipq40xx/patches-5.4/0003-v5.6-ARM-dts-qcom-Add-nodes-for-SMP-boot-in-IPQ40xx.patch b/feeds/ipq40xx/ipq40xx/patches-5.4/0003-v5.6-ARM-dts-qcom-Add-nodes-for-SMP-boot-in-IPQ40xx.patch new file mode 100644 index 000000000..3a4127feb --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/patches-5.4/0003-v5.6-ARM-dts-qcom-Add-nodes-for-SMP-boot-in-IPQ40xx.patch @@ -0,0 +1,71 @@ +From 5e4548922009870a38bcf1d887317676d4e08f54 Mon Sep 17 00:00:00 2001 +From: Damir Franusic +Date: Thu, 21 Nov 2019 16:29:02 +0100 +Subject: [PATCH] ARM: dts: qcom: Add nodes for SMP boot in IPQ40xx + +Add missing nodes and properties to enable SMP +support on IPQ40xx devices. + +Booting without "saw_l2" node: + +[ 0.001400] CPU: Testing write buffer coherency: ok +[ 0.001856] CPU0: thread -1, cpu 0, socket 0, mpidr 80000000 +[ 0.060163] Setting up static identity map for 0x80300000 - 0x80300060 +[ 0.080140] rcu: Hierarchical SRCU implementation. +[ 0.120258] smp: Bringing up secondary CPUs ... +[ 0.200540] CPU1: failed to boot: -19 +[ 0.280689] CPU2: failed to boot: -19 +[ 0.360874] CPU3: failed to boot: -19 +[ 0.360966] smp: Brought up 1 node, 1 CPU +[ 0.360979] SMP: Total of 1 processors activated (96.00 BogoMIPS). +[ 0.360988] CPU: All CPU(s) started in SVC mode. + +Then, booting with "saw_l2" node present (this patch applied): + +[ 0.001450] CPU: Testing write buffer coherency: ok +[ 0.001904] CPU0: thread -1, cpu 0, socket 0, mpidr 80000000 +[ 0.060161] Setting up static identity map for 0x80300000 - 0x80300060 +[ 0.080137] rcu: Hierarchical SRCU implementation. +[ 0.120252] smp: Bringing up secondary CPUs ... +[ 0.200958] CPU1: thread -1, cpu 1, socket 0, mpidr 80000001 +[ 0.281091] CPU2: thread -1, cpu 2, socket 0, mpidr 80000002 +[ 0.361264] CPU3: thread -1, cpu 3, socket 0, mpidr 80000003 +[ 0.361430] smp: Brought up 1 node, 4 CPUs +[ 0.361460] SMP: Total of 4 processors activated (384.00 BogoMIPS). +[ 0.361469] CPU: All CPU(s) started in SVC mode. + +Signed-off-by: Damir Franusic +Cc: Luka Perkov +Cc: Robert Marko +Cc: Andy Gross +Cc: Rob Herring +Cc: linux-arm-msm@vger.kernel.org +Link: https://lore.kernel.org/r/20191121152902.21394-1-damir.franusic@gmail.com +Signed-off-by: Bjorn Andersson +--- + arch/arm/boot/dts/qcom-ipq4019.dtsi | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/arch/arm/boot/dts/qcom-ipq4019.dtsi ++++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi +@@ -102,6 +102,7 @@ + L2: l2-cache { + compatible = "cache"; + cache-level = <2>; ++ qcom,saw = <&saw_l2>; + }; + }; + +@@ -353,6 +354,12 @@ + regulator; + }; + ++ saw_l2: regulator@b012000 { ++ compatible = "qcom,saw2"; ++ reg = <0xb012000 0x1000>; ++ regulator; ++ }; ++ + blsp1_uart1: serial@78af000 { + compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm"; + reg = <0x78af000 0x200>; diff --git a/feeds/ipq40xx/ipq40xx/patches-5.4/0003-v5.7-ARM-dts-qcom-add-gpio-ranges-property.patch b/feeds/ipq40xx/ipq40xx/patches-5.4/0003-v5.7-ARM-dts-qcom-add-gpio-ranges-property.patch new file mode 100644 index 000000000..6922bc8ff --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/patches-5.4/0003-v5.7-ARM-dts-qcom-add-gpio-ranges-property.patch @@ -0,0 +1,119 @@ +From 8b99dc0922618062a1589ebd74df6108b4f9ac22 Mon Sep 17 00:00:00 2001 +From: Christian Lamparter +Date: Wed, 8 Jan 2020 13:54:55 +0100 +Subject: [PATCH] ARM: dts: qcom: add gpio-ranges property + +This patch adds the gpio-ranges property to almost all of +the Qualcomm ARM platforms that utilize the pinctrl-msm +framework. + +The gpio-ranges property is part of the gpiolib subsystem. +As a result, the binding text is available in section +"2.1 gpio- and pin-controller interaction" of +Documentation/devicetree/bindings/gpio/gpio.txt + +For more information please see the patch titled: +"pinctrl: msm: fix gpio-hog related boot issues" from +this series. + +Reported-by: Sven Eckelmann +Tested-by: Sven Eckelmann [ipq4019] +Reviewed-by: Bjorn Andersson +Reviewed-by: Linus Walleij +Signed-off-by: Christian Lamparter +Tested-by: Robert Marko [ipq4019] +Cc: Luka Perkov +Signed-off-by: Robert Marko +Link: https://lore.kernel.org/r/20200108125455.308969-1-robert.marko@sartura.hr +Signed-off-by: Bjorn Andersson +--- + arch/arm/boot/dts/qcom-apq8064.dtsi | 1 + + arch/arm/boot/dts/qcom-apq8084.dtsi | 1 + + arch/arm/boot/dts/qcom-ipq4019.dtsi | 1 + + arch/arm/boot/dts/qcom-ipq8064.dtsi | 1 + + arch/arm/boot/dts/qcom-mdm9615.dtsi | 1 + + arch/arm/boot/dts/qcom-msm8660.dtsi | 1 + + arch/arm/boot/dts/qcom-msm8960.dtsi | 1 + + arch/arm/boot/dts/qcom-msm8974.dtsi | 1 + + 8 files changed, 8 insertions(+) + +--- a/arch/arm/boot/dts/qcom-apq8064.dtsi ++++ b/arch/arm/boot/dts/qcom-apq8064.dtsi +@@ -350,6 +350,7 @@ + reg = <0x800000 0x4000>; + + gpio-controller; ++ gpio-ranges = <&tlmm_pinmux 0 0 90>; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; +--- a/arch/arm/boot/dts/qcom-apq8084.dtsi ++++ b/arch/arm/boot/dts/qcom-apq8084.dtsi +@@ -401,6 +401,7 @@ + compatible = "qcom,apq8084-pinctrl"; + reg = <0xfd510000 0x4000>; + gpio-controller; ++ gpio-ranges = <&tlmm 0 0 147>; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; +--- a/arch/arm/boot/dts/qcom-ipq4019.dtsi ++++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi +@@ -201,6 +201,7 @@ + compatible = "qcom,ipq4019-pinctrl"; + reg = <0x01000000 0x300000>; + gpio-controller; ++ gpio-ranges = <&tlmm 0 0 100>; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; +--- a/arch/arm/boot/dts/qcom-ipq8064.dtsi ++++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi +@@ -119,6 +119,7 @@ + reg = <0x800000 0x4000>; + + gpio-controller; ++ gpio-ranges = <&qcom_pinmux 0 0 69>; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; +--- a/arch/arm/boot/dts/qcom-mdm9615.dtsi ++++ b/arch/arm/boot/dts/qcom-mdm9615.dtsi +@@ -128,6 +128,7 @@ + msmgpio: pinctrl@800000 { + compatible = "qcom,mdm9615-pinctrl"; + gpio-controller; ++ gpio-ranges = <&msmgpio 0 0 88>; + #gpio-cells = <2>; + interrupts = ; + interrupt-controller; +--- a/arch/arm/boot/dts/qcom-msm8660.dtsi ++++ b/arch/arm/boot/dts/qcom-msm8660.dtsi +@@ -115,6 +115,7 @@ + reg = <0x800000 0x4000>; + + gpio-controller; ++ gpio-ranges = <&tlmm 0 0 173>; + #gpio-cells = <2>; + interrupts = <0 16 0x4>; + interrupt-controller; +--- a/arch/arm/boot/dts/qcom-msm8960.dtsi ++++ b/arch/arm/boot/dts/qcom-msm8960.dtsi +@@ -107,6 +107,7 @@ + msmgpio: pinctrl@800000 { + compatible = "qcom,msm8960-pinctrl"; + gpio-controller; ++ gpio-ranges = <&msmgpio 0 0 152>; + #gpio-cells = <2>; + interrupts = <0 16 0x4>; + interrupt-controller; +--- a/arch/arm/boot/dts/qcom-msm8974.dtsi ++++ b/arch/arm/boot/dts/qcom-msm8974.dtsi +@@ -707,6 +707,7 @@ + compatible = "qcom,msm8974-pinctrl"; + reg = <0xfd510000 0x4000>; + gpio-controller; ++ gpio-ranges = <&msmgpio 0 0 146>; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; diff --git a/feeds/ipq40xx/ipq40xx/patches-5.4/0004-v5.8-ARM-dts-qcom-ipq4019-fix-high-resolution-timer.patch b/feeds/ipq40xx/ipq40xx/patches-5.4/0004-v5.8-ARM-dts-qcom-ipq4019-fix-high-resolution-timer.patch new file mode 100644 index 000000000..f82021f4c --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/patches-5.4/0004-v5.8-ARM-dts-qcom-ipq4019-fix-high-resolution-timer.patch @@ -0,0 +1,33 @@ +From 8acc36189dcaf4487d8c6ba7445948f39b1d248a Mon Sep 17 00:00:00 2001 +From: Abhishek Sahu +Date: Fri, 3 Apr 2020 13:40:40 +0200 +Subject: [PATCH] ARM: dts: qcom: ipq4019: fix high resolution timer + +Cherry-picked from CAF QSDK repo. +Original commit message: +The kernel is failing in switching the timer for high resolution +mode and clock source operates in 10ms resolution. The always-on +property needs to be given for timer device tree node to make +clock source working in 1ns resolution. + +Signed-off-by: Abhishek Sahu +Signed-off-by: Pavel Kubelun +Signed-off-by: Christian Lamparter +Tested-by: Robert Marko +Cc: Luka Perkov +Link: https://lore.kernel.org/r/20200403114040.349787-1-robert.marko@sartura.hr +Signed-off-by: Bjorn Andersson +--- + arch/arm/boot/dts/qcom-ipq4019.dtsi | 1 + + 1 file changed, 1 insertion(+) + +--- a/arch/arm/boot/dts/qcom-ipq4019.dtsi ++++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi +@@ -166,6 +166,7 @@ + <1 4 0xf08>, + <1 1 0xf08>; + clock-frequency = <48000000>; ++ always-on; + }; + + soc { diff --git a/feeds/ipq40xx/ipq40xx/patches-5.4/0005-01-v5.8-net-phy-mdio-add-IPQ4019-MDIO-driver.patch b/feeds/ipq40xx/ipq40xx/patches-5.4/0005-01-v5.8-net-phy-mdio-add-IPQ4019-MDIO-driver.patch new file mode 100644 index 000000000..d678f761f --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/patches-5.4/0005-01-v5.8-net-phy-mdio-add-IPQ4019-MDIO-driver.patch @@ -0,0 +1,210 @@ +From 466ed24fb22342f3ae1c10758a6a0c6a8c081b2d Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Thu, 30 Apr 2020 11:07:05 +0200 +Subject: [PATCH] net: phy: mdio: add IPQ4019 MDIO driver + +This patch adds the driver for the MDIO interface +inside of Qualcomm IPQ40xx series SoC-s. + +Signed-off-by: Christian Lamparter +Signed-off-by: Robert Marko +Reviewed-by: Andrew Lunn +Reviewed-by: Florian Fainelli +Cc: Luka Perkov +Signed-off-by: David S. Miller +--- + drivers/net/phy/Kconfig | 7 ++ + drivers/net/phy/Makefile | 1 + + drivers/net/phy/mdio-ipq4019.c | 160 +++++++++++++++++++++++++++++++++ + 3 files changed, 168 insertions(+) + create mode 100644 drivers/net/phy/mdio-ipq4019.c + +--- a/drivers/net/phy/Kconfig ++++ b/drivers/net/phy/Kconfig +@@ -156,6 +156,13 @@ config MDIO_I2C + + This is library mode. + ++config MDIO_IPQ4019 ++ tristate "Qualcomm IPQ4019 MDIO interface support" ++ depends on HAS_IOMEM && OF_MDIO ++ help ++ This driver supports the MDIO interface found in Qualcomm ++ IPQ40xx series Soc-s. ++ + config MDIO_MOXART + tristate "MOXA ART MDIO interface support" + depends on ARCH_MOXART || COMPILE_TEST +--- a/drivers/net/phy/Makefile ++++ b/drivers/net/phy/Makefile +@@ -50,6 +50,7 @@ obj-$(CONFIG_MDIO_CAVIUM) += mdio-cavium + obj-$(CONFIG_MDIO_GPIO) += mdio-gpio.o + obj-$(CONFIG_MDIO_HISI_FEMAC) += mdio-hisi-femac.o + obj-$(CONFIG_MDIO_I2C) += mdio-i2c.o ++obj-$(CONFIG_MDIO_IPQ4019) += mdio-ipq4019.o + obj-$(CONFIG_MDIO_MOXART) += mdio-moxart.o + obj-$(CONFIG_MDIO_MSCC_MIIM) += mdio-mscc-miim.o + obj-$(CONFIG_MDIO_OCTEON) += mdio-octeon.o +--- /dev/null ++++ b/drivers/net/phy/mdio-ipq4019.c +@@ -0,0 +1,160 @@ ++// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause ++/* Copyright (c) 2015, The Linux Foundation. All rights reserved. */ ++/* Copyright (c) 2020 Sartura Ltd. */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define MDIO_ADDR_REG 0x44 ++#define MDIO_DATA_WRITE_REG 0x48 ++#define MDIO_DATA_READ_REG 0x4c ++#define MDIO_CMD_REG 0x50 ++#define MDIO_CMD_ACCESS_BUSY BIT(16) ++#define MDIO_CMD_ACCESS_START BIT(8) ++#define MDIO_CMD_ACCESS_CODE_READ 0 ++#define MDIO_CMD_ACCESS_CODE_WRITE 1 ++ ++#define ipq4019_MDIO_TIMEOUT 10000 ++#define ipq4019_MDIO_SLEEP 10 ++ ++struct ipq4019_mdio_data { ++ void __iomem *membase; ++}; ++ ++static int ipq4019_mdio_wait_busy(struct mii_bus *bus) ++{ ++ struct ipq4019_mdio_data *priv = bus->priv; ++ unsigned int busy; ++ ++ return readl_poll_timeout(priv->membase + MDIO_CMD_REG, busy, ++ (busy & MDIO_CMD_ACCESS_BUSY) == 0, ++ ipq4019_MDIO_SLEEP, ipq4019_MDIO_TIMEOUT); ++} ++ ++static int ipq4019_mdio_read(struct mii_bus *bus, int mii_id, int regnum) ++{ ++ struct ipq4019_mdio_data *priv = bus->priv; ++ unsigned int cmd; ++ ++ /* Reject clause 45 */ ++ if (regnum & MII_ADDR_C45) ++ return -EOPNOTSUPP; ++ ++ if (ipq4019_mdio_wait_busy(bus)) ++ return -ETIMEDOUT; ++ ++ /* issue the phy address and reg */ ++ writel((mii_id << 8) | regnum, priv->membase + MDIO_ADDR_REG); ++ ++ cmd = MDIO_CMD_ACCESS_START | MDIO_CMD_ACCESS_CODE_READ; ++ ++ /* issue read command */ ++ writel(cmd, priv->membase + MDIO_CMD_REG); ++ ++ /* Wait read complete */ ++ if (ipq4019_mdio_wait_busy(bus)) ++ return -ETIMEDOUT; ++ ++ /* Read and return data */ ++ return readl(priv->membase + MDIO_DATA_READ_REG); ++} ++ ++static int ipq4019_mdio_write(struct mii_bus *bus, int mii_id, int regnum, ++ u16 value) ++{ ++ struct ipq4019_mdio_data *priv = bus->priv; ++ unsigned int cmd; ++ ++ /* Reject clause 45 */ ++ if (regnum & MII_ADDR_C45) ++ return -EOPNOTSUPP; ++ ++ if (ipq4019_mdio_wait_busy(bus)) ++ return -ETIMEDOUT; ++ ++ /* issue the phy address and reg */ ++ writel((mii_id << 8) | regnum, priv->membase + MDIO_ADDR_REG); ++ ++ /* issue write data */ ++ writel(value, priv->membase + MDIO_DATA_WRITE_REG); ++ ++ cmd = MDIO_CMD_ACCESS_START | MDIO_CMD_ACCESS_CODE_WRITE; ++ /* issue write command */ ++ writel(cmd, priv->membase + MDIO_CMD_REG); ++ ++ /* Wait write complete */ ++ if (ipq4019_mdio_wait_busy(bus)) ++ return -ETIMEDOUT; ++ ++ return 0; ++} ++ ++static int ipq4019_mdio_probe(struct platform_device *pdev) ++{ ++ struct ipq4019_mdio_data *priv; ++ struct mii_bus *bus; ++ int ret; ++ ++ bus = devm_mdiobus_alloc_size(&pdev->dev, sizeof(*priv)); ++ if (!bus) ++ return -ENOMEM; ++ ++ priv = bus->priv; ++ ++ priv->membase = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(priv->membase)) ++ return PTR_ERR(priv->membase); ++ ++ bus->name = "ipq4019_mdio"; ++ bus->read = ipq4019_mdio_read; ++ bus->write = ipq4019_mdio_write; ++ bus->parent = &pdev->dev; ++ snprintf(bus->id, MII_BUS_ID_SIZE, "%s%d", pdev->name, pdev->id); ++ ++ ret = of_mdiobus_register(bus, pdev->dev.of_node); ++ if (ret) { ++ dev_err(&pdev->dev, "Cannot register MDIO bus!\n"); ++ return ret; ++ } ++ ++ platform_set_drvdata(pdev, bus); ++ ++ return 0; ++} ++ ++static int ipq4019_mdio_remove(struct platform_device *pdev) ++{ ++ struct mii_bus *bus = platform_get_drvdata(pdev); ++ ++ mdiobus_unregister(bus); ++ ++ return 0; ++} ++ ++static const struct of_device_id ipq4019_mdio_dt_ids[] = { ++ { .compatible = "qcom,ipq4019-mdio" }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, ipq4019_mdio_dt_ids); ++ ++static struct platform_driver ipq4019_mdio_driver = { ++ .probe = ipq4019_mdio_probe, ++ .remove = ipq4019_mdio_remove, ++ .driver = { ++ .name = "ipq4019-mdio", ++ .of_match_table = ipq4019_mdio_dt_ids, ++ }, ++}; ++ ++module_platform_driver(ipq4019_mdio_driver); ++ ++MODULE_DESCRIPTION("ipq4019 MDIO interface driver"); ++MODULE_AUTHOR("Qualcomm Atheros"); ++MODULE_LICENSE("Dual BSD/GPL"); diff --git a/feeds/ipq40xx/ipq40xx/patches-5.4/0005-02-v5.8-02-ARM-dts-qcom-ipq4019-add-MDIO-node.patch b/feeds/ipq40xx/ipq40xx/patches-5.4/0005-02-v5.8-02-ARM-dts-qcom-ipq4019-add-MDIO-node.patch new file mode 100644 index 000000000..1976686e8 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/patches-5.4/0005-02-v5.8-02-ARM-dts-qcom-ipq4019-add-MDIO-node.patch @@ -0,0 +1,57 @@ +From 9c8c0f70ec6fdac2398632c723c48277be09b7c0 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Thu, 30 Apr 2020 11:07:07 +0200 +Subject: [PATCH] ARM: dts: qcom: ipq4019: add MDIO node + +This patch adds the necessary MDIO interface node +to the Qualcomm IPQ4019 DTSI. + +Built-in QCA8337N switch is managed using it, +and since we have a driver for it lets add it. + +Signed-off-by: Christian Lamparter +Signed-off-by: Robert Marko +Reviewed-by: Andrew Lunn +Reviewed-by: Florian Fainelli +Cc: Luka Perkov +Signed-off-by: David S. Miller +--- + arch/arm/boot/dts/qcom-ipq4019.dtsi | 28 ++++++++++++++++++++++++++++ + 1 file changed, 28 insertions(+) + +--- a/arch/arm/boot/dts/qcom-ipq4019.dtsi ++++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi +@@ -577,5 +577,33 @@ + "legacy"; + status = "disabled"; + }; ++ ++ mdio: mdio@90000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "qcom,ipq4019-mdio"; ++ reg = <0x90000 0x64>; ++ status = "disabled"; ++ ++ ethphy0: ethernet-phy@0 { ++ reg = <0>; ++ }; ++ ++ ethphy1: ethernet-phy@1 { ++ reg = <1>; ++ }; ++ ++ ethphy2: ethernet-phy@2 { ++ reg = <2>; ++ }; ++ ++ ethphy3: ethernet-phy@3 { ++ reg = <3>; ++ }; ++ ++ ethphy4: ethernet-phy@4 { ++ reg = <4>; ++ }; ++ }; + }; + }; diff --git a/feeds/ipq40xx/ipq40xx/patches-5.4/0006-v5.5-crypto-qce-add-CRYPTO_ALG_KERN_DRIVER_ONLY-flag.patch b/feeds/ipq40xx/ipq40xx/patches-5.4/0006-v5.5-crypto-qce-add-CRYPTO_ALG_KERN_DRIVER_ONLY-flag.patch new file mode 100644 index 000000000..415d6fff9 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/patches-5.4/0006-v5.5-crypto-qce-add-CRYPTO_ALG_KERN_DRIVER_ONLY-flag.patch @@ -0,0 +1,31 @@ +From: Eneas U de Queiroz +Subject: [PATCH] crypto: qce - add CRYPTO_ALG_KERN_DRIVER_ONLY flag + +Set the CRYPTO_ALG_KERN_DRIVER_ONLY flag to all algorithms exposed by +the qce driver, since they are all hardware accelerated, accessible +through a kernel driver only, and not available directly to userspace. + +Signed-off-by: Eneas U de Queiroz + +--- a/drivers/crypto/qce/ablkcipher.c ++++ b/drivers/crypto/qce/ablkcipher.c +@@ -380,7 +380,7 @@ static int qce_ablkcipher_register_one(c + + alg->cra_priority = 300; + alg->cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC | +- CRYPTO_ALG_NEED_FALLBACK; ++ CRYPTO_ALG_NEED_FALLBACK | CRYPTO_ALG_KERN_DRIVER_ONLY; + alg->cra_ctxsize = sizeof(struct qce_cipher_ctx); + alg->cra_alignmask = 0; + alg->cra_type = &crypto_ablkcipher_type; +--- a/drivers/crypto/qce/sha.c ++++ b/drivers/crypto/qce/sha.c +@@ -495,7 +495,7 @@ static int qce_ahash_register_one(const + base = &alg->halg.base; + base->cra_blocksize = def->blocksize; + base->cra_priority = 300; +- base->cra_flags = CRYPTO_ALG_ASYNC; ++ base->cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_KERN_DRIVER_ONLY; + base->cra_ctxsize = sizeof(struct qce_sha_ctx); + base->cra_alignmask = 0; + base->cra_module = THIS_MODULE; diff --git a/feeds/ipq40xx/ipq40xx/patches-5.4/0007-v5.5-crypto-qce-switch-to-skcipher-API.patch b/feeds/ipq40xx/ipq40xx/patches-5.4/0007-v5.5-crypto-qce-switch-to-skcipher-API.patch new file mode 100644 index 000000000..4dcb94215 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/patches-5.4/0007-v5.5-crypto-qce-switch-to-skcipher-API.patch @@ -0,0 +1,993 @@ +From f441873642eebf20566c18d2966a8cd4b433ec1c Mon Sep 17 00:00:00 2001 +From: Ard Biesheuvel +Date: Tue, 5 Nov 2019 14:28:17 +0100 +Subject: [PATCH] crypto: qce - switch to skcipher API + +Commit 7a7ffe65c8c5 ("crypto: skcipher - Add top-level skcipher interface") +dated 20 august 2015 introduced the new skcipher API which is supposed to +replace both blkcipher and ablkcipher. While all consumers of the API have +been converted long ago, some producers of the ablkcipher remain, forcing +us to keep the ablkcipher support routines alive, along with the matching +code to expose [a]blkciphers via the skcipher API. + +So switch this driver to the skcipher API, allowing us to finally drop the +blkcipher code in the near future. + +Reviewed-by: Stanimir Varbanov +Signed-off-by: Ard Biesheuvel +Backported-to-4.19-by: Eneas U de Queiroz + +--- a/drivers/crypto/qce/Makefile ++++ b/drivers/crypto/qce/Makefile +@@ -4,4 +4,4 @@ qcrypto-objs := core.o \ + common.o \ + dma.o \ + sha.o \ +- ablkcipher.o ++ skcipher.o +--- a/drivers/crypto/qce/cipher.h ++++ b/drivers/crypto/qce/cipher.h +@@ -45,12 +45,12 @@ struct qce_cipher_reqctx { + unsigned int cryptlen; + }; + +-static inline struct qce_alg_template *to_cipher_tmpl(struct crypto_tfm *tfm) ++static inline struct qce_alg_template *to_cipher_tmpl(struct crypto_skcipher *tfm) + { +- struct crypto_alg *alg = tfm->__crt_alg; +- return container_of(alg, struct qce_alg_template, alg.crypto); ++ struct skcipher_alg *alg = crypto_skcipher_alg(tfm); ++ return container_of(alg, struct qce_alg_template, alg.skcipher); + } + +-extern const struct qce_algo_ops ablkcipher_ops; ++extern const struct qce_algo_ops skcipher_ops; + + #endif /* _CIPHER_H_ */ +--- a/drivers/crypto/qce/common.c ++++ b/drivers/crypto/qce/common.c +@@ -304,13 +304,13 @@ go_proc: + return 0; + } + +-static int qce_setup_regs_ablkcipher(struct crypto_async_request *async_req, ++static int qce_setup_regs_skcipher(struct crypto_async_request *async_req, + u32 totallen, u32 offset) + { +- struct ablkcipher_request *req = ablkcipher_request_cast(async_req); +- struct qce_cipher_reqctx *rctx = ablkcipher_request_ctx(req); ++ struct skcipher_request *req = skcipher_request_cast(async_req); ++ struct qce_cipher_reqctx *rctx = skcipher_request_ctx(req); + struct qce_cipher_ctx *ctx = crypto_tfm_ctx(async_req->tfm); +- struct qce_alg_template *tmpl = to_cipher_tmpl(async_req->tfm); ++ struct qce_alg_template *tmpl = to_cipher_tmpl(crypto_skcipher_reqtfm(req)); + struct qce_device *qce = tmpl->qce; + __be32 enckey[QCE_MAX_CIPHER_KEY_SIZE / sizeof(__be32)] = {0}; + __be32 enciv[QCE_MAX_IV_SIZE / sizeof(__be32)] = {0}; +@@ -389,8 +389,8 @@ int qce_start(struct crypto_async_reques + u32 offset) + { + switch (type) { +- case CRYPTO_ALG_TYPE_ABLKCIPHER: +- return qce_setup_regs_ablkcipher(async_req, totallen, offset); ++ case CRYPTO_ALG_TYPE_SKCIPHER: ++ return qce_setup_regs_skcipher(async_req, totallen, offset); + case CRYPTO_ALG_TYPE_AHASH: + return qce_setup_regs_ahash(async_req, totallen, offset); + default: +--- a/drivers/crypto/qce/common.h ++++ b/drivers/crypto/qce/common.h +@@ -10,6 +10,7 @@ + #include + #include + #include ++#include + + /* key size in bytes */ + #define QCE_SHA_HMAC_KEY_SIZE 64 +@@ -79,7 +80,7 @@ struct qce_alg_template { + unsigned long alg_flags; + const u32 *std_iv; + union { +- struct crypto_alg crypto; ++ struct skcipher_alg skcipher; + struct ahash_alg ahash; + } alg; + struct qce_device *qce; +--- a/drivers/crypto/qce/core.c ++++ b/drivers/crypto/qce/core.c +@@ -22,7 +22,7 @@ + #define QCE_QUEUE_LENGTH 1 + + static const struct qce_algo_ops *qce_ops[] = { +- &ablkcipher_ops, ++ &skcipher_ops, + &ahash_ops, + }; + +--- a/drivers/crypto/qce/ablkcipher.c ++++ /dev/null +@@ -1,440 +0,0 @@ +-// SPDX-License-Identifier: GPL-2.0-only +-/* +- * Copyright (c) 2010-2014, The Linux Foundation. All rights reserved. +- */ +- +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include "cipher.h" +- +-static LIST_HEAD(ablkcipher_algs); +- +-static void qce_ablkcipher_done(void *data) +-{ +- struct crypto_async_request *async_req = data; +- struct ablkcipher_request *req = ablkcipher_request_cast(async_req); +- struct qce_cipher_reqctx *rctx = ablkcipher_request_ctx(req); +- struct qce_alg_template *tmpl = to_cipher_tmpl(async_req->tfm); +- struct qce_device *qce = tmpl->qce; +- enum dma_data_direction dir_src, dir_dst; +- u32 status; +- int error; +- bool diff_dst; +- +- diff_dst = (req->src != req->dst) ? true : false; +- dir_src = diff_dst ? DMA_TO_DEVICE : DMA_BIDIRECTIONAL; +- dir_dst = diff_dst ? DMA_FROM_DEVICE : DMA_BIDIRECTIONAL; +- +- error = qce_dma_terminate_all(&qce->dma); +- if (error) +- dev_dbg(qce->dev, "ablkcipher dma termination error (%d)\n", +- error); +- +- if (diff_dst) +- dma_unmap_sg(qce->dev, rctx->src_sg, rctx->src_nents, dir_src); +- dma_unmap_sg(qce->dev, rctx->dst_sg, rctx->dst_nents, dir_dst); +- +- sg_free_table(&rctx->dst_tbl); +- +- error = qce_check_status(qce, &status); +- if (error < 0) +- dev_dbg(qce->dev, "ablkcipher operation error (%x)\n", status); +- +- qce->async_req_done(tmpl->qce, error); +-} +- +-static int +-qce_ablkcipher_async_req_handle(struct crypto_async_request *async_req) +-{ +- struct ablkcipher_request *req = ablkcipher_request_cast(async_req); +- struct qce_cipher_reqctx *rctx = ablkcipher_request_ctx(req); +- struct crypto_ablkcipher *ablkcipher = crypto_ablkcipher_reqtfm(req); +- struct qce_alg_template *tmpl = to_cipher_tmpl(async_req->tfm); +- struct qce_device *qce = tmpl->qce; +- enum dma_data_direction dir_src, dir_dst; +- struct scatterlist *sg; +- bool diff_dst; +- gfp_t gfp; +- int ret; +- +- rctx->iv = req->info; +- rctx->ivsize = crypto_ablkcipher_ivsize(ablkcipher); +- rctx->cryptlen = req->nbytes; +- +- diff_dst = (req->src != req->dst) ? true : false; +- dir_src = diff_dst ? DMA_TO_DEVICE : DMA_BIDIRECTIONAL; +- dir_dst = diff_dst ? DMA_FROM_DEVICE : DMA_BIDIRECTIONAL; +- +- rctx->src_nents = sg_nents_for_len(req->src, req->nbytes); +- if (diff_dst) +- rctx->dst_nents = sg_nents_for_len(req->dst, req->nbytes); +- else +- rctx->dst_nents = rctx->src_nents; +- if (rctx->src_nents < 0) { +- dev_err(qce->dev, "Invalid numbers of src SG.\n"); +- return rctx->src_nents; +- } +- if (rctx->dst_nents < 0) { +- dev_err(qce->dev, "Invalid numbers of dst SG.\n"); +- return -rctx->dst_nents; +- } +- +- rctx->dst_nents += 1; +- +- gfp = (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ? +- GFP_KERNEL : GFP_ATOMIC; +- +- ret = sg_alloc_table(&rctx->dst_tbl, rctx->dst_nents, gfp); +- if (ret) +- return ret; +- +- sg_init_one(&rctx->result_sg, qce->dma.result_buf, QCE_RESULT_BUF_SZ); +- +- sg = qce_sgtable_add(&rctx->dst_tbl, req->dst); +- if (IS_ERR(sg)) { +- ret = PTR_ERR(sg); +- goto error_free; +- } +- +- sg = qce_sgtable_add(&rctx->dst_tbl, &rctx->result_sg); +- if (IS_ERR(sg)) { +- ret = PTR_ERR(sg); +- goto error_free; +- } +- +- sg_mark_end(sg); +- rctx->dst_sg = rctx->dst_tbl.sgl; +- +- ret = dma_map_sg(qce->dev, rctx->dst_sg, rctx->dst_nents, dir_dst); +- if (ret < 0) +- goto error_free; +- +- if (diff_dst) { +- ret = dma_map_sg(qce->dev, req->src, rctx->src_nents, dir_src); +- if (ret < 0) +- goto error_unmap_dst; +- rctx->src_sg = req->src; +- } else { +- rctx->src_sg = rctx->dst_sg; +- } +- +- ret = qce_dma_prep_sgs(&qce->dma, rctx->src_sg, rctx->src_nents, +- rctx->dst_sg, rctx->dst_nents, +- qce_ablkcipher_done, async_req); +- if (ret) +- goto error_unmap_src; +- +- qce_dma_issue_pending(&qce->dma); +- +- ret = qce_start(async_req, tmpl->crypto_alg_type, req->nbytes, 0); +- if (ret) +- goto error_terminate; +- +- return 0; +- +-error_terminate: +- qce_dma_terminate_all(&qce->dma); +-error_unmap_src: +- if (diff_dst) +- dma_unmap_sg(qce->dev, req->src, rctx->src_nents, dir_src); +-error_unmap_dst: +- dma_unmap_sg(qce->dev, rctx->dst_sg, rctx->dst_nents, dir_dst); +-error_free: +- sg_free_table(&rctx->dst_tbl); +- return ret; +-} +- +-static int qce_ablkcipher_setkey(struct crypto_ablkcipher *ablk, const u8 *key, +- unsigned int keylen) +-{ +- struct crypto_tfm *tfm = crypto_ablkcipher_tfm(ablk); +- struct qce_cipher_ctx *ctx = crypto_tfm_ctx(tfm); +- int ret; +- +- if (!key || !keylen) +- return -EINVAL; +- +- switch (keylen) { +- case AES_KEYSIZE_128: +- case AES_KEYSIZE_256: +- break; +- default: +- goto fallback; +- } +- +- ctx->enc_keylen = keylen; +- memcpy(ctx->enc_key, key, keylen); +- return 0; +-fallback: +- ret = crypto_sync_skcipher_setkey(ctx->fallback, key, keylen); +- if (!ret) +- ctx->enc_keylen = keylen; +- return ret; +-} +- +-static int qce_des_setkey(struct crypto_ablkcipher *ablk, const u8 *key, +- unsigned int keylen) +-{ +- struct qce_cipher_ctx *ctx = crypto_ablkcipher_ctx(ablk); +- int err; +- +- err = verify_ablkcipher_des_key(ablk, key); +- if (err) +- return err; +- +- ctx->enc_keylen = keylen; +- memcpy(ctx->enc_key, key, keylen); +- return 0; +-} +- +-static int qce_des3_setkey(struct crypto_ablkcipher *ablk, const u8 *key, +- unsigned int keylen) +-{ +- struct qce_cipher_ctx *ctx = crypto_ablkcipher_ctx(ablk); +- int err; +- +- err = verify_ablkcipher_des3_key(ablk, key); +- if (err) +- return err; +- +- ctx->enc_keylen = keylen; +- memcpy(ctx->enc_key, key, keylen); +- return 0; +-} +- +-static int qce_ablkcipher_crypt(struct ablkcipher_request *req, int encrypt) +-{ +- struct crypto_tfm *tfm = +- crypto_ablkcipher_tfm(crypto_ablkcipher_reqtfm(req)); +- struct qce_cipher_ctx *ctx = crypto_tfm_ctx(tfm); +- struct qce_cipher_reqctx *rctx = ablkcipher_request_ctx(req); +- struct qce_alg_template *tmpl = to_cipher_tmpl(tfm); +- int ret; +- +- rctx->flags = tmpl->alg_flags; +- rctx->flags |= encrypt ? QCE_ENCRYPT : QCE_DECRYPT; +- +- if (IS_AES(rctx->flags) && ctx->enc_keylen != AES_KEYSIZE_128 && +- ctx->enc_keylen != AES_KEYSIZE_256) { +- SYNC_SKCIPHER_REQUEST_ON_STACK(subreq, ctx->fallback); +- +- skcipher_request_set_sync_tfm(subreq, ctx->fallback); +- skcipher_request_set_callback(subreq, req->base.flags, +- NULL, NULL); +- skcipher_request_set_crypt(subreq, req->src, req->dst, +- req->nbytes, req->info); +- ret = encrypt ? crypto_skcipher_encrypt(subreq) : +- crypto_skcipher_decrypt(subreq); +- skcipher_request_zero(subreq); +- return ret; +- } +- +- return tmpl->qce->async_req_enqueue(tmpl->qce, &req->base); +-} +- +-static int qce_ablkcipher_encrypt(struct ablkcipher_request *req) +-{ +- return qce_ablkcipher_crypt(req, 1); +-} +- +-static int qce_ablkcipher_decrypt(struct ablkcipher_request *req) +-{ +- return qce_ablkcipher_crypt(req, 0); +-} +- +-static int qce_ablkcipher_init(struct crypto_tfm *tfm) +-{ +- struct qce_cipher_ctx *ctx = crypto_tfm_ctx(tfm); +- +- memset(ctx, 0, sizeof(*ctx)); +- tfm->crt_ablkcipher.reqsize = sizeof(struct qce_cipher_reqctx); +- +- ctx->fallback = crypto_alloc_sync_skcipher(crypto_tfm_alg_name(tfm), +- 0, CRYPTO_ALG_NEED_FALLBACK); +- return PTR_ERR_OR_ZERO(ctx->fallback); +-} +- +-static void qce_ablkcipher_exit(struct crypto_tfm *tfm) +-{ +- struct qce_cipher_ctx *ctx = crypto_tfm_ctx(tfm); +- +- crypto_free_sync_skcipher(ctx->fallback); +-} +- +-struct qce_ablkcipher_def { +- unsigned long flags; +- const char *name; +- const char *drv_name; +- unsigned int blocksize; +- unsigned int ivsize; +- unsigned int min_keysize; +- unsigned int max_keysize; +-}; +- +-static const struct qce_ablkcipher_def ablkcipher_def[] = { +- { +- .flags = QCE_ALG_AES | QCE_MODE_ECB, +- .name = "ecb(aes)", +- .drv_name = "ecb-aes-qce", +- .blocksize = AES_BLOCK_SIZE, +- .ivsize = AES_BLOCK_SIZE, +- .min_keysize = AES_MIN_KEY_SIZE, +- .max_keysize = AES_MAX_KEY_SIZE, +- }, +- { +- .flags = QCE_ALG_AES | QCE_MODE_CBC, +- .name = "cbc(aes)", +- .drv_name = "cbc-aes-qce", +- .blocksize = AES_BLOCK_SIZE, +- .ivsize = AES_BLOCK_SIZE, +- .min_keysize = AES_MIN_KEY_SIZE, +- .max_keysize = AES_MAX_KEY_SIZE, +- }, +- { +- .flags = QCE_ALG_AES | QCE_MODE_CTR, +- .name = "ctr(aes)", +- .drv_name = "ctr-aes-qce", +- .blocksize = AES_BLOCK_SIZE, +- .ivsize = AES_BLOCK_SIZE, +- .min_keysize = AES_MIN_KEY_SIZE, +- .max_keysize = AES_MAX_KEY_SIZE, +- }, +- { +- .flags = QCE_ALG_AES | QCE_MODE_XTS, +- .name = "xts(aes)", +- .drv_name = "xts-aes-qce", +- .blocksize = AES_BLOCK_SIZE, +- .ivsize = AES_BLOCK_SIZE, +- .min_keysize = AES_MIN_KEY_SIZE, +- .max_keysize = AES_MAX_KEY_SIZE, +- }, +- { +- .flags = QCE_ALG_DES | QCE_MODE_ECB, +- .name = "ecb(des)", +- .drv_name = "ecb-des-qce", +- .blocksize = DES_BLOCK_SIZE, +- .ivsize = 0, +- .min_keysize = DES_KEY_SIZE, +- .max_keysize = DES_KEY_SIZE, +- }, +- { +- .flags = QCE_ALG_DES | QCE_MODE_CBC, +- .name = "cbc(des)", +- .drv_name = "cbc-des-qce", +- .blocksize = DES_BLOCK_SIZE, +- .ivsize = DES_BLOCK_SIZE, +- .min_keysize = DES_KEY_SIZE, +- .max_keysize = DES_KEY_SIZE, +- }, +- { +- .flags = QCE_ALG_3DES | QCE_MODE_ECB, +- .name = "ecb(des3_ede)", +- .drv_name = "ecb-3des-qce", +- .blocksize = DES3_EDE_BLOCK_SIZE, +- .ivsize = 0, +- .min_keysize = DES3_EDE_KEY_SIZE, +- .max_keysize = DES3_EDE_KEY_SIZE, +- }, +- { +- .flags = QCE_ALG_3DES | QCE_MODE_CBC, +- .name = "cbc(des3_ede)", +- .drv_name = "cbc-3des-qce", +- .blocksize = DES3_EDE_BLOCK_SIZE, +- .ivsize = DES3_EDE_BLOCK_SIZE, +- .min_keysize = DES3_EDE_KEY_SIZE, +- .max_keysize = DES3_EDE_KEY_SIZE, +- }, +-}; +- +-static int qce_ablkcipher_register_one(const struct qce_ablkcipher_def *def, +- struct qce_device *qce) +-{ +- struct qce_alg_template *tmpl; +- struct crypto_alg *alg; +- int ret; +- +- tmpl = kzalloc(sizeof(*tmpl), GFP_KERNEL); +- if (!tmpl) +- return -ENOMEM; +- +- alg = &tmpl->alg.crypto; +- +- snprintf(alg->cra_name, CRYPTO_MAX_ALG_NAME, "%s", def->name); +- snprintf(alg->cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s", +- def->drv_name); +- +- alg->cra_blocksize = def->blocksize; +- alg->cra_ablkcipher.ivsize = def->ivsize; +- alg->cra_ablkcipher.min_keysize = def->min_keysize; +- alg->cra_ablkcipher.max_keysize = def->max_keysize; +- alg->cra_ablkcipher.setkey = IS_3DES(def->flags) ? qce_des3_setkey : +- IS_DES(def->flags) ? qce_des_setkey : +- qce_ablkcipher_setkey; +- alg->cra_ablkcipher.encrypt = qce_ablkcipher_encrypt; +- alg->cra_ablkcipher.decrypt = qce_ablkcipher_decrypt; +- +- alg->cra_priority = 300; +- alg->cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC | +- CRYPTO_ALG_NEED_FALLBACK | CRYPTO_ALG_KERN_DRIVER_ONLY; +- alg->cra_ctxsize = sizeof(struct qce_cipher_ctx); +- alg->cra_alignmask = 0; +- alg->cra_type = &crypto_ablkcipher_type; +- alg->cra_module = THIS_MODULE; +- alg->cra_init = qce_ablkcipher_init; +- alg->cra_exit = qce_ablkcipher_exit; +- +- INIT_LIST_HEAD(&tmpl->entry); +- tmpl->crypto_alg_type = CRYPTO_ALG_TYPE_ABLKCIPHER; +- tmpl->alg_flags = def->flags; +- tmpl->qce = qce; +- +- ret = crypto_register_alg(alg); +- if (ret) { +- kfree(tmpl); +- dev_err(qce->dev, "%s registration failed\n", alg->cra_name); +- return ret; +- } +- +- list_add_tail(&tmpl->entry, &ablkcipher_algs); +- dev_dbg(qce->dev, "%s is registered\n", alg->cra_name); +- return 0; +-} +- +-static void qce_ablkcipher_unregister(struct qce_device *qce) +-{ +- struct qce_alg_template *tmpl, *n; +- +- list_for_each_entry_safe(tmpl, n, &ablkcipher_algs, entry) { +- crypto_unregister_alg(&tmpl->alg.crypto); +- list_del(&tmpl->entry); +- kfree(tmpl); +- } +-} +- +-static int qce_ablkcipher_register(struct qce_device *qce) +-{ +- int ret, i; +- +- for (i = 0; i < ARRAY_SIZE(ablkcipher_def); i++) { +- ret = qce_ablkcipher_register_one(&ablkcipher_def[i], qce); +- if (ret) +- goto err; +- } +- +- return 0; +-err: +- qce_ablkcipher_unregister(qce); +- return ret; +-} +- +-const struct qce_algo_ops ablkcipher_ops = { +- .type = CRYPTO_ALG_TYPE_ABLKCIPHER, +- .register_algs = qce_ablkcipher_register, +- .unregister_algs = qce_ablkcipher_unregister, +- .async_req_handle = qce_ablkcipher_async_req_handle, +-}; +--- /dev/null ++++ b/drivers/crypto/qce/skcipher.c +@@ -0,0 +1,440 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (c) 2010-2014, The Linux Foundation. All rights reserved. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "cipher.h" ++ ++static LIST_HEAD(skcipher_algs); ++ ++static void qce_skcipher_done(void *data) ++{ ++ struct crypto_async_request *async_req = data; ++ struct skcipher_request *req = skcipher_request_cast(async_req); ++ struct qce_cipher_reqctx *rctx = skcipher_request_ctx(req); ++ struct qce_alg_template *tmpl = to_cipher_tmpl(crypto_skcipher_reqtfm(req)); ++ struct qce_device *qce = tmpl->qce; ++ enum dma_data_direction dir_src, dir_dst; ++ u32 status; ++ int error; ++ bool diff_dst; ++ ++ diff_dst = (req->src != req->dst) ? true : false; ++ dir_src = diff_dst ? DMA_TO_DEVICE : DMA_BIDIRECTIONAL; ++ dir_dst = diff_dst ? DMA_FROM_DEVICE : DMA_BIDIRECTIONAL; ++ ++ error = qce_dma_terminate_all(&qce->dma); ++ if (error) ++ dev_dbg(qce->dev, "skcipher dma termination error (%d)\n", ++ error); ++ ++ if (diff_dst) ++ dma_unmap_sg(qce->dev, rctx->src_sg, rctx->src_nents, dir_src); ++ dma_unmap_sg(qce->dev, rctx->dst_sg, rctx->dst_nents, dir_dst); ++ ++ sg_free_table(&rctx->dst_tbl); ++ ++ error = qce_check_status(qce, &status); ++ if (error < 0) ++ dev_dbg(qce->dev, "skcipher operation error (%x)\n", status); ++ ++ qce->async_req_done(tmpl->qce, error); ++} ++ ++static int ++qce_skcipher_async_req_handle(struct crypto_async_request *async_req) ++{ ++ struct skcipher_request *req = skcipher_request_cast(async_req); ++ struct qce_cipher_reqctx *rctx = skcipher_request_ctx(req); ++ struct crypto_skcipher *skcipher = crypto_skcipher_reqtfm(req); ++ struct qce_alg_template *tmpl = to_cipher_tmpl(crypto_skcipher_reqtfm(req)); ++ struct qce_device *qce = tmpl->qce; ++ enum dma_data_direction dir_src, dir_dst; ++ struct scatterlist *sg; ++ bool diff_dst; ++ gfp_t gfp; ++ int ret; ++ ++ rctx->iv = req->iv; ++ rctx->ivsize = crypto_skcipher_ivsize(skcipher); ++ rctx->cryptlen = req->cryptlen; ++ ++ diff_dst = (req->src != req->dst) ? true : false; ++ dir_src = diff_dst ? DMA_TO_DEVICE : DMA_BIDIRECTIONAL; ++ dir_dst = diff_dst ? DMA_FROM_DEVICE : DMA_BIDIRECTIONAL; ++ ++ rctx->src_nents = sg_nents_for_len(req->src, req->cryptlen); ++ if (diff_dst) ++ rctx->dst_nents = sg_nents_for_len(req->dst, req->cryptlen); ++ else ++ rctx->dst_nents = rctx->src_nents; ++ if (rctx->src_nents < 0) { ++ dev_err(qce->dev, "Invalid numbers of src SG.\n"); ++ return rctx->src_nents; ++ } ++ if (rctx->dst_nents < 0) { ++ dev_err(qce->dev, "Invalid numbers of dst SG.\n"); ++ return -rctx->dst_nents; ++ } ++ ++ rctx->dst_nents += 1; ++ ++ gfp = (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ? ++ GFP_KERNEL : GFP_ATOMIC; ++ ++ ret = sg_alloc_table(&rctx->dst_tbl, rctx->dst_nents, gfp); ++ if (ret) ++ return ret; ++ ++ sg_init_one(&rctx->result_sg, qce->dma.result_buf, QCE_RESULT_BUF_SZ); ++ ++ sg = qce_sgtable_add(&rctx->dst_tbl, req->dst); ++ if (IS_ERR(sg)) { ++ ret = PTR_ERR(sg); ++ goto error_free; ++ } ++ ++ sg = qce_sgtable_add(&rctx->dst_tbl, &rctx->result_sg); ++ if (IS_ERR(sg)) { ++ ret = PTR_ERR(sg); ++ goto error_free; ++ } ++ ++ sg_mark_end(sg); ++ rctx->dst_sg = rctx->dst_tbl.sgl; ++ ++ ret = dma_map_sg(qce->dev, rctx->dst_sg, rctx->dst_nents, dir_dst); ++ if (ret < 0) ++ goto error_free; ++ ++ if (diff_dst) { ++ ret = dma_map_sg(qce->dev, req->src, rctx->src_nents, dir_src); ++ if (ret < 0) ++ goto error_unmap_dst; ++ rctx->src_sg = req->src; ++ } else { ++ rctx->src_sg = rctx->dst_sg; ++ } ++ ++ ret = qce_dma_prep_sgs(&qce->dma, rctx->src_sg, rctx->src_nents, ++ rctx->dst_sg, rctx->dst_nents, ++ qce_skcipher_done, async_req); ++ if (ret) ++ goto error_unmap_src; ++ ++ qce_dma_issue_pending(&qce->dma); ++ ++ ret = qce_start(async_req, tmpl->crypto_alg_type, req->cryptlen, 0); ++ if (ret) ++ goto error_terminate; ++ ++ return 0; ++ ++error_terminate: ++ qce_dma_terminate_all(&qce->dma); ++error_unmap_src: ++ if (diff_dst) ++ dma_unmap_sg(qce->dev, req->src, rctx->src_nents, dir_src); ++error_unmap_dst: ++ dma_unmap_sg(qce->dev, rctx->dst_sg, rctx->dst_nents, dir_dst); ++error_free: ++ sg_free_table(&rctx->dst_tbl); ++ return ret; ++} ++ ++static int qce_skcipher_setkey(struct crypto_skcipher *ablk, const u8 *key, ++ unsigned int keylen) ++{ ++ struct crypto_tfm *tfm = crypto_skcipher_tfm(ablk); ++ struct qce_cipher_ctx *ctx = crypto_tfm_ctx(tfm); ++ int ret; ++ ++ if (!key || !keylen) ++ return -EINVAL; ++ ++ switch (keylen) { ++ case AES_KEYSIZE_128: ++ case AES_KEYSIZE_256: ++ break; ++ default: ++ goto fallback; ++ } ++ ++ ctx->enc_keylen = keylen; ++ memcpy(ctx->enc_key, key, keylen); ++ return 0; ++fallback: ++ ret = crypto_sync_skcipher_setkey(ctx->fallback, key, keylen); ++ if (!ret) ++ ctx->enc_keylen = keylen; ++ return ret; ++} ++ ++static int qce_des_setkey(struct crypto_skcipher *ablk, const u8 *key, ++ unsigned int keylen) ++{ ++ struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(ablk); ++ int err; ++ ++ err = verify_skcipher_des_key(ablk, key); ++ if (err) ++ return err; ++ ++ ctx->enc_keylen = keylen; ++ memcpy(ctx->enc_key, key, keylen); ++ return 0; ++} ++ ++static int qce_des3_setkey(struct crypto_skcipher *ablk, const u8 *key, ++ unsigned int keylen) ++{ ++ struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(ablk); ++ int err; ++ ++ err = verify_skcipher_des3_key(ablk, key); ++ if (err) ++ return err; ++ ++ ctx->enc_keylen = keylen; ++ memcpy(ctx->enc_key, key, keylen); ++ return 0; ++} ++ ++static int qce_skcipher_crypt(struct skcipher_request *req, int encrypt) ++{ ++ struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); ++ struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); ++ struct qce_cipher_reqctx *rctx = skcipher_request_ctx(req); ++ struct qce_alg_template *tmpl = to_cipher_tmpl(tfm); ++ int ret; ++ ++ rctx->flags = tmpl->alg_flags; ++ rctx->flags |= encrypt ? QCE_ENCRYPT : QCE_DECRYPT; ++ ++ if (IS_AES(rctx->flags) && ctx->enc_keylen != AES_KEYSIZE_128 && ++ ctx->enc_keylen != AES_KEYSIZE_256) { ++ SYNC_SKCIPHER_REQUEST_ON_STACK(subreq, ctx->fallback); ++ ++ skcipher_request_set_sync_tfm(subreq, ctx->fallback); ++ skcipher_request_set_callback(subreq, req->base.flags, ++ NULL, NULL); ++ skcipher_request_set_crypt(subreq, req->src, req->dst, ++ req->cryptlen, req->iv); ++ ret = encrypt ? crypto_skcipher_encrypt(subreq) : ++ crypto_skcipher_decrypt(subreq); ++ skcipher_request_zero(subreq); ++ return ret; ++ } ++ ++ return tmpl->qce->async_req_enqueue(tmpl->qce, &req->base); ++} ++ ++static int qce_skcipher_encrypt(struct skcipher_request *req) ++{ ++ return qce_skcipher_crypt(req, 1); ++} ++ ++static int qce_skcipher_decrypt(struct skcipher_request *req) ++{ ++ return qce_skcipher_crypt(req, 0); ++} ++ ++static int qce_skcipher_init(struct crypto_skcipher *tfm) ++{ ++ struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); ++ ++ memset(ctx, 0, sizeof(*ctx)); ++ crypto_skcipher_set_reqsize(tfm, sizeof(struct qce_cipher_reqctx)); ++ ++ ctx->fallback = crypto_alloc_sync_skcipher(crypto_tfm_alg_name(&tfm->base), ++ 0, CRYPTO_ALG_NEED_FALLBACK); ++ return PTR_ERR_OR_ZERO(ctx->fallback); ++} ++ ++static void qce_skcipher_exit(struct crypto_skcipher *tfm) ++{ ++ struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); ++ ++ crypto_free_sync_skcipher(ctx->fallback); ++} ++ ++struct qce_skcipher_def { ++ unsigned long flags; ++ const char *name; ++ const char *drv_name; ++ unsigned int blocksize; ++ unsigned int ivsize; ++ unsigned int min_keysize; ++ unsigned int max_keysize; ++}; ++ ++static const struct qce_skcipher_def skcipher_def[] = { ++ { ++ .flags = QCE_ALG_AES | QCE_MODE_ECB, ++ .name = "ecb(aes)", ++ .drv_name = "ecb-aes-qce", ++ .blocksize = AES_BLOCK_SIZE, ++ .ivsize = AES_BLOCK_SIZE, ++ .min_keysize = AES_MIN_KEY_SIZE, ++ .max_keysize = AES_MAX_KEY_SIZE, ++ }, ++ { ++ .flags = QCE_ALG_AES | QCE_MODE_CBC, ++ .name = "cbc(aes)", ++ .drv_name = "cbc-aes-qce", ++ .blocksize = AES_BLOCK_SIZE, ++ .ivsize = AES_BLOCK_SIZE, ++ .min_keysize = AES_MIN_KEY_SIZE, ++ .max_keysize = AES_MAX_KEY_SIZE, ++ }, ++ { ++ .flags = QCE_ALG_AES | QCE_MODE_CTR, ++ .name = "ctr(aes)", ++ .drv_name = "ctr-aes-qce", ++ .blocksize = AES_BLOCK_SIZE, ++ .ivsize = AES_BLOCK_SIZE, ++ .min_keysize = AES_MIN_KEY_SIZE, ++ .max_keysize = AES_MAX_KEY_SIZE, ++ }, ++ { ++ .flags = QCE_ALG_AES | QCE_MODE_XTS, ++ .name = "xts(aes)", ++ .drv_name = "xts-aes-qce", ++ .blocksize = AES_BLOCK_SIZE, ++ .ivsize = AES_BLOCK_SIZE, ++ .min_keysize = AES_MIN_KEY_SIZE, ++ .max_keysize = AES_MAX_KEY_SIZE, ++ }, ++ { ++ .flags = QCE_ALG_DES | QCE_MODE_ECB, ++ .name = "ecb(des)", ++ .drv_name = "ecb-des-qce", ++ .blocksize = DES_BLOCK_SIZE, ++ .ivsize = 0, ++ .min_keysize = DES_KEY_SIZE, ++ .max_keysize = DES_KEY_SIZE, ++ }, ++ { ++ .flags = QCE_ALG_DES | QCE_MODE_CBC, ++ .name = "cbc(des)", ++ .drv_name = "cbc-des-qce", ++ .blocksize = DES_BLOCK_SIZE, ++ .ivsize = DES_BLOCK_SIZE, ++ .min_keysize = DES_KEY_SIZE, ++ .max_keysize = DES_KEY_SIZE, ++ }, ++ { ++ .flags = QCE_ALG_3DES | QCE_MODE_ECB, ++ .name = "ecb(des3_ede)", ++ .drv_name = "ecb-3des-qce", ++ .blocksize = DES3_EDE_BLOCK_SIZE, ++ .ivsize = 0, ++ .min_keysize = DES3_EDE_KEY_SIZE, ++ .max_keysize = DES3_EDE_KEY_SIZE, ++ }, ++ { ++ .flags = QCE_ALG_3DES | QCE_MODE_CBC, ++ .name = "cbc(des3_ede)", ++ .drv_name = "cbc-3des-qce", ++ .blocksize = DES3_EDE_BLOCK_SIZE, ++ .ivsize = DES3_EDE_BLOCK_SIZE, ++ .min_keysize = DES3_EDE_KEY_SIZE, ++ .max_keysize = DES3_EDE_KEY_SIZE, ++ }, ++}; ++ ++static int qce_skcipher_register_one(const struct qce_skcipher_def *def, ++ struct qce_device *qce) ++{ ++ struct qce_alg_template *tmpl; ++ struct skcipher_alg *alg; ++ int ret; ++ ++ tmpl = kzalloc(sizeof(*tmpl), GFP_KERNEL); ++ if (!tmpl) ++ return -ENOMEM; ++ ++ alg = &tmpl->alg.skcipher; ++ ++ snprintf(alg->base.cra_name, CRYPTO_MAX_ALG_NAME, "%s", def->name); ++ snprintf(alg->base.cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s", ++ def->drv_name); ++ ++ alg->base.cra_blocksize = def->blocksize; ++ alg->ivsize = def->ivsize; ++ alg->min_keysize = def->min_keysize; ++ alg->max_keysize = def->max_keysize; ++ alg->setkey = IS_3DES(def->flags) ? qce_des3_setkey : ++ IS_DES(def->flags) ? qce_des_setkey : ++ qce_skcipher_setkey; ++ alg->encrypt = qce_skcipher_encrypt; ++ alg->decrypt = qce_skcipher_decrypt; ++ ++ alg->base.cra_priority = 300; ++ alg->base.cra_flags = CRYPTO_ALG_ASYNC | ++ CRYPTO_ALG_NEED_FALLBACK | ++ CRYPTO_ALG_KERN_DRIVER_ONLY; ++ alg->base.cra_ctxsize = sizeof(struct qce_cipher_ctx); ++ alg->base.cra_alignmask = 0; ++ alg->base.cra_module = THIS_MODULE; ++ ++ alg->init = qce_skcipher_init; ++ alg->exit = qce_skcipher_exit; ++ ++ INIT_LIST_HEAD(&tmpl->entry); ++ tmpl->crypto_alg_type = CRYPTO_ALG_TYPE_SKCIPHER; ++ tmpl->alg_flags = def->flags; ++ tmpl->qce = qce; ++ ++ ret = crypto_register_skcipher(alg); ++ if (ret) { ++ kfree(tmpl); ++ dev_err(qce->dev, "%s registration failed\n", alg->base.cra_name); ++ return ret; ++ } ++ ++ list_add_tail(&tmpl->entry, &skcipher_algs); ++ dev_dbg(qce->dev, "%s is registered\n", alg->base.cra_name); ++ return 0; ++} ++ ++static void qce_skcipher_unregister(struct qce_device *qce) ++{ ++ struct qce_alg_template *tmpl, *n; ++ ++ list_for_each_entry_safe(tmpl, n, &skcipher_algs, entry) { ++ crypto_unregister_skcipher(&tmpl->alg.skcipher); ++ list_del(&tmpl->entry); ++ kfree(tmpl); ++ } ++} ++ ++static int qce_skcipher_register(struct qce_device *qce) ++{ ++ int ret, i; ++ ++ for (i = 0; i < ARRAY_SIZE(skcipher_def); i++) { ++ ret = qce_skcipher_register_one(&skcipher_def[i], qce); ++ if (ret) ++ goto err; ++ } ++ ++ return 0; ++err: ++ qce_skcipher_unregister(qce); ++ return ret; ++} ++ ++const struct qce_algo_ops skcipher_ops = { ++ .type = CRYPTO_ALG_TYPE_SKCIPHER, ++ .register_algs = qce_skcipher_register, ++ .unregister_algs = qce_skcipher_unregister, ++ .async_req_handle = qce_skcipher_async_req_handle, ++}; diff --git a/feeds/ipq40xx/ipq40xx/patches-5.4/0008-v5.6-crypto-qce-fix-ctr-aes-qce-block-chunk-sizes.patch b/feeds/ipq40xx/ipq40xx/patches-5.4/0008-v5.6-crypto-qce-fix-ctr-aes-qce-block-chunk-sizes.patch new file mode 100644 index 000000000..ac4f163f4 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/patches-5.4/0008-v5.6-crypto-qce-fix-ctr-aes-qce-block-chunk-sizes.patch @@ -0,0 +1,43 @@ +From bb5c863b3d3cbd10e80b2ebf409934a091058f54 Mon Sep 17 00:00:00 2001 +From: Eneas U de Queiroz +Date: Fri, 20 Dec 2019 16:02:13 -0300 +Subject: [PATCH 02/11] crypto: qce - fix ctr-aes-qce block, chunk sizes + +Set blocksize of ctr-aes-qce to 1, so it can operate as a stream cipher, +adding the definition for chucksize instead, where the underlying block +size belongs. + +Signed-off-by: Eneas U de Queiroz +Signed-off-by: Herbert Xu +--- + drivers/crypto/qce/skcipher.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/drivers/crypto/qce/skcipher.c ++++ b/drivers/crypto/qce/skcipher.c +@@ -270,6 +270,7 @@ struct qce_skcipher_def { + const char *name; + const char *drv_name; + unsigned int blocksize; ++ unsigned int chunksize; + unsigned int ivsize; + unsigned int min_keysize; + unsigned int max_keysize; +@@ -298,7 +299,8 @@ static const struct qce_skcipher_def skc + .flags = QCE_ALG_AES | QCE_MODE_CTR, + .name = "ctr(aes)", + .drv_name = "ctr-aes-qce", +- .blocksize = AES_BLOCK_SIZE, ++ .blocksize = 1, ++ .chunksize = AES_BLOCK_SIZE, + .ivsize = AES_BLOCK_SIZE, + .min_keysize = AES_MIN_KEY_SIZE, + .max_keysize = AES_MAX_KEY_SIZE, +@@ -368,6 +370,7 @@ static int qce_skcipher_register_one(con + def->drv_name); + + alg->base.cra_blocksize = def->blocksize; ++ alg->chunksize = def->chunksize; + alg->ivsize = def->ivsize; + alg->min_keysize = def->min_keysize; + alg->max_keysize = def->max_keysize; diff --git a/feeds/ipq40xx/ipq40xx/patches-5.4/0009-v5.6-crypto-qce-fix-xts-aes-qce-key-sizes.patch b/feeds/ipq40xx/ipq40xx/patches-5.4/0009-v5.6-crypto-qce-fix-xts-aes-qce-key-sizes.patch new file mode 100644 index 000000000..4dcf1ac72 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/patches-5.4/0009-v5.6-crypto-qce-fix-xts-aes-qce-key-sizes.patch @@ -0,0 +1,60 @@ +From 7de4c2bd196f111e39cc60f6197654aff23ba2b4 Mon Sep 17 00:00:00 2001 +From: Eneas U de Queiroz +Date: Fri, 20 Dec 2019 16:02:14 -0300 +Subject: [PATCH 03/11] crypto: qce - fix xts-aes-qce key sizes + +XTS-mode uses two keys, so the keysizes should be doubled in +skcipher_def, and halved when checking if it is AES-128/192/256. + +Signed-off-by: Eneas U de Queiroz +Signed-off-by: Herbert Xu +--- + drivers/crypto/qce/skcipher.c | 13 ++++++++----- + 1 file changed, 8 insertions(+), 5 deletions(-) + +--- a/drivers/crypto/qce/skcipher.c ++++ b/drivers/crypto/qce/skcipher.c +@@ -154,12 +154,13 @@ static int qce_skcipher_setkey(struct cr + { + struct crypto_tfm *tfm = crypto_skcipher_tfm(ablk); + struct qce_cipher_ctx *ctx = crypto_tfm_ctx(tfm); ++ unsigned long flags = to_cipher_tmpl(ablk)->alg_flags; + int ret; + + if (!key || !keylen) + return -EINVAL; + +- switch (keylen) { ++ switch (IS_XTS(flags) ? keylen >> 1 : keylen) { + case AES_KEYSIZE_128: + case AES_KEYSIZE_256: + break; +@@ -213,13 +214,15 @@ static int qce_skcipher_crypt(struct skc + struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); + struct qce_cipher_reqctx *rctx = skcipher_request_ctx(req); + struct qce_alg_template *tmpl = to_cipher_tmpl(tfm); ++ int keylen; + int ret; + + rctx->flags = tmpl->alg_flags; + rctx->flags |= encrypt ? QCE_ENCRYPT : QCE_DECRYPT; ++ keylen = IS_XTS(rctx->flags) ? ctx->enc_keylen >> 1 : ctx->enc_keylen; + +- if (IS_AES(rctx->flags) && ctx->enc_keylen != AES_KEYSIZE_128 && +- ctx->enc_keylen != AES_KEYSIZE_256) { ++ if (IS_AES(rctx->flags) && keylen != AES_KEYSIZE_128 && ++ keylen != AES_KEYSIZE_256) { + SYNC_SKCIPHER_REQUEST_ON_STACK(subreq, ctx->fallback); + + skcipher_request_set_sync_tfm(subreq, ctx->fallback); +@@ -311,8 +314,8 @@ static const struct qce_skcipher_def skc + .drv_name = "xts-aes-qce", + .blocksize = AES_BLOCK_SIZE, + .ivsize = AES_BLOCK_SIZE, +- .min_keysize = AES_MIN_KEY_SIZE, +- .max_keysize = AES_MAX_KEY_SIZE, ++ .min_keysize = AES_MIN_KEY_SIZE * 2, ++ .max_keysize = AES_MAX_KEY_SIZE * 2, + }, + { + .flags = QCE_ALG_DES | QCE_MODE_ECB, diff --git a/feeds/ipq40xx/ipq40xx/patches-5.4/0010-v5.6-crypto-qce-save-a-sg-table-slot-for-result-buf.patch b/feeds/ipq40xx/ipq40xx/patches-5.4/0010-v5.6-crypto-qce-save-a-sg-table-slot-for-result-buf.patch new file mode 100644 index 000000000..2385d483f --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/patches-5.4/0010-v5.6-crypto-qce-save-a-sg-table-slot-for-result-buf.patch @@ -0,0 +1,85 @@ +From 3ee50c896d712dc2fc8f34c2cd1918d035e74045 Mon Sep 17 00:00:00 2001 +From: Eneas U de Queiroz +Date: Fri, 20 Dec 2019 16:02:15 -0300 +Subject: [PATCH 04/11] crypto: qce - save a sg table slot for result buf + +When ctr-aes-qce is used for gcm-mode, an extra sg entry for the +authentication tag is present, causing trouble when the qce driver +prepares the dst-results sg table for dma. + +It computes the number of entries needed with sg_nents_for_len, leaving +out the tag entry. Then it creates a sg table with that number plus +one, used to store a result buffer. + +When copying the sg table, there's no limit to the number of entries +copied, so the extra slot is filled with the authentication tag sg. +When the driver tries to add the result sg, the list is full, and it +returns EINVAL. + +By limiting the number of sg entries copied to the dest table, the slot +for the result buffer is guaranteed to be unused. + +Signed-off-by: Eneas U de Queiroz +Signed-off-by: Herbert Xu +--- + drivers/crypto/qce/dma.c | 6 ++++-- + drivers/crypto/qce/dma.h | 3 ++- + drivers/crypto/qce/skcipher.c | 4 ++-- + 3 files changed, 8 insertions(+), 5 deletions(-) + +--- a/drivers/crypto/qce/dma.c ++++ b/drivers/crypto/qce/dma.c +@@ -47,7 +47,8 @@ void qce_dma_release(struct qce_dma_data + } + + struct scatterlist * +-qce_sgtable_add(struct sg_table *sgt, struct scatterlist *new_sgl) ++qce_sgtable_add(struct sg_table *sgt, struct scatterlist *new_sgl, ++ int max_ents) + { + struct scatterlist *sg = sgt->sgl, *sg_last = NULL; + +@@ -60,12 +61,13 @@ qce_sgtable_add(struct sg_table *sgt, st + if (!sg) + return ERR_PTR(-EINVAL); + +- while (new_sgl && sg) { ++ while (new_sgl && sg && max_ents) { + sg_set_page(sg, sg_page(new_sgl), new_sgl->length, + new_sgl->offset); + sg_last = sg; + sg = sg_next(sg); + new_sgl = sg_next(new_sgl); ++ max_ents--; + } + + return sg_last; +--- a/drivers/crypto/qce/dma.h ++++ b/drivers/crypto/qce/dma.h +@@ -42,6 +42,7 @@ int qce_dma_prep_sgs(struct qce_dma_data + void qce_dma_issue_pending(struct qce_dma_data *dma); + int qce_dma_terminate_all(struct qce_dma_data *dma); + struct scatterlist * +-qce_sgtable_add(struct sg_table *sgt, struct scatterlist *sg_add); ++qce_sgtable_add(struct sg_table *sgt, struct scatterlist *sg_add, ++ int max_ents); + + #endif /* _DMA_H_ */ +--- a/drivers/crypto/qce/skcipher.c ++++ b/drivers/crypto/qce/skcipher.c +@@ -95,13 +95,13 @@ qce_skcipher_async_req_handle(struct cry + + sg_init_one(&rctx->result_sg, qce->dma.result_buf, QCE_RESULT_BUF_SZ); + +- sg = qce_sgtable_add(&rctx->dst_tbl, req->dst); ++ sg = qce_sgtable_add(&rctx->dst_tbl, req->dst, rctx->dst_nents - 1); + if (IS_ERR(sg)) { + ret = PTR_ERR(sg); + goto error_free; + } + +- sg = qce_sgtable_add(&rctx->dst_tbl, &rctx->result_sg); ++ sg = qce_sgtable_add(&rctx->dst_tbl, &rctx->result_sg, 1); + if (IS_ERR(sg)) { + ret = PTR_ERR(sg); + goto error_free; diff --git a/feeds/ipq40xx/ipq40xx/patches-5.4/0011-v5.6-crypto-qce-update-the-skcipher-IV.patch b/feeds/ipq40xx/ipq40xx/patches-5.4/0011-v5.6-crypto-qce-update-the-skcipher-IV.patch new file mode 100644 index 000000000..5efdb72c4 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/patches-5.4/0011-v5.6-crypto-qce-update-the-skcipher-IV.patch @@ -0,0 +1,31 @@ +From 3e806a12d10af2581aa26c37b58439286eab9782 Mon Sep 17 00:00:00 2001 +From: Eneas U de Queiroz +Date: Fri, 20 Dec 2019 16:02:16 -0300 +Subject: [PATCH 05/11] crypto: qce - update the skcipher IV + +Update the IV after the completion of each cipher operation. + +Signed-off-by: Eneas U de Queiroz +Signed-off-by: Herbert Xu +--- + drivers/crypto/qce/skcipher.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/crypto/qce/skcipher.c ++++ b/drivers/crypto/qce/skcipher.c +@@ -21,6 +21,7 @@ static void qce_skcipher_done(void *data + struct qce_cipher_reqctx *rctx = skcipher_request_ctx(req); + struct qce_alg_template *tmpl = to_cipher_tmpl(crypto_skcipher_reqtfm(req)); + struct qce_device *qce = tmpl->qce; ++ struct qce_result_dump *result_buf = qce->dma.result_buf; + enum dma_data_direction dir_src, dir_dst; + u32 status; + int error; +@@ -45,6 +46,7 @@ static void qce_skcipher_done(void *data + if (error < 0) + dev_dbg(qce->dev, "skcipher operation error (%x)\n", status); + ++ memcpy(rctx->iv, result_buf->encr_cntr_iv, rctx->ivsize); + qce->async_req_done(tmpl->qce, error); + } + diff --git a/feeds/ipq40xx/ipq40xx/patches-5.4/0012-v5.6-crypto-qce-initialize-fallback-only-for-AES.patch b/feeds/ipq40xx/ipq40xx/patches-5.4/0012-v5.6-crypto-qce-initialize-fallback-only-for-AES.patch new file mode 100644 index 000000000..84aef04ef --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/patches-5.4/0012-v5.6-crypto-qce-initialize-fallback-only-for-AES.patch @@ -0,0 +1,54 @@ +From 8ceda883205db6dfedb82e39f67feae3b50c95a1 Mon Sep 17 00:00:00 2001 +From: Eneas U de Queiroz +Date: Fri, 20 Dec 2019 16:02:17 -0300 +Subject: [PATCH 06/11] crypto: qce - initialize fallback only for AES + +Adjust cra_flags to add CRYPTO_NEED_FALLBACK only for AES ciphers, where +AES-192 is not handled by the qce hardware, and don't allocate & free +the fallback skcipher for other algorithms. + +Signed-off-by: Eneas U de Queiroz +Signed-off-by: Herbert Xu +--- + drivers/crypto/qce/skcipher.c | 17 ++++++++++++++--- + 1 file changed, 14 insertions(+), 3 deletions(-) + +--- a/drivers/crypto/qce/skcipher.c ++++ b/drivers/crypto/qce/skcipher.c +@@ -257,7 +257,14 @@ static int qce_skcipher_init(struct cryp + + memset(ctx, 0, sizeof(*ctx)); + crypto_skcipher_set_reqsize(tfm, sizeof(struct qce_cipher_reqctx)); ++ return 0; ++} ++ ++static int qce_skcipher_init_fallback(struct crypto_skcipher *tfm) ++{ ++ struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); + ++ qce_skcipher_init(tfm); + ctx->fallback = crypto_alloc_sync_skcipher(crypto_tfm_alg_name(&tfm->base), + 0, CRYPTO_ALG_NEED_FALLBACK); + return PTR_ERR_OR_ZERO(ctx->fallback); +@@ -387,14 +394,18 @@ static int qce_skcipher_register_one(con + + alg->base.cra_priority = 300; + alg->base.cra_flags = CRYPTO_ALG_ASYNC | +- CRYPTO_ALG_NEED_FALLBACK | + CRYPTO_ALG_KERN_DRIVER_ONLY; + alg->base.cra_ctxsize = sizeof(struct qce_cipher_ctx); + alg->base.cra_alignmask = 0; + alg->base.cra_module = THIS_MODULE; + +- alg->init = qce_skcipher_init; +- alg->exit = qce_skcipher_exit; ++ if (IS_AES(def->flags)) { ++ alg->base.cra_flags |= CRYPTO_ALG_NEED_FALLBACK; ++ alg->init = qce_skcipher_init_fallback; ++ alg->exit = qce_skcipher_exit; ++ } else { ++ alg->init = qce_skcipher_init; ++ } + + INIT_LIST_HEAD(&tmpl->entry); + tmpl->crypto_alg_type = CRYPTO_ALG_TYPE_SKCIPHER; diff --git a/feeds/ipq40xx/ipq40xx/patches-5.4/0013-v5.6-crypto-qce-allow-building-only-hashes-ciphers.patch b/feeds/ipq40xx/ipq40xx/patches-5.4/0013-v5.6-crypto-qce-allow-building-only-hashes-ciphers.patch new file mode 100644 index 000000000..5b1372d08 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/patches-5.4/0013-v5.6-crypto-qce-allow-building-only-hashes-ciphers.patch @@ -0,0 +1,419 @@ +From 59e056cda4beb5412e3653e6360c2eb0fa770baa Mon Sep 17 00:00:00 2001 +From: Eneas U de Queiroz +Date: Fri, 20 Dec 2019 16:02:18 -0300 +Subject: [PATCH 07/11] crypto: qce - allow building only hashes/ciphers + +Allow the user to choose whether to build support for all algorithms +(default), hashes-only, or skciphers-only. + +The QCE engine does not appear to scale as well as the CPU to handle +multiple crypto requests. While the ipq40xx chips have 4-core CPUs, the +QCE handles only 2 requests in parallel. + +Ipsec throughput seems to improve when disabling either family of +algorithms, sharing the load with the CPU. Enabling skciphers-only +appears to work best. + +Signed-off-by: Eneas U de Queiroz +Signed-off-by: Herbert Xu +--- + +--- a/drivers/crypto/Kconfig ++++ b/drivers/crypto/Kconfig +@@ -617,6 +617,14 @@ config CRYPTO_DEV_QCE + tristate "Qualcomm crypto engine accelerator" + depends on ARCH_QCOM || COMPILE_TEST + depends on HAS_IOMEM ++ help ++ This driver supports Qualcomm crypto engine accelerator ++ hardware. To compile this driver as a module, choose M here. The ++ module will be called qcrypto. ++ ++config CRYPTO_DEV_QCE_SKCIPHER ++ bool ++ depends on CRYPTO_DEV_QCE + select CRYPTO_AES + select CRYPTO_LIB_DES + select CRYPTO_ECB +@@ -624,10 +632,57 @@ config CRYPTO_DEV_QCE + select CRYPTO_XTS + select CRYPTO_CTR + select CRYPTO_BLKCIPHER ++ ++config CRYPTO_DEV_QCE_SHA ++ bool ++ depends on CRYPTO_DEV_QCE ++ ++choice ++ prompt "Algorithms enabled for QCE acceleration" ++ default CRYPTO_DEV_QCE_ENABLE_ALL ++ depends on CRYPTO_DEV_QCE + help +- This driver supports Qualcomm crypto engine accelerator +- hardware. To compile this driver as a module, choose M here. The +- module will be called qcrypto. ++ This option allows to choose whether to build support for all algorihtms ++ (default), hashes-only, or skciphers-only. ++ ++ The QCE engine does not appear to scale as well as the CPU to handle ++ multiple crypto requests. While the ipq40xx chips have 4-core CPUs, the ++ QCE handles only 2 requests in parallel. ++ ++ Ipsec throughput seems to improve when disabling either family of ++ algorithms, sharing the load with the CPU. Enabling skciphers-only ++ appears to work best. ++ ++ config CRYPTO_DEV_QCE_ENABLE_ALL ++ bool "All supported algorithms" ++ select CRYPTO_DEV_QCE_SKCIPHER ++ select CRYPTO_DEV_QCE_SHA ++ help ++ Enable all supported algorithms: ++ - AES (CBC, CTR, ECB, XTS) ++ - 3DES (CBC, ECB) ++ - DES (CBC, ECB) ++ - SHA1, HMAC-SHA1 ++ - SHA256, HMAC-SHA256 ++ ++ config CRYPTO_DEV_QCE_ENABLE_SKCIPHER ++ bool "Symmetric-key ciphers only" ++ select CRYPTO_DEV_QCE_SKCIPHER ++ help ++ Enable symmetric-key ciphers only: ++ - AES (CBC, CTR, ECB, XTS) ++ - 3DES (ECB, CBC) ++ - DES (ECB, CBC) ++ ++ config CRYPTO_DEV_QCE_ENABLE_SHA ++ bool "Hash/HMAC only" ++ select CRYPTO_DEV_QCE_SHA ++ help ++ Enable hashes/HMAC algorithms only: ++ - SHA1, HMAC-SHA1 ++ - SHA256, HMAC-SHA256 ++ ++endchoice + + config CRYPTO_DEV_QCOM_RNG + tristate "Qualcomm Random Number Generator Driver" +--- a/drivers/crypto/qce/Makefile ++++ b/drivers/crypto/qce/Makefile +@@ -2,6 +2,7 @@ + obj-$(CONFIG_CRYPTO_DEV_QCE) += qcrypto.o + qcrypto-objs := core.o \ + common.o \ +- dma.o \ +- sha.o \ +- skcipher.o ++ dma.o ++ ++qcrypto-$(CONFIG_CRYPTO_DEV_QCE_SHA) += sha.o ++qcrypto-$(CONFIG_CRYPTO_DEV_QCE_SKCIPHER) += skcipher.o +--- a/drivers/crypto/qce/common.c ++++ b/drivers/crypto/qce/common.c +@@ -45,52 +45,56 @@ qce_clear_array(struct qce_device *qce, + qce_write(qce, offset + i * sizeof(u32), 0); + } + +-static u32 qce_encr_cfg(unsigned long flags, u32 aes_key_size) ++static u32 qce_config_reg(struct qce_device *qce, int little) + { +- u32 cfg = 0; ++ u32 beats = (qce->burst_size >> 3) - 1; ++ u32 pipe_pair = qce->pipe_pair_id; ++ u32 config; + +- if (IS_AES(flags)) { +- if (aes_key_size == AES_KEYSIZE_128) +- cfg |= ENCR_KEY_SZ_AES128 << ENCR_KEY_SZ_SHIFT; +- else if (aes_key_size == AES_KEYSIZE_256) +- cfg |= ENCR_KEY_SZ_AES256 << ENCR_KEY_SZ_SHIFT; +- } ++ config = (beats << REQ_SIZE_SHIFT) & REQ_SIZE_MASK; ++ config |= BIT(MASK_DOUT_INTR_SHIFT) | BIT(MASK_DIN_INTR_SHIFT) | ++ BIT(MASK_OP_DONE_INTR_SHIFT) | BIT(MASK_ERR_INTR_SHIFT); ++ config |= (pipe_pair << PIPE_SET_SELECT_SHIFT) & PIPE_SET_SELECT_MASK; ++ config &= ~HIGH_SPD_EN_N_SHIFT; + +- if (IS_AES(flags)) +- cfg |= ENCR_ALG_AES << ENCR_ALG_SHIFT; +- else if (IS_DES(flags) || IS_3DES(flags)) +- cfg |= ENCR_ALG_DES << ENCR_ALG_SHIFT; ++ if (little) ++ config |= BIT(LITTLE_ENDIAN_MODE_SHIFT); + +- if (IS_DES(flags)) +- cfg |= ENCR_KEY_SZ_DES << ENCR_KEY_SZ_SHIFT; ++ return config; ++} + +- if (IS_3DES(flags)) +- cfg |= ENCR_KEY_SZ_3DES << ENCR_KEY_SZ_SHIFT; ++void qce_cpu_to_be32p_array(__be32 *dst, const u8 *src, unsigned int len) ++{ ++ __be32 *d = dst; ++ const u8 *s = src; ++ unsigned int n; + +- switch (flags & QCE_MODE_MASK) { +- case QCE_MODE_ECB: +- cfg |= ENCR_MODE_ECB << ENCR_MODE_SHIFT; +- break; +- case QCE_MODE_CBC: +- cfg |= ENCR_MODE_CBC << ENCR_MODE_SHIFT; +- break; +- case QCE_MODE_CTR: +- cfg |= ENCR_MODE_CTR << ENCR_MODE_SHIFT; +- break; +- case QCE_MODE_XTS: +- cfg |= ENCR_MODE_XTS << ENCR_MODE_SHIFT; +- break; +- case QCE_MODE_CCM: +- cfg |= ENCR_MODE_CCM << ENCR_MODE_SHIFT; +- cfg |= LAST_CCM_XFR << LAST_CCM_SHIFT; +- break; +- default: +- return ~0; ++ n = len / sizeof(u32); ++ for (; n > 0; n--) { ++ *d = cpu_to_be32p((const __u32 *) s); ++ s += sizeof(__u32); ++ d++; + } ++} + +- return cfg; ++static void qce_setup_config(struct qce_device *qce) ++{ ++ u32 config; ++ ++ /* get big endianness */ ++ config = qce_config_reg(qce, 0); ++ ++ /* clear status */ ++ qce_write(qce, REG_STATUS, 0); ++ qce_write(qce, REG_CONFIG, config); ++} ++ ++static inline void qce_crypto_go(struct qce_device *qce) ++{ ++ qce_write(qce, REG_GOPROC, BIT(GO_SHIFT) | BIT(RESULTS_DUMP_SHIFT)); + } + ++#ifdef CONFIG_CRYPTO_DEV_QCE_SHA + static u32 qce_auth_cfg(unsigned long flags, u32 key_size) + { + u32 cfg = 0; +@@ -137,88 +141,6 @@ static u32 qce_auth_cfg(unsigned long fl + return cfg; + } + +-static u32 qce_config_reg(struct qce_device *qce, int little) +-{ +- u32 beats = (qce->burst_size >> 3) - 1; +- u32 pipe_pair = qce->pipe_pair_id; +- u32 config; +- +- config = (beats << REQ_SIZE_SHIFT) & REQ_SIZE_MASK; +- config |= BIT(MASK_DOUT_INTR_SHIFT) | BIT(MASK_DIN_INTR_SHIFT) | +- BIT(MASK_OP_DONE_INTR_SHIFT) | BIT(MASK_ERR_INTR_SHIFT); +- config |= (pipe_pair << PIPE_SET_SELECT_SHIFT) & PIPE_SET_SELECT_MASK; +- config &= ~HIGH_SPD_EN_N_SHIFT; +- +- if (little) +- config |= BIT(LITTLE_ENDIAN_MODE_SHIFT); +- +- return config; +-} +- +-void qce_cpu_to_be32p_array(__be32 *dst, const u8 *src, unsigned int len) +-{ +- __be32 *d = dst; +- const u8 *s = src; +- unsigned int n; +- +- n = len / sizeof(u32); +- for (; n > 0; n--) { +- *d = cpu_to_be32p((const __u32 *) s); +- s += sizeof(__u32); +- d++; +- } +-} +- +-static void qce_xts_swapiv(__be32 *dst, const u8 *src, unsigned int ivsize) +-{ +- u8 swap[QCE_AES_IV_LENGTH]; +- u32 i, j; +- +- if (ivsize > QCE_AES_IV_LENGTH) +- return; +- +- memset(swap, 0, QCE_AES_IV_LENGTH); +- +- for (i = (QCE_AES_IV_LENGTH - ivsize), j = ivsize - 1; +- i < QCE_AES_IV_LENGTH; i++, j--) +- swap[i] = src[j]; +- +- qce_cpu_to_be32p_array(dst, swap, QCE_AES_IV_LENGTH); +-} +- +-static void qce_xtskey(struct qce_device *qce, const u8 *enckey, +- unsigned int enckeylen, unsigned int cryptlen) +-{ +- u32 xtskey[QCE_MAX_CIPHER_KEY_SIZE / sizeof(u32)] = {0}; +- unsigned int xtsklen = enckeylen / (2 * sizeof(u32)); +- unsigned int xtsdusize; +- +- qce_cpu_to_be32p_array((__be32 *)xtskey, enckey + enckeylen / 2, +- enckeylen / 2); +- qce_write_array(qce, REG_ENCR_XTS_KEY0, xtskey, xtsklen); +- +- /* xts du size 512B */ +- xtsdusize = min_t(u32, QCE_SECTOR_SIZE, cryptlen); +- qce_write(qce, REG_ENCR_XTS_DU_SIZE, xtsdusize); +-} +- +-static void qce_setup_config(struct qce_device *qce) +-{ +- u32 config; +- +- /* get big endianness */ +- config = qce_config_reg(qce, 0); +- +- /* clear status */ +- qce_write(qce, REG_STATUS, 0); +- qce_write(qce, REG_CONFIG, config); +-} +- +-static inline void qce_crypto_go(struct qce_device *qce) +-{ +- qce_write(qce, REG_GOPROC, BIT(GO_SHIFT) | BIT(RESULTS_DUMP_SHIFT)); +-} +- + static int qce_setup_regs_ahash(struct crypto_async_request *async_req, + u32 totallen, u32 offset) + { +@@ -303,6 +225,87 @@ go_proc: + + return 0; + } ++#endif ++ ++#ifdef CONFIG_CRYPTO_DEV_QCE_SKCIPHER ++static u32 qce_encr_cfg(unsigned long flags, u32 aes_key_size) ++{ ++ u32 cfg = 0; ++ ++ if (IS_AES(flags)) { ++ if (aes_key_size == AES_KEYSIZE_128) ++ cfg |= ENCR_KEY_SZ_AES128 << ENCR_KEY_SZ_SHIFT; ++ else if (aes_key_size == AES_KEYSIZE_256) ++ cfg |= ENCR_KEY_SZ_AES256 << ENCR_KEY_SZ_SHIFT; ++ } ++ ++ if (IS_AES(flags)) ++ cfg |= ENCR_ALG_AES << ENCR_ALG_SHIFT; ++ else if (IS_DES(flags) || IS_3DES(flags)) ++ cfg |= ENCR_ALG_DES << ENCR_ALG_SHIFT; ++ ++ if (IS_DES(flags)) ++ cfg |= ENCR_KEY_SZ_DES << ENCR_KEY_SZ_SHIFT; ++ ++ if (IS_3DES(flags)) ++ cfg |= ENCR_KEY_SZ_3DES << ENCR_KEY_SZ_SHIFT; ++ ++ switch (flags & QCE_MODE_MASK) { ++ case QCE_MODE_ECB: ++ cfg |= ENCR_MODE_ECB << ENCR_MODE_SHIFT; ++ break; ++ case QCE_MODE_CBC: ++ cfg |= ENCR_MODE_CBC << ENCR_MODE_SHIFT; ++ break; ++ case QCE_MODE_CTR: ++ cfg |= ENCR_MODE_CTR << ENCR_MODE_SHIFT; ++ break; ++ case QCE_MODE_XTS: ++ cfg |= ENCR_MODE_XTS << ENCR_MODE_SHIFT; ++ break; ++ case QCE_MODE_CCM: ++ cfg |= ENCR_MODE_CCM << ENCR_MODE_SHIFT; ++ cfg |= LAST_CCM_XFR << LAST_CCM_SHIFT; ++ break; ++ default: ++ return ~0; ++ } ++ ++ return cfg; ++} ++ ++static void qce_xts_swapiv(__be32 *dst, const u8 *src, unsigned int ivsize) ++{ ++ u8 swap[QCE_AES_IV_LENGTH]; ++ u32 i, j; ++ ++ if (ivsize > QCE_AES_IV_LENGTH) ++ return; ++ ++ memset(swap, 0, QCE_AES_IV_LENGTH); ++ ++ for (i = (QCE_AES_IV_LENGTH - ivsize), j = ivsize - 1; ++ i < QCE_AES_IV_LENGTH; i++, j--) ++ swap[i] = src[j]; ++ ++ qce_cpu_to_be32p_array(dst, swap, QCE_AES_IV_LENGTH); ++} ++ ++static void qce_xtskey(struct qce_device *qce, const u8 *enckey, ++ unsigned int enckeylen, unsigned int cryptlen) ++{ ++ u32 xtskey[QCE_MAX_CIPHER_KEY_SIZE / sizeof(u32)] = {0}; ++ unsigned int xtsklen = enckeylen / (2 * sizeof(u32)); ++ unsigned int xtsdusize; ++ ++ qce_cpu_to_be32p_array((__be32 *)xtskey, enckey + enckeylen / 2, ++ enckeylen / 2); ++ qce_write_array(qce, REG_ENCR_XTS_KEY0, xtskey, xtsklen); ++ ++ /* xts du size 512B */ ++ xtsdusize = min_t(u32, QCE_SECTOR_SIZE, cryptlen); ++ qce_write(qce, REG_ENCR_XTS_DU_SIZE, xtsdusize); ++} + + static int qce_setup_regs_skcipher(struct crypto_async_request *async_req, + u32 totallen, u32 offset) +@@ -384,15 +387,20 @@ static int qce_setup_regs_skcipher(struc + + return 0; + } ++#endif + + int qce_start(struct crypto_async_request *async_req, u32 type, u32 totallen, + u32 offset) + { + switch (type) { ++#ifdef CONFIG_CRYPTO_DEV_QCE_SKCIPHER + case CRYPTO_ALG_TYPE_SKCIPHER: + return qce_setup_regs_skcipher(async_req, totallen, offset); ++#endif ++#ifdef CONFIG_CRYPTO_DEV_QCE_SHA + case CRYPTO_ALG_TYPE_AHASH: + return qce_setup_regs_ahash(async_req, totallen, offset); ++#endif + default: + return -EINVAL; + } +--- a/drivers/crypto/qce/core.c ++++ b/drivers/crypto/qce/core.c +@@ -22,8 +22,12 @@ + #define QCE_QUEUE_LENGTH 1 + + static const struct qce_algo_ops *qce_ops[] = { ++#ifdef CONFIG_CRYPTO_DEV_QCE_SKCIPHER + &skcipher_ops, ++#endif ++#ifdef CONFIG_CRYPTO_DEV_QCE_SHA + &ahash_ops, ++#endif + }; + + static void qce_unregister_algs(struct qce_device *qce) diff --git a/feeds/ipq40xx/ipq40xx/patches-5.4/0014-v5.7-crypto-qce-use-cryptlen-when-adding-extra-sgl.patch b/feeds/ipq40xx/ipq40xx/patches-5.4/0014-v5.7-crypto-qce-use-cryptlen-when-adding-extra-sgl.patch new file mode 100644 index 000000000..160420b48 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/patches-5.4/0014-v5.7-crypto-qce-use-cryptlen-when-adding-extra-sgl.patch @@ -0,0 +1,89 @@ +From d6364b8128439a8c0e381f80c38667de9f15eef8 Mon Sep 17 00:00:00 2001 +From: Eneas U de Queiroz +Date: Fri, 7 Feb 2020 12:02:25 -0300 +Subject: [PATCH 09/11] crypto: qce - use cryptlen when adding extra sgl + +The qce crypto driver appends an extra entry to the dst sgl, to maintain +private state information. + +When the gcm driver sends requests to the ctr skcipher, it passes the +authentication tag after the actual crypto payload, but it must not be +touched. + +Commit 1336c2221bee ("crypto: qce - save a sg table slot for result +buf") limited the destination sgl to avoid overwriting the +authentication tag but it assumed the tag would be in a separate sgl +entry. + +This is not always the case, so it is better to limit the length of the +destination buffer to req->cryptlen before appending the result buf. + +Signed-off-by: Eneas U de Queiroz +Signed-off-by: Herbert Xu +--- + drivers/crypto/qce/dma.c | 11 ++++++----- + drivers/crypto/qce/dma.h | 2 +- + drivers/crypto/qce/skcipher.c | 5 +++-- + 3 files changed, 10 insertions(+), 8 deletions(-) + +--- a/drivers/crypto/qce/dma.c ++++ b/drivers/crypto/qce/dma.c +@@ -48,9 +48,10 @@ void qce_dma_release(struct qce_dma_data + + struct scatterlist * + qce_sgtable_add(struct sg_table *sgt, struct scatterlist *new_sgl, +- int max_ents) ++ unsigned int max_len) + { + struct scatterlist *sg = sgt->sgl, *sg_last = NULL; ++ unsigned int new_len; + + while (sg) { + if (!sg_page(sg)) +@@ -61,13 +62,13 @@ qce_sgtable_add(struct sg_table *sgt, st + if (!sg) + return ERR_PTR(-EINVAL); + +- while (new_sgl && sg && max_ents) { +- sg_set_page(sg, sg_page(new_sgl), new_sgl->length, +- new_sgl->offset); ++ while (new_sgl && sg && max_len) { ++ new_len = new_sgl->length > max_len ? max_len : new_sgl->length; ++ sg_set_page(sg, sg_page(new_sgl), new_len, new_sgl->offset); + sg_last = sg; + sg = sg_next(sg); + new_sgl = sg_next(new_sgl); +- max_ents--; ++ max_len -= new_len; + } + + return sg_last; +--- a/drivers/crypto/qce/dma.h ++++ b/drivers/crypto/qce/dma.h +@@ -43,6 +43,6 @@ void qce_dma_issue_pending(struct qce_dm + int qce_dma_terminate_all(struct qce_dma_data *dma); + struct scatterlist * + qce_sgtable_add(struct sg_table *sgt, struct scatterlist *sg_add, +- int max_ents); ++ unsigned int max_len); + + #endif /* _DMA_H_ */ +--- a/drivers/crypto/qce/skcipher.c ++++ b/drivers/crypto/qce/skcipher.c +@@ -97,13 +97,14 @@ qce_skcipher_async_req_handle(struct cry + + sg_init_one(&rctx->result_sg, qce->dma.result_buf, QCE_RESULT_BUF_SZ); + +- sg = qce_sgtable_add(&rctx->dst_tbl, req->dst, rctx->dst_nents - 1); ++ sg = qce_sgtable_add(&rctx->dst_tbl, req->dst, req->cryptlen); + if (IS_ERR(sg)) { + ret = PTR_ERR(sg); + goto error_free; + } + +- sg = qce_sgtable_add(&rctx->dst_tbl, &rctx->result_sg, 1); ++ sg = qce_sgtable_add(&rctx->dst_tbl, &rctx->result_sg, ++ QCE_RESULT_BUF_SZ); + if (IS_ERR(sg)) { + ret = PTR_ERR(sg); + goto error_free; diff --git a/feeds/ipq40xx/ipq40xx/patches-5.4/0015-v5.7-crypto-qce-use-AES-fallback-for-small-requests.patch b/feeds/ipq40xx/ipq40xx/patches-5.4/0015-v5.7-crypto-qce-use-AES-fallback-for-small-requests.patch new file mode 100644 index 000000000..0b5c8c6d6 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/patches-5.4/0015-v5.7-crypto-qce-use-AES-fallback-for-small-requests.patch @@ -0,0 +1,113 @@ +From ce163ba0bf298f1707321ac025ef639f88e62801 Mon Sep 17 00:00:00 2001 +From: Eneas U de Queiroz +Date: Fri, 7 Feb 2020 12:02:26 -0300 +Subject: [PATCH 10/11] crypto: qce - use AES fallback for small requests + +Process small blocks using the fallback cipher, as a workaround for an +observed failure (DMA-related, apparently) when computing the GCM ghash +key. This brings a speed gain as well, since it avoids the latency of +using the hardware engine to process small blocks. + +Using software for all 16-byte requests would be enough to make GCM +work, but to increase performance, a larger threshold would be better. +Measuring the performance of supported ciphers with openssl speed, +software matches hardware at around 768-1024 bytes. + +Considering the 256-bit ciphers, software is 2-3 times faster than qce +at 256-bytes, 30% faster at 512, and about even at 768-bytes. With +128-bit keys, the break-even point would be around 1024-bytes. + +This adds the 'aes_sw_max_len' parameter, to set the largest request +length processed by the software fallback. Its default is being set to +512 bytes, a little lower than the break-even point, to balance the cost +in CPU usage. + +Signed-off-by: Eneas U de Queiroz +Signed-off-by: Herbert Xu +--- + +--- a/drivers/crypto/Kconfig ++++ b/drivers/crypto/Kconfig +@@ -684,6 +684,29 @@ choice + + endchoice + ++config CRYPTO_DEV_QCE_SW_MAX_LEN ++ int "Default maximum request size to use software for AES" ++ depends on CRYPTO_DEV_QCE && CRYPTO_DEV_QCE_SKCIPHER ++ default 512 ++ help ++ This sets the default maximum request size to perform AES requests ++ using software instead of the crypto engine. It can be changed by ++ setting the aes_sw_max_len parameter. ++ ++ Small blocks are processed faster in software than hardware. ++ Considering the 256-bit ciphers, software is 2-3 times faster than ++ qce at 256-bytes, 30% faster at 512, and about even at 768-bytes. ++ With 128-bit keys, the break-even point would be around 1024-bytes. ++ ++ The default is set a little lower, to 512 bytes, to balance the ++ cost in CPU usage. The minimum recommended setting is 16-bytes ++ (1 AES block), since AES-GCM will fail if you set it lower. ++ Setting this to zero will send all requests to the hardware. ++ ++ Note that 192-bit keys are not supported by the hardware and are ++ always processed by the software fallback, and all DES requests ++ are done by the hardware. ++ + config CRYPTO_DEV_QCOM_RNG + tristate "Qualcomm Random Number Generator Driver" + depends on ARCH_QCOM || COMPILE_TEST +--- a/drivers/crypto/qce/skcipher.c ++++ b/drivers/crypto/qce/skcipher.c +@@ -5,6 +5,7 @@ + + #include + #include ++#include + #include + #include + #include +@@ -12,6 +13,13 @@ + + #include "cipher.h" + ++static unsigned int aes_sw_max_len = CONFIG_CRYPTO_DEV_QCE_SW_MAX_LEN; ++module_param(aes_sw_max_len, uint, 0644); ++MODULE_PARM_DESC(aes_sw_max_len, ++ "Only use hardware for AES requests larger than this " ++ "[0=always use hardware; anything <16 breaks AES-GCM; default=" ++ __stringify(CONFIG_CRYPTO_DEV_QCE_SOFT_THRESHOLD)"]"); ++ + static LIST_HEAD(skcipher_algs); + + static void qce_skcipher_done(void *data) +@@ -166,15 +174,10 @@ static int qce_skcipher_setkey(struct cr + switch (IS_XTS(flags) ? keylen >> 1 : keylen) { + case AES_KEYSIZE_128: + case AES_KEYSIZE_256: ++ memcpy(ctx->enc_key, key, keylen); + break; +- default: +- goto fallback; + } + +- ctx->enc_keylen = keylen; +- memcpy(ctx->enc_key, key, keylen); +- return 0; +-fallback: + ret = crypto_sync_skcipher_setkey(ctx->fallback, key, keylen); + if (!ret) + ctx->enc_keylen = keylen; +@@ -224,8 +227,9 @@ static int qce_skcipher_crypt(struct skc + rctx->flags |= encrypt ? QCE_ENCRYPT : QCE_DECRYPT; + keylen = IS_XTS(rctx->flags) ? ctx->enc_keylen >> 1 : ctx->enc_keylen; + +- if (IS_AES(rctx->flags) && keylen != AES_KEYSIZE_128 && +- keylen != AES_KEYSIZE_256) { ++ if (IS_AES(rctx->flags) && ++ ((keylen != AES_KEYSIZE_128 && keylen != AES_KEYSIZE_256) || ++ req->cryptlen <= aes_sw_max_len)) { + SYNC_SKCIPHER_REQUEST_ON_STACK(subreq, ctx->fallback); + + skcipher_request_set_sync_tfm(subreq, ctx->fallback); diff --git a/feeds/ipq40xx/ipq40xx/patches-5.4/0016-v5.7-crypto-qce-handle-AES-XTS-cases-that-qce-fails.patch b/feeds/ipq40xx/ipq40xx/patches-5.4/0016-v5.7-crypto-qce-handle-AES-XTS-cases-that-qce-fails.patch new file mode 100644 index 000000000..18beda629 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/patches-5.4/0016-v5.7-crypto-qce-handle-AES-XTS-cases-that-qce-fails.patch @@ -0,0 +1,59 @@ +From 7f19380b2cfd412dcef2facefb3f6c62788864d7 Mon Sep 17 00:00:00 2001 +From: Eneas U de Queiroz +Date: Fri, 7 Feb 2020 12:02:27 -0300 +Subject: [PATCH 11/11] crypto: qce - handle AES-XTS cases that qce fails + +QCE hangs when presented with an AES-XTS request whose length is larger +than QCE_SECTOR_SIZE (512-bytes), and is not a multiple of it. Let the +fallback cipher handle them. + +Signed-off-by: Eneas U de Queiroz +Signed-off-by: Herbert Xu +--- + drivers/crypto/qce/common.c | 2 -- + drivers/crypto/qce/common.h | 3 +++ + drivers/crypto/qce/skcipher.c | 9 +++++++-- + 3 files changed, 10 insertions(+), 4 deletions(-) + +--- a/drivers/crypto/qce/common.c ++++ b/drivers/crypto/qce/common.c +@@ -15,8 +15,6 @@ + #include "regs-v5.h" + #include "sha.h" + +-#define QCE_SECTOR_SIZE 512 +- + static inline u32 qce_read(struct qce_device *qce, u32 offset) + { + return readl(qce->base + offset); +--- a/drivers/crypto/qce/common.h ++++ b/drivers/crypto/qce/common.h +@@ -12,6 +12,9 @@ + #include + #include + ++/* xts du size */ ++#define QCE_SECTOR_SIZE 512 ++ + /* key size in bytes */ + #define QCE_SHA_HMAC_KEY_SIZE 64 + #define QCE_MAX_CIPHER_KEY_SIZE AES_KEYSIZE_256 +--- a/drivers/crypto/qce/skcipher.c ++++ b/drivers/crypto/qce/skcipher.c +@@ -227,9 +227,14 @@ static int qce_skcipher_crypt(struct skc + rctx->flags |= encrypt ? QCE_ENCRYPT : QCE_DECRYPT; + keylen = IS_XTS(rctx->flags) ? ctx->enc_keylen >> 1 : ctx->enc_keylen; + ++ /* qce is hanging when AES-XTS request len > QCE_SECTOR_SIZE and ++ * is not a multiple of it; pass such requests to the fallback ++ */ + if (IS_AES(rctx->flags) && +- ((keylen != AES_KEYSIZE_128 && keylen != AES_KEYSIZE_256) || +- req->cryptlen <= aes_sw_max_len)) { ++ (((keylen != AES_KEYSIZE_128 && keylen != AES_KEYSIZE_256) || ++ req->cryptlen <= aes_sw_max_len) || ++ (IS_XTS(rctx->flags) && req->cryptlen > QCE_SECTOR_SIZE && ++ req->cryptlen % QCE_SECTOR_SIZE))) { + SYNC_SKCIPHER_REQUEST_ON_STACK(subreq, ctx->fallback); + + skcipher_request_set_sync_tfm(subreq, ctx->fallback); diff --git a/feeds/ipq40xx/ipq40xx/patches-5.4/0017-v5.8-phy-add-driver-for-Qualcomm-IPQ40xx-USB-PHY.patch b/feeds/ipq40xx/ipq40xx/patches-5.4/0017-v5.8-phy-add-driver-for-Qualcomm-IPQ40xx-USB-PHY.patch new file mode 100644 index 000000000..ad09a9f25 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/patches-5.4/0017-v5.8-phy-add-driver-for-Qualcomm-IPQ40xx-USB-PHY.patch @@ -0,0 +1,197 @@ +From 3c9d8f6c03a2cda1849ec3c84f82ec030d1f49ef Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Sun, 3 May 2020 22:18:22 +0200 +Subject: [PATCH] phy: add driver for Qualcomm IPQ40xx USB PHY + +Add a driver to setup the USB PHY-s on Qualcom m IPQ40xx series SoCs. +The driver sets up HS and SS phys. + +Signed-off-by: John Crispin +Signed-off-by: Robert Marko +Cc: Luka Perkov +Link: https://lore.kernel.org/r/20200503201823.531757-1-robert.marko@sartura.hr +Signed-off-by: Vinod Koul +--- + drivers/phy/qualcomm/Kconfig | 7 + + drivers/phy/qualcomm/Makefile | 1 + + drivers/phy/qualcomm/phy-qcom-ipq4019-usb.c | 148 ++++++++++++++++++++ + 3 files changed, 156 insertions(+) + create mode 100644 drivers/phy/qualcomm/phy-qcom-ipq4019-usb.c + +--- a/drivers/phy/qualcomm/Kconfig ++++ b/drivers/phy/qualcomm/Kconfig +@@ -18,6 +18,13 @@ config PHY_QCOM_APQ8064_SATA + depends on OF + select GENERIC_PHY + ++config PHY_QCOM_IPQ4019_USB ++ tristate "Qualcomm IPQ4019 USB PHY driver" ++ depends on OF && (ARCH_QCOM || COMPILE_TEST) ++ select GENERIC_PHY ++ help ++ Support for the USB PHY-s on Qualcomm IPQ40xx SoC-s. ++ + config PHY_QCOM_IPQ806X_SATA + tristate "Qualcomm IPQ806x SATA SerDes/PHY driver" + depends on ARCH_QCOM +--- a/drivers/phy/qualcomm/Makefile ++++ b/drivers/phy/qualcomm/Makefile +@@ -1,6 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0 + obj-$(CONFIG_PHY_ATH79_USB) += phy-ath79-usb.o + obj-$(CONFIG_PHY_QCOM_APQ8064_SATA) += phy-qcom-apq8064-sata.o ++obj-$(CONFIG_PHY_QCOM_IPQ4019_USB) += phy-qcom-ipq4019-usb.o + obj-$(CONFIG_PHY_QCOM_IPQ806X_SATA) += phy-qcom-ipq806x-sata.o + obj-$(CONFIG_PHY_QCOM_PCIE2) += phy-qcom-pcie2.o + obj-$(CONFIG_PHY_QCOM_QMP) += phy-qcom-qmp.o +--- /dev/null ++++ b/drivers/phy/qualcomm/phy-qcom-ipq4019-usb.c +@@ -0,0 +1,148 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* ++ * Copyright (C) 2018 John Crispin ++ * ++ * Based on code from ++ * Allwinner Technology Co., Ltd. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++struct ipq4019_usb_phy { ++ struct device *dev; ++ struct phy *phy; ++ void __iomem *base; ++ struct reset_control *por_rst; ++ struct reset_control *srif_rst; ++}; ++ ++static int ipq4019_ss_phy_power_off(struct phy *_phy) ++{ ++ struct ipq4019_usb_phy *phy = phy_get_drvdata(_phy); ++ ++ reset_control_assert(phy->por_rst); ++ msleep(10); ++ ++ return 0; ++} ++ ++static int ipq4019_ss_phy_power_on(struct phy *_phy) ++{ ++ struct ipq4019_usb_phy *phy = phy_get_drvdata(_phy); ++ ++ ipq4019_ss_phy_power_off(_phy); ++ ++ reset_control_deassert(phy->por_rst); ++ ++ return 0; ++} ++ ++static struct phy_ops ipq4019_usb_ss_phy_ops = { ++ .power_on = ipq4019_ss_phy_power_on, ++ .power_off = ipq4019_ss_phy_power_off, ++}; ++ ++static int ipq4019_hs_phy_power_off(struct phy *_phy) ++{ ++ struct ipq4019_usb_phy *phy = phy_get_drvdata(_phy); ++ ++ reset_control_assert(phy->por_rst); ++ msleep(10); ++ ++ reset_control_assert(phy->srif_rst); ++ msleep(10); ++ ++ return 0; ++} ++ ++static int ipq4019_hs_phy_power_on(struct phy *_phy) ++{ ++ struct ipq4019_usb_phy *phy = phy_get_drvdata(_phy); ++ ++ ipq4019_hs_phy_power_off(_phy); ++ ++ reset_control_deassert(phy->srif_rst); ++ msleep(10); ++ ++ reset_control_deassert(phy->por_rst); ++ ++ return 0; ++} ++ ++static struct phy_ops ipq4019_usb_hs_phy_ops = { ++ .power_on = ipq4019_hs_phy_power_on, ++ .power_off = ipq4019_hs_phy_power_off, ++}; ++ ++static const struct of_device_id ipq4019_usb_phy_of_match[] = { ++ { .compatible = "qcom,usb-hs-ipq4019-phy", .data = &ipq4019_usb_hs_phy_ops}, ++ { .compatible = "qcom,usb-ss-ipq4019-phy", .data = &ipq4019_usb_ss_phy_ops}, ++ { }, ++}; ++MODULE_DEVICE_TABLE(of, ipq4019_usb_phy_of_match); ++ ++static int ipq4019_usb_phy_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct resource *res; ++ struct phy_provider *phy_provider; ++ struct ipq4019_usb_phy *phy; ++ ++ phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL); ++ if (!phy) ++ return -ENOMEM; ++ ++ phy->dev = &pdev->dev; ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ phy->base = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(phy->base)) { ++ dev_err(dev, "failed to remap register memory\n"); ++ return PTR_ERR(phy->base); ++ } ++ ++ phy->por_rst = devm_reset_control_get(phy->dev, "por_rst"); ++ if (IS_ERR(phy->por_rst)) { ++ if (PTR_ERR(phy->por_rst) != -EPROBE_DEFER) ++ dev_err(dev, "POR reset is missing\n"); ++ return PTR_ERR(phy->por_rst); ++ } ++ ++ phy->srif_rst = devm_reset_control_get_optional(phy->dev, "srif_rst"); ++ if (IS_ERR(phy->srif_rst)) ++ return PTR_ERR(phy->srif_rst); ++ ++ phy->phy = devm_phy_create(dev, NULL, of_device_get_match_data(dev)); ++ if (IS_ERR(phy->phy)) { ++ dev_err(dev, "failed to create PHY\n"); ++ return PTR_ERR(phy->phy); ++ } ++ phy_set_drvdata(phy->phy, phy); ++ ++ phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); ++ ++ return PTR_ERR_OR_ZERO(phy_provider); ++} ++ ++static struct platform_driver ipq4019_usb_phy_driver = { ++ .probe = ipq4019_usb_phy_probe, ++ .driver = { ++ .of_match_table = ipq4019_usb_phy_of_match, ++ .name = "ipq4019-usb-phy", ++ } ++}; ++module_platform_driver(ipq4019_usb_phy_driver); ++ ++MODULE_DESCRIPTION("QCOM/IPQ4019 USB phy driver"); ++MODULE_AUTHOR("John Crispin "); ++MODULE_LICENSE("GPL v2"); diff --git a/feeds/ipq40xx/ipq40xx/patches-5.4/0018-v5.9-pinctrl-msm-open-drain.patch b/feeds/ipq40xx/ipq40xx/patches-5.4/0018-v5.9-pinctrl-msm-open-drain.patch new file mode 100644 index 000000000..5cd4ccc30 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/patches-5.4/0018-v5.9-pinctrl-msm-open-drain.patch @@ -0,0 +1,81 @@ +From 5b08c1d567ee8e6af94696b3e549997cbdb2bb80 Mon Sep 17 00:00:00 2001 +From: Jaiganesh Narayanan +Date: Thu, 1 Sep 2016 10:40:38 +0530 +Subject: [PATCH] pinctrl: qcom: ipq4019: add open drain support + +Signed-off-by: Jaiganesh Narayanan +[ Brian: adapted from from the Chromium OS kernel used on IPQ4019-based + WiFi APs. ] +Signed-off-by: Brian Norris +--- +https://lore.kernel.org/linux-gpio/20200703080646.23233-1-computersforpeace@gmail.com/ + + drivers/pinctrl/qcom/pinctrl-ipq4019.c | 1 + + drivers/pinctrl/qcom/pinctrl-msm.c | 13 +++++++++++++ + drivers/pinctrl/qcom/pinctrl-msm.h | 2 ++ + 3 files changed, 16 insertions(+) + +--- a/drivers/pinctrl/qcom/pinctrl-ipq4019.c ++++ b/drivers/pinctrl/qcom/pinctrl-ipq4019.c +@@ -254,6 +254,7 @@ DECLARE_QCA_GPIO_PINS(99); + .mux_bit = 2, \ + .pull_bit = 0, \ + .drv_bit = 6, \ ++ .od_bit = 12, \ + .oe_bit = 9, \ + .in_bit = 0, \ + .out_bit = 1, \ +--- a/drivers/pinctrl/qcom/pinctrl-msm.c ++++ b/drivers/pinctrl/qcom/pinctrl-msm.c +@@ -225,6 +225,10 @@ static int msm_config_reg(struct msm_pin + *bit = g->pull_bit; + *mask = 3; + break; ++ case PIN_CONFIG_DRIVE_OPEN_DRAIN: ++ *bit = g->od_bit; ++ *mask = 1; ++ break; + case PIN_CONFIG_DRIVE_STRENGTH: + *bit = g->drv_bit; + *mask = 7; +@@ -302,6 +306,12 @@ static int msm_config_group_get(struct p + if (!arg) + return -EINVAL; + break; ++ case PIN_CONFIG_DRIVE_OPEN_DRAIN: ++ /* Pin is not open-drain */ ++ if (!arg) ++ return -EINVAL; ++ arg = 1; ++ break; + case PIN_CONFIG_DRIVE_STRENGTH: + arg = msm_regval_to_drive(arg); + break; +@@ -374,6 +384,9 @@ static int msm_config_group_set(struct p + else + arg = MSM_PULL_UP; + break; ++ case PIN_CONFIG_DRIVE_OPEN_DRAIN: ++ arg = 1; ++ break; + case PIN_CONFIG_DRIVE_STRENGTH: + /* Check for invalid values */ + if (arg > 16 || arg < 2 || (arg % 2) != 0) +--- a/drivers/pinctrl/qcom/pinctrl-msm.h ++++ b/drivers/pinctrl/qcom/pinctrl-msm.h +@@ -38,6 +38,7 @@ struct msm_function { + * @mux_bit: Offset in @ctl_reg for the pinmux function selection. + * @pull_bit: Offset in @ctl_reg for the bias configuration. + * @drv_bit: Offset in @ctl_reg for the drive strength configuration. ++ * @od_bit: Offset in @ctl_reg for controlling open drain. + * @oe_bit: Offset in @ctl_reg for controlling output enable. + * @in_bit: Offset in @io_reg for the input bit value. + * @out_bit: Offset in @io_reg for the output bit value. +@@ -75,6 +76,7 @@ struct msm_pingroup { + unsigned pull_bit:5; + unsigned drv_bit:5; + ++ unsigned od_bit:5; + unsigned oe_bit:5; + unsigned in_bit:5; + unsigned out_bit:5; diff --git a/feeds/ipq40xx/ipq40xx/patches-5.4/0019-v5.6-mtd-spi-nor-Add-support-for-mx25r3235f.patch b/feeds/ipq40xx/ipq40xx/patches-5.4/0019-v5.6-mtd-spi-nor-Add-support-for-mx25r3235f.patch new file mode 100644 index 000000000..f1be01c8e --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/patches-5.4/0019-v5.6-mtd-spi-nor-Add-support-for-mx25r3235f.patch @@ -0,0 +1,29 @@ +From 707745e8d4e75b638b990d67950ab292b3b8ea2a Mon Sep 17 00:00:00 2001 +From: David Bauer +Date: Mon, 16 Dec 2019 01:36:46 +0100 +Subject: [PATCH] mtd: spi-nor: Add support for mx25r3235f + +Add MTD support for the Macronix MX25R3235F SPI NOR chip from Macronix. +The chip has 4MB of total capacity, divided into a total of 64 sectors, +each 64KB sized. The chip also supports 4KB large sectors. +Additionally, it supports dual and quad read modes. + +Functionality was verified on an HPE/Aruba AP-303 board. + +Signed-off-by: David Bauer +Signed-off-by: Tudor Ambarus +--- + drivers/mtd/spi-nor/spi-nor.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/mtd/spi-nor/spi-nor.c ++++ b/drivers/mtd/spi-nor/spi-nor.c +@@ -2353,6 +2353,8 @@ static const struct flash_info spi_nor_i + { "mx25u6435f", INFO(0xc22537, 0, 64 * 1024, 128, SECT_4K) }, + { "mx25l12805d", INFO(0xc22018, 0, 64 * 1024, 256, 0) }, + { "mx25l12855e", INFO(0xc22618, 0, 64 * 1024, 256, 0) }, ++ { "mx25r3235f", INFO(0xc22816, 0, 64 * 1024, 64, ++ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + { "mx25u12835f", INFO(0xc22538, 0, 64 * 1024, 256, + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + { "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512, diff --git a/feeds/ipq40xx/ipq40xx/patches-5.4/100-GPIO-add-named-gpio-exports.patch b/feeds/ipq40xx/ipq40xx/patches-5.4/100-GPIO-add-named-gpio-exports.patch new file mode 100644 index 000000000..805836fcc --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/patches-5.4/100-GPIO-add-named-gpio-exports.patch @@ -0,0 +1,165 @@ +From 4267880319bc1a2270d352e0ded6d6386242a7ef Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Tue, 12 Aug 2014 20:49:27 +0200 +Subject: [PATCH 24/53] GPIO: add named gpio exports + +Signed-off-by: John Crispin +--- + drivers/gpio/gpiolib-of.c | 68 +++++++++++++++++++++++++++++++++++++++++ + drivers/gpio/gpiolib-sysfs.c | 10 +++++- + include/asm-generic/gpio.h | 6 ++++ + include/linux/gpio/consumer.h | 8 +++++ + 4 files changed, 91 insertions(+), 1 deletion(-) + +--- a/drivers/gpio/gpiolib-of.c ++++ b/drivers/gpio/gpiolib-of.c +@@ -19,6 +19,8 @@ + #include + #include + #include ++#include ++#include + + #include "gpiolib.h" + #include "gpiolib-of.h" +@@ -915,3 +917,68 @@ void of_gpiochip_remove(struct gpio_chip + { + of_node_put(chip->of_node); + } ++ ++static struct of_device_id gpio_export_ids[] = { ++ { .compatible = "gpio-export" }, ++ { /* sentinel */ } ++}; ++ ++static int of_gpio_export_probe(struct platform_device *pdev) ++{ ++ struct device_node *np = pdev->dev.of_node; ++ struct device_node *cnp; ++ u32 val; ++ int nb = 0; ++ ++ for_each_child_of_node(np, cnp) { ++ const char *name = NULL; ++ int gpio; ++ bool dmc; ++ int max_gpio = 1; ++ int i; ++ ++ of_property_read_string(cnp, "gpio-export,name", &name); ++ ++ if (!name) ++ max_gpio = of_gpio_count(cnp); ++ ++ for (i = 0; i < max_gpio; i++) { ++ unsigned flags = 0; ++ enum of_gpio_flags of_flags; ++ ++ gpio = of_get_gpio_flags(cnp, i, &of_flags); ++ if (!gpio_is_valid(gpio)) ++ return gpio; ++ ++ if (of_flags == OF_GPIO_ACTIVE_LOW) ++ flags |= GPIOF_ACTIVE_LOW; ++ ++ if (!of_property_read_u32(cnp, "gpio-export,output", &val)) ++ flags |= val ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW; ++ else ++ flags |= GPIOF_IN; ++ ++ if (devm_gpio_request_one(&pdev->dev, gpio, flags, name ? name : of_node_full_name(np))) ++ continue; ++ ++ dmc = of_property_read_bool(cnp, "gpio-export,direction_may_change"); ++ gpio_export_with_name(gpio, dmc, name); ++ nb++; ++ } ++ } ++ ++ dev_info(&pdev->dev, "%d gpio(s) exported\n", nb); ++ ++ return 0; ++} ++ ++static struct platform_driver gpio_export_driver = { ++ .driver = { ++ .name = "gpio-export", ++ .owner = THIS_MODULE, ++ .of_match_table = of_match_ptr(gpio_export_ids), ++ }, ++ .probe = of_gpio_export_probe, ++}; ++ ++module_platform_driver(gpio_export_driver); +--- a/drivers/gpio/gpiolib-sysfs.c ++++ b/drivers/gpio/gpiolib-sysfs.c +@@ -571,7 +571,7 @@ static struct class gpio_class = { + * + * Returns zero on success, else an error. + */ +-int gpiod_export(struct gpio_desc *desc, bool direction_may_change) ++int __gpiod_export(struct gpio_desc *desc, bool direction_may_change, const char *name) + { + struct gpio_chip *chip; + struct gpio_device *gdev; +@@ -633,6 +633,8 @@ int gpiod_export(struct gpio_desc *desc, + offset = gpio_chip_hwgpio(desc); + if (chip->names && chip->names[offset]) + ioname = chip->names[offset]; ++ if (name) ++ ioname = name; + + dev = device_create_with_groups(&gpio_class, &gdev->dev, + MKDEV(0, 0), data, gpio_groups, +@@ -654,6 +656,12 @@ err_unlock: + gpiod_dbg(desc, "%s: status %d\n", __func__, status); + return status; + } ++EXPORT_SYMBOL_GPL(__gpiod_export); ++ ++int gpiod_export(struct gpio_desc *desc, bool direction_may_change) ++{ ++ return __gpiod_export(desc, direction_may_change, NULL); ++} + EXPORT_SYMBOL_GPL(gpiod_export); + + static int match_export(struct device *dev, const void *desc) +--- a/include/asm-generic/gpio.h ++++ b/include/asm-generic/gpio.h +@@ -127,6 +127,12 @@ static inline int gpio_export(unsigned g + return gpiod_export(gpio_to_desc(gpio), direction_may_change); + } + ++int __gpiod_export(struct gpio_desc *desc, bool direction_may_change, const char *name); ++static inline int gpio_export_with_name(unsigned gpio, bool direction_may_change, const char *name) ++{ ++ return __gpiod_export(gpio_to_desc(gpio), direction_may_change, name); ++} ++ + static inline int gpio_export_link(struct device *dev, const char *name, + unsigned gpio) + { +--- a/include/linux/gpio/consumer.h ++++ b/include/linux/gpio/consumer.h +@@ -668,6 +668,7 @@ static inline void devm_acpi_dev_remove_ + + #if IS_ENABLED(CONFIG_GPIOLIB) && IS_ENABLED(CONFIG_GPIO_SYSFS) + ++int _gpiod_export(struct gpio_desc *desc, bool direction_may_change, const char *name); + int gpiod_export(struct gpio_desc *desc, bool direction_may_change); + int gpiod_export_link(struct device *dev, const char *name, + struct gpio_desc *desc); +@@ -675,6 +676,13 @@ void gpiod_unexport(struct gpio_desc *de + + #else /* CONFIG_GPIOLIB && CONFIG_GPIO_SYSFS */ + ++static inline int _gpiod_export(struct gpio_desc *desc, ++ bool direction_may_change, ++ const char *name) ++{ ++ return -ENOSYS; ++} ++ + static inline int gpiod_export(struct gpio_desc *desc, + bool direction_may_change) + { diff --git a/feeds/ipq40xx/ipq40xx/patches-5.4/101-arm-dts-IPQ4019-add-SDHCI-VQMMC-LDO-node.patch b/feeds/ipq40xx/ipq40xx/patches-5.4/101-arm-dts-IPQ4019-add-SDHCI-VQMMC-LDO-node.patch new file mode 100644 index 000000000..14affc28c --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/patches-5.4/101-arm-dts-IPQ4019-add-SDHCI-VQMMC-LDO-node.patch @@ -0,0 +1,32 @@ +From 77d9b11ae7269dcf376c3b9493209f712524e986 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Wed, 22 Jan 2020 12:56:35 +0100 +Subject: [PATCH] arm: dts: IPQ4019: add SDHCI VQMMC LDO node + +Since we now have driver for the SDHCI VQMMC LDO needed +for I/0 voltage levels lets introduce the necessary node for it. + +Signed-off-by: Robert Marko +--- + arch/arm/boot/dts/qcom-ipq4019.dtsi | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +--- a/arch/arm/boot/dts/qcom-ipq4019.dtsi ++++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi +@@ -209,6 +209,16 @@ + interrupts = ; + }; + ++ vqmmc: regulator@1948000 { ++ compatible = "qcom,vqmmc-ipq4019-regulator"; ++ reg = <0x01948000 0x4>; ++ regulator-name = "vqmmc"; ++ regulator-min-microvolt = <1500000>; ++ regulator-max-microvolt = <3000000>; ++ regulator-always-on; ++ status = "disabled"; ++ }; ++ + sdhci: sdhci@7824900 { + compatible = "qcom,sdhci-msm-v4"; + reg = <0x7824900 0x11c>, <0x7824000 0x800>; diff --git a/feeds/ipq40xx/ipq40xx/patches-5.4/102-ARM-dts-qcom-ipq4019-add-USB-devicetree-nodes.patch b/feeds/ipq40xx/ipq40xx/patches-5.4/102-ARM-dts-qcom-ipq4019-add-USB-devicetree-nodes.patch new file mode 100644 index 000000000..b033a1bae --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/patches-5.4/102-ARM-dts-qcom-ipq4019-add-USB-devicetree-nodes.patch @@ -0,0 +1,97 @@ +From 193856b5fe11c50a0b6ff22457dd674c1a45fec6 Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Wed, 9 Sep 2020 18:31:03 +0200 +Subject: [PATCH] ARM: dts: qcom: ipq4019: add USB devicetree nodes + +Since we now have driver for the USB PHY, and USB controller is already supported by the DWC3 driver lets add the necessary nodes to DTSI. + +Signed-off-by: John Crispin +Signed-off-by: Robert Marko +Cc: Luka Perkov +Reviewed-by: Vinod Koul +--- + arch/arm/boot/dts/qcom-ipq4019.dtsi | 74 +++++++++++++++++++++++++++++ + 1 file changed, 74 insertions(+) + +--- a/arch/arm/boot/dts/qcom-ipq4019.dtsi ++++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi +@@ -615,5 +615,79 @@ + reg = <4>; + }; + }; ++ ++ usb3_ss_phy: ssphy@9a000 { ++ compatible = "qcom,usb-ss-ipq4019-phy"; ++ #phy-cells = <0>; ++ reg = <0x9a000 0x800>; ++ reg-names = "phy_base"; ++ resets = <&gcc USB3_UNIPHY_PHY_ARES>; ++ reset-names = "por_rst"; ++ status = "disabled"; ++ }; ++ ++ usb3_hs_phy: hsphy@a6000 { ++ compatible = "qcom,usb-hs-ipq4019-phy"; ++ #phy-cells = <0>; ++ reg = <0xa6000 0x40>; ++ reg-names = "phy_base"; ++ resets = <&gcc USB3_HSPHY_POR_ARES>, <&gcc USB3_HSPHY_S_ARES>; ++ reset-names = "por_rst", "srif_rst"; ++ status = "disabled"; ++ }; ++ ++ usb3: usb3@8af8800 { ++ compatible = "qcom,dwc3"; ++ reg = <0x8af8800 0x100>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ clocks = <&gcc GCC_USB3_MASTER_CLK>, ++ <&gcc GCC_USB3_SLEEP_CLK>, ++ <&gcc GCC_USB3_MOCK_UTMI_CLK>; ++ clock-names = "master", "sleep", "mock_utmi"; ++ ranges; ++ status = "disabled"; ++ ++ dwc3@8a00000 { ++ compatible = "snps,dwc3"; ++ reg = <0x8a00000 0xf8000>; ++ interrupts = ; ++ phys = <&usb3_hs_phy>, <&usb3_ss_phy>; ++ phy-names = "usb2-phy", "usb3-phy"; ++ dr_mode = "host"; ++ }; ++ }; ++ ++ usb2_hs_phy: hsphy@a8000 { ++ compatible = "qcom,usb-hs-ipq4019-phy"; ++ #phy-cells = <0>; ++ reg = <0xa8000 0x40>; ++ reg-names = "phy_base"; ++ resets = <&gcc USB2_HSPHY_POR_ARES>, <&gcc USB2_HSPHY_S_ARES>; ++ reset-names = "por_rst", "srif_rst"; ++ status = "disabled"; ++ }; ++ ++ usb2: usb2@60f8800 { ++ compatible = "qcom,dwc3"; ++ reg = <0x60f8800 0x100>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ clocks = <&gcc GCC_USB2_MASTER_CLK>, ++ <&gcc GCC_USB2_SLEEP_CLK>, ++ <&gcc GCC_USB2_MOCK_UTMI_CLK>; ++ clock-names = "master", "sleep", "mock_utmi"; ++ ranges; ++ status = "disabled"; ++ ++ dwc3@6000000 { ++ compatible = "snps,dwc3"; ++ reg = <0x6000000 0xf8000>; ++ interrupts = ; ++ phys = <&usb2_hs_phy>; ++ phy-names = "usb2-phy"; ++ dr_mode = "host"; ++ }; ++ }; + }; + }; diff --git a/feeds/ipq40xx/ipq40xx/patches-5.4/103-arm-dts-qcom-ipq4019-add-more-labels.patch b/feeds/ipq40xx/ipq40xx/patches-5.4/103-arm-dts-qcom-ipq4019-add-more-labels.patch new file mode 100644 index 000000000..0e215ee7c --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/patches-5.4/103-arm-dts-qcom-ipq4019-add-more-labels.patch @@ -0,0 +1,42 @@ +From caa3ee6b094ee18021943504c938919fcac325ec Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Wed, 9 Sep 2020 20:40:33 +0200 +Subject: [PATCH] arm: dts: qcom: ipq4019: add more labels + +Lets add labels to more commonly used nodes for easier modification in board DTS files. + +Signed-off-by: Robert Marko +Cc: Luka Perkov +--- + arch/arm/boot/dts/qcom-ipq4019.dtsi | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/arch/arm/boot/dts/qcom-ipq4019.dtsi ++++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi +@@ -190,7 +190,7 @@ + reg = <0x1800000 0x60000>; + }; + +- rng@22000 { ++ prng: rng@22000 { + compatible = "qcom,prng"; + reg = <0x22000 0x140>; + clocks = <&gcc GCC_PRNG_AHB_CLK>; +@@ -310,7 +310,7 @@ + status = "disabled"; + }; + +- crypto@8e3a000 { ++ crypto: crypto@8e3a000 { + compatible = "qcom,crypto-v5.1"; + reg = <0x08e3a000 0x6000>; + clocks = <&gcc GCC_CRYPTO_AHB_CLK>, +@@ -396,7 +396,7 @@ + dma-names = "rx", "tx"; + }; + +- watchdog@b017000 { ++ watchdog: watchdog@b017000 { + compatible = "qcom,kpss-wdt", "qcom,kpss-wdt-ipq4019"; + reg = <0xb017000 0x40>; + clocks = <&sleep_clk>; diff --git a/feeds/ipq40xx/ipq40xx/patches-5.4/104-clk-fix-apss-cpu-overclocking.patch b/feeds/ipq40xx/ipq40xx/patches-5.4/104-clk-fix-apss-cpu-overclocking.patch new file mode 100644 index 000000000..25a2020bd --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/patches-5.4/104-clk-fix-apss-cpu-overclocking.patch @@ -0,0 +1,115 @@ +From f2b87dc1028b710ec8ce25808b9d21f92b376184 Mon Sep 17 00:00:00 2001 +From: Christian Lamparter +Date: Sun, 11 Mar 2018 14:41:31 +0100 +Subject: [PATCH 2/2] clk: fix apss cpu overclocking + +There's an interaction issue between the clk changes:" +clk: qcom: ipq4019: Add the apss cpu pll divider clock node +clk: qcom: ipq4019: remove fixed clocks and add pll clocks +" and the cpufreq-dt. + +cpufreq-dt is now spamming the kernel-log with the following: + +[ 1099.190658] cpu cpu0: dev_pm_opp_set_rate: failed to find current OPP +for freq 761142857 (-34) + +This only happens on certain devices like the Compex WPJ428 +and AVM FritzBox!4040. However, other devices like the Asus +RT-AC58U and Meraki MR33 work just fine. + +The issue stem from the fact that all higher CPU-Clocks +are achieved by switching the clock-parent to the P_DDRPLLAPSS +(ddrpllapss). Which is set by Qualcomm's proprietary bootcode +as part of the DDR calibration. + +For example, the FB4040 uses 256 MiB Nanya NT5CC128M16IP clocked +at round 533 MHz (ddrpllsdcc = 190285714 Hz). + +whereas the 128 MiB Nanya NT5CC64M16GP-DI in the ASUS RT-AC58U is +clocked at a slightly higher 537 MHz ( ddrpllsdcc = 192000000 Hz). + +This patch attempts to fix the issue by modifying +clk_cpu_div_round_rate(), clk_cpu_div_set_rate(), clk_cpu_div_recalc_rate() +to use a new qcom_find_freq_close() function, which returns the closest +matching frequency, instead of the next higher. This way, the SoC in +the FB4040 (with its max clock speed of 710.4 MHz) will no longer +try to overclock to 761 MHz. + +Fixes: d83dcacea18 ("clk: qcom: ipq4019: Add the apss cpu pll divider clock node") +Signed-off-by: Christian Lamparter +Signed-off-by: John Crispin +--- + drivers/clk/qcom/gcc-ipq4019.c | 34 +++++++++++++++++++++++++++++++--- + 1 file changed, 31 insertions(+), 3 deletions(-) + +--- a/drivers/clk/qcom/gcc-ipq4019.c ++++ b/drivers/clk/qcom/gcc-ipq4019.c +@@ -1243,6 +1243,29 @@ static const struct clk_fepll_vco gcc_fe + .reg = 0x2f020, + }; + ++ ++const struct freq_tbl *qcom_find_freq_close(const struct freq_tbl *f, ++ unsigned long rate) ++{ ++ const struct freq_tbl *last = NULL; ++ ++ for ( ; f->freq; f++) { ++ if (rate == f->freq) ++ return f; ++ ++ if (f->freq > rate) { ++ if (!last || ++ (f->freq - rate) < (rate - last->freq)) ++ return f; ++ else ++ return last; ++ } ++ last = f; ++ } ++ ++ return last; ++} ++ + /* + * Round rate function for APSS CPU PLL Clock divider. + * It looks up the frequency table and returns the next higher frequency +@@ -1255,7 +1278,7 @@ static long clk_cpu_div_round_rate(struc + struct clk_hw *p_hw; + const struct freq_tbl *f; + +- f = qcom_find_freq(pll->freq_tbl, rate); ++ f = qcom_find_freq_close(pll->freq_tbl, rate); + if (!f) + return -EINVAL; + +@@ -1278,7 +1301,7 @@ static int clk_cpu_div_set_rate(struct c + u32 mask; + int ret; + +- f = qcom_find_freq(pll->freq_tbl, rate); ++ f = qcom_find_freq_close(pll->freq_tbl, rate); + if (!f) + return -EINVAL; + +@@ -1305,6 +1328,7 @@ static unsigned long + clk_cpu_div_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) + { ++ const struct freq_tbl *f; + struct clk_fepll *pll = to_clk_fepll(hw); + u32 cdiv, pre_div; + u64 rate; +@@ -1325,7 +1349,11 @@ clk_cpu_div_recalc_rate(struct clk_hw *h + rate = clk_fepll_vco_calc_rate(pll, parent_rate) * 2; + do_div(rate, pre_div); + +- return rate; ++ f = qcom_find_freq_close(pll->freq_tbl, rate); ++ if (!f) ++ return rate; ++ ++ return f->freq; + }; + + static const struct clk_ops clk_regmap_cpu_div_ops = { diff --git a/feeds/ipq40xx/ipq40xx/patches-5.4/300-clk-qcom-ipq4019-add-ess-reset.patch b/feeds/ipq40xx/ipq40xx/patches-5.4/300-clk-qcom-ipq4019-add-ess-reset.patch new file mode 100644 index 000000000..4297f32e0 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/patches-5.4/300-clk-qcom-ipq4019-add-ess-reset.patch @@ -0,0 +1,52 @@ +From 480c1f7648fc586db12d6003c717c23667a4fcf0 Mon Sep 17 00:00:00 2001 +From: Ram Chandra Jangir +Date: Tue, 28 Mar 2017 22:35:33 +0530 +Subject: [PATCH] clk: qcom: ipq4019: add ess reset + +Added the ESS reset in IPQ4019 GCC. + +Signed-off-by: Ram Chandra Jangir +--- + drivers/clk/qcom/gcc-ipq4019.c | 11 +++++++++++ + include/dt-bindings/clock/qcom,gcc-ipq4019.h | 11 +++++++++++ + 2 files changed, 22 insertions(+) + +--- a/drivers/clk/qcom/gcc-ipq4019.c ++++ b/drivers/clk/qcom/gcc-ipq4019.c +@@ -1736,6 +1736,17 @@ static const struct qcom_reset_map gcc_i + [GCC_TCSR_BCR] = {0x22000, 0}, + [GCC_MPM_BCR] = {0x24000, 0}, + [GCC_SPDM_BCR] = {0x25000, 0}, ++ [ESS_MAC1_ARES] = {0x1200C, 0}, ++ [ESS_MAC2_ARES] = {0x1200C, 1}, ++ [ESS_MAC3_ARES] = {0x1200C, 2}, ++ [ESS_MAC4_ARES] = {0x1200C, 3}, ++ [ESS_MAC5_ARES] = {0x1200C, 4}, ++ [ESS_PSGMII_ARES] = {0x1200C, 5}, ++ [ESS_MAC1_CLK_DIS] = {0x1200C, 8}, ++ [ESS_MAC2_CLK_DIS] = {0x1200C, 9}, ++ [ESS_MAC3_CLK_DIS] = {0x1200C, 10}, ++ [ESS_MAC4_CLK_DIS] = {0x1200C, 11}, ++ [ESS_MAC5_CLK_DIS] = {0x1200C, 12}, + }; + + static const struct regmap_config gcc_ipq4019_regmap_config = { +--- a/include/dt-bindings/clock/qcom,gcc-ipq4019.h ++++ b/include/dt-bindings/clock/qcom,gcc-ipq4019.h +@@ -165,5 +165,16 @@ + #define GCC_QDSS_BCR 69 + #define GCC_MPM_BCR 70 + #define GCC_SPDM_BCR 71 ++#define ESS_MAC1_ARES 72 ++#define ESS_MAC2_ARES 73 ++#define ESS_MAC3_ARES 74 ++#define ESS_MAC4_ARES 75 ++#define ESS_MAC5_ARES 76 ++#define ESS_PSGMII_ARES 77 ++#define ESS_MAC1_CLK_DIS 78 ++#define ESS_MAC2_CLK_DIS 79 ++#define ESS_MAC3_CLK_DIS 80 ++#define ESS_MAC4_CLK_DIS 81 ++#define ESS_MAC5_CLK_DIS 82 + + #endif diff --git a/feeds/ipq40xx/ipq40xx/patches-5.4/301-arm-compressed-add-appended-DTB-section.patch b/feeds/ipq40xx/ipq40xx/patches-5.4/301-arm-compressed-add-appended-DTB-section.patch new file mode 100644 index 000000000..7e6184fc7 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/patches-5.4/301-arm-compressed-add-appended-DTB-section.patch @@ -0,0 +1,48 @@ +From 0843a61d6913bdac8889eb048ed89f7903059787 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Fri, 30 Oct 2020 13:36:31 +0100 +Subject: [PATCH] arm: compressed: add appended DTB section + +This adds a appended_dtb section to the ARM decompressor +linker script. + +This allows using the existing ARM zImage appended DTB support for +appending a DTB to the raw ELF kernel. + +Its size is set to 1MB max to match the zImage appended DTB size limit. + +To use it to pass the DTB to the kernel, objcopy is used: + +objcopy --set-section-flags=.appended_dtb=alloc,contents \ + --update-section=.appended_dtb=.dtb vmlinux + +This is based off the following patch: +https://github.com/openwrt/openwrt/commit/c063e27e02a9dcac0e7f5877fb154e58fa3e1a69 + +Signed-off-by: Robert Marko +--- + arch/arm/boot/compressed/vmlinux.lds.S | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +--- a/arch/arm/boot/compressed/vmlinux.lds.S ++++ b/arch/arm/boot/compressed/vmlinux.lds.S +@@ -93,6 +93,13 @@ SECTIONS + + _edata = .; + ++ .appended_dtb : { ++ /* leave space for appended DTB */ ++ . += 0x100000; ++ } ++ ++ _edata_dtb = .; ++ + /* + * The image_end section appears after any additional loadable sections + * that the linker may decide to insert in the binary image. Having +@@ -132,4 +139,4 @@ SECTIONS + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + } +-ASSERT(_edata_real == _edata, "error: zImage file size is incorrect"); ++ASSERT(_edata_real == _edata_dtb, "error: zImage file size is incorrect"); diff --git a/feeds/ipq40xx/ipq40xx/patches-5.4/302-arm-compressed-set-ipq40xx-watchdog-to-allow-boot.patch b/feeds/ipq40xx/ipq40xx/patches-5.4/302-arm-compressed-set-ipq40xx-watchdog-to-allow-boot.patch new file mode 100644 index 000000000..71618a40f --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/patches-5.4/302-arm-compressed-set-ipq40xx-watchdog-to-allow-boot.patch @@ -0,0 +1,66 @@ +From 11d6a6128a5a07c429941afc202b6e62a19771be Mon Sep 17 00:00:00 2001 +From: John Thomson +Date: Fri, 23 Oct 2020 19:42:36 +1000 +Subject: [PATCH 2/2] arm: compressed: set ipq40xx watchdog to allow boot + +For IPQ40XX systems where the SoC watchdog is activated before linux, +the watchdog timer may be too small for linux to finish uncompress, +boot, and watchdog management start. +If the watchdog is enabled, set the timeout for it to 30 seconds. +The functionality and offsets were copied from: +drivers/watchdog/qcom-wdt.c qcom_wdt_set_timeout & qcom_wdt_start +The watchdog memory address was taken from: +arch/arm/boot/dts/qcom-ipq4019.dtsi + +This was required on Mikrotik IPQ40XX consumer hardware using Mikrotik's +RouterBoot bootloader. + +Signed-off-by: John Thomson +--- + arch/arm/boot/compressed/head.S | 35 +++++++++++++++++++++++++++++++++ + 1 file changed, 35 insertions(+) + +--- a/arch/arm/boot/compressed/head.S ++++ b/arch/arm/boot/compressed/head.S +@@ -599,6 +599,41 @@ not_relocated: mov r0, #0 + bic r4, r4, #1 + blne cache_on + ++/* Set the Qualcom IPQ40xx watchdog timeout to 30 seconds ++ * if it is enabled, so that there is time for kernel ++ * to decompress, boot, and take over the watchdog. ++ * data and functionality from drivers/watchdog/qcom-wdt.c ++ * address from arch/arm/boot/dts/qcom-ipq4019.dtsi ++ */ ++#ifdef CONFIG_ARCH_IPQ40XX ++watchdog_set: ++ /* offsets: ++ * 0x04 reset (=1 resets countdown) ++ * 0x08 enable (=0 disables) ++ * 0x0c status (=1 when SoC was reset by watchdog) ++ * 0x10 bark (=timeout warning in ticks) ++ * 0x14 bite (=timeout reset in ticks) ++ * clock rate is 1<<15 hertz ++ */ ++ .equ watchdog, 0x0b017000 @Store watchdog base address ++ movw r0, #:lower16:watchdog ++ movt r0, #:upper16:watchdog ++ ldr r1, [r0, #0x08] @Get enabled? ++ cmp r1, #1 @If not enabled, do not change ++ bne watchdog_finished ++ mov r1, #0 ++ str r1, [r0, #0x08] @Disable the watchdog ++ mov r1, #1 ++ str r1, [r0, #0x04] @Pet the watchdog ++ mov r1, #30 @30 seconds timeout ++ lsl r1, r1, #15 @converted to ticks ++ str r1, [r0, #0x10] @Set the bark timeout ++ str r1, [r0, #0x14] @Set the bite timeout ++ mov r1, #1 ++ str r1, [r0, #0x08] @Enable the watchdog ++watchdog_finished: ++#endif /* CONFIG_ARCH_IPQ40XX */ ++ + /* + * The C runtime environment should now be setup sufficiently. + * Set up some pointers, and start decompressing. diff --git a/feeds/ipq40xx/ipq40xx/patches-5.4/400-mmc-sdhci-sdhci-msm-use-sdhci_set_clock-instead-of-s.patch b/feeds/ipq40xx/ipq40xx/patches-5.4/400-mmc-sdhci-sdhci-msm-use-sdhci_set_clock-instead-of-s.patch new file mode 100644 index 000000000..eaf7ae30b --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/patches-5.4/400-mmc-sdhci-sdhci-msm-use-sdhci_set_clock-instead-of-s.patch @@ -0,0 +1,25 @@ +From 0e28623a11f3916c1fe5b7e789c7ab8ca932a929 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Wed, 22 Jan 2020 13:02:13 +0100 +Subject: [PATCH] mmc: sdhci: sdhci-msm: use sdhci_set_clock instead of + sdhci_msm_set_clock + +When using sdhci_msm_set_clock clock setting will fail, so lets +use the generic sdhci_set_clock. + +Signed-off-by: Robert Marko +--- + drivers/mmc/host/sdhci-msm.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/mmc/host/sdhci-msm.c ++++ b/drivers/mmc/host/sdhci-msm.c +@@ -1763,7 +1763,7 @@ MODULE_DEVICE_TABLE(of, sdhci_msm_dt_mat + + static const struct sdhci_ops sdhci_msm_ops = { + .reset = sdhci_reset, +- .set_clock = sdhci_msm_set_clock, ++ .set_clock = sdhci_set_clock, + .get_min_clock = sdhci_msm_get_min_clock, + .get_max_clock = sdhci_msm_get_max_clock, + .set_bus_width = sdhci_set_bus_width, diff --git a/feeds/ipq40xx/ipq40xx/patches-5.4/702-dts-ipq4019-add-PHY-switch-nodes.patch b/feeds/ipq40xx/ipq40xx/patches-5.4/702-dts-ipq4019-add-PHY-switch-nodes.patch new file mode 100644 index 000000000..cfbf7bd41 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/patches-5.4/702-dts-ipq4019-add-PHY-switch-nodes.patch @@ -0,0 +1,46 @@ +From 9deeec35dd3b628b95624e41d4e04acf728991ba Mon Sep 17 00:00:00 2001 +From: Christian Lamparter +Date: Sun, 20 Nov 2016 02:20:54 +0100 +Subject: [PATCH] dts: ipq4019: add PHY/switch nodes + +This patch adds both the "qcom,ess-switch" and "qcom,ess-psgmii" +nodes which are needed for the ar40xx.c driver to initialize the +switch. + +Signed-off-by: Christian Lamparter +--- + arch/arm/boot/dts/qcom-ipq4019.dtsi | 23 +++++++++++++++++++++++ + 1 file changed, 23 insertions(+) + +--- a/arch/arm/boot/dts/qcom-ipq4019.dtsi ++++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi +@@ -616,6 +616,29 @@ + }; + }; + ++ ess-switch@c000000 { ++ compatible = "qcom,ess-switch"; ++ reg = <0xc000000 0x80000>; ++ switch_access_mode = "local bus"; ++ resets = <&gcc ESS_RESET>; ++ reset-names = "ess_rst"; ++ clocks = <&gcc GCC_ESS_CLK>; ++ clock-names = "ess_clk"; ++ switch_cpu_bmp = <0x1>; ++ switch_lan_bmp = <0x1e>; ++ switch_wan_bmp = <0x20>; ++ switch_mac_mode = <0>; /* PORT_WRAPPER_PSGMII */ ++ switch_initvlas = <0x7c 0x54>; ++ status = "disabled"; ++ }; ++ ++ ess-psgmii@98000 { ++ compatible = "qcom,ess-psgmii"; ++ reg = <0x98000 0x800>; ++ psgmii_access_mode = "local bus"; ++ status = "disabled"; ++ }; ++ + usb3_ss_phy: ssphy@9a000 { + compatible = "qcom,usb-ss-ipq4019-phy"; + #phy-cells = <0>; diff --git a/feeds/ipq40xx/ipq40xx/patches-5.4/703-net-IPQ4019-needs-rfs-vlan_tag-callbacks-in.patch b/feeds/ipq40xx/ipq40xx/patches-5.4/703-net-IPQ4019-needs-rfs-vlan_tag-callbacks-in.patch new file mode 100644 index 000000000..167673bd1 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/patches-5.4/703-net-IPQ4019-needs-rfs-vlan_tag-callbacks-in.patch @@ -0,0 +1,53 @@ +From 7c129254adb1093d10a62ed7bf7b956fcc6ffe34 Mon Sep 17 00:00:00 2001 +From: Rakesh Nair +Date: Wed, 20 Jul 2016 15:02:01 +0530 +Subject: [PATCH] net: IPQ4019 needs rfs/vlan_tag callbacks in + netdev_ops + +Add callback support to get default vlan tag and register +receive flow steering filter. + +Used by IPQ4019 ess-edma driver. + +BUG=chrome-os-partner:33096 +TEST=none + +Change-Id: I266070e4a0fbe4a0d9966fe79a71e50ec4f26c75 +Signed-off-by: Rakesh Nair +Reviewed-on: https://chromium-review.googlesource.com/362203 +Commit-Ready: Grant Grundler +Tested-by: Grant Grundler +Reviewed-by: Grant Grundler +--- + include/linux/netdevice.h | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +--- a/include/linux/netdevice.h ++++ b/include/linux/netdevice.h +@@ -776,6 +776,16 @@ struct xps_map { + #define XPS_MIN_MAP_ALLOC ((L1_CACHE_ALIGN(offsetof(struct xps_map, queues[1])) \ + - sizeof(struct xps_map)) / sizeof(u16)) + ++#ifdef CONFIG_RFS_ACCEL ++typedef int (*set_rfs_filter_callback_t)(struct net_device *dev, ++ __be32 src, ++ __be32 dst, ++ __be16 sport, ++ __be16 dport, ++ u8 proto, ++ u16 rxq_index, ++ u32 action); ++#endif + /* + * This structure holds all XPS maps for device. Maps are indexed by CPU. + */ +@@ -1379,6 +1389,9 @@ struct net_device_ops { + const struct sk_buff *skb, + u16 rxq_index, + u32 flow_id); ++ int (*ndo_register_rfs_filter)(struct net_device *dev, ++ set_rfs_filter_callback_t set_filter); ++ int (*ndo_get_default_vlan_tag)(struct net_device *net); + #endif + int (*ndo_add_slave)(struct net_device *dev, + struct net_device *slave_dev, diff --git a/feeds/ipq40xx/ipq40xx/patches-5.4/705-net-add-qualcomm-ar40xx-phy.patch b/feeds/ipq40xx/ipq40xx/patches-5.4/705-net-add-qualcomm-ar40xx-phy.patch new file mode 100644 index 000000000..9adddcabc --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/patches-5.4/705-net-add-qualcomm-ar40xx-phy.patch @@ -0,0 +1,26 @@ +--- a/drivers/net/phy/Kconfig ++++ b/drivers/net/phy/Kconfig +@@ -584,6 +584,13 @@ config XILINX_GMII2RGMII + the Reduced Gigabit Media Independent Interface(RGMII) between + Ethernet physical media devices and the Gigabit Ethernet controller. + ++config AR40XX_PHY ++ tristate "Driver for Qualcomm Atheros IPQ40XX switches" ++ depends on HAS_IOMEM && OF && OF_MDIO ++ select SWCONFIG ++ help ++ This is the driver for Qualcomm Atheros IPQ40XX ESS switches. ++ + endif # PHYLIB + + config MICREL_KS8995MA +--- a/drivers/net/phy/Makefile ++++ b/drivers/net/phy/Makefile +@@ -69,6 +69,7 @@ ifdef CONFIG_HWMON + aquantia-objs += aquantia_hwmon.o + endif + obj-$(CONFIG_AQUANTIA_PHY) += aquantia.o ++obj-$(CONFIG_AR40XX_PHY) += ar40xx.o + obj-$(CONFIG_AX88796B_PHY) += ax88796b.o + obj-$(CONFIG_AT803X_PHY) += at803x.o + obj-$(CONFIG_BCM63XX_PHY) += bcm63xx.o diff --git a/feeds/ipq40xx/ipq40xx/patches-5.4/706-dt-bindings-net-add-QCA807x-PHY.patch b/feeds/ipq40xx/ipq40xx/patches-5.4/706-dt-bindings-net-add-QCA807x-PHY.patch new file mode 100644 index 000000000..dfb8d692a --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/patches-5.4/706-dt-bindings-net-add-QCA807x-PHY.patch @@ -0,0 +1,61 @@ +From c66863c1ba8995b61e6d727d78a241c734f5bb57 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Thu, 1 Oct 2020 15:05:35 +0200 +Subject: [PATCH] dt-bindings: net: add QCA807x PHY + +Add DT bindings for Qualcomm QCA807x PHY series. + +Signed-off-by: Robert Marko +--- + include/dt-bindings/net/qcom-qca807x.h | 45 ++++++++++++++++++++++++++ + 1 file changed, 45 insertions(+) + create mode 100644 include/dt-bindings/net/qcom-qca807x.h + +--- /dev/null ++++ b/include/dt-bindings/net/qcom-qca807x.h +@@ -0,0 +1,45 @@ ++/* SPDX-License-Identifier: GPL-2.0-or-later */ ++/* ++ * Device Tree constants for the Qualcomm QCA807X PHYs ++ */ ++ ++#ifndef _DT_BINDINGS_QCOM_QCA807X_H ++#define _DT_BINDINGS_QCOM_QCA807X_H ++ ++#define PSGMII_QSGMII_TX_DRIVER_140MV 0 ++#define PSGMII_QSGMII_TX_DRIVER_160MV 1 ++#define PSGMII_QSGMII_TX_DRIVER_180MV 2 ++#define PSGMII_QSGMII_TX_DRIVER_200MV 3 ++#define PSGMII_QSGMII_TX_DRIVER_220MV 4 ++#define PSGMII_QSGMII_TX_DRIVER_240MV 5 ++#define PSGMII_QSGMII_TX_DRIVER_260MV 6 ++#define PSGMII_QSGMII_TX_DRIVER_280MV 7 ++#define PSGMII_QSGMII_TX_DRIVER_300MV 8 ++#define PSGMII_QSGMII_TX_DRIVER_320MV 9 ++#define PSGMII_QSGMII_TX_DRIVER_400MV 10 ++#define PSGMII_QSGMII_TX_DRIVER_500MV 11 ++/* Default value */ ++#define PSGMII_QSGMII_TX_DRIVER_600MV 12 ++ ++/* Full amplitude, full bias current */ ++#define QCA807X_CONTROL_DAC_FULL_VOLT_BIAS 0 ++/* Amplitude follow DSP (amplitude is adjusted based on cable length), half bias current */ ++#define QCA807X_CONTROL_DAC_DSP_VOLT_HALF_BIAS 1 ++/* Full amplitude, bias current follow DSP (bias current is adjusted based on cable length) */ ++#define QCA807X_CONTROL_DAC_FULL_VOLT_DSP_BIAS 2 ++/* Both amplitude and bias current follow DSP */ ++#define QCA807X_CONTROL_DAC_DSP_VOLT_BIAS 3 ++/* Full amplitude, half bias current */ ++#define QCA807X_CONTROL_DAC_FULL_VOLT_HALF_BIAS 4 ++/* Amplitude follow DSP setting; 1/4 bias current when cable<10m, ++ * otherwise half bias current ++ */ ++#define QCA807X_CONTROL_DAC_DSP_VOLT_QUARTER_BIAS 5 ++/* Full amplitude; same bias current setting with “010” and “011”, ++ * but half more bias is reduced when cable <10m ++ */ ++#define QCA807X_CONTROL_DAC_FULL_VOLT_HALF_BIAS_SHORT 6 ++/* Amplitude follow DSP; same bias current setting with “110”, default value */ ++#define QCA807X_CONTROL_DAC_DSP_VOLT_HALF_BIAS_SHORT 7 ++ ++#endif diff --git a/feeds/ipq40xx/ipq40xx/patches-5.4/707-net-phy-Add-Qualcom-QCA807x-driver.patch b/feeds/ipq40xx/ipq40xx/patches-5.4/707-net-phy-Add-Qualcom-QCA807x-driver.patch new file mode 100644 index 000000000..b71b28d94 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/patches-5.4/707-net-phy-Add-Qualcom-QCA807x-driver.patch @@ -0,0 +1,50 @@ +From f825cdc8bfde7616a14e2163f16303a8973031d2 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Wed, 7 Oct 2020 17:38:48 +0200 +Subject: [PATCH] net: phy: Add Qualcom QCA807x driver + +This adds driver for the Qualcomm QCA8072 and QCA8075 PHY-s. + +They are 2 or 5 port IEEE 802.3 clause 22 compliant 10BASE-Te, 100BASE-TX and 1000BASE-T PHY-s. + +They feature 2 SerDes, one for PSGMII or QSGMII connection with MAC, while second one is SGMII for connection to MAC or fiber. + +Both models have a combo port that supports 1000BASE-X and 100BASE-FX fiber. + +Each PHY inside of QCA807x series has 4 digitally controlled output only pins that natively drive LED-s. +But some vendors used these to driver generic LED-s controlled by userspace, +so lets enable registering each PHY as GPIO controller and add driver for it. + +These are commonly used in Qualcomm IPQ40xx, IPQ60xx and IPQ807x boards. + +Signed-off-by: Robert Marko +--- + drivers/net/phy/Kconfig | 6 ++++++ + drivers/net/phy/Makefile | 1 + + 2 files changed, 7 insertions(+) + +--- a/drivers/net/phy/Kconfig ++++ b/drivers/net/phy/Kconfig +@@ -537,6 +537,12 @@ config NXP_TJA11XX_PHY + ---help--- + Currently supports the NXP TJA1100 and TJA1101 PHY. + ++config QCA807X_PHY ++ tristate "Qualcomm QCA807X PHYs" ++ depends on OF_MDIO ++ help ++ Currently supports the QCA8072 and QCA8075 models. ++ + config QSEMI_PHY + tristate "Quality Semiconductor PHYs" + ---help--- +--- a/drivers/net/phy/Makefile ++++ b/drivers/net/phy/Makefile +@@ -103,6 +103,7 @@ obj-$(CONFIG_MICROSEMI_PHY) += mscc.o + obj-$(CONFIG_NATIONAL_PHY) += national.o + obj-$(CONFIG_NXP_TJA11XX_PHY) += nxp-tja11xx.o + obj-$(CONFIG_QSEMI_PHY) += qsemi.o ++obj-$(CONFIG_QCA807X_PHY) += qca807x.o + obj-$(CONFIG_REALTEK_PHY) += realtek.o + obj-$(CONFIG_RENESAS_PHY) += uPD60620.o + obj-$(CONFIG_ROCKCHIP_PHY) += rockchip.o diff --git a/feeds/ipq40xx/ipq40xx/patches-5.4/708-arm-dts-ipq4019-QCA807x-properties.patch b/feeds/ipq40xx/ipq40xx/patches-5.4/708-arm-dts-ipq4019-QCA807x-properties.patch new file mode 100644 index 000000000..4b04a3ce9 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/patches-5.4/708-arm-dts-ipq4019-QCA807x-properties.patch @@ -0,0 +1,62 @@ +From e0fa88eaa3c176b71e563da68949ac2ab45aaa61 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Fri, 2 Oct 2020 10:43:26 +0200 +Subject: [PATCH] arm: dts: ipq4019: QCA807x properties + +This adds necessary DT properties for QCA807x PHY-s to IPQ4019 DTSI. + +Signed-off-by: Robert Marko +--- + arch/arm/boot/dts/qcom-ipq4019.dtsi | 18 ++++++++++++++++++ + 1 file changed, 18 insertions(+) + +--- a/arch/arm/boot/dts/qcom-ipq4019.dtsi ++++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi +@@ -8,6 +8,7 @@ + #include + #include + #include ++#include + + / { + #address-cells = <1>; +@@ -597,22 +598,39 @@ + + ethphy0: ethernet-phy@0 { + reg = <0>; ++ ++ qcom,control-dac = ; + }; + + ethphy1: ethernet-phy@1 { + reg = <1>; ++ ++ qcom,control-dac = ; + }; + + ethphy2: ethernet-phy@2 { + reg = <2>; ++ ++ qcom,control-dac = ; + }; + + ethphy3: ethernet-phy@3 { + reg = <3>; ++ ++ qcom,control-dac = ; + }; + + ethphy4: ethernet-phy@4 { + reg = <4>; ++ ++ qcom,control-dac = ; ++ }; ++ ++ psgmiiphy: psgmii-phy@5 { ++ reg = <5>; ++ ++ qcom,tx-driver-strength = ; ++ qcom,psgmii-az; + }; + }; + diff --git a/feeds/ipq40xx/ipq40xx/patches-5.4/710-net-add-qualcomm-essedma-ethernet-driver.patch b/feeds/ipq40xx/ipq40xx/patches-5.4/710-net-add-qualcomm-essedma-ethernet-driver.patch new file mode 100644 index 000000000..793ce7214 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/patches-5.4/710-net-add-qualcomm-essedma-ethernet-driver.patch @@ -0,0 +1,37 @@ +From 12e9319da1adacac92930c899c99f0e1970cac11 Mon Sep 17 00:00:00 2001 +From: Christian Lamparter +Date: Thu, 19 Jan 2017 02:01:31 +0100 +Subject: [PATCH 33/38] NET: add qualcomm essedma ethernet driver + +Signed-off-by: Christian Lamparter +--- + drivers/net/ethernet/qualcomm/Kconfig | 9 +++++++++ + drivers/net/ethernet/qualcomm/Makefile | 1 + + 2 files changed, 10 insertions(+) + +--- a/drivers/net/ethernet/qualcomm/Kconfig ++++ b/drivers/net/ethernet/qualcomm/Kconfig +@@ -62,4 +62,14 @@ config QCOM_EMAC + + source "drivers/net/ethernet/qualcomm/rmnet/Kconfig" + ++config ESSEDMA ++ tristate "Qualcomm Atheros ESS Edma support" ++ depends on OF_MDIO ++ help ++ This driver supports ethernet edma adapter. ++ Say Y to build this driver. ++ ++ To compile this driver as a module, choose M here. The module ++ will be called essedma.ko. ++ + endif # NET_VENDOR_QUALCOMM +--- a/drivers/net/ethernet/qualcomm/Makefile ++++ b/drivers/net/ethernet/qualcomm/Makefile +@@ -10,5 +10,6 @@ obj-$(CONFIG_QCA7000_UART) += qcauart.o + qcauart-objs := qca_uart.o + + obj-y += emac/ ++obj-$(CONFIG_ESSEDMA) += essedma/ + + obj-$(CONFIG_RMNET) += rmnet/ diff --git a/feeds/ipq40xx/ipq40xx/patches-5.4/711-dts-ipq4019-add-ethernet-essedma-node.patch b/feeds/ipq40xx/ipq40xx/patches-5.4/711-dts-ipq4019-add-ethernet-essedma-node.patch new file mode 100644 index 000000000..7b2ddfe00 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/patches-5.4/711-dts-ipq4019-add-ethernet-essedma-node.patch @@ -0,0 +1,92 @@ +From c611d3780fa101662a822d10acf8feb04ca97409 Mon Sep 17 00:00:00 2001 +From: Christian Lamparter +Date: Sun, 20 Nov 2016 01:01:10 +0100 +Subject: [PATCH] dts: ipq4019: add ethernet essedma node + +This patch adds the device-tree node for the ethernet +interfaces. + +Note: The driver isn't anywhere close to be upstream, +so the info might change. + +Signed-off-by: Christian Lamparter +--- + arch/arm/boot/dts/qcom-ipq4019.dtsi | 60 +++++++++++++++++++++++++++++++++++++ + 1 file changed, 60 insertions(+) + +--- a/arch/arm/boot/dts/qcom-ipq4019.dtsi ++++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi +@@ -39,6 +39,8 @@ + spi1 = &blsp1_spi2; + i2c0 = &blsp1_i2c3; + i2c1 = &blsp1_i2c4; ++ ethernet0 = &gmac0; ++ ethernet1 = &gmac1; + }; + + cpus { +@@ -657,6 +659,64 @@ + status = "disabled"; + }; + ++ edma@c080000 { ++ compatible = "qcom,ess-edma"; ++ reg = <0xc080000 0x8000>; ++ qcom,page-mode = <0>; ++ qcom,rx_head_buf_size = <1540>; ++ qcom,mdio_supported; ++ qcom,poll_required = <1>; ++ qcom,num_gmac = <2>; ++ interrupts = <0 65 IRQ_TYPE_EDGE_RISING ++ 0 66 IRQ_TYPE_EDGE_RISING ++ 0 67 IRQ_TYPE_EDGE_RISING ++ 0 68 IRQ_TYPE_EDGE_RISING ++ 0 69 IRQ_TYPE_EDGE_RISING ++ 0 70 IRQ_TYPE_EDGE_RISING ++ 0 71 IRQ_TYPE_EDGE_RISING ++ 0 72 IRQ_TYPE_EDGE_RISING ++ 0 73 IRQ_TYPE_EDGE_RISING ++ 0 74 IRQ_TYPE_EDGE_RISING ++ 0 75 IRQ_TYPE_EDGE_RISING ++ 0 76 IRQ_TYPE_EDGE_RISING ++ 0 77 IRQ_TYPE_EDGE_RISING ++ 0 78 IRQ_TYPE_EDGE_RISING ++ 0 79 IRQ_TYPE_EDGE_RISING ++ 0 80 IRQ_TYPE_EDGE_RISING ++ 0 240 IRQ_TYPE_EDGE_RISING ++ 0 241 IRQ_TYPE_EDGE_RISING ++ 0 242 IRQ_TYPE_EDGE_RISING ++ 0 243 IRQ_TYPE_EDGE_RISING ++ 0 244 IRQ_TYPE_EDGE_RISING ++ 0 245 IRQ_TYPE_EDGE_RISING ++ 0 246 IRQ_TYPE_EDGE_RISING ++ 0 247 IRQ_TYPE_EDGE_RISING ++ 0 248 IRQ_TYPE_EDGE_RISING ++ 0 249 IRQ_TYPE_EDGE_RISING ++ 0 250 IRQ_TYPE_EDGE_RISING ++ 0 251 IRQ_TYPE_EDGE_RISING ++ 0 252 IRQ_TYPE_EDGE_RISING ++ 0 253 IRQ_TYPE_EDGE_RISING ++ 0 254 IRQ_TYPE_EDGE_RISING ++ 0 255 IRQ_TYPE_EDGE_RISING>; ++ ++ status = "disabled"; ++ ++ gmac0: gmac0 { ++ local-mac-address = [00 00 00 00 00 00]; ++ vlan_tag = <1 0x1f>; ++ }; ++ ++ gmac1: gmac1 { ++ local-mac-address = [00 00 00 00 00 00]; ++ qcom,phy_mdio_addr = <4>; ++ qcom,poll_required = <1>; ++ qcom,forced_speed = <1000>; ++ qcom,forced_duplex = <1>; ++ vlan_tag = <2 0x20>; ++ }; ++ }; ++ + usb3_ss_phy: ssphy@9a000 { + compatible = "qcom,usb-ss-ipq4019-phy"; + #phy-cells = <0>; diff --git a/feeds/ipq40xx/ipq40xx/patches-5.4/850-soc-add-qualcomm-syscon.patch b/feeds/ipq40xx/ipq40xx/patches-5.4/850-soc-add-qualcomm-syscon.patch new file mode 100644 index 000000000..17e9047df --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/patches-5.4/850-soc-add-qualcomm-syscon.patch @@ -0,0 +1,180 @@ +From: Christian Lamparter +Subject: SoC: add qualcomm syscon +--- a/drivers/soc/qcom/Makefile ++++ b/drivers/soc/qcom/Makefile +@@ -20,6 +20,7 @@ obj-$(CONFIG_QCOM_SMP2P) += smp2p.o + obj-$(CONFIG_QCOM_SMSM) += smsm.o + obj-$(CONFIG_QCOM_SOCINFO) += socinfo.o + obj-$(CONFIG_QCOM_WCNSS_CTRL) += wcnss_ctrl.o ++obj-$(CONFIG_QCOM_TCSR) += qcom_tcsr.o + obj-$(CONFIG_QCOM_APR) += apr.o + obj-$(CONFIG_QCOM_LLCC) += llcc-slice.o + obj-$(CONFIG_QCOM_SDM845_LLCC) += llcc-sdm845.o +--- a/drivers/soc/qcom/Kconfig ++++ b/drivers/soc/qcom/Kconfig +@@ -183,6 +183,13 @@ config QCOM_SOCINFO + Say yes here to support the Qualcomm socinfo driver, providing + information about the SoC to user space. + ++config QCOM_TCSR ++ tristate "QCOM Top Control and Status Registers" ++ depends on ARCH_QCOM ++ help ++ Say y here to enable TCSR support. The TCSR provides control ++ functions for various peripherals. ++ + config QCOM_WCNSS_CTRL + tristate "Qualcomm WCNSS control driver" + depends on ARCH_QCOM || COMPILE_TEST +--- /dev/null ++++ b/drivers/soc/qcom/qcom_tcsr.c +@@ -0,0 +1,98 @@ ++/* ++ * Copyright (c) 2014, The Linux foundation. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License rev 2 and ++ * only rev 2 as published by the free Software foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or fITNESS fOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define TCSR_USB_PORT_SEL 0xb0 ++#define TCSR_USB_HSPHY_CONFIG 0xC ++ ++#define TCSR_ESS_INTERFACE_SEL_OFFSET 0x0 ++#define TCSR_ESS_INTERFACE_SEL_MASK 0xf ++ ++#define TCSR_WIFI0_GLB_CFG_OFFSET 0x0 ++#define TCSR_WIFI1_GLB_CFG_OFFSET 0x4 ++#define TCSR_PNOC_SNOC_MEMTYPE_M0_M2 0x4 ++ ++static int tcsr_probe(struct platform_device *pdev) ++{ ++ struct resource *res; ++ const struct device_node *node = pdev->dev.of_node; ++ void __iomem *base; ++ u32 val; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ base = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(base)) ++ return PTR_ERR(base); ++ ++ if (!of_property_read_u32(node, "qcom,usb-ctrl-select", &val)) { ++ dev_err(&pdev->dev, "setting usb port select = %d\n", val); ++ writel(val, base + TCSR_USB_PORT_SEL); ++ } ++ ++ if (!of_property_read_u32(node, "qcom,usb-hsphy-mode-select", &val)) { ++ dev_info(&pdev->dev, "setting usb hs phy mode select = %x\n", val); ++ writel(val, base + TCSR_USB_HSPHY_CONFIG); ++ } ++ ++ if (!of_property_read_u32(node, "qcom,ess-interface-select", &val)) { ++ u32 tmp = 0; ++ dev_info(&pdev->dev, "setting ess interface select = %x\n", val); ++ tmp = readl(base + TCSR_ESS_INTERFACE_SEL_OFFSET); ++ tmp = tmp & (~TCSR_ESS_INTERFACE_SEL_MASK); ++ tmp = tmp | (val&TCSR_ESS_INTERFACE_SEL_MASK); ++ writel(tmp, base + TCSR_ESS_INTERFACE_SEL_OFFSET); ++ } ++ ++ if (!of_property_read_u32(node, "qcom,wifi_glb_cfg", &val)) { ++ dev_info(&pdev->dev, "setting wifi_glb_cfg = %x\n", val); ++ writel(val, base + TCSR_WIFI0_GLB_CFG_OFFSET); ++ writel(val, base + TCSR_WIFI1_GLB_CFG_OFFSET); ++ } ++ ++ if (!of_property_read_u32(node, "qcom,wifi_noc_memtype_m0_m2", &val)) { ++ dev_info(&pdev->dev, ++ "setting wifi_noc_memtype_m0_m2 = %x\n", val); ++ writel(val, base + TCSR_PNOC_SNOC_MEMTYPE_M0_M2); ++ } ++ ++ return 0; ++} ++ ++static const struct of_device_id tcsr_dt_match[] = { ++ { .compatible = "qcom,tcsr", }, ++ { }, ++}; ++ ++MODULE_DEVICE_TABLE(of, tcsr_dt_match); ++ ++static struct platform_driver tcsr_driver = { ++ .driver = { ++ .name = "tcsr", ++ .owner = THIS_MODULE, ++ .of_match_table = tcsr_dt_match, ++ }, ++ .probe = tcsr_probe, ++}; ++ ++module_platform_driver(tcsr_driver); ++ ++MODULE_AUTHOR("Andy Gross "); ++MODULE_DESCRIPTION("QCOM TCSR driver"); ++MODULE_LICENSE("GPL v2"); +--- /dev/null ++++ b/include/dt-bindings/soc/qcom,tcsr.h +@@ -0,0 +1,48 @@ ++/* Copyright (c) 2014, The Linux Foundation. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 and ++ * only version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++#ifndef __DT_BINDINGS_QCOM_TCSR_H ++#define __DT_BINDINGS_QCOM_TCSR_H ++ ++#define TCSR_USB_SELECT_USB3_P0 0x1 ++#define TCSR_USB_SELECT_USB3_P1 0x2 ++#define TCSR_USB_SELECT_USB3_DUAL 0x3 ++ ++/* IPQ40xx HS PHY Mode Select */ ++#define TCSR_USB_HSPHY_HOST_MODE 0x00E700E7 ++#define TCSR_USB_HSPHY_DEVICE_MODE 0x00C700E7 ++ ++/* IPQ40xx ess interface mode select */ ++#define TCSR_ESS_PSGMII 0 ++#define TCSR_ESS_PSGMII_RGMII5 1 ++#define TCSR_ESS_PSGMII_RMII0 2 ++#define TCSR_ESS_PSGMII_RMII1 4 ++#define TCSR_ESS_PSGMII_RMII0_RMII1 6 ++#define TCSR_ESS_PSGMII_RGMII4 9 ++ ++/* ++ * IPQ40xx WiFi Global Config ++ * Bit 30:AXID_EN ++ * Enable AXI master bus Axid translating to confirm all txn submitted by order ++ * Bit 24: Use locally generated socslv_wxi_bvalid ++ * 1: use locally generate socslv_wxi_bvalid for performance. ++ * 0: use SNOC socslv_wxi_bvalid. ++ */ ++#define TCSR_WIFI_GLB_CFG 0x41000000 ++ ++/* IPQ40xx MEM_TYPE_SEL_M0_M2 Select Bit 26:24 - 2 NORMAL */ ++#define TCSR_WIFI_NOC_MEMTYPE_M0_M2 0x02222222 ++ ++/* TCSR A/B REG */ ++#define IPQ806X_TCSR_REG_A_ADM_CRCI_MUX_SEL 0 ++#define IPQ806X_TCSR_REG_B_ADM_CRCI_MUX_SEL 1 ++ ++#endif diff --git a/feeds/ipq40xx/ipq40xx/patches-5.4/900-dts-ipq4019-ap-dk01.1.patch b/feeds/ipq40xx/ipq40xx/patches-5.4/900-dts-ipq4019-ap-dk01.1.patch new file mode 100644 index 000000000..5a245eb43 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/patches-5.4/900-dts-ipq4019-ap-dk01.1.patch @@ -0,0 +1,176 @@ +--- a/arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1.dtsi ++++ b/arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1.dtsi +@@ -15,6 +15,7 @@ + */ + + #include "qcom-ipq4019.dtsi" ++#include + + / { + model = "Qualcomm Technologies, Inc. IPQ4019/AP-DK01.1"; +@@ -29,6 +30,32 @@ + }; + + soc { ++ tcsr@194b000 { ++ /* select hostmode */ ++ compatible = "qcom,tcsr"; ++ reg = <0x194b000 0x100>; ++ qcom,usb-hsphy-mode-select = ; ++ status = "okay"; ++ }; ++ ++ ess_tcsr@1953000 { ++ compatible = "qcom,tcsr"; ++ reg = <0x1953000 0x1000>; ++ qcom,ess-interface-select = ; ++ }; ++ ++ tcsr@1949000 { ++ compatible = "qcom,tcsr"; ++ reg = <0x1949000 0x100>; ++ qcom,wifi_glb_cfg = ; ++ }; ++ ++ tcsr@1957000 { ++ compatible = "qcom,tcsr"; ++ reg = <0x1957000 0x100>; ++ qcom,wifi_noc_memtype_m0_m2 = ; ++ }; ++ + rng@22000 { + status = "ok"; + }; +@@ -74,14 +101,6 @@ + pinctrl-names = "default"; + status = "ok"; + cs-gpios = <&tlmm 54 0>; +- +- mx25l25635e@0 { +- #address-cells = <1>; +- #size-cells = <1>; +- reg = <0>; +- compatible = "mx25l25635e"; +- spi-max-frequency = <24000000>; +- }; + }; + + serial@78af000 { +@@ -109,5 +128,41 @@ + wifi@a800000 { + status = "ok"; + }; ++ ++ mdio@90000 { ++ status = "okay"; ++ }; ++ ++ ess-switch@c000000 { ++ status = "okay"; ++ }; ++ ++ ess-psgmii@98000 { ++ status = "okay"; ++ }; ++ ++ edma@c080000 { ++ status = "okay"; ++ }; ++ ++ usb3_ss_phy: ssphy@9a000 { ++ status = "okay"; ++ }; ++ ++ usb3_hs_phy: hsphy@a6000 { ++ status = "okay"; ++ }; ++ ++ usb3: usb3@8af8800 { ++ status = "okay"; ++ }; ++ ++ usb2_hs_phy: hsphy@a8000 { ++ status = "okay"; ++ }; ++ ++ usb2: usb2@60f8800 { ++ status = "okay"; ++ }; + }; + }; +--- a/arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1-c1.dts ++++ b/arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1-c1.dts +@@ -18,5 +18,73 @@ + + / { + model = "Qualcomm Technologies, Inc. IPQ40xx/AP-DK01.1-C1"; ++ compatible = "qcom,ap-dk01.1-c1", "qcom,ap-dk01.2-c1"; + ++ memory { ++ device_type = "memory"; ++ reg = <0x80000000 0x10000000>; ++ }; ++}; ++ ++&blsp1_spi1 { ++ mx25l25635f@0 { ++ compatible = "mx25l25635f", "jedec,spi-nor"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ reg = <0>; ++ spi-max-frequency = <24000000>; ++ ++ SBL1@0 { ++ label = "SBL1"; ++ reg = <0x0 0x40000>; ++ read-only; ++ }; ++ MIBIB@40000 { ++ label = "MIBIB"; ++ reg = <0x40000 0x20000>; ++ read-only; ++ }; ++ QSEE@60000 { ++ label = "QSEE"; ++ reg = <0x60000 0x60000>; ++ read-only; ++ }; ++ CDT@c0000 { ++ label = "CDT"; ++ reg = <0xc0000 0x10000>; ++ read-only; ++ }; ++ DDRPARAMS@d0000 { ++ label = "DDRPARAMS"; ++ reg = <0xd0000 0x10000>; ++ read-only; ++ }; ++ APPSBLENV@e0000 { ++ label = "APPSBLENV"; ++ reg = <0xe0000 0x10000>; ++ read-only; ++ }; ++ APPSBL@f0000 { ++ label = "APPSBL"; ++ reg = <0xf0000 0x80000>; ++ read-only; ++ }; ++ ART@170000 { ++ label = "ART"; ++ reg = <0x170000 0x10000>; ++ read-only; ++ }; ++ kernel@180000 { ++ label = "kernel"; ++ reg = <0x180000 0x400000>; ++ }; ++ rootfs@580000 { ++ label = "rootfs"; ++ reg = <0x580000 0x1600000>; ++ }; ++ firmware@180000 { ++ label = "firmware"; ++ reg = <0x180000 0x1a00000>; ++ }; ++ }; + }; diff --git a/feeds/ipq40xx/ipq40xx/patches-5.4/901-arm-boot-add-dts-files.patch b/feeds/ipq40xx/ipq40xx/patches-5.4/901-arm-boot-add-dts-files.patch new file mode 100644 index 000000000..c4ecf6231 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/patches-5.4/901-arm-boot-add-dts-files.patch @@ -0,0 +1,77 @@ +From a10fab12a927e60b7141a602e740d70cb4d09e4a Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Thu, 9 Mar 2017 11:03:18 +0100 +Subject: [PATCH] arm: boot: add dts files + +Signed-off-by: John Crispin +--- + arch/arm/boot/dts/Makefile | 23 +++++++++++++++++++++++ + 1 file changed, 23 insertions(+) + +--- a/arch/arm/boot/dts/Makefile ++++ b/arch/arm/boot/dts/Makefile +@@ -837,11 +837,64 @@ dtb-$(CONFIG_ARCH_QCOM) += \ + qcom-apq8074-dragonboard.dtb \ + qcom-apq8084-ifc6540.dtb \ + qcom-apq8084-mtp.dtb \ ++ qcom-ipq4018-a42.dtb \ ++ qcom-ipq4018-ap120c-ac.dtb \ ++ qcom-ipq4018-dap-2610.dtb \ ++ qcom-ipq4018-cs-w3-wd1200g-eup.dtb \ ++ qcom-ipq4018-magic-2-wifi-next.dtb \ ++ qcom-ipq4018-ea6350v3.dtb \ ++ qcom-ipq4018-eap1300.dtb \ ++ qcom-ipq4018-ecw5211.dtb \ ++ qcom-ipq4018-spw2ac1200.dtb \ ++ qcom-ipq4018-spw2ac1200-lan-poe.dtb \ ++ qcom-ipq4018-emd1.dtb \ ++ qcom-ipq4018-emr3500.dtb \ ++ qcom-ipq4018-ens620ext.dtb \ ++ qcom-ipq4018-ex6100v2.dtb \ ++ qcom-ipq4018-ex6150v2.dtb \ ++ qcom-ipq4018-fritzbox-4040.dtb \ ++ qcom-ipq4018-gl-ap1300.dtb \ ++ qcom-ipq4018-jalapeno.dtb \ ++ qcom-ipq4018-meshpoint-one.dtb \ ++ qcom-ipq4018-hap-ac2.dtb \ ++ qcom-ipq4018-sxtsq-5-ac.dtb \ ++ qcom-ipq4018-nbg6617.dtb \ ++ qcom-ipq4019-oap100.dtb \ ++ qcom-ipq4018-pa1200.dtb \ ++ qcom-ipq4018-rt-ac58u.dtb \ ++ qcom-ipq4018-wre6606.dtb \ ++ qcom-ipq4018-wrtq-329acn.dtb \ + qcom-ipq4019-ap.dk01.1-c1.dtb \ + qcom-ipq4019-ap.dk04.1-c1.dtb \ + qcom-ipq4019-ap.dk04.1-c3.dtb \ + qcom-ipq4019-ap.dk07.1-c1.dtb \ + qcom-ipq4019-ap.dk07.1-c2.dtb \ ++ qcom-ipq4019-a62.dtb \ ++ qcom-ipq4029-ap-cig-wf610d.dtb \ ++ qcom-ipq4019-cm520-79f.dtb \ ++ qcom-ipq4019-ea8300.dtb \ ++ qcom-ipq4019-eap2200.dtb \ ++ qcom-ipq4019-fritzbox-7530.dtb \ ++ qcom-ipq4019-fritzrepeater-1200.dtb \ ++ qcom-ipq4019-fritzrepeater-3000.dtb \ ++ qcom-ipq4019-map-ac2200.dtb \ ++ qcom-ipq4019-mr8300.dtb \ ++ qcom-ipq4019-e2600ac-c1.dtb \ ++ qcom-ipq4019-e2600ac-c2.dtb \ ++ qcom-ipq4019-habanero-dvk.dtb \ ++ qcom-ipq4019-pa2200.dtb \ ++ qcom-ipq4019-rtl30vw.dtb \ ++ qcom-ipq4019-u4019-32m.dtb \ ++ qcom-ipq4019-wpj419.dtb \ ++ qcom-ipq4019-wtr-m2133hp.dtb \ ++ qcom-ipq4028-wpj428.dtb \ ++ qcom-ipq4029-ap-303.dtb \ ++ qcom-ipq4029-ap-303h.dtb \ ++ qcom-ipq4029-ap-365.dtb \ ++ qcom-ipq4029-gl-b1300.dtb \ ++ qcom-ipq4029-gl-s1300.dtb \ ++ qcom-ipq4029-mr33.dtb \ ++ qcom-ipq40x9-dr40x9.dtb \ + qcom-ipq8064-ap148.dtb \ + qcom-msm8660-surf.dtb \ + qcom-msm8960-cdp.dtb \ diff --git a/feeds/ipq40xx/ipq40xx/patches-5.4/902-dts-ipq4019-ap-dk04.1.patch b/feeds/ipq40xx/ipq40xx/patches-5.4/902-dts-ipq4019-ap-dk04.1.patch new file mode 100644 index 000000000..ca3214484 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/patches-5.4/902-dts-ipq4019-ap-dk04.1.patch @@ -0,0 +1,167 @@ +--- a/arch/arm/boot/dts/qcom-ipq4019-ap.dk04.1.dtsi ++++ b/arch/arm/boot/dts/qcom-ipq4019-ap.dk04.1.dtsi +@@ -17,53 +17,79 @@ + stdout-path = "serial0:115200n8"; + }; + +- memory { +- device_type = "memory"; +- reg = <0x80000000 0x10000000>; /* 256MB */ +- }; +- + soc { ++ rng@22000 { ++ status = "okay"; ++ }; ++ + pinctrl@1000000 { + serial_0_pins: serial0-pinmux { +- pins = "gpio16", "gpio17"; +- function = "blsp_uart0"; +- bias-disable; ++ mux { ++ pins = "gpio16", "gpio17"; ++ function = "blsp_uart0"; ++ bias-disable; ++ }; + }; + + serial_1_pins: serial1-pinmux { +- pins = "gpio8", "gpio9", +- "gpio10", "gpio11"; +- function = "blsp_uart1"; +- bias-disable; ++ mux { ++ pins = "gpio8", "gpio9"; ++ function = "blsp_uart1"; ++ bias-disable; ++ }; + }; + + spi_0_pins: spi-0-pinmux { + pinmux { + function = "blsp_spi0"; + pins = "gpio13", "gpio14", "gpio15"; +- bias-disable; + }; + pinmux_cs { + function = "gpio"; + pins = "gpio12"; ++ }; ++ pinconf { ++ pins = "gpio13", "gpio14", "gpio15"; ++ drive-strength = <12>; ++ bias-disable; ++ }; ++ pinconf_cs { ++ pins = "gpio12"; ++ drive-strength = <2>; + bias-disable; + output-high; + }; + }; + + i2c_0_pins: i2c-0-pinmux { +- pins = "gpio20", "gpio21"; +- function = "blsp_i2c0"; +- bias-disable; ++ pinmux { ++ function = "blsp_i2c0"; ++ pins = "gpio10", "gpio11"; ++ }; ++ pinconf { ++ pins = "gpio10", "gpio11"; ++ drive-strength = <16>; ++ bias-disable; ++ }; + }; + + nand_pins: nand-pins { +- pins = "gpio53", "gpio55", "gpio56", +- "gpio57", "gpio58", "gpio59", +- "gpio60", "gpio62", "gpio63", +- "gpio64", "gpio65", "gpio66", +- "gpio67", "gpio68", "gpio69"; +- function = "qpic"; ++ pullups { ++ pins = "gpio52", "gpio53", "gpio58", ++ "gpio59"; ++ function = "qpic"; ++ bias-pull-up; ++ }; ++ ++ pulldowns { ++ pins = "gpio54", "gpio55", "gpio56", ++ "gpio57", "gpio60", "gpio61", ++ "gpio62", "gpio63", "gpio64", ++ "gpio65", "gpio66", "gpio67", ++ "gpio68", "gpio69"; ++ function = "qpic"; ++ bias-pull-down; ++ }; + }; + }; + +@@ -89,11 +115,11 @@ + status = "ok"; + cs-gpios = <&tlmm 12 0>; + +- m25p80@0 { ++ mx25l25635e@0 { + #address-cells = <1>; + #size-cells = <1>; + reg = <0>; +- compatible = "n25q128a11"; ++ compatible = "mx25l25635e"; + spi-max-frequency = <24000000>; + }; + }; +@@ -103,9 +129,48 @@ + perst-gpio = <&tlmm 38 0x1>; + }; + ++ i2c0: i2c@78b7000 { /* BLSP1 QUP2 */ ++ pinctrl-0 = <&i2c_0_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++ }; ++ + qpic-nand@79b0000 { + pinctrl-0 = <&nand_pins>; + pinctrl-names = "default"; + }; ++ ++ usb3_ss_phy: ssphy@9a000 { ++ status = "okay"; ++ }; ++ ++ usb3_hs_phy: hsphy@a6000 { ++ status = "okay"; ++ }; ++ ++ usb3: usb3@8af8800 { ++ status = "okay"; ++ }; ++ ++ usb2_hs_phy: hsphy@a8000 { ++ status = "okay"; ++ }; ++ ++ usb2: usb2@60f8800 { ++ status = "okay"; ++ }; ++ ++ cryptobam: dma@8e04000 { ++ status = "okay"; ++ }; ++ ++ crypto@8e3a000 { ++ status = "okay"; ++ }; ++ ++ watchdog@b017000 { ++ status = "okay"; ++ }; + }; + }; diff --git a/feeds/ipq40xx/ipq40xx/patches-5.4/903-pstore.patch b/feeds/ipq40xx/ipq40xx/patches-5.4/903-pstore.patch new file mode 100644 index 000000000..89ea4a438 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/patches-5.4/903-pstore.patch @@ -0,0 +1,17 @@ +Index: linux-5.4.105/arch/arm/boot/dts/qcom-ipq4019.dtsi +=================================================================== +--- linux-5.4.105.orig/arch/arm/boot/dts/qcom-ipq4019.dtsi ++++ linux-5.4.105/arch/arm/boot/dts/qcom-ipq4019.dtsi +@@ -32,6 +32,12 @@ + reg = <0x87e80000 0x180000>; + no-map; + }; ++ ++ ramoops@87f00000 { ++ compatible = "ramoops"; ++ reg = <0x87df0000 0x10000>; ++ record-size = <0x1000>; ++ }; + }; + + aliases { diff --git a/feeds/ipq40xx/ipq40xx/patches-5.4/911-dts-ipq4019-indio-um-325ac.patch b/feeds/ipq40xx/ipq40xx/patches-5.4/911-dts-ipq4019-indio-um-325ac.patch new file mode 100644 index 000000000..5c591e1a4 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/patches-5.4/911-dts-ipq4019-indio-um-325ac.patch @@ -0,0 +1,13 @@ +diff -Nurb a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile +--- a/arch/arm/boot/dts/Makefile 2022-03-21 14:59:54.834759752 +0000 ++++ b/arch/arm/boot/dts/Makefile 2022-03-21 15:01:21.535371530 +0000 +@@ -906,7 +906,8 @@ + qcom-msm8974-sony-xperia-amami.dtb \ + qcom-msm8974-sony-xperia-castor.dtb \ + qcom-msm8974-sony-xperia-honami.dtb \ +- qcom-mdm9615-wp8548-mangoh-green.dtb ++ qcom-mdm9615-wp8548-mangoh-green.dtb \ ++ qcom-ipq4019-um-325ac.dtb + dtb-$(CONFIG_ARCH_RDA) += \ + rda8810pl-orangepi-2g-iot.dtb \ + rda8810pl-orangepi-i96.dtb diff --git a/feeds/ipq40xx/ipq40xx/patches-5.4/912-dts-ipq4019-indio-um-550ac.patch b/feeds/ipq40xx/ipq40xx/patches-5.4/912-dts-ipq4019-indio-um-550ac.patch new file mode 100644 index 000000000..876eb48d0 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/patches-5.4/912-dts-ipq4019-indio-um-550ac.patch @@ -0,0 +1,13 @@ +diff -Nurb a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile +--- a/arch/arm/boot/dts/Makefile 2022-03-27 09:16:13.544943010 +0000 ++++ b/arch/arm/boot/dts/Makefile 2022-03-27 09:17:15.574098533 +0000 +@@ -907,7 +907,8 @@ + qcom-msm8974-sony-xperia-castor.dtb \ + qcom-msm8974-sony-xperia-honami.dtb \ + qcom-mdm9615-wp8548-mangoh-green.dtb \ +- qcom-ipq4019-um-325ac.dtb ++ qcom-ipq4019-um-325ac.dtb \ ++ qcom-ipq4019-um-550ac.dtb + dtb-$(CONFIG_ARCH_RDA) += \ + rda8810pl-orangepi-2g-iot.dtb \ + rda8810pl-orangepi-i96.dtb diff --git a/feeds/ipq40xx/ipq40xx/patches-5.4/913-dts-ipq4019-indio-um-510ac-v3.patch b/feeds/ipq40xx/ipq40xx/patches-5.4/913-dts-ipq4019-indio-um-510ac-v3.patch new file mode 100644 index 000000000..dd22a709a --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/patches-5.4/913-dts-ipq4019-indio-um-510ac-v3.patch @@ -0,0 +1,11 @@ +diff -Nurb a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile +--- a/arch/arm/boot/dts/Makefile 2022-03-31 03:03:23.379141391 +0000 ++++ b/arch/arm/boot/dts/Makefile 2022-03-31 03:07:24.671320669 +0000 +@@ -908,6 +908,7 @@ + qcom-msm8974-sony-xperia-honami.dtb \ + qcom-mdm9615-wp8548-mangoh-green.dtb \ + qcom-ipq4019-um-325ac.dtb \ ++ qcom-ipq4019-um-510ac-v3.dtb \ + qcom-ipq4019-um-550ac.dtb + dtb-$(CONFIG_ARCH_RDA) += \ + rda8810pl-orangepi-2g-iot.dtb \ diff --git a/feeds/ipq40xx/ipq40xx/patches-5.4/997-device_tree_cmdline.patch b/feeds/ipq40xx/ipq40xx/patches-5.4/997-device_tree_cmdline.patch new file mode 100644 index 000000000..3cc032fdd --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/patches-5.4/997-device_tree_cmdline.patch @@ -0,0 +1,12 @@ +--- a/drivers/of/fdt.c ++++ b/drivers/of/fdt.c +@@ -1059,6 +1059,9 @@ int __init early_init_dt_scan_chosen(uns + p = of_get_flat_dt_prop(node, "bootargs", &l); + if (p != NULL && l > 0) + strlcpy(data, p, min(l, COMMAND_LINE_SIZE)); ++ p = of_get_flat_dt_prop(node, "bootargs-append", &l); ++ if (p != NULL && l > 0) ++ strlcat(data, p, min_t(int, strlen(data) + (int)l, COMMAND_LINE_SIZE)); + + /* + * CONFIG_CMDLINE is meant to be a default in case nothing else diff --git a/feeds/ipq40xx/ipq40xx/patches-5.4/998-tp-link-ec420-g1.patch b/feeds/ipq40xx/ipq40xx/patches-5.4/998-tp-link-ec420-g1.patch new file mode 100644 index 000000000..40c913323 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/patches-5.4/998-tp-link-ec420-g1.patch @@ -0,0 +1,12 @@ +Index: linux-5.4.111/arch/arm/boot/dts/Makefile +=================================================================== +--- linux-5.4.111.orig/arch/arm/boot/dts/Makefile ++++ linux-5.4.111/arch/arm/boot/dts/Makefile +@@ -883,6 +883,7 @@ dtb-$(CONFIG_ARCH_QCOM) += \ + qcom-ipq4019-u4019-32m.dtb \ + qcom-ipq4019-wpj419.dtb \ + qcom-ipq4019-wtr-m2133hp.dtb \ ++ qcom-ipq4019-tp-link-ec420-g1.dtb \ + qcom-ipq4028-wpj428.dtb \ + qcom-ipq4029-ap-303.dtb \ + qcom-ipq4029-ap-303h.dtb \ diff --git a/feeds/ipq40xx/ipq40xx/patches-5.4/999-hfcl_ion.patch b/feeds/ipq40xx/ipq40xx/patches-5.4/999-hfcl_ion.patch new file mode 100644 index 000000000..5100c408b --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/patches-5.4/999-hfcl_ion.patch @@ -0,0 +1,20 @@ +Index: linux-5.4.158/arch/arm/boot/dts/Makefile +=================================================================== +--- linux-5.4.158.orig/arch/arm/boot/dts/Makefile ++++ linux-5.4.158/arch/arm/boot/dts/Makefile +@@ -888,6 +888,7 @@ dtb-$(CONFIG_ARCH_QCOM) += \ + qcom-ipq4019-wpj419.dtb \ + qcom-ipq4019-wtr-m2133hp.dtb \ + qcom-ipq4019-tp-link-ec420-g1.dtb \ ++ qcom-ipq4019-hfcl-ion4.dtb \ + qcom-ipq4028-wpj428.dtb \ + qcom-ipq4029-ap-303.dtb \ + qcom-ipq4029-ap-303h.dtb \ +@@ -908,6 +909,7 @@ dtb-$(CONFIG_ARCH_QCOM) += \ + qcom-mdm9615-wp8548-mangoh-green.dtb \ + qcom-ipq4019-um-325ac.dtb \ + qcom-ipq4019-um-510ac-v3.dtb \ ++ qcom-ipq4018-udaya-a5-id2.dtb \ + qcom-ipq4019-um-550ac.dtb + dtb-$(CONFIG_ARCH_RDA) += \ + rda8810pl-orangepi-2g-iot.dtb \ diff --git a/feeds/ipq40xx/ipq40xx/patches-5.4/9991-arm-boot-add-oap100e-dts-files.patch b/feeds/ipq40xx/ipq40xx/patches-5.4/9991-arm-boot-add-oap100e-dts-files.patch new file mode 100644 index 000000000..3e397ae68 --- /dev/null +++ b/feeds/ipq40xx/ipq40xx/patches-5.4/9991-arm-boot-add-oap100e-dts-files.patch @@ -0,0 +1,10 @@ +--- a/arch/arm/boot/dts/Makefile 2022-11-16 16:35:30.232986884 +0800 ++++ b/arch/arm/boot/dts/Makefile 2022-11-16 16:35:48.949080170 +0800 +@@ -860,6 +860,7 @@ + qcom-ipq4018-sxtsq-5-ac.dtb \ + qcom-ipq4018-nbg6617.dtb \ + qcom-ipq4019-oap100.dtb \ ++ qcom-ipq4019-oap100e.dtb \ + qcom-ipq4018-pa1200.dtb \ + qcom-ipq4018-rt-ac58u.dtb \ + qcom-ipq4018-wre6606.dtb \ diff --git a/feeds/ipq40xx/mac80211/Makefile b/feeds/ipq40xx/mac80211/Makefile new file mode 100644 index 000000000..95346c8d8 --- /dev/null +++ b/feeds/ipq40xx/mac80211/Makefile @@ -0,0 +1,528 @@ +# +# Copyright (C) 2007-2015 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/kernel.mk + +PKG_NAME:=mac80211 + +PKG_VERSION:=5.8-1 +PKG_RELEASE:=1 +PKG_SOURCE_URL:=@KERNEL/linux/kernel/projects/backports/stable/v5.8/ +PKG_HASH:=19b4174d89bf11ee221458e11f1e8dace26558498774b823051156f522d2036b + +PKG_SOURCE:=backports-$(PKG_VERSION).tar.xz +PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/backports-$(PKG_VERSION) +PKG_BUILD_PARALLEL:=1 + +PKG_MAINTAINER:=Felix Fietkau + +PKG_DRIVERS = \ + adm8211 \ + hermes hermes-pci hermes-pcmcia hermes-plx\ + lib80211 \ + mac80211-hwsim \ + mt7601u \ + p54-common p54-pci p54-usb \ + rsi91x rsi91x-usb rsi91x-sdio\ + wlcore wl12xx wl18xx \ + zd1211rw + +PKG_CONFIG_DEPENDS:= \ + CONFIG_PACKAGE_kmod-mac80211 \ + CONFIG_PACKAGE_CFG80211_TESTMODE \ + CONFIG_PACKAGE_MAC80211_DEBUGFS \ + CONFIG_PACKAGE_MAC80211_MESH \ + CONFIG_PACKAGE_MAC80211_TRACING \ + CONFIG_PACKAGE_IWLWIFI_DEBUG \ + CONFIG_PACKAGE_IWLWIFI_DEBUGFS \ + CONFIG_PACKAGE_RTLWIFI_DEBUG \ + +include $(INCLUDE_DIR)/package.mk + +WMENU:=Wireless Drivers + +define KernelPackage/mac80211/Default + SUBMENU:=$(WMENU) + URL:=https://wireless.wiki.kernel.org/ + MAINTAINER:=Felix Fietkau +endef + +config_package=$(if $(CONFIG_PACKAGE_kmod-$(1)),m) + +config-y:= \ + WLAN \ + CFG80211_WEXT \ + CFG80211_CERTIFICATION_ONUS \ + MAC80211_RC_MINSTREL \ + MAC80211_RC_MINSTREL_HT \ + MAC80211_RC_MINSTREL_VHT \ + MAC80211_RC_DEFAULT_MINSTREL \ + WLAN_VENDOR_ADMTEK \ + WLAN_VENDOR_ATH \ + WLAN_VENDOR_ATMEL \ + WLAN_VENDOR_BROADCOM \ + WLAN_VENDOR_CISCO \ + WLAN_VENDOR_INTEL \ + WLAN_VENDOR_INTERSIL \ + WLAN_VENDOR_MARVELL \ + WLAN_VENDOR_MEDIATEK \ + WLAN_VENDOR_RALINK \ + WLAN_VENDOR_REALTEK \ + WLAN_VENDOR_RSI \ + WLAN_VENDOR_ST \ + WLAN_VENDOR_TI \ + WLAN_VENDOR_ZYDAS \ + +config-$(call config_package,cfg80211) += CFG80211 +config-$(CONFIG_PACKAGE_CFG80211_TESTMODE) += NL80211_TESTMODE + +config-$(call config_package,mac80211) += MAC80211 +config-$(CONFIG_PACKAGE_MAC80211_MESH) += MAC80211_MESH + +include ath.mk +include broadcom.mk +include intel.mk +include marvell.mk +include ralink.mk +include realtek.mk + +PKG_CONFIG_DEPENDS += \ + $(patsubst %,CONFIG_PACKAGE_kmod-%,$(PKG_DRIVERS)) + +define KernelPackage/cfg80211 + $(call KernelPackage/mac80211/Default) + TITLE:=cfg80211 - wireless configuration API + DEPENDS+= +iw +iwinfo +wireless-regdb +USE_RFKILL:kmod-rfkill + ABI_VERSION:=$(PKG_VERSION)-$(PKG_RELEASE) + FILES:= \ + $(PKG_BUILD_DIR)/compat/compat.ko \ + $(PKG_BUILD_DIR)/net/wireless/cfg80211.ko +endef + +define KernelPackage/cfg80211/description +cfg80211 is the Linux wireless LAN (802.11) configuration API. +endef + +define KernelPackage/cfg80211/config + if PACKAGE_kmod-cfg80211 + + config PACKAGE_CFG80211_TESTMODE + bool "Enable testmode command support" + default n + help + This is typically used for tests and calibration during + manufacturing, or vendor specific debugging features + + endif +endef + + +define KernelPackage/mac80211 + $(call KernelPackage/mac80211/Default) + TITLE:=Linux 802.11 Wireless Networking Stack + # +kmod-crypto-cmac is a runtime only dependency of net/mac80211/aes_cmac.c + DEPENDS+= +kmod-cfg80211 +kmod-crypto-cmac +kmod-crypto-ccm +kmod-crypto-gcm + KCONFIG:=\ + CONFIG_AVERAGE=y + FILES:= $(PKG_BUILD_DIR)/net/mac80211/mac80211.ko + ABI_VERSION:=$(PKG_VERSION)-$(PKG_RELEASE) + MENU:=1 +endef + +define KernelPackage/mac80211/config + if PACKAGE_kmod-mac80211 + + config PACKAGE_MAC80211_DEBUGFS + bool "Export mac80211 internals in DebugFS" + select KERNEL_DEBUG_FS + default y + help + Select this to see extensive information about + the internal state of mac80211 in debugfs. + + config PACKAGE_MAC80211_TRACING + bool "Enable tracing (mac80211 and supported drivers)" + select KERNEL_FTRACE + select KERNEL_ENABLE_DEFAULT_TRACERS + default n + help + Select this to enable tracing of mac80211 and + related wifi drivers (using trace-cmd). + + config PACKAGE_MAC80211_MESH + bool "Enable 802.11s mesh support" + default y + + endif +endef + +define KernelPackage/mac80211/description +Generic IEEE 802.11 Networking Stack (mac80211) +endef + +define KernelPackage/adm8211 + $(call KernelPackage/mac80211/Default) + TITLE:=ADMTek 8211 support + DEPENDS+=@PCI_SUPPORT +kmod-mac80211 +kmod-eeprom-93cx6 + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/admtek/adm8211.ko + AUTOLOAD:=$(call AutoProbe,adm8211) +endef + +define KernelPackage/hermes + $(call KernelPackage/mac80211/Default) + TITLE:=Hermes 802.11b chipset support + DEPENDS:=@PCI_SUPPORT||PCMCIA_SUPPORT +kmod-cfg80211 +@DRIVER_WEXT_SUPPORT +kmod-crypto-michael-mic + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/intersil/orinoco/orinoco.ko + AUTOLOAD:=$(call AutoProbe,orinoco) +endef + +define KernelPackage/hermes/description + Kernel support for Hermes 802.11b chipsets +endef + +define KernelPackage/hermes-pci + $(call KernelPackage/mac80211/Default) + TITLE:=Intersil Prism 2.5 PCI support + DEPENDS:=@PCI_SUPPORT +kmod-hermes + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/intersil/orinoco/orinoco_pci.ko + AUTOLOAD:=$(call AutoProbe,orinoco_pci) +endef + +define KernelPackage/hermes-pci/description + Kernel modules for Intersil Prism 2.5 PCI support +endef + +define KernelPackage/hermes-plx + $(call KernelPackage/mac80211/Default) + TITLE:=PLX9052 based PCI adaptor + DEPENDS:=@PCI_SUPPORT +kmod-hermes + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/intersil/orinoco/orinoco_plx.ko + AUTOLOAD:=$(call AutoProbe,orinoco_plx) +endef + +define KernelPackage/hermes-plx/description + Kernel modules for Hermes in PLX9052 based PCI adaptors +endef + +define KernelPackage/hermes-pcmcia + $(call KernelPackage/mac80211/Default) + TITLE:=Hermes based PCMCIA adaptors + DEPENDS:=@PCMCIA_SUPPORT +kmod-hermes +kmod-pcmcia-core + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/intersil/orinoco/orinoco_cs.ko + AUTOLOAD:=$(call AutoProbe,orinoco_cs) +endef + +define KernelPackage/hermes-pcmcia/description + Kernel modules for Hermes based PCMCIA adaptors +endef + + +define KernelPackage/lib80211 + $(call KernelPackage/mac80211/Default) + TITLE:=802.11 Networking stack + DEPENDS:=+kmod-cfg80211 +kmod-crypto-hash +kmod-crypto-ccm + FILES:= \ + $(PKG_BUILD_DIR)/net/wireless/lib80211.ko \ + $(PKG_BUILD_DIR)/net/wireless/lib80211_crypt_wep.ko \ + $(PKG_BUILD_DIR)/net/wireless/lib80211_crypt_ccmp.ko \ + $(PKG_BUILD_DIR)/net/wireless/lib80211_crypt_tkip.ko + AUTOLOAD:=$(call AutoProbe, \ + lib80211 \ + lib80211_crypt_wep \ + lib80211_crypt_ccmp \ + lib80211_crypt_tkip \ + ) +endef + +define KernelPackage/lib80211/description + Kernel modules for 802.11 Networking stack + Includes: + - lib80211 + - lib80211_crypt_wep + - lib80211_crypt_tkip + - lib80211_crytp_ccmp +endef + + +define KernelPackage/mac80211-hwsim + $(call KernelPackage/mac80211/Default) + TITLE:=mac80211 HW simulation device + DEPENDS+= +kmod-mac80211 +@DRIVER_11AC_SUPPORT +@DRIVER_11N_SUPPORT + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/mac80211_hwsim.ko + AUTOLOAD:=$(call AutoProbe,mac80211_hwsim) +endef + + +define KernelPackage/mt7601u + $(call KernelPackage/mac80211/Default) + TITLE:=MT7601U-based USB dongles Wireless Driver + DEPENDS+= +kmod-mac80211 +@DRIVER_11N_SUPPORT @USB_SUPPORT +kmod-usb-core +mt7601u-firmware + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/mediatek/mt7601u/mt7601u.ko + AUTOLOAD:=$(call AutoProbe,mt7601u) +endef + +define KernelPackage/p54/Default + $(call KernelPackage/mac80211/Default) + TITLE:=Prism54 Drivers +endef + +define KernelPackage/p54/description + Kernel module for Prism54 chipsets (mac80211) +endef + +define KernelPackage/p54-common + $(call KernelPackage/p54/Default) + DEPENDS+= @(PCI_SUPPORT||USB_SUPPORT) +kmod-mac80211 +kmod-lib-crc-ccitt + TITLE+= (COMMON) + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/intersil/p54/p54common.ko +endef + +define KernelPackage/p54-pci + $(call KernelPackage/p54/Default) + TITLE+= (PCI) + DEPENDS+= @PCI_SUPPORT +kmod-p54-common +p54-pci-firmware + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/intersil/p54/p54pci.ko + AUTOLOAD:=$(call AutoProbe,p54pci) +endef + +define KernelPackage/p54-usb + $(call KernelPackage/p54/Default) + TITLE+= (USB) + DEPENDS+= @USB_SUPPORT +kmod-usb-core +kmod-p54-common +p54-usb-firmware + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/intersil/p54/p54usb.ko + AUTOLOAD:=$(call AutoProbe,p54usb) +endef + +define KernelPackage/rsi91x + $(call KernelPackage/mac80211/Default) + TITLE:=Redpine Signals Inc 91x WLAN driver support + DEPENDS+= +kmod-mac80211 +rs9113-firmware +@DRIVER_11N_SUPPORT + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rsi/rsi_91x.ko +endef + +define KernelPackage/rsi91x-usb + $(call KernelPackage/mac80211/Default) + TITLE:=Redpine Signals USB bus support + DEPENDS+=@USB_SUPPORT +kmod-usb-core +kmod-mac80211 +kmod-rsi91x +rs9113-firmware + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rsi/rsi_usb.ko + AUTOLOAD:=$(call AutoProbe,rsi_usb) +endef + +define KernelPackage/rsi91x-sdio + $(call KernelPackage/mac80211/Default) + TITLE:=Redpine Signals SDIO bus support + DEPENDS+= +kmod-mac80211 +kmod-mmc +kmod-rsi91x +rs9113-firmware + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rsi/rsi_sdio.ko + AUTOLOAD:=$(call AutoProbe,rsi_sdio) +endef + + +define KernelPackage/wlcore + $(call KernelPackage/mac80211/Default) + TITLE:=TI common driver part + 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 + AUTOLOAD:=$(call AutoProbe,wlcore wlcore_sdio) +endef + +define KernelPackage/wlcore/description + This module contains some common parts needed by TI Wireless drivers. +endef + +define KernelPackage/wl12xx + $(call KernelPackage/mac80211/Default) + TITLE:=Driver for TI WL12xx + URL:=https://wireless.wiki.kernel.org/en/users/drivers/wl12xx + DEPENDS+= +kmod-wlcore +wl12xx-firmware + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ti/wl12xx/wl12xx.ko + AUTOLOAD:=$(call AutoProbe,wl12xx) +endef + +define KernelPackage/wl12xx/description + Kernel modules for TI WL12xx +endef + +define KernelPackage/wl18xx + $(call KernelPackage/mac80211/Default) + TITLE:=Driver for TI WL18xx + URL:=https://wireless.wiki.kernel.org/en/users/drivers/wl18xx + DEPENDS+= +kmod-wlcore +wl18xx-firmware + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ti/wl18xx/wl18xx.ko + AUTOLOAD:=$(call AutoProbe,wl18xx) +endef + +define KernelPackage/wl18xx/description + Kernel modules for TI WL18xx +endef + + +ZD1211FW_NAME:=zd1211-firmware +ZD1211FW_VERSION:=1.4 +define Download/zd1211rw + FILE:=$(ZD1211FW_NAME)-$(ZD1211FW_VERSION).tar.bz2 + URL:=@SF/zd1211/ + HASH:=866308f6f59f7075f075d4959dff2ede47735c751251fecd1496df1ba4d338e1 +endef +$(eval $(call Download,zd1211rw)) + +define KernelPackage/zd1211rw + $(call KernelPackage/mac80211/Default) + TITLE:=Zydas ZD1211 support + DEPENDS+= @USB_SUPPORT +kmod-usb-core +kmod-mac80211 + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/zydas/zd1211rw/zd1211rw.ko + AUTOLOAD:=$(call AutoProbe,zd1211rw) +endef + +ifdef CONFIG_PACKAGE_MAC80211_DEBUGFS + config-y += \ + CFG80211_DEBUGFS \ + MAC80211_DEBUGFS +endif + +ifdef CONFIG_PACKAGE_MAC80211_TRACING + config-y += \ + IWLWIFI_DEVICE_TRACING +endif + +config-$(call config_package,lib80211) += LIB80211 LIB80211_CRYPT_WEP LIB80211_CRYPT_CCMP LIB80211_CRYPT_TKIP + +config-$(call config_package,mac80211-hwsim) += MAC80211_HWSIM +config-$(call config_package,mt7601u) += MT7601U +config-y += WL_MEDIATEK + +config-$(call config_package,p54-common) += P54_COMMON +config-$(call config_package,p54-pci) += P54_PCI +config-$(call config_package,p54-usb) += P54_USB + +config-$(call config_package,hermes) += HERMES +config-$(call config_package,hermes-pci) += PCI_HERMES +config-$(call config_package,hermes-plx) += PLX_HERMES +config-$(call config_package,hermes-pcmcia) += PCMCIA_HERMES +config-y += HERMES_PRISM + +config-$(call config_package,adm8211) += ADM8211 +config-$(call config_package,wlcore) += WLCORE WLCORE_SDIO +config-$(call config_package,wl12xx) += WL12XX +config-$(call config_package,wl18xx) += WL18XX +config-y += WL_TI WILINK_PLATFORM_DATA +config-$(call config_package,zd1211rw) += ZD1211RW +config-$(call config_package,rsi91x) += RSI_91X +config-$(call config_package,rsi91x-usb) += RSI_USB +config-$(call config_package,rsi91x-sdio) += RSI_SDIO + +config-$(CONFIG_LEDS_TRIGGERS) += MAC80211_LEDS + +MAKE_OPTS:= -C "$(PKG_BUILD_DIR)" \ + $(KERNEL_MAKE_FLAGS) \ + EXTRA_CFLAGS="-I$(PKG_BUILD_DIR)/include $(IREMAP_CFLAGS)" \ + KLIB_BUILD="$(LINUX_DIR)" \ + MODPROBE=true \ + KLIB=$(TARGET_MODULES_DIR) \ + KERNEL_SUBLEVEL=$(lastword $(subst ., ,$(KERNEL_PATCHVER))) \ + KBUILD_LDFLAGS_MODULE_PREREQ= + +define ConfigVars +$(subst $(space),,$(foreach opt,$(config-$(1)),CPTCFG_$(opt)=$(1) +)) +endef + +define mac80211_config +$(call ConfigVars,m)$(call ConfigVars,y) +endef +$(eval $(call shexport,mac80211_config)) + +define Build/Prepare + rm -rf $(PKG_BUILD_DIR) + mkdir -p $(PKG_BUILD_DIR) + $(PKG_UNPACK) + $(Build/Patch) + $(TAR) -C $(PKG_BUILD_DIR) -xzf $(DL_DIR)/$(IPW2100_NAME)-$(IPW2100_VERSION).tgz + $(TAR) -C $(PKG_BUILD_DIR) -xzf $(DL_DIR)/$(IPW2200_NAME)-$(IPW2200_VERSION).tgz + $(TAR) -C $(PKG_BUILD_DIR) -xjf $(DL_DIR)/$(ZD1211FW_NAME)-$(ZD1211FW_VERSION).tar.bz2 + rm -rf \ + $(PKG_BUILD_DIR)/include/linux/ssb \ + $(PKG_BUILD_DIR)/include/linux/bcma \ + $(PKG_BUILD_DIR)/include/net/bluetooth + + rm -f \ + $(PKG_BUILD_DIR)/include/linux/cordic.h \ + $(PKG_BUILD_DIR)/include/linux/crc8.h \ + $(PKG_BUILD_DIR)/include/linux/eeprom_93cx6.h \ + $(PKG_BUILD_DIR)/include/linux/wl12xx.h \ + $(PKG_BUILD_DIR)/include/linux/spi/libertas_spi.h \ + $(PKG_BUILD_DIR)/include/net/ieee80211.h \ + $(PKG_BUILD_DIR)/backport-include/linux/bcm47xx_nvram.h + + echo 'compat-wireless-$(PKG_VERSION)-$(PKG_RELEASE)-$(REVISION)' > $(PKG_BUILD_DIR)/compat_version +endef + +ifneq ($(CONFIG_PACKAGE_kmod-cfg80211)$(CONFIG_PACKAGE_kmod-lib80211),) + define Build/Compile/kmod + rm -rf $(PKG_BUILD_DIR)/modules + +$(MAKE) $(PKG_JOBS) $(MAKE_OPTS) modules + endef +endif + +define Build/Patch + $(if $(QUILT),rm -rf $(PKG_BUILD_DIR)/patches; mkdir -p $(PKG_BUILD_DIR)/patches) + $(call PatchDir,$(PKG_BUILD_DIR),$(PATCH_DIR)/build,build/) + $(call PatchDir,$(PKG_BUILD_DIR),$(PATCH_DIR)/subsys,subsys/) + $(call PatchDir,$(PKG_BUILD_DIR),$(PATCH_DIR)/ath,ath/) + $(call PatchDir,$(PKG_BUILD_DIR),$(PATCH_DIR)/rt2x00,rt2x00/) + $(call PatchDir,$(PKG_BUILD_DIR),$(PATCH_DIR)/mwl,mwl/) + $(call PatchDir,$(PKG_BUILD_DIR),$(PATCH_DIR)/brcm,brcm/) + $(if $(QUILT),touch $(PKG_BUILD_DIR)/.quilt_used) +endef + +define Quilt/Refresh/Package + $(call Quilt/RefreshDir,$(PKG_BUILD_DIR),$(PATCH_DIR)/build,build/) + $(call Quilt/RefreshDir,$(PKG_BUILD_DIR),$(PATCH_DIR)/subsys,subsys/) + $(call Quilt/RefreshDir,$(PKG_BUILD_DIR),$(PATCH_DIR)/ath,ath/) + $(call Quilt/RefreshDir,$(PKG_BUILD_DIR),$(PATCH_DIR)/rt2x00,rt2x00/) + $(call Quilt/RefreshDir,$(PKG_BUILD_DIR),$(PATCH_DIR)/mwl,mwl/) + $(call Quilt/RefreshDir,$(PKG_BUILD_DIR),$(PATCH_DIR)/brcm,brcm/) +endef + +define Build/Compile + $(SH_FUNC) var2file "$(call shvar,mac80211_config)" $(PKG_BUILD_DIR)/.config + $(MAKE) $(MAKE_OPTS) allnoconfig + $(call Build/Compile/kmod) +endef + +define Build/InstallDev + mkdir -p \ + $(1)/usr/include/mac80211 \ + $(1)/usr/include/mac80211-backport \ + $(1)/usr/include/mac80211/ath \ + $(1)/usr/include/net/mac80211 + $(CP) $(PKG_BUILD_DIR)/net/mac80211/*.h $(PKG_BUILD_DIR)/include/* $(1)/usr/include/mac80211/ + $(CP) $(PKG_BUILD_DIR)/backport-include/* $(1)/usr/include/mac80211-backport/ + $(CP) $(PKG_BUILD_DIR)/net/mac80211/rate.h $(1)/usr/include/net/mac80211/ + $(CP) $(PKG_BUILD_DIR)/drivers/net/wireless/ath/*.h $(1)/usr/include/mac80211/ath/ + rm -f $(1)/usr/include/mac80211-backport/linux/module.h +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 + +define KernelPackage/zd1211rw/install + $(INSTALL_DIR) $(1)/lib/firmware/zd1211 + $(INSTALL_DATA) $(PKG_BUILD_DIR)/$(ZD1211FW_NAME)/zd1211* $(1)/lib/firmware/zd1211 +endef + +$(eval $(foreach drv,$(PKG_DRIVERS),$(call KernelPackage,$(drv)))) +$(eval $(call KernelPackage,cfg80211)) +$(eval $(call KernelPackage,mac80211)) diff --git a/feeds/ipq40xx/mac80211/ath.mk b/feeds/ipq40xx/mac80211/ath.mk new file mode 100644 index 000000000..5db4be8da --- /dev/null +++ b/feeds/ipq40xx/mac80211/ath.mk @@ -0,0 +1,310 @@ +PKG_DRIVERS += \ + ath ath5k ath6kl ath6kl-sdio ath6kl-usb ath9k ath9k-common ath9k-htc ath10k \ + carl9170 owl-loader ar5523 + +PKG_CONFIG_DEPENDS += \ + CONFIG_PACKAGE_ATH_DEBUG \ + CONFIG_PACKAGE_ATH_DFS \ + CONFIG_PACKAGE_ATH_SPECTRAL \ + CONFIG_PACKAGE_ATH_DYNACK \ + CONFIG_ATH9K_HWRNG \ + CONFIG_ATH9K_SUPPORT_PCOEM \ + CONFIG_ATH9K_TX99 \ + CONFIG_ATH10K_LEDS \ + CONFIG_ATH10K_THERMAL \ + CONFIG_ATH_USER_REGD + +ifdef CONFIG_PACKAGE_MAC80211_DEBUGFS + config-y += \ + ATH9K_DEBUGFS \ + ATH9K_HTC_DEBUGFS \ + ATH10K_DEBUGFS \ + CARL9170_DEBUGFS \ + ATH5K_DEBUG \ + ATH6KL_DEBUG +endif + +ifdef CONFIG_PACKAGE_MAC80211_TRACING + config-y += \ + ATH10K_TRACING \ + ATH6KL_TRACING \ + ATH_TRACEPOINTS \ + ATH5K_TRACER +endif + +config-$(call config_package,ath) += ATH_CARDS ATH_COMMON ATH_REG_DYNAMIC_USER_REG_HINTS +config-$(CONFIG_PACKAGE_ATH_DEBUG) += ATH_DEBUG ATH10K_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 +config-$(CONFIG_PACKAGE_ATH_DYNACK) += ATH9K_DYNACK +config-$(call config_package,ath9k) += ATH9K +config-$(call config_package,ath9k-common) += ATH9K_COMMON +config-$(call config_package,owl-loader) += ATH9K_PCI_NO_EEPROM +config-$(CONFIG_TARGET_ath79) += ATH9K_AHB +config-$(CONFIG_TARGET_ipq40xx) += ATH10K_AHB +config-$(CONFIG_PCI) += ATH9K_PCI +config-$(CONFIG_ATH_USER_REGD) += ATH_USER_REGD +config-$(CONFIG_ATH9K_HWRNG) += ATH9K_HWRNG +config-$(CONFIG_ATH9K_SUPPORT_PCOEM) += ATH9K_PCOEM +config-$(CONFIG_ATH9K_TX99) += ATH9K_TX99 +config-$(CONFIG_ATH9K_UBNTHSR) += ATH9K_UBNTHSR +config-$(CONFIG_ATH10K_LEDS) += ATH10K_LEDS +config-$(CONFIG_ATH10K_THERMAL) += ATH10K_THERMAL + +config-$(call config_package,ath9k-htc) += ATH9K_HTC +config-$(call config_package,ath10k) += ATH10K ATH10K_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 +config-$(call config_package,ath6kl-usb) += ATH6KL_USB + +config-$(call config_package,carl9170) += CARL9170 +config-$(call config_package,ar5523) += AR5523 + +define KernelPackage/ath/config + if PACKAGE_kmod-ath + config ATH_USER_REGD + bool "Force Atheros drivers to respect the user's regdomain settings" + default y + help + Atheros' idea of regulatory handling is that the EEPROM of the card defines + the regulatory limits and the user is only allowed to restrict the settings + even further, even if the country allows frequencies or power levels that + are forbidden by the EEPROM settings. + + Select this option if you want the driver to respect the user's decision about + regulatory settings. + + config PACKAGE_ATH_DEBUG + bool "Atheros wireless debugging" + help + Say Y, if you want to debug atheros wireless drivers. + Only ath9k & ath10k make use of this. + + config PACKAGE_ATH_DFS + bool "Enable DFS support" + default y + help + Dynamic frequency selection (DFS) is required for most of the 5 GHz band + channels in Europe, US, and Japan. + + Select this option if you want to use such channels. + + config PACKAGE_ATH_SPECTRAL + bool "Atheros spectral scan support" + depends on PACKAGE_ATH_DEBUG + select KERNEL_RELAY + help + Say Y to enable access to the FFT/spectral data via debugfs. + + config PACKAGE_ATH_DYNACK + bool "Enable Dynack support" + depends on PACKAGE_kmod-ath9k-common + help + Enables support for Dynamic ACK estimation, which allows the fastest possible speed + at any distance automatically by increasing/decreasing the max frame ACK time for + the most remote station detected. It can be enabled by using iw (iw phy0 set distance auto), + or by sending the NL80211_ATTR_WIPHY_DYN_ACK flag to mac80211 driver using netlink. + + Select this option if you want to enable this feature + + endif +endef + +define KernelPackage/ath + $(call KernelPackage/mac80211/Default) + TITLE:=Atheros common driver part + DEPENDS+= @PCI_SUPPORT||USB_SUPPORT||TARGET_ath79||TARGET_ath25 +kmod-mac80211 + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath.ko + MENU:=1 +endef + +define KernelPackage/ath/description + This module contains some common parts needed by Atheros Wireless drivers. +endef + +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||TARGET_ath25) +kmod-ath +@DRIVER_11W_SUPPORT + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath5k/ath5k.ko + AUTOLOAD:=$(call AutoProbe,ath5k) +endef + +define KernelPackage/ath5k/description + This module adds support for wireless adapters based on + Atheros 5xxx chipset. +endef + +define KernelPackage/ath6kl + $(call KernelPackage/mac80211/Default) + 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 +@DRIVER_11N_SUPPORT + FILES:= $(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath6kl/ath6kl_core.ko +endef + +define KernelPackage/ath6kl-sdio + $(call KernelPackage/mac80211/Default) + TITLE:=Atheros 802.11n SDIO wireless cards support + URL:=https://wireless.wiki.kernel.org/en/users/drivers/ath6kl + DEPENDS+= +kmod-mmc +kmod-ath6kl + FILES:= $(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath6kl/ath6kl_sdio.ko + AUTOLOAD:=$(call AutoProbe,ath6kl_sdio) +endef + +define KernelPackage/ath6kl-sdio/description +This module adds support for wireless adapters based on +Atheros IEEE 802.11n AR6003 and AR6004 family of chipsets. +endef + +define KernelPackage/ath6kl-usb + $(call KernelPackage/mac80211/Default) + TITLE:=Atheros 802.11n USB wireless cards support + URL:=https://wireless.wiki.kernel.org/en/users/drivers/ath6kl + DEPENDS+= @USB_SUPPORT +kmod-usb-core +kmod-ath6kl + FILES:= $(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath6kl/ath6kl_usb.ko + AUTOLOAD:=$(call AutoProbe,ath6kl_usb) +endef + +define KernelPackage/ath6kl-usb/description +This module adds support for wireless adapters based on the +Atheros IEEE 802.11n AR6004 chipset. +endef + +define KernelPackage/ath9k-common + $(call KernelPackage/mac80211/Default) + TITLE:=Atheros 802.11n wireless devices (common code for ath9k and ath9k_htc) + URL:=https://wireless.wiki.kernel.org/en/users/drivers/ath9k + HIDDEN:=1 + DEPENDS+= @PCI_SUPPORT||USB_SUPPORT||TARGET_ath79 +kmod-ath +@DRIVER_11N_SUPPORT +@DRIVER_11W_SUPPORT + FILES:= \ + $(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath9k/ath9k_common.ko \ + $(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath9k/ath9k_hw.ko +endef + +define KernelPackage/ath9k + $(call KernelPackage/mac80211/Default) + TITLE:=Atheros 802.11n PCI wireless cards support + URL:=https://wireless.wiki.kernel.org/en/users/drivers/ath9k + DEPENDS+= @PCI_SUPPORT||TARGET_ath79 +kmod-ath9k-common + FILES:= \ + $(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath9k/ath9k.ko + AUTOLOAD:=$(call AutoProbe,ath9k) +endef + +define KernelPackage/ath9k/description +This module adds support for wireless adapters based on +Atheros IEEE 802.11n AR5008 and AR9001 family of chipsets. +endef + +define KernelPackage/ath9k/config + + config ATH9K_HWRNG + bool "Add wireless noise as source of randomness to kernel entropy pool" + depends on PACKAGE_kmod-ath9k + select PACKAGE_kmod-random-core + default n + + config ATH9K_SUPPORT_PCOEM + bool "Support chips used in PC OEM cards" + depends on PACKAGE_kmod-ath9k + + config ATH9K_TX99 + bool "Enable TX99 support (WARNING: testing only, breaks normal operation!)" + depends on PACKAGE_kmod-ath9k + + config ATH9K_UBNTHSR + bool "Support for Ubiquiti UniFi Outdoor+ access point" + depends on PACKAGE_kmod-ath9k && TARGET_ath79 + default y + +endef + +define KernelPackage/ath9k-htc + $(call KernelPackage/mac80211/Default) + TITLE:=Atheros 802.11n USB device support + URL:=https://wireless.wiki.kernel.org/en/users/drivers/ath9k + DEPENDS+= @USB_SUPPORT +kmod-ath9k-common +kmod-usb-core +ath9k-htc-firmware + FILES:= \ + $(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath9k/ath9k_htc.ko + AUTOLOAD:=$(call AutoProbe,ath9k_htc) +endef + +define KernelPackage/ath9k-htc/description +This module adds support for wireless adapters based on +Atheros USB AR9271 and AR7010 family of chipsets. +endef + +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_11N_SUPPORT +@DRIVER_11AC_SUPPORT +@DRIVER_11W_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_pci) +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. +endef + +define KernelPackage/ath10k/config + + config ATH10K_LEDS + bool "Enable LED support" + default y + depends on PACKAGE_kmod-ath10k + + config ATH10K_THERMAL + bool "Enable thermal sensors and throttling support" + depends on PACKAGE_kmod-ath10k + +endef + +define KernelPackage/carl9170 + $(call KernelPackage/mac80211/Default) + TITLE:=Driver for Atheros AR9170 USB sticks + DEPENDS:=@USB_SUPPORT +kmod-mac80211 +kmod-ath +kmod-usb-core +kmod-input-core +@DRIVER_11N_SUPPORT +@DRIVER_11W_SUPPORT +carl9170-firmware + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ath/carl9170/carl9170.ko + AUTOLOAD:=$(call AutoProbe,carl9170) +endef + +define KernelPackage/owl-loader + $(call KernelPackage/mac80211/Default) + TITLE:=Owl loader for initializing Atheros PCI(e) Wifi chips + DEPENDS:=@PCI_SUPPORT +kmod-ath9k + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath9k/ath9k_pci_owl_loader.ko + AUTOLOAD:=$(call AutoProbe,ath9k_pci_owl_loader) +endef + +define KernelPackage/owl-loader/description + Kernel module that helps to initialize certain Qualcomm + Atheros' PCI(e) Wifi chips, which have the init data + (which contains the PCI device ID for example) stored + together with the calibration data in the file system. + + This is necessary for devices like the Cisco Meraki Z1. +endef + +define KernelPackage/ar5523 + $(call KernelPackage/mac80211/Default) + TITLE:=Driver for Atheros AR5523 USB sticks + DEPENDS:=@USB_SUPPORT +kmod-mac80211 +kmod-ath +kmod-usb-core +kmod-input-core + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ath/ar5523/ar5523.ko + AUTOLOAD:=$(call AutoProbe,ar5523) +endef diff --git a/feeds/ipq40xx/mac80211/broadcom.mk b/feeds/ipq40xx/mac80211/broadcom.mk new file mode 100644 index 000000000..4dfc4e29a --- /dev/null +++ b/feeds/ipq40xx/mac80211/broadcom.mk @@ -0,0 +1,510 @@ +PKG_DRIVERS += \ + b43 b43legacy brcmsmac brcmfmac brcmutil + +PKG_CONFIG_DEPENDS += \ + CONFIG_PACKAGE_B43_DEBUG \ + CONFIG_PACKAGE_B43_PIO \ + CONFIG_PACKAGE_B43_PHY_G \ + CONFIG_PACKAGE_B43_PHY_N \ + CONFIG_PACKAGE_B43_PHY_LP \ + CONFIG_PACKAGE_B43_PHY_HT \ + CONFIG_PACKAGE_B43_BUSES_BCMA_AND_SSB \ + CONFIG_PACKAGE_B43_BUSES_BCMA \ + CONFIG_PACKAGE_B43_BUSES_SSB \ + CONFIG_PACKAGE_BRCM80211_DEBUG + +config-$(call config_package,b43) += B43 +config-$(CONFIG_PACKAGE_B43_BUSES_BCMA_AND_SSB) += B43_BUSES_BCMA_AND_SSB +config-$(CONFIG_PACKAGE_B43_BUSES_BCMA) += B43_BUSES_BCMA +config-$(CONFIG_PACKAGE_B43_BUSES_SSB) += B43_BUSES_SSB +config-$(CONFIG_PACKAGE_B43_PHY_G) += B43_PHY_G +config-$(CONFIG_PACKAGE_B43_PHY_N) += B43_PHY_N +config-$(CONFIG_PACKAGE_B43_PHY_LP) += B43_PHY_LP +config-$(CONFIG_PACKAGE_B43_PHY_HT) += B43_PHY_HT +config-$(CONFIG_PACKAGE_B43_PIO) += B43_PIO +config-$(CONFIG_PACKAGE_B43_DEBUG) += B43_DEBUG + +config-$(call config_package,b43legacy) += B43LEGACY +config-y += B43LEGACY_DMA_MODE + +config-$(call config_package,brcmutil) += BRCMUTIL +config-$(call config_package,brcmsmac) += BRCMSMAC +config-$(call config_package,brcmfmac) += BRCMFMAC +config-$(CONFIG_BRCMFMAC_SDIO) += BRCMFMAC_SDIO +config-$(CONFIG_BRCMFMAC_USB) += BRCMFMAC_USB +config-$(CONFIG_BRCMFMAC_PCIE) += BRCMFMAC_PCIE +config-$(CONFIG_PACKAGE_BRCM80211_DEBUG) += BRCMDBG + +config-$(CONFIG_LEDS_TRIGGERS) += B43_LEDS B43LEGACY_LEDS + +#Broadcom firmware +ifneq ($(CONFIG_B43_FW_6_30),) + PKG_B43_FWV4_NAME:=broadcom-wl + PKG_B43_FWV4_VERSION:=6.30.163.46 + PKG_B43_FWV4_OBJECT:=$(PKG_B43_FWV4_NAME)-$(PKG_B43_FWV4_VERSION).wl_apsta.o + PKG_B43_FWV4_SOURCE:=$(PKG_B43_FWV4_NAME)-$(PKG_B43_FWV4_VERSION).tar.bz2 + PKG_B43_FWV4_SOURCE_URL:=http://www.lwfinger.com/b43-firmware/ + PKG_B43_FWV4_HASH:=a07c3b6b277833c7dbe61daa511f908cd66c5e2763eb7a0859abc36cd9335c2d +else +ifneq ($(CONFIG_B43_FW_5_10),) + PKG_B43_FWV4_NAME:=broadcom-wl + PKG_B43_FWV4_VERSION:=5.10.56.27.3 + PKG_B43_FWV4_OBJECT:=$(PKG_B43_FWV4_NAME)-$(PKG_B43_FWV4_VERSION)/driver/wl_apsta/wl_prebuilt.o + PKG_B43_FWV4_SOURCE:=$(PKG_B43_FWV4_NAME)-$(PKG_B43_FWV4_VERSION)_mipsel.tar.bz2 + PKG_B43_FWV4_SOURCE_URL:=http://mirror2.openwrt.org/sources/ + PKG_B43_FWV4_HASH:=26a8c370f48fc129d0731cfd751c36cae1419b0bc8ca35781126744e60eae009 +else +ifneq ($(CONFIG_B43_FW_4_178),) + PKG_B43_FWV4_NAME:=broadcom-wl + PKG_B43_FWV4_VERSION:=4.178.10.4 + PKG_B43_FWV4_OBJECT:=$(PKG_B43_FWV4_NAME)-$(PKG_B43_FWV4_VERSION)/linux/wl_apsta.o + PKG_B43_FWV4_SOURCE:=$(PKG_B43_FWV4_NAME)-$(PKG_B43_FWV4_VERSION).tar.bz2 + PKG_B43_FWV4_SOURCE_URL:=http://mirror2.openwrt.org/sources/ + PKG_B43_FWV4_HASH:=32f6ad98facbb9045646fdc8b54bb03086d204153253f9c65d0234a5d90ae53f +else +ifneq ($(CONFIG_B43_FW_5_100_138),) + PKG_B43_FWV4_NAME:=broadcom-wl + PKG_B43_FWV4_VERSION:=5.100.138 + PKG_B43_FWV4_OBJECT:=$(PKG_B43_FWV4_NAME)-$(PKG_B43_FWV4_VERSION)/linux/wl_apsta.o + PKG_B43_FWV4_SOURCE:=$(PKG_B43_FWV4_NAME)-$(PKG_B43_FWV4_VERSION).tar.bz2 + PKG_B43_FWV4_SOURCE_URL:=http://www.lwfinger.com/b43-firmware/ + PKG_B43_FWV4_HASH:=f1e7067aac5b62b67b8b6e4c517990277804339ac16065eb13c731ff909ae46f +else + PKG_B43_FWV4_NAME:=broadcom-wl + PKG_B43_FWV4_VERSION:=4.150.10.5 + PKG_B43_FWV4_OBJECT:=$(PKG_B43_FWV4_NAME)-$(PKG_B43_FWV4_VERSION)/driver/wl_apsta_mimo.o + PKG_B43_FWV4_SOURCE:=$(PKG_B43_FWV4_NAME)-$(PKG_B43_FWV4_VERSION).tar.bz2 + PKG_B43_FWV4_SOURCE_URL:=http://mirror2.openwrt.org/sources/ + PKG_B43_FWV4_HASH:=a9f4e276a4d8d3a1cd0f2eb87080ae89b77f0a7140f06d4e9e2135fc44fdd533 +endif +endif +endif +endif +ifneq ($(CONFIG_B43_OPENFIRMWARE),) + PKG_B43_FWV4_NAME:=broadcom-wl + PKG_B43_FWV4_VERSION:=5.2 + PKG_B43_FWV4_OBJECT:=openfwwf-$(PKG_B43_FWV4_VERSION) + PKG_B43_FWV4_SOURCE:=openfwwf-$(PKG_B43_FWV4_VERSION).tar.gz + PKG_B43_FWV4_SOURCE_URL:=http://netweb.ing.unibs.it/~openfwwf/firmware + PKG_B43_FWV4_HASH:=9de03320083201080b2e94b81637ac07a159cf4e6f3481383e1a217e627bc0dc +endif + + +define Download/b43 + FILE:=$(PKG_B43_FWV4_SOURCE) + URL:=$(PKG_B43_FWV4_SOURCE_URL) + HASH:=$(PKG_B43_FWV4_HASH) +endef +$(eval $(call Download,b43)) + +define KernelPackage/b43 + $(call KernelPackage/mac80211/Default) + TITLE:=Broadcom 43xx wireless support + URL:=https://wireless.wiki.kernel.org/en/users/drivers/b43 + KCONFIG:= \ + CONFIG_HW_RANDOM=y + # Depend on PCI_SUPPORT to make sure we can select kmod-bcma or kmod-ssb + DEPENDS += \ + @PCI_SUPPORT +@DRIVER_11W_SUPPORT +kmod-mac80211 +kmod-lib-cordic \ + $(if $(CONFIG_PACKAGE_B43_USE_SSB),+kmod-ssb) \ + $(if $(CONFIG_PACKAGE_B43_USE_BCMA),+kmod-bcma) + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/broadcom/b43/b43.ko + AUTOLOAD:=$(call AutoProbe,b43) + MENU:=1 +endef + +define KernelPackage/b43/config + +config PACKAGE_B43_USE_SSB + select PACKAGE_kmod-ssb + tristate + depends on !TARGET_bcm47xx && !TARGET_bcm63xx + default PACKAGE_kmod-b43 if PACKAGE_B43_BUSES_BCMA_AND_SSB + default PACKAGE_kmod-b43 if PACKAGE_B43_BUSES_SSB + +config PACKAGE_B43_USE_BCMA + select PACKAGE_kmod-bcma + tristate + depends on !TARGET_bcm47xx && !TARGET_bcm53xx + default PACKAGE_kmod-b43 if PACKAGE_B43_BUSES_BCMA_AND_SSB + default PACKAGE_kmod-b43 if PACKAGE_B43_BUSES_BCMA + + if PACKAGE_kmod-b43 + + choice + prompt "b43 firmware version" + default B43_FW_5_100_138 + help + This option allows you to select the version of the b43 firmware. + + config B43_FW_4_150 + bool "Firmware 410.2160 from driver 4.150.10.5 (old stable)" + help + Old stable firmware for BCM43xx devices. + + If unsure, select this. + + config B43_FW_4_178 + bool "Firmware 478.104 from driver 4.178.10.4" + help + Older firmware for BCM43xx devices. + + If unsure, select the "stable" firmware. + + config B43_FW_5_10 + bool "Firmware 508.1084 from driver 5.10.56.27" + help + Older firmware for BCM43xx devices. + + If unsure, select the "stable" firmware. + + config B43_FW_5_100_138 + bool "Firmware 666.2 from driver 5.100.138 (stable)" + help + The currently default firmware for BCM43xx devices. + + This firmware currently gets most of the testing and is needed for some N-PHY devices. + + If unsure, select the this firmware. + + config B43_FW_6_30 + bool "Firmware 784.2 from driver 6.30.163.46 (experimental)" + help + Newer experimental firmware for BCM43xx devices. + + This firmware is mostly untested. + + If unsure, select the "stable" firmware. + + config B43_OPENFIRMWARE + bool "Open FirmWare for WiFi networks" + help + Opensource firmware for BCM43xx devices. + + Do _not_ select this, unless you know what you are doing. + The Opensource firmware is not suitable for embedded devices, yet. + It does not support QoS, which is bad for AccessPoints. + It does not support hardware crypto acceleration, which is a showstopper + for embedded devices with low CPU resources. + + If unsure, select the "stable" firmware. + + endchoice + + config B43_FW_SQUASH + bool "Remove unnecessary firmware files" + depends on !B43_OPENFIRMWARE + default y + help + This options allows you to remove unnecessary b43 firmware files + from the final rootfs image. This can reduce the rootfs size by + up to 200k. + + If unsure, say Y. + + config B43_FW_SQUASH_COREREVS + string "Core revisions to include" + depends on B43_FW_SQUASH + default "5,6,7,8,9,10,11,13,15" if TARGET_bcm47xx_legacy + default "16,28,29,30" if TARGET_bcm47xx_mips74k + default "5,6,7,8,9,10,11,13,15,16,28,29,30" + help + This is a comma seperated list of core revision numbers. + + Example (keep files for rev5 only): + 5 + + Example (keep files for rev5 and rev11): + 5,11 + + config B43_FW_SQUASH_PHYTYPES + string "PHY types to include" + depends on B43_FW_SQUASH + default "G,N,LP" if TARGET_bcm47xx_legacy + default "N,HT" if TARGET_bcm47xx_mips74k + default "G,N,LP,HT" + help + This is a comma seperated list of PHY types: + A => A-PHY + AG => Dual A-PHY G-PHY + G => G-PHY + LP => LP-PHY + N => N-PHY + HT => HT-PHY + LCN => LCN-PHY + LCN40 => LCN40-PHY + AC => AC-PHY + + Example (keep files for G-PHY only): + G + + Example (keep files for G-PHY and N-PHY): + G,N + + choice + prompt "Supported buses" + default PACKAGE_B43_BUSES_BCMA_AND_SSB + help + 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 + bool "BCMA and SSB" + + config PACKAGE_B43_BUSES_BCMA + depends on !TARGET_bcm47xx_legacy + bool "BCMA only" + + config PACKAGE_B43_BUSES_SSB + depends on !TARGET_bcm47xx_mips74k && !TARGET_bcm53xx + bool "SSB only" + + endchoice + + config PACKAGE_B43_DEBUG + bool "Enable debug output and debugfs for b43" + default n + help + Enable additional debug output and runtime sanity checks for b43 + and enables the debugfs interface. + + If unsure, say N. + + config PACKAGE_B43_PIO + bool "Enable support for PIO transfer mode" + default n + help + Enable support for using PIO instead of DMA. Unless you have DMA + transfer problems you don't need this. + + If unsure, say N. + + config PACKAGE_B43_PHY_G + bool "Enable support for G-PHYs" + default n if TARGET_bcm47xx_mips74k + default y + help + Enable support for G-PHY. This includes support for the following devices: + PCI: BCM4306, BCM4311, BCM4318 + SoC: BCM5352E, BCM4712 + + If unsure, say Y. + + config PACKAGE_B43_PHY_N + bool "Enable support for N-PHYs" + default y + help + Enable support for N-PHY. This includes support for the following devices: + PCI: BCM4321, BCM4322, BCM43222, BCM43224, BCM43225 + SoC: BCM4716, BCM4717, BCM4718 + + Currently only 11g speed is available. + + If unsure, say Y. + + config PACKAGE_B43_PHY_LP + bool "Enable support for LP-PHYs" + default n if TARGET_bcm47xx_mips74k + default y + help + Enable support for LP-PHY. This includes support for the following devices: + PCI: BCM4312 + SoC: BCM5354 + + If unsure, say Y. + + config PACKAGE_B43_PHY_HT + bool "Enable support for HT-PHYs" + default n if TARGET_bcm47xx_legacy + default y + help + Enable support for HT-PHY. This includes support for the following devices: + PCI: BCM4331 + + Currently only 11g speed is available. + + If unsure, say Y. + + config PACKAGE_B43_PHY_LCN + bool "Enable support for LCN-PHYs" + depends on BROKEN + default n + help + Currently broken. + + If unsure, say N. + + endif +endef + +define KernelPackage/b43/description +Kernel module for Broadcom 43xx wireless support (mac80211 stack) new +endef + +define KernelPackage/b43legacy + $(call KernelPackage/mac80211/Default) + TITLE:=Broadcom 43xx-legacy wireless support + URL:=https://wireless.wiki.kernel.org/en/users/drivers/b43 + KCONFIG:= \ + CONFIG_HW_RANDOM=y + DEPENDS+= +kmod-mac80211 +!(TARGET_bcm47xx||TARGET_bcm63xx):kmod-ssb @!TARGET_bcm47xx_mips74k +b43legacy-firmware +@DRIVER_11W_SUPPORT + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/broadcom/b43legacy/b43legacy.ko + AUTOLOAD:=$(call AutoProbe,b43legacy) + MENU:=1 +endef + +define KernelPackage/b43legacy/description +Kernel module for Broadcom 43xx-legacy wireless support (mac80211 stack) new +endef + + +define KernelPackage/brcmutil + $(call KernelPackage/mac80211/Default) + TITLE:=Broadcom IEEE802.11n common driver parts + URL:=https://wireless.wiki.kernel.org/en/users/drivers/brcm80211 + DEPENDS+=@PCI_SUPPORT||USB_SUPPORT + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/broadcom/brcm80211/brcmutil/brcmutil.ko + AUTOLOAD:=$(call AutoProbe,brcmutil) + MENU:=1 +endef + +define KernelPackage/brcmutil/description + This module contains some common parts needed by Broadcom Wireless drivers brcmsmac and brcmfmac. +endef + +define KernelPackage/brcmutil/config + if PACKAGE_kmod-brcmutil + + config PACKAGE_BRCM80211_DEBUG + bool "Broadcom wireless driver debugging" + help + Say Y, if you want to debug brcmsmac and brcmfmac wireless driver. + + endif +endef + +PKG_BRCMSMAC_FW_NAME:=broadcom-wl +PKG_BRCMSMAC_FW_VERSION:=5.100.138 +PKG_BRCMSMAC_FW_OBJECT:=$(PKG_BRCMSMAC_FW_NAME)-$(PKG_BRCMSMAC_FW_VERSION)/linux/wl_apsta.o +PKG_BRCMSMAC_FW_SOURCE:=$(PKG_BRCMSMAC_FW_NAME)-$(PKG_BRCMSMAC_FW_VERSION).tar.bz2 +PKG_BRCMSMAC_FW_SOURCE_URL:=http://www.lwfinger.com/b43-firmware/ +PKG_BRCMSMAC_FW_HASH:=f1e7067aac5b62b67b8b6e4c517990277804339ac16065eb13c731ff909ae46f + +define Download/brcmsmac + FILE:=$(PKG_BRCMSMAC_FW_SOURCE) + URL:=$(PKG_BRCMSMAC_FW_SOURCE_URL) + HASH:=$(PKG_BRCMSMAC_FW_HASH) +endef +$(eval $(call Download,brcmsmac)) + +define KernelPackage/brcmsmac + $(call KernelPackage/mac80211/Default) + TITLE:=Broadcom IEEE802.11n PCIe SoftMAC WLAN driver + URL:=https://wireless.wiki.kernel.org/en/users/drivers/brcm80211 + DEPENDS+= +kmod-mac80211 +@DRIVER_11N_SUPPORT +!TARGET_bcm47xx:kmod-bcma +kmod-lib-cordic +kmod-lib-crc8 +kmod-brcmutil +!BRCMSMAC_USE_FW_FROM_WL:brcmsmac-firmware + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/broadcom/brcm80211/brcmsmac/brcmsmac.ko + AUTOLOAD:=$(call AutoProbe,brcmsmac) + MENU:=1 +endef + +define KernelPackage/brcmsmac/description + Kernel module for Broadcom IEEE802.11n PCIe Wireless cards +endef + +define KernelPackage/brcmsmac/config + if PACKAGE_kmod-brcmsmac + + config BRCMSMAC_USE_FW_FROM_WL + bool "Use firmware extracted from broadcom proprietary driver" + default y + help + Instead of using the official brcmsmac firmware a firmware + version 666.2 extracted from the proprietary Broadcom driver + is used. This is needed to get core rev 17 used in bcm4716 + to work. + + If unsure, say Y. + + endif +endef + + +define KernelPackage/brcmfmac + $(call KernelPackage/mac80211/Default) + TITLE:=Broadcom IEEE802.11n USB FullMAC WLAN driver + URL:=https://wireless.wiki.kernel.org/en/users/drivers/brcm80211 + DEPENDS+= @USB_SUPPORT +kmod-cfg80211 +@DRIVER_11N_SUPPORT +@DRIVER_11AC_SUPPORT +@DRIVER_11W_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 + AUTOLOAD:=$(call AutoProbe,brcmfmac) +endef + +define KernelPackage/brcmfmac/description + Kernel module for Broadcom IEEE802.11n USB Wireless cards +endef + +define KernelPackage/brcmfmac/config + if PACKAGE_kmod-brcmfmac + + config BRCMFMAC_SDIO + bool "Enable SDIO bus interface support" + default y if TARGET_bcm27xx + default y if TARGET_sunxi + default n + help + Enable support for cards attached to an SDIO bus. + Select this option only if you are sure that your + board has a Broadcom wireless chip atacched to + that bus. + + config BRCMFMAC_USB + bool "Enable USB bus interface support" + depends on USB_SUPPORT + default y + help + Supported USB connected chipsets: + BCM43235, BCM43236, BCM43238 (all in revision 3 only) + BCM43143, BCM43242, BCM43566, BCM43569 + + config BRCMFMAC_PCIE + bool "Enable PCIE bus interface support" + depends on PCI_SUPPORT + default y + help + Supported PCIe connected chipsets: + BCM4354, BCM4356, BCM43567, BCM43570, BCM43602 + + endif +endef + + +define KernelPackage/b43/install + rm -rf $(1)/lib/firmware/ +ifeq ($(CONFIG_B43_OPENFIRMWARE),y) + tar xzf "$(DL_DIR)/$(PKG_B43_FWV4_SOURCE)" -C "$(PKG_BUILD_DIR)" +else + tar xjf "$(DL_DIR)/$(PKG_B43_FWV4_SOURCE)" -C "$(PKG_BUILD_DIR)" +endif + $(INSTALL_DIR) $(1)/lib/firmware/ +ifeq ($(CONFIG_B43_OPENFIRMWARE),y) + $(MAKE) -C "$(PKG_BUILD_DIR)/$(PKG_B43_FWV4_OBJECT)/" + $(INSTALL_DIR) $(1)/lib/firmware/b43-open/ + $(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_B43_FWV4_OBJECT)/ucode5.fw $(1)/lib/firmware/b43-open/ucode5.fw + $(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_B43_FWV4_OBJECT)/b0g0bsinitvals5.fw $(1)/lib/firmware/b43-open/b0g0bsinitvals5.fw + $(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_B43_FWV4_OBJECT)/b0g0initvals5.fw $(1)/lib/firmware/b43-open/b0g0initvals5.fw +else + b43-fwcutter -w $(1)/lib/firmware/ $(PKG_BUILD_DIR)/$(PKG_B43_FWV4_OBJECT) +endif +ifneq ($(CONFIG_B43_FW_SQUASH),) + b43-fwsquash.py "$(CONFIG_B43_FW_SQUASH_PHYTYPES)" "$(CONFIG_B43_FW_SQUASH_COREREVS)" "$(1)/lib/firmware/b43" +endif +endef + +define KernelPackage/brcmsmac/install + $(INSTALL_DIR) $(1)/lib/firmware/brcm +ifeq ($(CONFIG_BRCMSMAC_USE_FW_FROM_WL),y) + tar xjf "$(DL_DIR)/$(PKG_BRCMSMAC_FW_SOURCE)" -C "$(PKG_BUILD_DIR)" + b43-fwcutter --brcmsmac -w $(1)/lib/firmware/ $(PKG_BUILD_DIR)/$(PKG_BRCMSMAC_FW_OBJECT) +endif +endef diff --git a/feeds/ipq40xx/mac80211/files/lib/netifd/wireless/mac80211.sh b/feeds/ipq40xx/mac80211/files/lib/netifd/wireless/mac80211.sh new file mode 100644 index 000000000..dcf41441e --- /dev/null +++ b/feeds/ipq40xx/mac80211/files/lib/netifd/wireless/mac80211.sh @@ -0,0 +1,1170 @@ +#!/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" + +wdev_tool() { + ucode /usr/share/hostap/wdev.uc "$@" +} + +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_int num_global_macaddr + 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_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 + + config_add_int fils_discovery_max_interval + + # 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=0 + + [ "$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 min_tx_power:0 tx_burst + json_get_values ht_capab_list ht_capab + 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" ]; 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" <> /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_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)) + + append active_ifnames "$ifname" + set_default wds 0 + set_default powersave 0 + json_add_string _ifname "$ifname" + + [ -n "$macaddr" ] || { + macaddr="$(mac80211_generate_mac $phy $multiple_bssid)" + macidx="$(($macidx + 1))" + } + json_add_string _macaddr "$macaddr" + json_select .. + + + [ "$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 + 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 + + [ -n "$hostapd_ctrl" ] || { + ap_ifname="${ifname}" + hostapd_ctrl="${hostapd_ctrl:-/var/run/hostapd/$ifname}" + } + ;; + esac + + json_select .. +} + +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_add_mesh_params() { + for var in $MP_CONFIG_INT $MP_CONFIG_BOOL $MP_CONFIG_STRING; do + eval "mp_val=\"\$$var\"" + [ -n "$mp_val" ] && json_add_string "$var" "$mp_val" + done +} + +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" + + local prev + json_set_namespace wdev_uc prev + + json_add_object "$ifname" + json_add_string mode adhoc + json_add_string macaddr "$macaddr" + json_add_string ssid "$ssid" + json_add_string freq "$freq" + json_add_string htmode "$iw_htmode" + [ -n "$bssid" ] && json_add_string bssid "$bssid" + json_add_int beacon-interval "$beacon_int" + [ -n "$brstr" ] && json_add_string basic-rates "$brstr" + [ -n "$mcval" ] && json_add_string mcast-rate "$mcval" + [ -n "$keyspec" ] && json_add_string keys "$keyspec" + json_close_object + + json_set_namespace "$prev" +} + +mac80211_setup_mesh() { + json_get_vars ssid mesh_id mcast_rate + + mcval= + [ -n "$mcast_rate" ] && wpa_supplicant_add_rate mcval "$mcast_rate" + [ -n "$mesh_id" ] && ssid="$mesh_id" + + local prev + json_set_namespace wdev_uc prev + + json_add_object "$ifname" + json_add_string mode mesh + json_add_string macaddr "$macaddr" + json_add_string ssid "$ssid" + json_add_string freq "$freq" + json_add_string htmode "$iw_htmode" + [ -n "$mcval" ] && json_add_string mcast-rate "$mcval" + json_add_int beacon-interval "$beacon_int" + mac80211_add_mesh_params + + json_close_object + + json_set_namespace "$prev" +} + +mac80211_setup_monitor() { + local prev + json_set_namespace wdev_uc prev + + json_add_object "$ifname" + json_add_string mode monitor + [ -n "$freq" ] && json_add_string freq "$freq" + json_add_string htmode "$iw_htmode" + json_close_object + + json_set_namespace "$prev" +} + +mac80211_set_vif_txpower() { + local name="$1" + + json_select config + json_get_var ifname _ifname + json_get_vars vif_txpower wds + json_select .. + + set_default wds 0 + [ -z "$vif_txpower" ] || iw dev "$ifname" set txpower fixed "${vif_txpower%%.*}00" + [ "$wds" -gt 0 ] && echo 1 > /sys/kernel/debug/ieee80211/$phy/netdev\:$ifname/disable_offload +} + +wpa_supplicant_init_config() { + json_set_namespace wpa_supp prev + + json_init + json_add_array config + + json_set_namespace "$prev" +} + +wpa_supplicant_add_interface() { + local ifname="$1" + local mode="$2" + local hostapd_ctrl="$3" + local prev + + _wpa_supplicant_common "$ifname" + + json_set_namespace wpa_supp prev + + json_add_object + json_add_string ctrl "$_rpath" + json_add_string iface "$ifname" + json_add_string mode "$mode" + json_add_string config "$_config" + json_add_string macaddr "$macaddr" + [ -n "$network_bridge" ] && json_add_string bridge "$network_bridge" + [ -n "$hostapd_ctrl" ] && json_add_string hostapd_ctrl "$hostapd_ctrl" + [ -n "$wds" ] && json_add_boolean 4addr "$wds" + json_add_boolean powersave "$powersave" + [ "$mode" = "mesh" ] && mac80211_add_mesh_params + json_close_object + + json_set_namespace "$prev" + + wpa_supp_init=1 +} + +wpa_supplicant_set_config() { + local phy="$1" + local prev + + json_set_namespace wpa_supp prev + json_close_array + json_add_string phy "$phy" + json_add_boolean defer 1 + local data="$(json_dump)" + + json_cleanup + json_set_namespace "$prev" + + ubus -S -t 0 wait_for wpa_supplicant || { + [ -n "$wpa_supp_init" ] || return 0 + + ubus wait_for wpa_supplicant + } + + local supplicant_res="$(ubus call wpa_supplicant config_set "$data")" + ret="$?" + [ "$ret" != 0 -o -z "$supplicant_res" ] && wireless_setup_vif_failed WPA_SUPPLICANT_FAILED + + wireless_add_process "$(jsonfilter -s "$supplicant_res" -l 1 -e @.pid)" "/usr/sbin/wpa_supplicant" 1 1 + +} + +hostapd_set_config() { + [ -n "$hostapd_ctrl" ] || { + ubus call hostapd config_set '{ "phy": "'"$phy"'", "config": "", "prev_config": "'"${hostapd_conf_file}.prev"'" }' > /dev/null + return 0; + } + + ubus wait_for hostapd + local hostapd_res="$(ubus call hostapd config_set "{ \"phy\": \"$phy\", \"config\":\"${hostapd_conf_file}\", \"prev_config\": \"${hostapd_conf_file}.prev\"}")" + 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 +} + + +wpa_supplicant_start() { + local phy="$1" + + [ -n "$wpa_supp_init" ] || return 0 + + ubus call wpa_supplicant config_set '{ "phy": "'"$phy"'" }' > /dev/null +} + +mac80211_setup_supplicant() { + local enable=$1 + local add_sp=0 + + wpa_supplicant_prepare_interface "$ifname" nl80211 || return 1 + + if [ "$mode" = "sta" ]; then + wpa_supplicant_add_network "$ifname" + else + wpa_supplicant_add_network "$ifname" "$freq" "$htmode" "$noscan" + fi + + wpa_supplicant_add_interface "$ifname" "$mode" "$hostapd_ctrl" + + return 0 +} + +mac80211_setup_vif() { + local name="$1" + local failed + + json_select config + json_get_var ifname _ifname + json_get_var macaddr _macaddr + json_get_vars mode wds powersave + + set_default powersave 0 + set_default wds 0 + + case "$mode" in + mesh) + json_get_vars $MP_CONFIG_INT $MP_CONFIG_BOOL $MP_CONFIG_STRING + wireless_vif_parse_encryption + [ -z "$htmode" ] && htmode="NOHT"; + if wpa_supplicant -vmesh; then + mac80211_setup_supplicant || failed=1 + else + mac80211_setup_mesh + fi + ;; + adhoc) + wireless_vif_parse_encryption + if [ "$wpa" -gt 0 -o "$auto_channel" -gt 0 ]; then + mac80211_setup_supplicant || failed=1 + else + mac80211_setup_adhoc + fi + ;; + sta) + mac80211_setup_supplicant || failed=1 + ;; + monitor) + mac80211_setup_monitor + ;; + 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_set_noscan() { + hostapd_noscan=1 +} + +drv_mac80211_cleanup() { + hostapd_common_cleanup +} + +mac80211_reset_config() { + local phy="$1" + + hostapd_conf_file="/var/run/hostapd-$phy.conf" + ubus call hostapd config_set '{ "phy": "'"$phy"'", "config": "", "prev_config": "'"$hostapd_conf_file"'" }' > /dev/null + ubus call wpa_supplicant config_set '{ "phy": "'"$phy"'", "config": [] }' > /dev/null + wdev_tool "$phy" '{}' +} + +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 \ + multiple_bssid:0 \ + num_global_macaddr + json_get_values basic_rate_list basic_rate + json_get_values scan_list scan_list + json_select .. + + json_select data && { + json_get_var prev_rxantenna rxantenna + json_get_var prev_txantenna txantenna + json_select .. + } + + find_phy || { + echo "Could not find PHY for device '$1'" + wireless_set_retry 0 + return 1 + } + + [ "$band" = "6g" ] && set_default multiple_bssid 1 + + local wdev + local cwdev + local found + + # 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" + + 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 + set_default num_global_macaddr 1 + + [ "$txantenna" = "all" ] && txantenna=0xffffffff + [ "$rxantenna" = "all" ] && rxantenna=0xffffffff + + [ "$rxantenna" = "$prev_rxantenna" -a "$txantenna" = "$prev_txantenna" ] || mac80211_reset_config "$phy" + wireless_set_data phy="$phy" txantenna="$txantenna" rxantenna="$rxantenna" + + 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= + wpa_supp_init= + for_each_interface "ap" mac80211_check_ap + + [ -f "$hostapd_conf_file" ] && mv "$hostapd_conf_file" "$hostapd_conf_file.prev" + + for_each_interface "sta adhoc mesh" mac80211_set_noscan + [ -n "$has_ap" ] && mac80211_hostapd_setup_base "$phy" + + local prev + json_set_namespace wdev_uc prev + json_init + json_set_namespace "$prev" + + wpa_supplicant_init_config + + mac80211_prepare_iw_htmode + active_ifnames= + for_each_interface "ap sta adhoc mesh monitor" mac80211_prepare_vif ${multiple_bssid} + for_each_interface "ap sta adhoc mesh monitor" mac80211_setup_vif + + [ -x /usr/sbin/wpa_supplicant ] && wpa_supplicant_set_config "$phy" + [ -x /usr/sbin/hostapd ] && hostapd_set_config "$phy" + + [ -x /usr/sbin/wpa_supplicant ] && wpa_supplicant_start "$phy" + + json_set_namespace wdev_uc prev + wdev_tool "$phy" "$(json_dump)" $active_ifnames + json_set_namespace "$prev" + + for_each_interface "ap sta adhoc mesh monitor" mac80211_set_vif_txpower + 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_reset_config "$phy" + + for wdev in $(list_phy_interfaces "$phy"); do + ip link set dev "$wdev" down + iw dev "$wdev" del + done +} + +add_driver mac80211 diff --git a/feeds/ipq40xx/mac80211/files/lib/wifi/mac80211.sh b/feeds/ipq40xx/mac80211/files/lib/wifi/mac80211.sh new file mode 100644 index 000000000..6aa46b0c7 --- /dev/null +++ b/feeds/ipq40xx/mac80211/files/lib/wifi/mac80211.sh @@ -0,0 +1,190 @@ +#!/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=1 + + 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/feeds/ipq40xx/mac80211/files/mac80211.hotplug b/feeds/ipq40xx/mac80211/files/mac80211.hotplug new file mode 100644 index 000000000..b86555266 --- /dev/null +++ b/feeds/ipq40xx/mac80211/files/mac80211.hotplug @@ -0,0 +1,5 @@ +#!/bin/sh + +[ "${ACTION}" = "add" ] && { + /sbin/wifi config +} diff --git a/feeds/ipq40xx/mac80211/intel.mk b/feeds/ipq40xx/mac80211/intel.mk new file mode 100644 index 000000000..a8ae4ff7c --- /dev/null +++ b/feeds/ipq40xx/mac80211/intel.mk @@ -0,0 +1,200 @@ +PKG_DRIVERS += \ + iwl-legacy iwl3945 iwl4965 iwlwifi \ + libipw ipw2100 ipw2200 \ + +config-$(call config_package,iwl-legacy) += IWLEGACY +config-$(call config_package,iwl3945) += IWL3945 +config-$(call config_package,iwl4965) += IWL4965 +config-$(call config_package,iwlwifi) += IWLWIFI IWLDVM IWLMVM +config-$(CONFIG_PACKAGE_IWLWIFI_DEBUG)+= IWLWIFI_DEBUG +config-$(CONFIG_PACKAGE_IWLWIFI_DEBUGFS)+= IWLWIFI_DEBUGFS + +config-$(call config_package,libipw) += LIBIPW +config-$(call config_package,ipw2100) += IPW2100 +config-$(call config_package,ipw2200) += IPW2200 + +define KernelPackage/iwlwifi + $(call KernelPackage/mac80211/Default) + DEPENDS:= +kmod-mac80211 @PCI_SUPPORT +@DRIVER_11N_SUPPORT +@DRIVER_11AC_SUPPORT +@DRIVER_11W_SUPPORT + TITLE:=Intel AGN Wireless support + FILES:= \ + $(PKG_BUILD_DIR)/drivers/net/wireless/intel/iwlwifi/iwlwifi.ko \ + $(PKG_BUILD_DIR)/drivers/net/wireless/intel/iwlwifi/dvm/iwldvm.ko \ + $(PKG_BUILD_DIR)/drivers/net/wireless/intel/iwlwifi/mvm/iwlmvm.ko + AUTOLOAD:=$(call AutoProbe,iwlwifi iwldvm iwlmvm) + MENU:=1 +endef + +define KernelPackage/iwlwifi/description + iwlwifi kernel module for + Intel Wireless WiFi Link 6250AGN Adapter + Intel 6000 Series Wi-Fi Adapters (6200AGN and 6300AGN) + Intel WiFi Link 1000BGN + Intel Wireless WiFi 5150AGN + Intel Wireless WiFi 5100AGN, 5300AGN, and 5350AGN + Intel 6005 Series Wi-Fi Adapters + Intel 6030 Series Wi-Fi Adapters + Intel Wireless WiFi Link 6150BGN 2 Adapter + Intel 100 Series Wi-Fi Adapters (100BGN and 130BGN) + Intel 2000 Series Wi-Fi Adapters + Intel 7260 Wi-Fi Adapter + Intel 3160 Wi-Fi Adapter + Intel 7265 Wi-Fi Adapter + Intel 8260 Wi-Fi Adapter + Intel 3165 Wi-Fi Adapter +endef + +define KernelPackage/iwlwifi/config + if PACKAGE_kmod-iwlwifi + + config PACKAGE_IWLWIFI_DEBUG + bool "Enable full debugging output in the iwlwifi driver" + default n + help + This option will enable debug tracing output for the iwlwifi drivers + + This will result in the kernel module being ~100k larger. You can + control which debug output is sent to the kernel log by setting the + value in + + /sys/module/iwlwifi/parameters/debug + + This entry will only exist if this option is enabled. + + To set a value, simply echo an 8-byte hex value to the same file: + + % echo 0x43fff > /sys/module/iwlwifi/parameters/debug + + You can find the list of debug mask values in: + drivers/net/wireless/intel/iwlwifi/iwl-debug.h + + If this is your first time using this driver, you should say Y here + as the debug information can assist others in helping you resolve + any problems you may encounter. + + config PACKAGE_IWLWIFI_DEBUGFS + bool "iwlwifi debugfs support" + depends on PACKAGE_MAC80211_DEBUGFS + default n + help + Enable creation of debugfs files for the iwlwifi drivers. This + is a low-impact option that allows getting insight into the + driver's state at runtime. + + endif +endef + +define KernelPackage/iwl-legacy + $(call KernelPackage/mac80211/Default) + DEPENDS:= +kmod-mac80211 @PCI_SUPPORT + TITLE:=Intel legacy Wireless support + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/intel/iwlegacy/iwlegacy.ko + AUTOLOAD:=$(call AutoProbe,iwlegacy) +endef + +define KernelPackage/iwl-legacy/description + iwl-legacy kernel module for legacy Intel wireless support +endef + +define KernelPackage/iwl3945 + $(call KernelPackage/mac80211/Default) + DEPENDS:= +kmod-mac80211 +kmod-iwl-legacy +iwl3945-firmware + TITLE:=Intel iwl3945 Wireless support + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/intel/iwlegacy/iwl3945.ko + AUTOLOAD:=$(call AutoProbe,iwl3945) +endef + +define KernelPackage/iwl3945/description + iwl3945 kernel module for Intel 3945 support +endef + +define KernelPackage/iwl4965 + $(call KernelPackage/mac80211/Default) + DEPENDS:= +kmod-mac80211 +kmod-iwl-legacy +@DRIVER_11N_SUPPORT +iwl4965-firmware + TITLE:=Intel iwl4965 Wireless support + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/intel/iwlegacy/iwl4965.ko + AUTOLOAD:=$(call AutoProbe,iwl4965) +endef + +define KernelPackage/iwl4965/description + iwl4965 kernel module for Intel 4965 support +endef + + +define KernelPackage/libipw + $(call KernelPackage/mac80211/Default) + TITLE:=libipw for ipw2100 and ipw2200 + DEPENDS:=@PCI_SUPPORT +kmod-crypto-michael-mic +kmod-crypto-ecb +kmod-lib80211 +kmod-cfg80211 +@DRIVER_WEXT_SUPPORT @!BIG_ENDIAN + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/intel/ipw2x00/libipw.ko + AUTOLOAD:=$(call AutoProbe,libipw) +endef + +define KernelPackage/libipw/description + Hardware independent IEEE 802.11 networking stack for ipw2100 and ipw2200. +endef + +IPW2100_NAME:=ipw2100-fw +IPW2100_VERSION:=1.3 + +define Download/ipw2100 + URL:= \ + https://src.fedoraproject.org/repo/pkgs/ipw2100-firmware/ipw2100-fw-1.3.tgz/46aa75bcda1a00efa841f9707bbbd113/ \ + https://archlinux.mirror.pkern.at/other/packages/ipw2100-fw/ \ + http://mirror.ox.ac.uk/sites/ftp.openbsd.org/pub/OpenBSD/distfiles/firmware/ \ + http://firmware.openbsd.org/firmware-dist/ + FILE:=$(IPW2100_NAME)-$(IPW2100_VERSION).tgz + HASH:=e1107c455e48d324a616b47a622593bc8413dcce72026f72731c0b03dae3a7a2 +endef +$(eval $(call Download,ipw2100)) + +define KernelPackage/ipw2100 + $(call KernelPackage/mac80211/Default) + TITLE:=Intel IPW2100 driver + DEPENDS:=@PCI_SUPPORT +kmod-libipw + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/intel/ipw2x00/ipw2100.ko + AUTOLOAD:=$(call AutoProbe,ipw2100) +endef + +define KernelPackage/ipw2100/description + Kernel support for Intel IPW2100 + Includes: + - ipw2100 +endef + +IPW2200_NAME:=ipw2200-fw +IPW2200_VERSION:=3.1 + +define Download/ipw2200 + URL:= \ + https://src.fedoraproject.org/repo/pkgs/ipw2200-firmware/ipw2200-fw-3.1.tgz/eaba788643c7cc7483dd67ace70f6e99/ \ + https://archlinux.mirror.pkern.at/other/packages/ipw2200-fw/ \ + http://mirror.ox.ac.uk/sites/ftp.openbsd.org/pub/OpenBSD/distfiles/firmware/ \ + http://firmware.openbsd.org/firmware-dist/ + FILE:=$(IPW2200_NAME)-$(IPW2200_VERSION).tgz + HASH:=c6818c11c18cc030d55ff83f64b2bad8feef485e7742f84f94a61d811a6258bd +endef +$(eval $(call Download,ipw2200)) + +define KernelPackage/ipw2200 + $(call KernelPackage/mac80211/Default) + TITLE:=Intel IPW2200 driver + DEPENDS:=@PCI_SUPPORT +kmod-libipw + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/intel/ipw2x00/ipw2200.ko + AUTOLOAD:=$(call AutoProbe,ipw2200) +endef + +define KernelPackage/ipw2200/description + Kernel support for Intel IPW2200 + Includes: + - ipw2200 +endef + +define KernelPackage/ipw2100/install + $(INSTALL_DIR) $(1)/lib/firmware + $(INSTALL_DATA) $(PKG_BUILD_DIR)/ipw2100-$(IPW2100_VERSION)*.fw $(1)/lib/firmware +endef + +define KernelPackage/ipw2200/install + $(INSTALL_DIR) $(1)/lib/firmware + $(INSTALL_DATA) $(PKG_BUILD_DIR)/$(IPW2200_NAME)-$(IPW2200_VERSION)/ipw2200*.fw $(1)/lib/firmware +endef diff --git a/feeds/ipq40xx/mac80211/marvell.mk b/feeds/ipq40xx/mac80211/marvell.mk new file mode 100644 index 000000000..a0e67091e --- /dev/null +++ b/feeds/ipq40xx/mac80211/marvell.mk @@ -0,0 +1,90 @@ +PKG_DRIVERS += \ + libertas-sdio libertas-usb libertas-spi \ + mwl8k mwifiex-pcie mwifiex-sdio + +config-$(call config_package,libertas-sdio) += LIBERTAS LIBERTAS_SDIO +config-$(call config_package,libertas-usb) += LIBERTAS LIBERTAS_USB +config-$(call config_package,libertas-spi) += LIBERTAS LIBERTAS_SPI +config-$(call config_package,mwl8k) += MWL8K +config-$(call config_package,mwifiex-pcie) += MWIFIEX MWIFIEX_PCIE +config-$(call config_package,mwifiex-sdio) += MWIFIEX MWIFIEX_SDIO + +define KernelPackage/libertas-usb + $(call KernelPackage/mac80211/Default) + DEPENDS+= @USB_SUPPORT +kmod-cfg80211 +kmod-usb-core +kmod-lib80211 +@DRIVER_WEXT_SUPPORT +libertas-usb-firmware + TITLE:=Marvell 88W8015 Wireless Driver + FILES:= \ + $(PKG_BUILD_DIR)/drivers/net/wireless/marvell/libertas/libertas.ko \ + $(PKG_BUILD_DIR)/drivers/net/wireless/marvell/libertas/usb8xxx.ko + AUTOLOAD:=$(call AutoProbe,libertas usb8xxx) +endef + +define KernelPackage/libertas-sdio + $(call KernelPackage/mac80211/Default) + DEPENDS+= +kmod-cfg80211 +kmod-lib80211 +kmod-mmc +@DRIVER_WEXT_SUPPORT @!TARGET_uml +libertas-sdio-firmware + TITLE:=Marvell 88W8686 Wireless Driver + FILES:= \ + $(PKG_BUILD_DIR)/drivers/net/wireless/marvell/libertas/libertas.ko \ + $(PKG_BUILD_DIR)/drivers/net/wireless/marvell/libertas/libertas_sdio.ko + AUTOLOAD:=$(call AutoProbe,libertas libertas_sdio) +endef + +define KernelPackage/libertas-spi + $(call KernelPackage/mac80211/Default) + SUBMENU:=Wireless Drivers + DEPENDS+= +kmod-cfg80211 +kmod-lib80211 +@DRIVER_WEXT_SUPPORT @!TARGET_uml +libertas-spi-firmware + KCONFIG := \ + CONFIG_SPI=y \ + CONFIG_SPI_MASTER=y + TITLE:=Marvell 88W8686 SPI Wireless Driver + FILES:= \ + $(PKG_BUILD_DIR)/drivers/net/wireless/marvell/libertas/libertas.ko \ + $(PKG_BUILD_DIR)/drivers/net/wireless/marvell/libertas/libertas_spi.ko + AUTOLOAD:=$(call AutoProbe,libertas libertas_spi) +endef + + +define KernelPackage/mwl8k + $(call KernelPackage/mac80211/Default) + TITLE:=Driver for Marvell TOPDOG 802.11 Wireless cards + URL:=https://wireless.wiki.kernel.org/en/users/drivers/mwl8k + DEPENDS+= @PCI_SUPPORT +kmod-mac80211 +@DRIVER_11N_SUPPORT +mwl8k-firmware + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/marvell/mwl8k.ko + AUTOLOAD:=$(call AutoProbe,mwl8k) +endef + +define KernelPackage/mwl8k/description + Kernel modules for Marvell TOPDOG 802.11 Wireless cards +endef + + +define KernelPackage/mwifiex-pcie + $(call KernelPackage/mac80211/Default) + TITLE:=Driver for Marvell 802.11n/802.11ac PCIe Wireless cards + URL:=https://wireless.wiki.kernel.org/en/users/drivers/mwifiex + DEPENDS+= @PCI_SUPPORT +kmod-mac80211 +@DRIVER_11N_SUPPORT +@DRIVER_11AC_SUPPORT +mwifiex-pcie-firmware + FILES:= \ + $(PKG_BUILD_DIR)/drivers/net/wireless/marvell/mwifiex/mwifiex.ko \ + $(PKG_BUILD_DIR)/drivers/net/wireless/marvell/mwifiex/mwifiex_pcie.ko + AUTOLOAD:=$(call AutoProbe,mwifiex_pcie) +endef + +define KernelPackage/mwifiex-pcie/description + Kernel modules for Marvell 802.11n/802.11ac PCIe Wireless cards +endef + +define KernelPackage/mwifiex-sdio + $(call KernelPackage/mac80211/Default) + TITLE:=Driver for Marvell 802.11n/802.11ac SDIO Wireless cards + URL:=https://wireless.wiki.kernel.org/en/users/drivers/mwifiex + DEPENDS+= +kmod-mmc +kmod-mac80211 +@DRIVER_11N_SUPPORT +@DRIVER_11AC_SUPPORT +mwifiex-sdio-firmware + FILES:= \ + $(PKG_BUILD_DIR)/drivers/net/wireless/marvell/mwifiex/mwifiex.ko \ + $(PKG_BUILD_DIR)/drivers/net/wireless/marvell/mwifiex/mwifiex_sdio.ko + AUTOLOAD:=$(call AutoProbe,mwifiex_sdio) +endef + +define KernelPackage/mwifiex-sdio/description + Kernel modules for Marvell 802.11n/802.11ac SDIO Wireless cards +endef + diff --git a/feeds/ipq40xx/mac80211/patches/ath/070-ath_common_config.patch b/feeds/ipq40xx/mac80211/patches/ath/070-ath_common_config.patch new file mode 100644 index 000000000..3d0b4d6b1 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/ath/070-ath_common_config.patch @@ -0,0 +1,10 @@ +--- a/drivers/net/wireless/ath/Kconfig ++++ b/drivers/net/wireless/ath/Kconfig +@@ -1,6 +1,6 @@ + # SPDX-License-Identifier: ISC + config ATH_COMMON +- tristate ++ tristate "ath.ko" + depends on m + + config WLAN_VENDOR_ATH diff --git a/feeds/ipq40xx/mac80211/patches/ath/080-ath10k_thermal_config.patch b/feeds/ipq40xx/mac80211/patches/ath/080-ath10k_thermal_config.patch new file mode 100644 index 000000000..de6f9d9bb --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/ath/080-ath10k_thermal_config.patch @@ -0,0 +1,47 @@ +--- a/drivers/net/wireless/ath/ath10k/Kconfig ++++ b/drivers/net/wireless/ath/ath10k/Kconfig +@@ -86,6 +86,12 @@ config ATH10K_TRACING + help + Select this to ath10k use tracing infrastructure. + ++config ATH10K_THERMAL ++ bool "Atheros ath10k thermal monitoring support" ++ depends on THERMAL ++ ---help--- ++ Select this to ath10k use hwmon for thermal measurement. ++ + config ATH10K_DFS_CERTIFIED + bool "Atheros DFS support for certified platforms" + depends on ATH10K && CFG80211_CERTIFICATION_ONUS +--- a/drivers/net/wireless/ath/ath10k/Makefile ++++ b/drivers/net/wireless/ath/ath10k/Makefile +@@ -18,7 +18,7 @@ ath10k_core-y += mac.o \ + ath10k_core-$(CPTCFG_ATH10K_SPECTRAL) += spectral.o + ath10k_core-$(CPTCFG_NL80211_TESTMODE) += testmode.o + ath10k_core-$(CPTCFG_ATH10K_TRACING) += trace.o +-ath10k_core-$(CONFIG_THERMAL) += thermal.o ++ath10k_core-$(CPTCFG_ATH10K_THERMAL) += thermal.o + ath10k_core-$(CPTCFG_MAC80211_DEBUGFS) += debugfs_sta.o + ath10k_core-$(CONFIG_PM) += wow.o + ath10k_core-$(CONFIG_DEV_COREDUMP) += coredump.o +--- a/drivers/net/wireless/ath/ath10k/thermal.h ++++ b/drivers/net/wireless/ath/ath10k/thermal.h +@@ -25,7 +25,7 @@ struct ath10k_thermal { + int temperature; + }; + +-#if IS_REACHABLE(CONFIG_THERMAL) ++#if IS_REACHABLE(CPTCFG_ATH10K_THERMAL) + int ath10k_thermal_register(struct ath10k *ar); + void ath10k_thermal_unregister(struct ath10k *ar); + void ath10k_thermal_event_temperature(struct ath10k *ar, int temperature); +--- a/local-symbols ++++ b/local-symbols +@@ -142,6 +142,7 @@ ATH10K_SNOC= + ATH10K_DEBUG= + ATH10K_DEBUGFS= + ATH10K_SPECTRAL= ++ATH10K_THERMAL= + ATH10K_TRACING= + ATH10K_DFS_CERTIFIED= + WCN36XX= diff --git a/feeds/ipq40xx/mac80211/patches/ath/120-owl-loader-compat.patch b/feeds/ipq40xx/mac80211/patches/ath/120-owl-loader-compat.patch new file mode 100644 index 000000000..d1d6c9e2e --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/ath/120-owl-loader-compat.patch @@ -0,0 +1,53 @@ +From: Christian Lamparter +Date: Sat, 16 Nov 2019 19:25:24 +0100 +Subject: [PATCH] owl_loader: compatibility patch + +This patch includes OpenWrt specific changes that are +not included in the upstream owl-loader. + +This includes a platform data handling changes for ar71xx. + +Signed-off-by: Christian Lamparter + +--- a/drivers/net/wireless/ath/ath9k/ath9k_pci_owl_loader.c ++++ b/drivers/net/wireless/ath/ath9k/ath9k_pci_owl_loader.c +@@ -103,6 +103,7 @@ static void owl_fw_cb(const struct firmw + { + struct pci_dev *pdev = (struct pci_dev *)context; + struct owl_ctx *ctx = (struct owl_ctx *)pci_get_drvdata(pdev); ++ struct ath9k_platform_data *pdata = dev_get_platdata(&pdev->dev); + struct pci_bus *bus; + + complete(&ctx->eeprom_load); +@@ -118,6 +119,16 @@ static void owl_fw_cb(const struct firmw + goto release; + } + ++ if (pdata) { ++ memcpy(pdata->eeprom_data, fw->data, fw->size); ++ ++ /* ++ * eeprom has been successfully loaded - pass the data to ath9k ++ * but remove the eeprom_name, so it doesn't try to load it too. ++ */ ++ pdata->eeprom_name = NULL; ++ } ++ + if (ath9k_pci_fixup(pdev, (const u16 *)fw->data, fw->size)) + goto release; + +@@ -137,8 +148,14 @@ release: + static const char *owl_get_eeprom_name(struct pci_dev *pdev) + { + struct device *dev = &pdev->dev; ++ struct ath9k_platform_data *pdata; + char *eeprom_name; + ++ /* try the existing platform data first */ ++ pdata = dev_get_platdata(dev); ++ if (pdata && pdata->eeprom_name) ++ return pdata->eeprom_name; ++ + dev_dbg(dev, "using auto-generated eeprom filename\n"); + + eeprom_name = devm_kzalloc(dev, EEPROM_FILENAME_LEN, GFP_KERNEL); diff --git a/feeds/ipq40xx/mac80211/patches/ath/201-ath5k-WAR-for-AR71xx-PCI-bug.patch b/feeds/ipq40xx/mac80211/patches/ath/201-ath5k-WAR-for-AR71xx-PCI-bug.patch new file mode 100644 index 000000000..21516ffde --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/ath/201-ath5k-WAR-for-AR71xx-PCI-bug.patch @@ -0,0 +1,38 @@ +--- a/drivers/net/wireless/ath/ath5k/initvals.c ++++ b/drivers/net/wireless/ath/ath5k/initvals.c +@@ -62,8 +62,14 @@ static const struct ath5k_ini ar5210_ini + { AR5K_IMR, 0 }, + { AR5K_IER, AR5K_IER_DISABLE }, + { AR5K_BSR, 0, AR5K_INI_READ }, ++#if !defined(CONFIG_ATHEROS_AR71XX) && !defined(CONFIG_ATH79) + { AR5K_TXCFG, AR5K_DMASIZE_128B }, + { AR5K_RXCFG, AR5K_DMASIZE_128B }, ++#else ++ /* WAR for AR71xx PCI bug */ ++ { AR5K_TXCFG, AR5K_DMASIZE_128B }, ++ { AR5K_RXCFG, AR5K_DMASIZE_4B }, ++#endif + { AR5K_CFG, AR5K_INIT_CFG }, + { AR5K_TOPS, 8 }, + { AR5K_RXNOFRM, 8 }, +--- a/drivers/net/wireless/ath/ath5k/dma.c ++++ b/drivers/net/wireless/ath/ath5k/dma.c +@@ -869,10 +869,18 @@ ath5k_hw_dma_init(struct ath5k_hw *ah) + * guess we can tweak it and see how it goes ;-) + */ + if (ah->ah_version != AR5K_AR5210) { ++#if !defined(CONFIG_ATHEROS_AR71XX) && !defined(CONFIG_ATH79) + AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG, + AR5K_TXCFG_SDMAMR, AR5K_DMASIZE_128B); + AR5K_REG_WRITE_BITS(ah, AR5K_RXCFG, + AR5K_RXCFG_SDMAMW, AR5K_DMASIZE_128B); ++#else ++ /* WAR for AR71xx PCI bug */ ++ AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG, ++ AR5K_TXCFG_SDMAMR, AR5K_DMASIZE_128B); ++ AR5K_REG_WRITE_BITS(ah, AR5K_RXCFG, ++ AR5K_RXCFG_SDMAMW, AR5K_DMASIZE_4B); ++#endif + } + + /* Pre-enable interrupts on 5211/5212*/ diff --git a/feeds/ipq40xx/mac80211/patches/ath/350-ath9k_hw-reset-AHB-WMAC-interface-on-AR91xx.patch b/feeds/ipq40xx/mac80211/patches/ath/350-ath9k_hw-reset-AHB-WMAC-interface-on-AR91xx.patch new file mode 100644 index 000000000..d648a3a3e --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/ath/350-ath9k_hw-reset-AHB-WMAC-interface-on-AR91xx.patch @@ -0,0 +1,25 @@ +From: Felix Fietkau +Date: Sat, 9 Jul 2016 15:25:24 +0200 +Subject: [PATCH] ath9k_hw: reset AHB-WMAC interface on AR91xx + +Should fix a few stability issues + +Signed-off-by: Felix Fietkau +--- + +--- a/drivers/net/wireless/ath/ath9k/hw.c ++++ b/drivers/net/wireless/ath/ath9k/hw.c +@@ -1435,8 +1435,12 @@ static bool ath9k_hw_set_reset(struct at + if (!AR_SREV_9100(ah)) + REG_WRITE(ah, AR_RC, 0); + +- if (AR_SREV_9100(ah)) ++ if (AR_SREV_9100(ah)) { ++ /* Reset the AHB-WMAC interface */ ++ if (ah->external_reset) ++ ah->external_reset(); + udelay(50); ++ } + + return true; + } diff --git a/feeds/ipq40xx/mac80211/patches/ath/351-ath9k_hw-issue-external-reset-for-QCA955x.patch b/feeds/ipq40xx/mac80211/patches/ath/351-ath9k_hw-issue-external-reset-for-QCA955x.patch new file mode 100644 index 000000000..5f265b84c --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/ath/351-ath9k_hw-issue-external-reset-for-QCA955x.patch @@ -0,0 +1,129 @@ +From: Felix Fietkau +Date: Sat, 9 Jul 2016 15:26:44 +0200 +Subject: [PATCH] ath9k_hw: issue external reset for QCA955x + +The RTC interface on the SoC needs to be reset along with the rest of +the WMAC. + +Signed-off-by: Felix Fietkau +--- + +--- a/drivers/net/wireless/ath/ath9k/hw.c ++++ b/drivers/net/wireless/ath/ath9k/hw.c +@@ -1312,39 +1312,56 @@ void ath9k_hw_get_delta_slope_vals(struc + *coef_exponent = coef_exp - 16; + } + +-/* AR9330 WAR: +- * call external reset function to reset WMAC if: +- * - doing a cold reset +- * - we have pending frames in the TX queues. +- */ +-static bool ath9k_hw_ar9330_reset_war(struct ath_hw *ah, int type) ++static bool ath9k_hw_need_external_reset(struct ath_hw *ah, int type) + { +- int i, npend = 0; ++ int i; + +- for (i = 0; i < AR_NUM_QCU; i++) { +- npend = ath9k_hw_numtxpending(ah, i); +- if (npend) +- break; +- } +- +- if (ah->external_reset && +- (npend || type == ATH9K_RESET_COLD)) { +- int reset_err = 0; +- +- ath_dbg(ath9k_hw_common(ah), RESET, +- "reset MAC via external reset\n"); +- +- reset_err = ah->external_reset(); +- if (reset_err) { +- ath_err(ath9k_hw_common(ah), +- "External reset failed, err=%d\n", +- reset_err); +- return false; ++ if (type == ATH9K_RESET_COLD) ++ return true; ++ ++ if (AR_SREV_9550(ah)) ++ return true; ++ ++ /* AR9330 WAR: ++ * call external reset function to reset WMAC if: ++ * - doing a cold reset ++ * - we have pending frames in the TX queues. ++ */ ++ if (AR_SREV_9330(ah)) { ++ for (i = 0; i < AR_NUM_QCU; i++) { ++ if (ath9k_hw_numtxpending(ah, i)) ++ return true; + } ++ } ++ ++ return false; ++} ++ ++static bool ath9k_hw_external_reset(struct ath_hw *ah, int type) ++{ ++ int err; ++ ++ if (!ah->external_reset || !ath9k_hw_need_external_reset(ah, type)) ++ return true; ++ ++ ath_dbg(ath9k_hw_common(ah), RESET, ++ "reset MAC via external reset\n"); + +- REG_WRITE(ah, AR_RTC_RESET, 1); ++ err = ah->external_reset(); ++ if (err) { ++ ath_err(ath9k_hw_common(ah), ++ "External reset failed, err=%d\n", err); ++ return false; + } + ++ if (AR_SREV_9550(ah)) { ++ REG_WRITE(ah, AR_RTC_RESET, 0); ++ udelay(10); ++ } ++ ++ REG_WRITE(ah, AR_RTC_RESET, 1); ++ udelay(10); ++ + return true; + } + +@@ -1397,24 +1414,24 @@ static bool ath9k_hw_set_reset(struct at + rst_flags |= AR_RTC_RC_MAC_COLD; + } + +- if (AR_SREV_9330(ah)) { +- if (!ath9k_hw_ar9330_reset_war(ah, type)) +- return false; +- } +- + if (ath9k_hw_mci_is_enabled(ah)) + ar9003_mci_check_gpm_offset(ah); + + /* DMA HALT added to resolve ar9300 and ar9580 bus error during +- * RTC_RC reg read ++ * RTC_RC reg read. Also needed for AR9550 external reset + */ +- if (AR_SREV_9300(ah) || AR_SREV_9580(ah)) { ++ if (AR_SREV_9300(ah) || AR_SREV_9580(ah) || AR_SREV_9550(ah)) { + REG_SET_BIT(ah, AR_CFG, AR_CFG_HALT_REQ); + ath9k_hw_wait(ah, AR_CFG, AR_CFG_HALT_ACK, AR_CFG_HALT_ACK, + 20 * AH_WAIT_TIMEOUT); +- REG_CLR_BIT(ah, AR_CFG, AR_CFG_HALT_REQ); + } + ++ if (!AR_SREV_9100(ah)) ++ ath9k_hw_external_reset(ah, type); ++ ++ 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, rst_flags); + + REGWRITE_BUFFER_FLUSH(ah); diff --git a/feeds/ipq40xx/mac80211/patches/ath/354-ath9k-force-rx_clear-when-disabling-rx.patch b/feeds/ipq40xx/mac80211/patches/ath/354-ath9k-force-rx_clear-when-disabling-rx.patch new file mode 100644 index 000000000..8aaccf49b --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/ath/354-ath9k-force-rx_clear-when-disabling-rx.patch @@ -0,0 +1,35 @@ +From: Felix Fietkau +Date: Sun, 7 Jun 2015 13:53:35 +0200 +Subject: [PATCH] ath9k: force rx_clear when disabling rx + +This makes stopping Rx more reliable and should reduce the frequency of +Rx related DMA stop warnings. Don't use rx_clear in TX99 mode. + +Cc: stable@vger.kernel.org +Signed-off-by: Felix Fietkau +Signed-off-by: Helmut Schaa +--- + +--- a/drivers/net/wireless/ath/ath9k/mac.c ++++ b/drivers/net/wireless/ath/ath9k/mac.c +@@ -678,13 +678,18 @@ void ath9k_hw_startpcureceive(struct ath + + ath9k_ani_reset(ah, is_scanning); + +- REG_CLR_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT)); ++ REG_CLR_BIT(ah, AR_DIAG_SW, ++ AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT | AR_DIAG_FORCE_RX_CLEAR); + } + EXPORT_SYMBOL(ath9k_hw_startpcureceive); + + void ath9k_hw_abortpcurecv(struct ath_hw *ah) + { +- REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_ABORT | AR_DIAG_RX_DIS); ++ u32 reg = AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT; ++ ++ if (!IS_ENABLED(CPTCFG_ATH9K_TX99)) ++ reg |= AR_DIAG_FORCE_RX_CLEAR; ++ REG_SET_BIT(ah, AR_DIAG_SW, reg); + + ath9k_hw_disable_mib_counters(ah); + } diff --git a/feeds/ipq40xx/mac80211/patches/ath/356-Revert-ath9k-interpret-requested-txpower-in-EIRP-dom.patch b/feeds/ipq40xx/mac80211/patches/ath/356-Revert-ath9k-interpret-requested-txpower-in-EIRP-dom.patch new file mode 100644 index 000000000..385eea011 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/ath/356-Revert-ath9k-interpret-requested-txpower-in-EIRP-dom.patch @@ -0,0 +1,36 @@ +From: Felix Fietkau +Date: Sat, 14 May 2016 14:51:02 +0200 +Subject: [PATCH] Revert "ath9k: interpret requested txpower in EIRP + domain" + +This reverts commit 71f5137bf010c6faffab50c0ec15374c59c4a411. +--- + +--- a/drivers/net/wireless/ath/ath9k/hw.c ++++ b/drivers/net/wireless/ath/ath9k/hw.c +@@ -2977,7 +2977,8 @@ void ath9k_hw_apply_txpower(struct ath_h + { + struct ath_regulatory *reg = ath9k_hw_regulatory(ah); + struct ieee80211_channel *channel; +- int chan_pwr, new_pwr; ++ int chan_pwr, new_pwr, max_gain; ++ int ant_gain, ant_reduction = 0; + u16 ctl = NO_CTL; + + if (!chan) +@@ -2989,9 +2990,14 @@ void ath9k_hw_apply_txpower(struct ath_h + channel = chan->chan; + chan_pwr = min_t(int, channel->max_power * 2, MAX_COMBINED_POWER); + new_pwr = min_t(int, chan_pwr, reg->power_limit); ++ max_gain = chan_pwr - new_pwr + channel->max_antenna_gain * 2; ++ ++ ant_gain = get_antenna_gain(ah, chan); ++ if (ant_gain > max_gain) ++ ant_reduction = ant_gain - max_gain; + + ah->eep_ops->set_txpower(ah, chan, ctl, +- get_antenna_gain(ah, chan), new_pwr, test); ++ ant_reduction, new_pwr, test); + } + + void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit, bool test) diff --git a/feeds/ipq40xx/mac80211/patches/ath/365-ath9k-adjust-tx-power-reduction-for-US-regulatory-do.patch b/feeds/ipq40xx/mac80211/patches/ath/365-ath9k-adjust-tx-power-reduction-for-US-regulatory-do.patch new file mode 100644 index 000000000..0c3edc126 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/ath/365-ath9k-adjust-tx-power-reduction-for-US-regulatory-do.patch @@ -0,0 +1,24 @@ +From: Felix Fietkau +Date: Wed, 19 Jul 2017 08:49:31 +0200 +Subject: [PATCH] ath9k: adjust tx power reduction for US regulatory + domain + +FCC regulatory rules allow for up to 6 dBi antenna gain. Account for +this in the EEPROM based tx power reduction code. + +Signed-off-by: Felix Fietkau +--- + +--- a/drivers/net/wireless/ath/ath9k/hw.c ++++ b/drivers/net/wireless/ath/ath9k/hw.c +@@ -2996,6 +2996,10 @@ void ath9k_hw_apply_txpower(struct ath_h + if (ant_gain > max_gain) + ant_reduction = ant_gain - max_gain; + ++ /* FCC allows maximum antenna gain of 6 dBi */ ++ if (reg->region == NL80211_DFS_FCC) ++ ant_reduction = max_t(int, ant_reduction - 12, 0); ++ + ah->eep_ops->set_txpower(ah, chan, ctl, + ant_reduction, new_pwr, test); + } diff --git a/feeds/ipq40xx/mac80211/patches/ath/400-ath_move_debug_code.patch b/feeds/ipq40xx/mac80211/patches/ath/400-ath_move_debug_code.patch new file mode 100644 index 000000000..db10c4510 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/ath/400-ath_move_debug_code.patch @@ -0,0 +1,31 @@ +--- a/drivers/net/wireless/ath/Makefile ++++ b/drivers/net/wireless/ath/Makefile +@@ -15,10 +15,10 @@ ath-objs := main.o \ + regd.o \ + hw.o \ + key.o \ ++ debug.o \ + dfs_pattern_detector.o \ + dfs_pri_detector.o + +-ath-$(CPTCFG_ATH_DEBUG) += debug.o + ath-$(CPTCFG_ATH_TRACEPOINTS) += trace.o + + CFLAGS_trace.o := -I$(src) +--- a/drivers/net/wireless/ath/ath.h ++++ b/drivers/net/wireless/ath/ath.h +@@ -316,14 +316,7 @@ void _ath_dbg(struct ath_common *common, + #endif /* CPTCFG_ATH_DEBUG */ + + /** Returns string describing opmode, or NULL if unknown mode. */ +-#ifdef CPTCFG_ATH_DEBUG + const char *ath_opmode_to_string(enum nl80211_iftype opmode); +-#else +-static inline const char *ath_opmode_to_string(enum nl80211_iftype opmode) +-{ +- return "UNKNOWN"; +-} +-#endif + + extern const char *ath_bus_type_strings[]; + static inline const char *ath_bus_type_to_string(enum ath_bus_type bustype) diff --git a/feeds/ipq40xx/mac80211/patches/ath/401-ath9k_blink_default.patch b/feeds/ipq40xx/mac80211/patches/ath/401-ath9k_blink_default.patch new file mode 100644 index 000000000..3eb57bb1c --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/ath/401-ath9k_blink_default.patch @@ -0,0 +1,11 @@ +--- a/drivers/net/wireless/ath/ath9k/init.c ++++ b/drivers/net/wireless/ath/ath9k/init.c +@@ -48,7 +48,7 @@ int ath9k_modparam_nohwcrypt; + module_param_named(nohwcrypt, ath9k_modparam_nohwcrypt, int, 0444); + MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption"); + +-int ath9k_led_blink; ++int ath9k_led_blink = 1; + module_param_named(blink, ath9k_led_blink, int, 0444); + MODULE_PARM_DESC(blink, "Enable LED blink on activity"); + diff --git a/feeds/ipq40xx/mac80211/patches/ath/402-ath_regd_optional.patch b/feeds/ipq40xx/mac80211/patches/ath/402-ath_regd_optional.patch new file mode 100644 index 000000000..bf87d3551 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/ath/402-ath_regd_optional.patch @@ -0,0 +1,92 @@ +--- a/drivers/net/wireless/ath/regd.c ++++ b/drivers/net/wireless/ath/regd.c +@@ -24,6 +24,7 @@ + #include "regd_common.h" + + static int __ath_regd_init(struct ath_regulatory *reg); ++static struct reg_dmn_pair_mapping *ath_get_regpair(int regdmn); + + /* + * This is a set of common rules used by our world regulatory domains. +@@ -116,6 +117,9 @@ static const struct ieee80211_regdomain + + static bool dynamic_country_user_possible(struct ath_regulatory *reg) + { ++ if (IS_ENABLED(CPTCFG_ATH_USER_REGD)) ++ return true; ++ + if (IS_ENABLED(CPTCFG_ATH_REG_DYNAMIC_USER_CERT_TESTING)) + return true; + +@@ -188,6 +192,8 @@ static bool dynamic_country_user_possibl + + static bool ath_reg_dyn_country_user_allow(struct ath_regulatory *reg) + { ++ if (IS_ENABLED(CPTCFG_ATH_USER_REGD)) ++ return true; + if (!IS_ENABLED(CPTCFG_ATH_REG_DYNAMIC_USER_REG_HINTS)) + return false; + if (!dynamic_country_user_possible(reg)) +@@ -345,6 +351,9 @@ ath_reg_apply_beaconing_flags(struct wip + struct ieee80211_channel *ch; + unsigned int i; + ++ if (IS_ENABLED(CPTCFG_ATH_USER_REGD)) ++ return; ++ + for (band = 0; band < NUM_NL80211_BANDS; band++) { + if (!wiphy->bands[band]) + continue; +@@ -378,6 +387,9 @@ ath_reg_apply_ir_flags(struct wiphy *wip + { + struct ieee80211_supported_band *sband; + ++ if (IS_ENABLED(CPTCFG_ATH_USER_REGD)) ++ return; ++ + sband = wiphy->bands[NL80211_BAND_2GHZ]; + if (!sband) + return; +@@ -407,6 +419,9 @@ static void ath_reg_apply_radar_flags(st + struct ieee80211_channel *ch; + unsigned int i; + ++ if (IS_ENABLED(CPTCFG_ATH_USER_REGD)) ++ return; ++ + if (!wiphy->bands[NL80211_BAND_5GHZ]) + return; + +@@ -639,6 +654,10 @@ ath_regd_init_wiphy(struct ath_regulator + const struct ieee80211_regdomain *regd; + + wiphy->reg_notifier = reg_notifier; ++ ++ if (IS_ENABLED(CPTCFG_ATH_USER_REGD)) ++ return 0; ++ + wiphy->regulatory_flags |= REGULATORY_STRICT_REG | + REGULATORY_CUSTOM_REG; + +--- a/drivers/net/wireless/ath/Kconfig ++++ b/drivers/net/wireless/ath/Kconfig +@@ -24,6 +24,9 @@ config WLAN_VENDOR_ATH + + if WLAN_VENDOR_ATH + ++config ATH_USER_REGD ++ bool "Do not enforce EEPROM regulatory restrictions" ++ + config ATH_DEBUG + bool "Atheros wireless debugging" + help +--- a/local-symbols ++++ b/local-symbols +@@ -85,6 +85,7 @@ ADM8211= + ATH_COMMON= + WLAN_VENDOR_ATH= + ATH_DEBUG= ++ATH_USER_REGD= + ATH_TRACEPOINTS= + ATH_REG_DYNAMIC_USER_REG_HINTS= + ATH_REG_DYNAMIC_USER_CERT_TESTING= diff --git a/feeds/ipq40xx/mac80211/patches/ath/403-world_regd_fixup.patch b/feeds/ipq40xx/mac80211/patches/ath/403-world_regd_fixup.patch new file mode 100644 index 000000000..ed616b753 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/ath/403-world_regd_fixup.patch @@ -0,0 +1,84 @@ +--- a/drivers/net/wireless/ath/regd.c ++++ b/drivers/net/wireless/ath/regd.c +@@ -44,7 +44,8 @@ static struct reg_dmn_pair_mapping *ath_ + NL80211_RRF_NO_OFDM) + + /* We allow IBSS on these on a case by case basis by regulatory domain */ +-#define ATH_5GHZ_5150_5350 REG_RULE(5150-10, 5350+10, 80, 0, 30,\ ++#define ATH_5GHZ_5150_5350 REG_RULE(5150-10, 5240+10, 80, 0, 30, 0),\ ++ REG_RULE(5260-10, 5350+10, 80, 0, 30,\ + NL80211_RRF_NO_IR) + #define ATH_5GHZ_5470_5850 REG_RULE(5470-10, 5850+10, 80, 0, 30,\ + NL80211_RRF_NO_IR) +@@ -62,57 +63,56 @@ static struct reg_dmn_pair_mapping *ath_ + #define ATH_5GHZ_NO_MIDBAND ATH_5GHZ_5150_5350, \ + ATH_5GHZ_5725_5850 + ++#define REGD_RULES(...) \ ++ .reg_rules = { __VA_ARGS__ }, \ ++ .n_reg_rules = ARRAY_SIZE(((struct ieee80211_reg_rule[]) { __VA_ARGS__ })) ++ + /* Can be used for: + * 0x60, 0x61, 0x62 */ + static const struct ieee80211_regdomain ath_world_regdom_60_61_62 = { +- .n_reg_rules = 5, + .alpha2 = "99", +- .reg_rules = { ++ REGD_RULES( + ATH_2GHZ_ALL, + ATH_5GHZ_ALL, +- } ++ ) + }; + + /* Can be used by 0x63 and 0x65 */ + static const struct ieee80211_regdomain ath_world_regdom_63_65 = { +- .n_reg_rules = 4, + .alpha2 = "99", +- .reg_rules = { ++ REGD_RULES( + ATH_2GHZ_CH01_11, + ATH_2GHZ_CH12_13, + ATH_5GHZ_NO_MIDBAND, +- } ++ ) + }; + + /* Can be used by 0x64 only */ + static const struct ieee80211_regdomain ath_world_regdom_64 = { +- .n_reg_rules = 3, + .alpha2 = "99", +- .reg_rules = { ++ REGD_RULES( + ATH_2GHZ_CH01_11, + ATH_5GHZ_NO_MIDBAND, +- } ++ ) + }; + + /* Can be used by 0x66 and 0x69 */ + static const struct ieee80211_regdomain ath_world_regdom_66_69 = { +- .n_reg_rules = 3, + .alpha2 = "99", +- .reg_rules = { ++ REGD_RULES( + ATH_2GHZ_CH01_11, + ATH_5GHZ_ALL, +- } ++ ) + }; + + /* Can be used by 0x67, 0x68, 0x6A and 0x6C */ + static const struct ieee80211_regdomain ath_world_regdom_67_68_6A_6C = { +- .n_reg_rules = 4, + .alpha2 = "99", +- .reg_rules = { ++ REGD_RULES( + ATH_2GHZ_CH01_11, + ATH_2GHZ_CH12_13, + ATH_5GHZ_ALL, +- } ++ ) + }; + + static bool dynamic_country_user_possible(struct ath_regulatory *reg) diff --git a/feeds/ipq40xx/mac80211/patches/ath/404-regd_no_assoc_hints.patch b/feeds/ipq40xx/mac80211/patches/ath/404-regd_no_assoc_hints.patch new file mode 100644 index 000000000..89e26af76 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/ath/404-regd_no_assoc_hints.patch @@ -0,0 +1,19 @@ +--- a/net/wireless/reg.c ++++ b/net/wireless/reg.c +@@ -3042,6 +3042,8 @@ void regulatory_hint_country_ie(struct w + enum environment_cap env = ENVIRON_ANY; + struct regulatory_request *request = NULL, *lr; + ++ return; ++ + /* IE len must be evenly divisible by 2 */ + if (country_ie_len & 0x01) + return; +@@ -3293,6 +3295,7 @@ static bool is_wiphy_all_set_reg_flag(en + + void regulatory_hint_disconnect(void) + { ++ return; + /* Restore of regulatory settings is not required when wiphy(s) + * ignore IE from connected access point but clearance of beacon hints + * is required when wiphy(s) supports beacon hints. diff --git a/feeds/ipq40xx/mac80211/patches/ath/405-ath_regd_us.patch b/feeds/ipq40xx/mac80211/patches/ath/405-ath_regd_us.patch new file mode 100644 index 000000000..088833199 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/ath/405-ath_regd_us.patch @@ -0,0 +1,26 @@ +--- a/drivers/net/wireless/ath/regd_common.h ++++ b/drivers/net/wireless/ath/regd_common.h +@@ -32,6 +32,7 @@ enum EnumRd { + FCC2_WORLD = 0x21, + FCC2_ETSIC = 0x22, + FCC6_WORLD = 0x23, ++ FCC3_FCCA_2 = 0x2A, + FRANCE_RES = 0x31, + FCC3_FCCA = 0x3A, + FCC3_WORLD = 0x3B, +@@ -172,6 +173,7 @@ static struct reg_dmn_pair_mapping regDo + {FCC2_WORLD, CTL_FCC, CTL_ETSI}, + {FCC2_ETSIC, CTL_FCC, CTL_ETSI}, + {FCC3_FCCA, CTL_FCC, CTL_FCC}, ++ {FCC3_FCCA_2, CTL_FCC, CTL_FCC}, + {FCC3_WORLD, CTL_FCC, CTL_ETSI}, + {FCC3_ETSIC, CTL_FCC, CTL_ETSI}, + {FCC4_FCCA, CTL_FCC, CTL_FCC}, +@@ -483,6 +485,7 @@ static struct country_code_to_enum_rd al + {CTRY_UAE, NULL1_WORLD, "AE"}, + {CTRY_UNITED_KINGDOM, ETSI1_WORLD, "GB"}, + {CTRY_UNITED_STATES, FCC3_FCCA, "US"}, ++ {CTRY_UNITED_STATES, FCC3_FCCA_2, "US"}, + {CTRY_UNITED_STATES2, FCC3_FCCA, "US"}, + {CTRY_UNITED_STATES3, FCC3_FCCA, "US"}, + /* This "PS" is for US public safety actually... to support this we diff --git a/feeds/ipq40xx/mac80211/patches/ath/406-ath_relax_default_regd.patch b/feeds/ipq40xx/mac80211/patches/ath/406-ath_relax_default_regd.patch new file mode 100644 index 000000000..35b0f2b76 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/ath/406-ath_relax_default_regd.patch @@ -0,0 +1,51 @@ +--- a/drivers/net/wireless/ath/regd.c ++++ b/drivers/net/wireless/ath/regd.c +@@ -115,6 +115,16 @@ static const struct ieee80211_regdomain + ) + }; + ++static u16 ath_regd_get_eepromRD(struct ath_regulatory *reg) ++{ ++ return reg->current_rd & ~WORLDWIDE_ROAMING_FLAG; ++} ++ ++static bool is_default_regd(struct ath_regulatory *reg) ++{ ++ return ath_regd_get_eepromRD(reg) == CTRY_DEFAULT; ++} ++ + static bool dynamic_country_user_possible(struct ath_regulatory *reg) + { + if (IS_ENABLED(CPTCFG_ATH_USER_REGD)) +@@ -123,6 +133,9 @@ static bool dynamic_country_user_possibl + if (IS_ENABLED(CPTCFG_ATH_REG_DYNAMIC_USER_CERT_TESTING)) + return true; + ++ if (is_default_regd(reg)) ++ return true; ++ + switch (reg->country_code) { + case CTRY_UNITED_STATES: + case CTRY_JAPAN1: +@@ -208,11 +221,6 @@ static inline bool is_wwr_sku(u16 regd) + (regd == WORLD)); + } + +-static u16 ath_regd_get_eepromRD(struct ath_regulatory *reg) +-{ +- return reg->current_rd & ~WORLDWIDE_ROAMING_FLAG; +-} +- + bool ath_is_world_regd(struct ath_regulatory *reg) + { + return is_wwr_sku(ath_regd_get_eepromRD(reg)); +@@ -658,6 +666,9 @@ ath_regd_init_wiphy(struct ath_regulator + if (IS_ENABLED(CPTCFG_ATH_USER_REGD)) + return 0; + ++ if (is_default_regd(reg)) ++ return 0; ++ + wiphy->regulatory_flags |= REGULATORY_STRICT_REG | + REGULATORY_CUSTOM_REG; + diff --git a/feeds/ipq40xx/mac80211/patches/ath/410-ath9k_allow_adhoc_and_ap.patch b/feeds/ipq40xx/mac80211/patches/ath/410-ath9k_allow_adhoc_and_ap.patch new file mode 100644 index 000000000..bdf784968 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/ath/410-ath9k_allow_adhoc_and_ap.patch @@ -0,0 +1,10 @@ +--- a/drivers/net/wireless/ath/ath9k/init.c ++++ b/drivers/net/wireless/ath/ath9k/init.c +@@ -831,6 +831,7 @@ static const struct ieee80211_iface_limi + BIT(NL80211_IFTYPE_AP) }, + { .max = 1, .types = BIT(NL80211_IFTYPE_P2P_CLIENT) | + BIT(NL80211_IFTYPE_P2P_GO) }, ++ { .max = 1, .types = BIT(NL80211_IFTYPE_ADHOC) }, + }; + + #ifdef CPTCFG_WIRELESS_WDS diff --git a/feeds/ipq40xx/mac80211/patches/ath/411-ath5k_allow_adhoc_and_ap.patch b/feeds/ipq40xx/mac80211/patches/ath/411-ath5k_allow_adhoc_and_ap.patch new file mode 100644 index 000000000..9dbe047c9 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/ath/411-ath5k_allow_adhoc_and_ap.patch @@ -0,0 +1,46 @@ +--- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c ++++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c +@@ -86,13 +86,8 @@ ath5k_add_interface(struct ieee80211_hw + goto end; + } + +- /* Don't allow other interfaces if one ad-hoc is configured. +- * TODO: Fix the problems with ad-hoc and multiple other interfaces. +- * We would need to operate the HW in ad-hoc mode to allow TSF updates +- * for the IBSS, but this breaks with additional AP or STA interfaces +- * at the moment. */ +- if (ah->num_adhoc_vifs || +- (ah->nvifs && vif->type == NL80211_IFTYPE_ADHOC)) { ++ /* Don't allow more than one ad-hoc interface */ ++ if (ah->num_adhoc_vifs && vif->type == NL80211_IFTYPE_ADHOC) { + ATH5K_ERR(ah, "Only one single ad-hoc interface is allowed.\n"); + ret = -ELNRNG; + goto end; +--- a/drivers/net/wireless/ath/ath5k/base.c ++++ b/drivers/net/wireless/ath/ath5k/base.c +@@ -1964,7 +1964,7 @@ ath5k_beacon_send(struct ath5k_hw *ah) + } + + if ((ah->opmode == NL80211_IFTYPE_AP && ah->num_ap_vifs + +- ah->num_mesh_vifs > 1) || ++ ah->num_adhoc_vifs + ah->num_mesh_vifs > 1) || + ah->opmode == NL80211_IFTYPE_MESH_POINT) { + u64 tsf = ath5k_hw_get_tsf64(ah); + u32 tsftu = TSF_TO_TU(tsf); +@@ -2050,7 +2050,7 @@ ath5k_beacon_update_timers(struct ath5k_ + + intval = ah->bintval & AR5K_BEACON_PERIOD; + if (ah->opmode == NL80211_IFTYPE_AP && ah->num_ap_vifs +- + ah->num_mesh_vifs > 1) { ++ + ah->num_adhoc_vifs + ah->num_mesh_vifs > 1) { + intval /= ATH_BCBUF; /* staggered multi-bss beacons */ + if (intval < 15) + ATH5K_WARN(ah, "intval %u is too low, min 15\n", +@@ -2516,6 +2516,7 @@ static const struct ieee80211_iface_limi + BIT(NL80211_IFTYPE_MESH_POINT) | + #endif + BIT(NL80211_IFTYPE_AP) }, ++ { .max = 1, .types = BIT(NL80211_IFTYPE_ADHOC) }, + }; + + static const struct ieee80211_iface_combination if_comb = { diff --git a/feeds/ipq40xx/mac80211/patches/ath/420-ath5k_disable_fast_cc.patch b/feeds/ipq40xx/mac80211/patches/ath/420-ath5k_disable_fast_cc.patch new file mode 100644 index 000000000..414f49508 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/ath/420-ath5k_disable_fast_cc.patch @@ -0,0 +1,18 @@ +--- a/drivers/net/wireless/ath/ath5k/reset.c ++++ b/drivers/net/wireless/ath/ath5k/reset.c +@@ -1154,6 +1154,7 @@ ath5k_hw_reset(struct ath5k_hw *ah, enum + tsf_lo = 0; + mode = 0; + ++#if 0 + /* + * Sanity check for fast flag + * Fast channel change only available +@@ -1161,6 +1162,7 @@ ath5k_hw_reset(struct ath5k_hw *ah, enum + */ + if (fast && (ah->ah_radio != AR5K_RF2413) && + (ah->ah_radio != AR5K_RF5413)) ++#endif + fast = false; + + /* Disable sleep clock operation diff --git a/feeds/ipq40xx/mac80211/patches/ath/430-add_ath5k_platform.patch b/feeds/ipq40xx/mac80211/patches/ath/430-add_ath5k_platform.patch new file mode 100644 index 000000000..b213e2a81 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/ath/430-add_ath5k_platform.patch @@ -0,0 +1,33 @@ +--- /dev/null ++++ b/include/linux/ath5k_platform.h +@@ -0,0 +1,30 @@ ++/* ++ * Copyright (c) 2008 Atheros Communications Inc. ++ * Copyright (c) 2009 Gabor Juhos ++ * Copyright (c) 2009 Imre Kaloz ++ * Copyright (c) 2010 Daniel Golle ++ * ++ * 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 _LINUX_ATH5K_PLATFORM_H ++#define _LINUX_ATH5K_PLATFORM_H ++ ++#define ATH5K_PLAT_EEP_MAX_WORDS 2048 ++ ++struct ath5k_platform_data { ++ u16 *eeprom_data; ++ u8 *macaddr; ++}; ++ ++#endif /* _LINUX_ATH5K_PLATFORM_H */ diff --git a/feeds/ipq40xx/mac80211/patches/ath/431-add_platform_eeprom_support_to_ath5k.patch b/feeds/ipq40xx/mac80211/patches/ath/431-add_platform_eeprom_support_to_ath5k.patch new file mode 100644 index 000000000..136be1989 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/ath/431-add_platform_eeprom_support_to_ath5k.patch @@ -0,0 +1,56 @@ +--- a/drivers/net/wireless/ath/ath5k/pci.c ++++ b/drivers/net/wireless/ath/ath5k/pci.c +@@ -20,6 +20,7 @@ + #include + #include + #include ++#include + #include "../ath.h" + #include "ath5k.h" + #include "debug.h" +@@ -71,7 +72,7 @@ static void ath5k_pci_read_cachesize(str + } + + /* +- * Read from eeprom ++ * Read from eeprom or platform_data + */ + 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 = (struct ath5k_hw *) common->ah; + u32 status, timeout; + ++ struct ath5k_platform_data *pdata = NULL; ++ ++ if (ah->pdev) ++ pdata = ah->pdev->dev.platform_data; ++ ++ if (pdata && pdata->eeprom_data && pdata->eeprom_data[61] == AR5K_EEPROM_MAGIC_VALUE) { ++ if (offset >= ATH5K_PLAT_EEP_MAX_WORDS) ++ return false; ++ ++ *data = pdata->eeprom_data[offset]; ++ return true; ++ } ++ + /* + * Initialize EEPROM access + */ +@@ -122,6 +136,16 @@ static int ath5k_pci_eeprom_read_mac(str + u16 data; + int octet; + ++ struct ath5k_platform_data *pdata = NULL; ++ ++ if (ah->pdev) ++ pdata = ah->pdev->dev.platform_data; ++ ++ if (pdata && pdata->macaddr) { ++ memcpy(mac, pdata->macaddr, ETH_ALEN); ++ return 0; ++ } ++ + AR5K_EEPROM_READ(0x20, data); + + for (offset = 0x1f, octet = 0, total = 0; offset >= 0x1d; offset--) { diff --git a/feeds/ipq40xx/mac80211/patches/ath/432-ath5k_add_pciids.patch b/feeds/ipq40xx/mac80211/patches/ath/432-ath5k_add_pciids.patch new file mode 100644 index 000000000..bd0e6707a --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/ath/432-ath5k_add_pciids.patch @@ -0,0 +1,11 @@ +--- a/drivers/net/wireless/ath/ath5k/pci.c ++++ b/drivers/net/wireless/ath/ath5k/pci.c +@@ -47,6 +47,8 @@ static const struct pci_device_id ath5k_ + { PCI_VDEVICE(ATHEROS, 0x001b) }, /* 5413 Eagle */ + { PCI_VDEVICE(ATHEROS, 0x001c) }, /* PCI-E cards */ + { PCI_VDEVICE(ATHEROS, 0x001d) }, /* 2417 Nala */ ++ { PCI_VDEVICE(ATHEROS, 0xff16) }, /* 2413,2414 sx76x on lantiq_danube */ ++ { PCI_VDEVICE(ATHEROS, 0xff1a) }, /* 2417 arv45xx on lantiq_danube */ + { PCI_VDEVICE(ATHEROS, 0xff1b) }, /* AR5BXB63 */ + { 0 } + }; diff --git a/feeds/ipq40xx/mac80211/patches/ath/440-ath5k_channel_bw_debugfs.patch b/feeds/ipq40xx/mac80211/patches/ath/440-ath5k_channel_bw_debugfs.patch new file mode 100644 index 000000000..57d336327 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/ath/440-ath5k_channel_bw_debugfs.patch @@ -0,0 +1,142 @@ +This adds a bwmode debugfs file which can be used to set alternate +channel operating bandwidths. Only tested with AR5413 and only at +5 and 20 mhz channels. + +Signed-off-by: Pat Erley +--- +Other devices will need to be added to the switch in write_file_bwmode + +drivers/net/wireless/ath/ath5k/debug.c | 86 ++++++++++++++++++++++++++++++++ + 1 files changed, 86 insertions(+), 0 deletions(-) + +--- a/drivers/net/wireless/ath/ath5k/debug.c ++++ b/drivers/net/wireless/ath/ath5k/debug.c +@@ -822,6 +822,97 @@ static const struct file_operations fops + .llseek = default_llseek, + }; + ++/* debugfs: bwmode */ ++ ++static ssize_t read_file_bwmode(struct file *file, char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct ath5k_hw *ah = file->private_data; ++ char buf[15]; ++ unsigned int len = 0; ++ ++ int cur_ah_bwmode = ah->ah_bwmode_debug; ++ ++#define print_selected(MODE, LABEL) \ ++ if (cur_ah_bwmode == MODE) \ ++ len += snprintf(buf+len, sizeof(buf)-len, "[%s]", LABEL); \ ++ else \ ++ len += snprintf(buf+len, sizeof(buf)-len, "%s", LABEL); \ ++ len += snprintf(buf+len, sizeof(buf)-len, " "); ++ ++ print_selected(AR5K_BWMODE_5MHZ, "5"); ++ print_selected(AR5K_BWMODE_10MHZ, "10"); ++ print_selected(AR5K_BWMODE_DEFAULT, "20"); ++ print_selected(AR5K_BWMODE_40MHZ, "40"); ++#undef print_selected ++ ++ len += snprintf(buf+len, sizeof(buf)-len, "\n"); ++ ++ return simple_read_from_buffer(user_buf, count, ppos, buf, len); ++} ++ ++static ssize_t write_file_bwmode(struct file *file, ++ const char __user *userbuf, ++ size_t count, loff_t *ppos) ++{ ++ struct ath5k_hw *ah = file->private_data; ++ char buf[3]; ++ int bw = 20; ++ int tobwmode = AR5K_BWMODE_DEFAULT; ++ ++ if (copy_from_user(buf, userbuf, min(count, sizeof(buf)))) ++ return -EFAULT; ++ ++ /* TODO: Add check for active interface */ ++ ++ if(strncmp(buf, "5", 1) == 0 ) { ++ tobwmode = AR5K_BWMODE_5MHZ; ++ bw = 5; ++ } else if ( strncmp(buf, "10", 2) == 0 ) { ++ tobwmode = AR5K_BWMODE_10MHZ; ++ bw = 10; ++ } else if ( strncmp(buf, "20", 2) == 0 ) { ++ tobwmode = AR5K_BWMODE_DEFAULT; ++ bw = 20; ++ } else if ( strncmp(buf, "40", 2) == 0 ) { ++ tobwmode = AR5K_BWMODE_40MHZ; ++ bw = 40; ++ } else ++ return -EINVAL; ++ ++ ATH5K_INFO(ah, "Changing to %imhz channel width[%i]\n", ++ bw, tobwmode); ++ ++ switch (ah->ah_radio) { ++ /* TODO: only define radios that actually support 5/10mhz channels */ ++ case AR5K_RF5413: ++ case AR5K_RF5110: ++ case AR5K_RF5111: ++ case AR5K_RF5112: ++ case AR5K_RF2413: ++ case AR5K_RF2316: ++ case AR5K_RF2317: ++ case AR5K_RF2425: ++ if(ah->ah_bwmode_debug != tobwmode) { ++ mutex_lock(&ah->lock); ++ ah->ah_bwmode = tobwmode; ++ ah->ah_bwmode_debug = tobwmode; ++ mutex_unlock(&ah->lock); ++ } ++ break; ++ default: ++ return -EOPNOTSUPP; ++ } ++ return count; ++} ++ ++static const struct file_operations fops_bwmode = { ++ .read = read_file_bwmode, ++ .write = write_file_bwmode, ++ .open = simple_open, ++ .owner = THIS_MODULE, ++ .llseek = default_llseek, ++}; + + /* debugfs: queues etc */ + +@@ -1016,6 +1107,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); ++ debugfs_create_file("bwmode", S_IWUSR | S_IRUSR, phydir, ah, ++ &fops_bwmode); + } + + /* functions used in other places */ +--- a/drivers/net/wireless/ath/ath5k/ath5k.h ++++ b/drivers/net/wireless/ath/ath5k/ath5k.h +@@ -1372,6 +1372,7 @@ struct ath5k_hw { + u8 ah_coverage_class; + bool ah_ack_bitrate_high; + u8 ah_bwmode; ++ u8 ah_bwmode_debug; + bool ah_short_slot; + + /* Antenna Control */ +--- a/drivers/net/wireless/ath/ath5k/base.c ++++ b/drivers/net/wireless/ath/ath5k/base.c +@@ -466,6 +466,9 @@ ath5k_chan_set(struct ath5k_hw *ah, stru + return -EINVAL; + } + ++ if (ah->ah_bwmode_debug != AR5K_BWMODE_DEFAULT) ++ ah->ah_bwmode = ah->ah_bwmode_debug; ++ + /* + * To switch channels clear any pending DMA operations; + * wait long enough for the RX fifo to drain, reset the diff --git a/feeds/ipq40xx/mac80211/patches/ath/450-ath9k-enabled-MFP-capability-unconditionally.patch b/feeds/ipq40xx/mac80211/patches/ath/450-ath9k-enabled-MFP-capability-unconditionally.patch new file mode 100644 index 000000000..c75d6c798 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/ath/450-ath9k-enabled-MFP-capability-unconditionally.patch @@ -0,0 +1,34 @@ +From d946085ff5a331de64e91a2e3c96b9ca79d740f5 Mon Sep 17 00:00:00 2001 +From: David Bauer +Date: Mon, 15 Jun 2020 00:10:34 +0200 +Subject: [PATCH] ath9k: enabled MFP capability unconditionally + +ath9k will already fallback on software-crypto for chipsets not +supporting IEEE802.11w (MFP). So advertising MFP is not dependent +on disabling HW crypto for all traffic entirely. + +Signed-off-by: David Bauer +--- + drivers/net/wireless/ath/ath9k/init.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +--- a/drivers/net/wireless/ath/ath9k/init.c ++++ b/drivers/net/wireless/ath/ath9k/init.c +@@ -928,6 +928,7 @@ static void ath9k_set_hw_capab(struct at + ieee80211_hw_set(hw, HOST_BROADCAST_PS_BUFFERING); + ieee80211_hw_set(hw, SUPPORT_FAST_XMIT); + ieee80211_hw_set(hw, SUPPORTS_CLONED_SKBS); ++ ieee80211_hw_set(hw, MFP_CAPABLE); + + if (ath9k_ps_enable) + ieee80211_hw_set(hw, SUPPORTS_PS); +@@ -940,9 +941,6 @@ static void ath9k_set_hw_capab(struct at + IEEE80211_RADIOTAP_MCS_HAVE_STBC; + } + +- if (AR_SREV_9160_10_OR_LATER(sc->sc_ah) || ath9k_modparam_nohwcrypt) +- ieee80211_hw_set(hw, MFP_CAPABLE); +- + hw->wiphy->features |= NL80211_FEATURE_ACTIVE_MONITOR | + NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE | + NL80211_FEATURE_P2P_GO_CTWIN; diff --git a/feeds/ipq40xx/mac80211/patches/ath/500-ath9k_eeprom_debugfs.patch b/feeds/ipq40xx/mac80211/patches/ath/500-ath9k_eeprom_debugfs.patch new file mode 100644 index 000000000..786a3ed3f --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/ath/500-ath9k_eeprom_debugfs.patch @@ -0,0 +1,65 @@ +--- a/drivers/net/wireless/ath/ath9k/debug.c ++++ b/drivers/net/wireless/ath/ath9k/debug.c +@@ -1361,6 +1361,53 @@ void ath9k_deinit_debug(struct ath_softc + ath9k_cmn_spectral_deinit_debug(&sc->spec_priv); + } + ++static ssize_t read_file_eeprom(struct file *file, char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ 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; ++ int size = 4096; ++ u16 val; ++ int i; ++ ++ if (AR_SREV_9300_20_OR_LATER(ah)) ++ size = 16384; ++ ++ if (*ppos < 0) ++ return -EINVAL; ++ ++ if (count > size - *ppos) ++ count = size - *ppos; ++ ++ for (i = *ppos / 2; count > 0; count -= bytes, *ppos += bytes, i++) { ++ void *from = &val; ++ ++ if (!common->bus_ops->eeprom_read(common, i, &val)) ++ val = 0xffff; ++ ++ if (*ppos % 2) { ++ from++; ++ bytes = 1; ++ } else if (count == 1) { ++ bytes = 1; ++ } else { ++ bytes = 2; ++ } ++ copy_to_user(user_buf, from, bytes); ++ user_buf += bytes; ++ } ++ return *ppos - pos; ++} ++ ++static const struct file_operations fops_eeprom = { ++ .read = read_file_eeprom, ++ .open = simple_open, ++ .owner = THIS_MODULE ++}; ++ + int ath9k_init_debug(struct ath_hw *ah) + { + struct ath_common *common = ath9k_hw_common(ah); +@@ -1380,6 +1427,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); + 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/feeds/ipq40xx/mac80211/patches/ath/501-ath9k_ahb_init.patch b/feeds/ipq40xx/mac80211/patches/ath/501-ath9k_ahb_init.patch new file mode 100644 index 000000000..b9c784eb2 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/ath/501-ath9k_ahb_init.patch @@ -0,0 +1,34 @@ +--- a/drivers/net/wireless/ath/ath9k/init.c ++++ b/drivers/net/wireless/ath/ath9k/init.c +@@ -1143,25 +1143,25 @@ static int __init ath9k_init(void) + { + int error; + +- error = ath_pci_init(); ++ error = ath_ahb_init(); + if (error < 0) { +- pr_err("No PCI devices found, driver not installed\n"); + error = -ENODEV; + goto err_out; + } + +- error = ath_ahb_init(); ++ error = ath_pci_init(); + if (error < 0) { ++ pr_err("No PCI devices found, driver not installed\n"); + error = -ENODEV; +- goto err_pci_exit; ++ goto err_ahb_exit; + } + + dmi_check_system(ath9k_quirks); + + return 0; + +- err_pci_exit: +- ath_pci_exit(); ++ err_ahb_exit: ++ ath_ahb_exit(); + err_out: + return error; + } diff --git a/feeds/ipq40xx/mac80211/patches/ath/510-ath9k_intr_mitigation_tweak.patch b/feeds/ipq40xx/mac80211/patches/ath/510-ath9k_intr_mitigation_tweak.patch new file mode 100644 index 000000000..75b48b480 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/ath/510-ath9k_intr_mitigation_tweak.patch @@ -0,0 +1,18 @@ +--- a/drivers/net/wireless/ath/ath9k/hw.c ++++ b/drivers/net/wireless/ath/ath9k/hw.c +@@ -403,13 +403,8 @@ static void ath9k_hw_init_config(struct + + ah->config.rx_intr_mitigation = true; + +- if (AR_SREV_9300_20_OR_LATER(ah)) { +- ah->config.rimt_last = 500; +- ah->config.rimt_first = 2000; +- } else { +- ah->config.rimt_last = 250; +- ah->config.rimt_first = 700; +- } ++ ah->config.rimt_last = 250; ++ ah->config.rimt_first = 500; + + if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) + ah->config.pll_pwrsave = 7; diff --git a/feeds/ipq40xx/mac80211/patches/ath/511-ath9k_reduce_rxbuf.patch b/feeds/ipq40xx/mac80211/patches/ath/511-ath9k_reduce_rxbuf.patch new file mode 100644 index 000000000..15b8d7b86 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/ath/511-ath9k_reduce_rxbuf.patch @@ -0,0 +1,11 @@ +--- a/drivers/net/wireless/ath/ath9k/ath9k.h ++++ b/drivers/net/wireless/ath/ath9k/ath9k.h +@@ -88,7 +88,7 @@ int ath_descdma_setup(struct ath_softc * + (_l) &= ((_sz) - 1); \ + } while (0) + +-#define ATH_RXBUF 512 ++#define ATH_RXBUF 256 + #define ATH_TXBUF 512 + #define ATH_TXBUF_RESERVE 5 + #define ATH_TXMAXTRY 13 diff --git a/feeds/ipq40xx/mac80211/patches/ath/512-ath9k_channelbw_debugfs.patch b/feeds/ipq40xx/mac80211/patches/ath/512-ath9k_channelbw_debugfs.patch new file mode 100644 index 000000000..80e33182f --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/ath/512-ath9k_channelbw_debugfs.patch @@ -0,0 +1,125 @@ +--- a/drivers/net/wireless/ath/ath9k/debug.c ++++ b/drivers/net/wireless/ath/ath9k/debug.c +@@ -1408,6 +1408,52 @@ static const struct file_operations fops + .owner = THIS_MODULE + }; + ++ ++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); +@@ -1429,6 +1475,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 +@@ -149,6 +149,7 @@ struct ath_common { + int debug_mask; + enum ath_device_state state; + unsigned long op_flags; ++ u32 chan_bw; + + struct ath_ani 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 + /* + * Update internal channel flags. + */ +-static void ath9k_cmn_update_ichannel(struct ath9k_channel *ichan, ++static void ath9k_cmn_update_ichannel(struct ath_common *common, ++ struct ath9k_channel *ichan, + struct cfg80211_chan_def *chandef) + { + struct ieee80211_channel *chan = chandef->chan; + u16 flags = 0; ++ int width; + + ichan->channel = chan->center_freq; + ichan->chan = chan; +@@ -309,7 +311,19 @@ static void ath9k_cmn_update_ichannel(st + if (chan->band == NL80211_BAND_5GHZ) + flags |= CHANNEL_5GHZ; + +- switch (chandef->width) { ++ switch (common->chan_bw) { ++ case 5: ++ width = NL80211_CHAN_WIDTH_5; ++ break; ++ case 10: ++ width = NL80211_CHAN_WIDTH_10; ++ break; ++ default: ++ width = chandef->width; ++ break; ++ } ++ ++ switch (width) { + case NL80211_CHAN_WIDTH_5: + flags |= CHANNEL_QUARTER; + break; +@@ -342,10 +356,11 @@ struct ath9k_channel *ath9k_cmn_get_chan + struct cfg80211_chan_def *chandef) + { + struct ieee80211_channel *curchan = chandef->chan; ++ struct ath_common *common = ath9k_hw_common(ah); + struct ath9k_channel *channel; + + channel = &ah->channels[curchan->hw_value]; +- ath9k_cmn_update_ichannel(channel, chandef); ++ ath9k_cmn_update_ichannel(common, channel, chandef); + + return channel; + } diff --git a/feeds/ipq40xx/mac80211/patches/ath/513-ath9k_add_pci_ids.patch b/feeds/ipq40xx/mac80211/patches/ath/513-ath9k_add_pci_ids.patch new file mode 100644 index 000000000..113c35625 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/ath/513-ath9k_add_pci_ids.patch @@ -0,0 +1,30 @@ +--- a/drivers/net/wireless/ath/ath9k/hw.c ++++ b/drivers/net/wireless/ath/ath9k/hw.c +@@ -663,6 +663,7 @@ int ath9k_hw_init(struct ath_hw *ah) + + /* These are all the AR5008/AR9001/AR9002/AR9003 hardware family of chipsets */ + switch (ah->hw_version.devid) { ++ case AR9300_DEVID_INVALID: + case AR5416_DEVID_PCI: + case AR5416_DEVID_PCIE: + case AR5416_AR9100_DEVID: +--- a/drivers/net/wireless/ath/ath9k/hw.h ++++ b/drivers/net/wireless/ath/ath9k/hw.h +@@ -36,6 +36,7 @@ + + #define ATHEROS_VENDOR_ID 0x168c + ++#define AR9300_DEVID_INVALID 0xabcd + #define AR5416_DEVID_PCI 0x0023 + #define AR5416_DEVID_PCIE 0x0024 + #define AR9160_DEVID_PCI 0x0027 +--- a/drivers/net/wireless/ath/ath9k/pci.c ++++ b/drivers/net/wireless/ath/ath9k/pci.c +@@ -774,6 +774,7 @@ static const struct pci_device_id ath_pc + .driver_data = ATH9K_PCI_BT_ANT_DIV }, + #endif + ++ { PCI_VDEVICE(ATHEROS, 0xabcd) }, /* PCI-E internal chip default ID */ + { 0 } + }; + diff --git a/feeds/ipq40xx/mac80211/patches/ath/530-ath9k_extra_leds.patch b/feeds/ipq40xx/mac80211/patches/ath/530-ath9k_extra_leds.patch new file mode 100644 index 000000000..1f1948306 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/ath/530-ath9k_extra_leds.patch @@ -0,0 +1,267 @@ +--- a/drivers/net/wireless/ath/ath9k/ath9k.h ++++ b/drivers/net/wireless/ath/ath9k/ath9k.h +@@ -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); ++int ath_create_gpio_led(struct ath_softc *sc, int gpio, const char *name, ++ const char *trigger, bool active_low); ++ + #else + static inline void ath_init_leds(struct ath_softc *sc) + { +@@ -979,6 +982,13 @@ void ath_ant_comb_scan(struct ath_softc + + #define ATH9K_NUM_CHANCTX 2 /* supports 2 operating channels */ + ++struct ath_led { ++ struct list_head list; ++ struct ath_softc *sc; ++ const struct gpio_led *gpio; ++ struct led_classdev cdev; ++}; ++ + struct ath_softc { + struct ieee80211_hw *hw; + struct device *dev; +@@ -1032,9 +1042,8 @@ struct ath_softc { + spinlock_t chan_lock; + + #ifdef CPTCFG_MAC80211_LEDS +- bool led_registered; +- char led_name[32]; +- struct led_classdev led_cdev; ++ const char *led_default_trigger; ++ struct list_head leds; + #endif + + #ifdef CPTCFG_ATH9K_DEBUGFS +--- a/drivers/net/wireless/ath/ath9k/gpio.c ++++ b/drivers/net/wireless/ath/ath9k/gpio.c +@@ -39,61 +39,111 @@ static void ath_fill_led_pin(struct ath_ + else + ah->led_pin = ATH_LED_PIN_DEF; + } ++} ++ ++static void ath_led_brightness(struct led_classdev *led_cdev, ++ enum led_brightness brightness) ++{ ++ struct ath_led *led = container_of(led_cdev, struct ath_led, cdev); ++ struct ath_softc *sc = led->sc; ++ ++ ath9k_ps_wakeup(sc); ++ ath9k_hw_set_gpio(sc->sc_ah, led->gpio->gpio, ++ (brightness != LED_OFF) ^ led->gpio->active_low); ++ ath9k_ps_restore(sc); ++} ++ ++static int ath_add_led(struct ath_softc *sc, struct ath_led *led) ++{ ++ const struct gpio_led *gpio = led->gpio; ++ int ret; ++ ++ led->cdev.name = gpio->name; ++ led->cdev.default_trigger = gpio->default_trigger; ++ led->cdev.brightness_set = ath_led_brightness; ++ ++ ret = led_classdev_register(wiphy_dev(sc->hw->wiphy), &led->cdev); ++ if (ret < 0) ++ return ret; ++ ++ led->sc = sc; ++ list_add(&led->list, &sc->leds); + + /* Configure gpio for output */ +- ath9k_hw_gpio_request_out(ah, ah->led_pin, "ath9k-led", ++ ath9k_hw_gpio_request_out(sc->sc_ah, gpio->gpio, gpio->name, + AR_GPIO_OUTPUT_MUX_AS_OUTPUT); + +- /* LED off, active low */ +- ath9k_hw_set_gpio(ah, ah->led_pin, ah->config.led_active_high ? 0 : 1); ++ /* LED off */ ++ ath9k_hw_set_gpio(sc->sc_ah, gpio->gpio, gpio->active_low); ++ ++ return 0; + } + +-static void ath_led_brightness(struct led_classdev *led_cdev, +- enum led_brightness brightness) ++int ath_create_gpio_led(struct ath_softc *sc, int gpio_num, const char *name, ++ const char *trigger, bool active_low) + { +- struct ath_softc *sc = container_of(led_cdev, struct ath_softc, led_cdev); +- u32 val = (brightness == LED_OFF); ++ struct ath_led *led; ++ struct gpio_led *gpio; ++ char *_name; ++ int ret; + +- if (sc->sc_ah->config.led_active_high) +- val = !val; ++ led = kzalloc(sizeof(*led) + sizeof(*gpio) + strlen(name) + 1, ++ GFP_KERNEL); ++ if (!led) ++ return -ENOMEM; ++ ++ led->gpio = gpio = (struct gpio_led *) (led + 1); ++ _name = (char *) (led->gpio + 1); ++ ++ strcpy(_name, name); ++ gpio->name = _name; ++ gpio->gpio = gpio_num; ++ gpio->active_low = active_low; ++ gpio->default_trigger = trigger; ++ ++ ret = ath_add_led(sc, led); ++ if (unlikely(ret < 0)) ++ kfree(led); + +- ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, val); ++ return ret; + } + + void ath_deinit_leds(struct ath_softc *sc) + { +- if (!sc->led_registered) +- return; ++ struct ath_led *led; + +- ath_led_brightness(&sc->led_cdev, LED_OFF); +- led_classdev_unregister(&sc->led_cdev); +- +- ath9k_hw_gpio_free(sc->sc_ah, sc->sc_ah->led_pin); ++ while (!list_empty(&sc->leds)) { ++ led = list_first_entry(&sc->leds, struct ath_led, list); ++ list_del(&led->list); ++ ath_led_brightness(&led->cdev, LED_OFF); ++ led_classdev_unregister(&led->cdev); ++ ath9k_hw_gpio_free(sc->sc_ah, led->gpio->gpio); ++ kfree(led); ++ } + } + + void ath_init_leds(struct ath_softc *sc) + { +- int ret; ++ char led_name[32]; ++ const char *trigger; ++ ++ INIT_LIST_HEAD(&sc->leds); + + if (AR_SREV_9100(sc->sc_ah)) + return; + + ath_fill_led_pin(sc); + +- if (!ath9k_led_blink) +- sc->led_cdev.default_trigger = +- ieee80211_get_radio_led_name(sc->hw); +- +- snprintf(sc->led_name, sizeof(sc->led_name), +- "ath9k-%s", wiphy_name(sc->hw->wiphy)); +- sc->led_cdev.name = sc->led_name; +- sc->led_cdev.brightness_set = ath_led_brightness; ++ snprintf(led_name, sizeof(led_name), "ath9k-%s", ++ wiphy_name(sc->hw->wiphy)); + +- ret = led_classdev_register(wiphy_dev(sc->hw->wiphy), &sc->led_cdev); +- if (ret < 0) +- return; ++ if (ath9k_led_blink) ++ trigger = sc->led_default_trigger; ++ else ++ trigger = ieee80211_get_radio_led_name(sc->hw); + +- sc->led_registered = true; ++ ath_create_gpio_led(sc, sc->sc_ah->led_pin, led_name, trigger, ++ !sc->sc_ah->config.led_active_high); + } + #endif + +--- a/drivers/net/wireless/ath/ath9k/init.c ++++ b/drivers/net/wireless/ath/ath9k/init.c +@@ -1055,7 +1055,7 @@ int ath9k_init_device(u16 devid, struct + + #ifdef CPTCFG_MAC80211_LEDS + /* must be initialized before ieee80211_register_hw */ +- sc->led_cdev.default_trigger = ieee80211_create_tpt_led_trigger(sc->hw, ++ sc->led_default_trigger = ieee80211_create_tpt_led_trigger(sc->hw, + IEEE80211_TPT_LEDTRIG_FL_RADIO, ath9k_tpt_blink, + ARRAY_SIZE(ath9k_tpt_blink)); + #endif +--- a/drivers/net/wireless/ath/ath9k/debug.c ++++ b/drivers/net/wireless/ath/ath9k/debug.c +@@ -1453,6 +1453,61 @@ static const struct file_operations fops + .llseek = default_llseek, + }; + ++#ifdef CONFIG_MAC80211_LEDS ++ ++static ssize_t write_file_gpio_led(struct file *file, const char __user *ubuf, ++ size_t count, loff_t *ppos) ++{ ++ struct ath_softc *sc = file->private_data; ++ char buf[32], *str, *name, *c; ++ ssize_t len; ++ unsigned int gpio; ++ bool active_low = false; ++ ++ len = min(count, sizeof(buf) - 1); ++ if (copy_from_user(buf, ubuf, len)) ++ return -EFAULT; ++ ++ buf[len] = '\0'; ++ name = strchr(buf, ','); ++ if (!name) ++ return -EINVAL; ++ ++ *(name++) = 0; ++ if (!*name) ++ return -EINVAL; ++ ++ c = strchr(name, '\n'); ++ if (c) ++ *c = 0; ++ ++ str = buf; ++ if (*str == '!') { ++ str++; ++ active_low = true; ++ } ++ ++ if (kstrtouint(str, 0, &gpio) < 0) ++ return -EINVAL; ++ ++ if (gpio >= sc->sc_ah->caps.num_gpio_pins) ++ return -EINVAL; ++ ++ if (ath_create_gpio_led(sc, gpio, name, NULL, active_low) < 0) ++ return -EINVAL; ++ ++ return count; ++} ++ ++static const struct file_operations fops_gpio_led = { ++ .write = write_file_gpio_led, ++ .open = simple_open, ++ .owner = THIS_MODULE, ++ .llseek = default_llseek, ++}; ++ ++#endif ++ + + int ath9k_init_debug(struct ath_hw *ah) + { +@@ -1477,6 +1532,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); ++#endif + 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/feeds/ipq40xx/mac80211/patches/ath/531-ath9k_extra_platform_leds.patch b/feeds/ipq40xx/mac80211/patches/ath/531-ath9k_extra_platform_leds.patch new file mode 100644 index 000000000..8ed7ad8a0 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/ath/531-ath9k_extra_platform_leds.patch @@ -0,0 +1,76 @@ +--- 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 @@ + */ + + #include "ath9k.h" ++#include + + /********************************/ + /* LED functions */ +@@ -108,6 +109,24 @@ int ath_create_gpio_led(struct ath_softc + return ret; + } + ++static int ath_create_platform_led(struct ath_softc *sc, ++ const struct gpio_led *gpio) ++{ ++ struct ath_led *led; ++ int ret; ++ ++ led = kzalloc(sizeof(*led), GFP_KERNEL); ++ if (!led) ++ return -ENOMEM; ++ ++ led->gpio = gpio; ++ ret = ath_add_led(sc, led); ++ if (ret < 0) ++ kfree(led); ++ ++ return ret; ++} ++ + void ath_deinit_leds(struct ath_softc *sc) + { + struct ath_led *led; +@@ -124,8 +143,10 @@ void ath_deinit_leds(struct ath_softc *s + + void ath_init_leds(struct ath_softc *sc) + { ++ struct ath9k_platform_data *pdata = sc->dev->platform_data; + char led_name[32]; + const char *trigger; ++ int i; + + INIT_LIST_HEAD(&sc->leds); + +@@ -134,6 +155,17 @@ void ath_init_leds(struct ath_softc *sc) + + ath_fill_led_pin(sc); + ++ if (pdata && pdata->leds && pdata->num_leds) ++ for (i = 0; i < pdata->num_leds; i++) { ++ if (pdata->leds[i].gpio == sc->sc_ah->led_pin) ++ sc->sc_ah->led_pin = -1; ++ ++ ath_create_platform_led(sc, &pdata->leds[i]); ++ } ++ ++ if (sc->sc_ah->led_pin < 0) ++ return; ++ + snprintf(led_name, sizeof(led_name), "ath9k-%s", + wiphy_name(sc->hw->wiphy)); + diff --git a/feeds/ipq40xx/mac80211/patches/ath/540-ath9k_reduce_ani_interval.patch b/feeds/ipq40xx/mac80211/patches/ath/540-ath9k_reduce_ani_interval.patch new file mode 100644 index 000000000..e89990347 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/ath/540-ath9k_reduce_ani_interval.patch @@ -0,0 +1,11 @@ +--- a/drivers/net/wireless/ath/ath9k/ani.h ++++ b/drivers/net/wireless/ath/ath9k/ani.h +@@ -42,7 +42,7 @@ + #define ATH9K_ANI_PERIOD 300 + + /* in ms */ +-#define ATH9K_ANI_POLLINTERVAL 1000 ++#define ATH9K_ANI_POLLINTERVAL 300 + + #define ATH9K_SIG_FIRSTEP_SETTING_MIN 0 + #define ATH9K_SIG_FIRSTEP_SETTING_MAX 20 diff --git a/feeds/ipq40xx/mac80211/patches/ath/542-ath9k_debugfs_diag.patch b/feeds/ipq40xx/mac80211/patches/ath/542-ath9k_debugfs_diag.patch new file mode 100644 index 000000000..5220157de --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/ath/542-ath9k_debugfs_diag.patch @@ -0,0 +1,139 @@ +--- a/drivers/net/wireless/ath/ath9k/debug.c ++++ b/drivers/net/wireless/ath/ath9k/debug.c +@@ -1509,6 +1509,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) ++{ ++ struct ath_softc *sc = file->private_data; ++ struct ath_hw *ah = sc->sc_ah; ++ char buf[32]; ++ unsigned int len; ++ ++ len = sprintf(buf, "0x%08lx\n", ah->diag); ++ return simple_read_from_buffer(user_buf, count, ppos, buf, len); ++} ++ ++static ssize_t write_file_diag(struct file *file, const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct ath_softc *sc = file->private_data; ++ struct ath_hw *ah = sc->sc_ah; ++ unsigned long diag; ++ 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, &diag)) ++ return -EINVAL; ++ ++ ah->diag = diag; ++ ath9k_hw_update_diag(ah); ++ ++ return count; ++} ++ ++static const struct file_operations fops_diag = { ++ .read = read_file_diag, ++ .write = write_file_diag, ++ .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); +@@ -1536,6 +1580,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 ++ debugfs_create_file("diag", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, ++ sc, &fops_diag); + 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/ath9k/hw.h ++++ b/drivers/net/wireless/ath/ath9k/hw.h +@@ -522,6 +522,12 @@ enum { + ATH9K_RESET_COLD, + }; + ++enum { ++ ATH_DIAG_DISABLE_RX, ++ ATH_DIAG_DISABLE_TX, ++ ATH_DIAG_TRIGGER_ERROR, ++}; ++ + struct ath9k_hw_version { + u32 magic; + u16 devid; +@@ -810,6 +816,8 @@ struct ath_hw { + u32 ah_flags; + s16 nf_override; + ++ unsigned long diag; ++ + bool reset_power_on; + bool htc_reset_init; + +@@ -1076,6 +1084,7 @@ void ath9k_hw_check_nav(struct ath_hw *a + bool ath9k_hw_check_alive(struct ath_hw *ah); + + bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode); ++void ath9k_hw_update_diag(struct ath_hw *ah); + + /* Generic hw timer primitives */ + struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah, +--- a/drivers/net/wireless/ath/ath9k/hw.c ++++ b/drivers/net/wireless/ath/ath9k/hw.c +@@ -1883,6 +1883,20 @@ u32 ath9k_hw_get_tsf_offset(struct times + } + EXPORT_SYMBOL(ath9k_hw_get_tsf_offset); + ++void ath9k_hw_update_diag(struct ath_hw *ah) ++{ ++ if (test_bit(ATH_DIAG_DISABLE_RX, &ah->diag)) ++ REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS); ++ else ++ REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS); ++ ++ if (test_bit(ATH_DIAG_DISABLE_TX, &ah->diag)) ++ REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_LOOP_BACK); ++ else ++ REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_LOOP_BACK); ++} ++EXPORT_SYMBOL(ath9k_hw_update_diag); ++ + int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, + struct ath9k_hw_cal_data *caldata, bool fastcc) + { +@@ -2091,6 +2105,7 @@ int ath9k_hw_reset(struct ath_hw *ah, st + ar9003_hw_disable_phy_restart(ah); + + ath9k_hw_apply_gpio_override(ah); ++ ath9k_hw_update_diag(ah); + + if (AR_SREV_9565(ah) && common->bt_ant_diversity) + 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 +@@ -528,6 +528,11 @@ irqreturn_t ath_isr(int irq, void *dev) + if (test_bit(ATH_OP_HW_RESET, &common->op_flags)) + return IRQ_HANDLED; + ++ if (test_bit(ATH_DIAG_TRIGGER_ERROR, &ah->diag)) { ++ status |= ATH9K_INT_FATAL; ++ clear_bit(ATH_DIAG_TRIGGER_ERROR, &ah->diag); ++ } ++ + /* + * If there are no status bits set, then this interrupt was not + * for me (should have been caught above). diff --git a/feeds/ipq40xx/mac80211/patches/ath/543-ath9k_entropy_from_adc.patch b/feeds/ipq40xx/mac80211/patches/ath/543-ath9k_entropy_from_adc.patch new file mode 100644 index 000000000..f59654e41 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/ath/543-ath9k_entropy_from_adc.patch @@ -0,0 +1,186 @@ +--- a/drivers/net/wireless/ath/ath9k/hw.h ++++ b/drivers/net/wireless/ath/ath9k/hw.h +@@ -723,6 +723,7 @@ struct ath_spec_scan { + * @config_pci_powersave: + * @calibrate: periodic calibration for NF, ANI, IQ, ADC gain, ADC-DC + * ++ * @get_adc_entropy: get entropy from the raw ADC I/Q output + * @spectral_scan_config: set parameters for spectral scan and enable/disable it + * @spectral_scan_trigger: trigger a spectral scan run + * @spectral_scan_wait: wait for a spectral scan run to finish +@@ -745,6 +746,7 @@ struct ath_hw_ops { + struct ath_hw_antcomb_conf *antconf); + void (*antdiv_comb_conf_set)(struct ath_hw *ah, + struct ath_hw_antcomb_conf *antconf); ++ void (*get_adc_entropy)(struct ath_hw *ah, u8 *buf, size_t len); + void (*spectral_scan_config)(struct ath_hw *ah, + struct ath_spec_scan *param); + 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 +@@ -1927,6 +1927,26 @@ void ar9003_hw_init_rate_txpower(struct + } + } + ++static void ar9003_hw_get_adc_entropy(struct ath_hw *ah, u8 *buf, size_t len) ++{ ++ int i, j; ++ ++ 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++) { ++ for (j = 0; j < 4; j++) { ++ u32 regval = REG_READ(ah, AR_PHY_TST_ADC); ++ ++ buf[i] <<= 2; ++ buf[i] |= (regval & 1) | ((regval & BIT(10)) >> 9); ++ udelay(1); ++ } ++ } ++} ++ + void ar9003_hw_attach_phy_ops(struct ath_hw *ah) + { + struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); +@@ -1963,6 +1983,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; + ++ ops->get_adc_entropy = ar9003_hw_get_adc_entropy; + ops->antdiv_comb_conf_get = ar9003_hw_antdiv_comb_conf_get; + ops->antdiv_comb_conf_set = ar9003_hw_antdiv_comb_conf_set; + 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 +@@ -819,7 +819,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); + +- ah->curchan = curchan; ++ if (curchan) ++ ah->curchan = curchan; + } + + static const struct ieee80211_iface_limit if_limits[] = { +@@ -1015,6 +1016,18 @@ static void ath9k_set_hw_capab(struct at + NL80211_EXT_FEATURE_MULTICAST_REGISTRATIONS); + } + ++static void ath_get_initial_entropy(struct ath_softc *sc) ++{ ++ struct ath_hw *ah = sc->sc_ah; ++ char buf[256]; ++ ++ /* reuse last channel initialized by the tx power test */ ++ ath9k_hw_reset(ah, ah->curchan, NULL, false); ++ ++ ath9k_hw_get_adc_entropy(ah, buf, sizeof(buf)); ++ add_device_randomness(buf, sizeof(buf)); ++} ++ + int ath9k_init_device(u16 devid, struct ath_softc *sc, + const struct ath_bus_ops *bus_ops) + { +@@ -1060,6 +1073,8 @@ int ath9k_init_device(u16 devid, struct + ARRAY_SIZE(ath9k_tpt_blink)); + #endif + ++ ath_get_initial_entropy(sc); ++ + /* Register with mac80211 */ + error = ieee80211_register_hw(hw); + if (error) +--- a/drivers/net/wireless/ath/ath9k/hw-ops.h ++++ b/drivers/net/wireless/ath/ath9k/hw-ops.h +@@ -100,6 +100,12 @@ static inline void ath9k_hw_tx99_set_txp + ath9k_hw_ops(ah)->tx99_set_txpower(ah, power); + } + ++static inline void ath9k_hw_get_adc_entropy(struct ath_hw *ah, ++ u8 *buf, size_t len) ++{ ++ ath9k_hw_ops(ah)->get_adc_entropy(ah, buf, len); ++} ++ + #ifdef CPTCFG_ATH9K_BTCOEX_SUPPORT + + static inline void ath9k_hw_set_bt_ant_diversity(struct ath_hw *ah, bool enable) +--- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c ++++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c +@@ -1320,9 +1320,30 @@ void ar5008_hw_init_rate_txpower(struct + } + } + ++static void ar5008_hw_get_adc_entropy(struct ath_hw *ah, u8 *buf, size_t len) ++{ ++ int i, j; ++ ++ 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_TEST2, AR_PHY_TEST2_RX_OBS_SEL, 0); ++ ++ memset(buf, 0, len); ++ for (i = 0; i < len; i++) { ++ for (j = 0; j < 4; j++) { ++ u32 regval = REG_READ(ah, AR_PHY_TST_ADC); ++ ++ buf[i] <<= 2; ++ buf[i] |= (regval & 1) | ((regval & BIT(9)) >> 8); ++ udelay(1); ++ } ++ } ++} ++ + int ar5008_hw_attach_phy_ops(struct ath_hw *ah) + { + struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); ++ struct ath_hw_ops *ops = ath9k_hw_ops(ah); + static const u32 ar5416_cca_regs[6] = { + AR_PHY_CCA, + AR_PHY_CH1_CCA, +@@ -1337,6 +1358,8 @@ int ar5008_hw_attach_phy_ops(struct ath_ + if (ret) + return ret; + ++ ops->get_adc_entropy = ar5008_hw_get_adc_entropy; ++ + priv_ops->rf_set_freq = ar5008_hw_set_channel; + priv_ops->spur_mitigate_freq = ar5008_hw_spur_mitigate; + +--- a/drivers/net/wireless/ath/ath9k/ar9002_phy.h ++++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.h +@@ -20,6 +20,12 @@ + #define PHY_AGC_CLR 0x10000000 + #define RFSILENT_BB 0x00002000 + ++#define AR_PHY_TEST_BBB_OBS_SEL 0x780000 ++#define AR_PHY_TEST_BBB_OBS_SEL_S 19 ++ ++#define AR_PHY_TEST_RX_OBS_SEL_BIT5_S 23 ++#define AR_PHY_TEST_RX_OBS_SEL_BIT5 (1 << AR_PHY_TEST_RX_OBS_SEL_BIT5_S) ++ + #define AR_PHY_TURBO 0x9804 + #define AR_PHY_FC_TURBO_MODE 0x00000001 + #define AR_PHY_FC_TURBO_SHORT 0x00000002 +@@ -36,6 +42,9 @@ + + #define AR_PHY_TEST2 0x9808 + ++#define AR_PHY_TEST2_RX_OBS_SEL 0x3C00 ++#define AR_PHY_TEST2_RX_OBS_SEL_S 10 ++ + #define AR_PHY_TIMING2 0x9810 + #define AR_PHY_TIMING3 0x9814 + #define AR_PHY_TIMING3_DSC_MAN 0xFFFE0000 +@@ -393,6 +402,8 @@ + #define AR_PHY_RFBUS_GRANT 0x9C20 + #define AR_PHY_RFBUS_GRANT_EN 0x00000001 + ++#define AR_PHY_TST_ADC 0x9C24 ++ + #define AR_PHY_CHAN_INFO_GAIN_DIFF 0x9CF4 + #define AR_PHY_CHAN_INFO_GAIN_DIFF_UPPER_LIMIT 320 + diff --git a/feeds/ipq40xx/mac80211/patches/ath/544-ath9k-ar933x-usb-hang-workaround.patch b/feeds/ipq40xx/mac80211/patches/ath/544-ath9k-ar933x-usb-hang-workaround.patch new file mode 100644 index 000000000..93eee34b6 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/ath/544-ath9k-ar933x-usb-hang-workaround.patch @@ -0,0 +1,79 @@ +--- a/drivers/net/wireless/ath/ath9k/hw.c ++++ b/drivers/net/wireless/ath/ath9k/hw.c +@@ -248,6 +248,19 @@ void ath9k_hw_get_channel_centers(struct + centers->synth_center + (extoff * HT40_CHANNEL_CENTER_SHIFT); + } + ++static inline void ath9k_hw_disable_pll_lock_detect(struct ath_hw *ah) ++{ ++ /* On AR9330 and AR9340 devices, some PHY registers must be ++ * tuned to gain better stability/performance. These registers ++ * might be changed while doing wlan reset so the registers must ++ * be reprogrammed after each reset. ++ */ ++ REG_CLR_BIT(ah, AR_PHY_USB_CTRL1, BIT(20)); ++ REG_RMW(ah, AR_PHY_USB_CTRL2, ++ (1 << 21) | (0xf << 22), ++ (1 << 21) | (0x3 << 22)); ++} ++ + /******************/ + /* Chip Revisions */ + /******************/ +@@ -1455,6 +1468,9 @@ static bool ath9k_hw_set_reset(struct at + udelay(50); + } + ++ if (AR_SREV_9330(ah) || AR_SREV_9340(ah)) ++ ath9k_hw_disable_pll_lock_detect(ah); ++ + return true; + } + +@@ -1554,6 +1570,9 @@ static bool ath9k_hw_chip_reset(struct a + ar9003_hw_internal_regulator_apply(ah); + ath9k_hw_init_pll(ah, chan); + ++ if (AR_SREV_9330(ah) || AR_SREV_9340(ah)) ++ ath9k_hw_disable_pll_lock_detect(ah); ++ + return true; + } + +@@ -1861,8 +1880,14 @@ static int ath9k_hw_do_fastcc(struct ath + if (AR_SREV_9271(ah)) + ar9002_hw_load_ani_reg(ah, chan); + ++ if (AR_SREV_9330(ah) || AR_SREV_9340(ah)) ++ ath9k_hw_disable_pll_lock_detect(ah); ++ + return 0; + fail: ++ if (AR_SREV_9330(ah) || AR_SREV_9340(ah)) ++ ath9k_hw_disable_pll_lock_detect(ah); ++ + return -EINVAL; + } + +@@ -2116,6 +2141,9 @@ int ath9k_hw_reset(struct ath_hw *ah, st + ath9k_hw_set_radar_params(ah); + } + ++ if (AR_SREV_9330(ah) || AR_SREV_9340(ah)) ++ ath9k_hw_disable_pll_lock_detect(ah); ++ + return 0; + } + EXPORT_SYMBOL(ath9k_hw_reset); +--- a/drivers/net/wireless/ath/ath9k/phy.h ++++ b/drivers/net/wireless/ath/ath9k/phy.h +@@ -48,6 +48,9 @@ + #define AR_PHY_PLL_CONTROL 0x16180 + #define AR_PHY_PLL_MODE 0x16184 + ++#define AR_PHY_USB_CTRL1 0x16c84 ++#define AR_PHY_USB_CTRL2 0x16c88 ++ + enum ath9k_ant_div_comb_lna_conf { + ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2, + ATH_ANT_DIV_COMB_LNA2, diff --git a/feeds/ipq40xx/mac80211/patches/ath/545-ath9k_ani_ws_detect.patch b/feeds/ipq40xx/mac80211/patches/ath/545-ath9k_ani_ws_detect.patch new file mode 100644 index 000000000..48cc17113 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/ath/545-ath9k_ani_ws_detect.patch @@ -0,0 +1,155 @@ +--- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c ++++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c +@@ -949,55 +949,6 @@ static bool ar5008_hw_ani_control_new(st + * on == 0 means more noise imm + */ + u32 on = param ? 1 : 0; +- /* +- * make register setting for default +- * (weak sig detect ON) come from INI file +- */ +- int m1ThreshLow = on ? +- aniState->iniDef.m1ThreshLow : m1ThreshLow_off; +- int m2ThreshLow = on ? +- aniState->iniDef.m2ThreshLow : m2ThreshLow_off; +- int m1Thresh = on ? +- aniState->iniDef.m1Thresh : m1Thresh_off; +- int m2Thresh = on ? +- aniState->iniDef.m2Thresh : m2Thresh_off; +- int m2CountThr = on ? +- aniState->iniDef.m2CountThr : m2CountThr_off; +- int m2CountThrLow = on ? +- aniState->iniDef.m2CountThrLow : m2CountThrLow_off; +- int m1ThreshLowExt = on ? +- aniState->iniDef.m1ThreshLowExt : m1ThreshLowExt_off; +- int m2ThreshLowExt = on ? +- aniState->iniDef.m2ThreshLowExt : m2ThreshLowExt_off; +- int m1ThreshExt = on ? +- aniState->iniDef.m1ThreshExt : m1ThreshExt_off; +- int m2ThreshExt = on ? +- aniState->iniDef.m2ThreshExt : m2ThreshExt_off; +- +- REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, +- AR_PHY_SFCORR_LOW_M1_THRESH_LOW, +- m1ThreshLow); +- REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, +- AR_PHY_SFCORR_LOW_M2_THRESH_LOW, +- m2ThreshLow); +- REG_RMW_FIELD(ah, AR_PHY_SFCORR, +- AR_PHY_SFCORR_M1_THRESH, m1Thresh); +- REG_RMW_FIELD(ah, AR_PHY_SFCORR, +- AR_PHY_SFCORR_M2_THRESH, m2Thresh); +- REG_RMW_FIELD(ah, AR_PHY_SFCORR, +- AR_PHY_SFCORR_M2COUNT_THR, m2CountThr); +- REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, +- AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW, +- m2CountThrLow); +- +- REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, +- AR_PHY_SFCORR_EXT_M1_THRESH_LOW, m1ThreshLowExt); +- REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, +- AR_PHY_SFCORR_EXT_M2_THRESH_LOW, m2ThreshLowExt); +- REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, +- AR_PHY_SFCORR_EXT_M1_THRESH, m1ThreshExt); +- REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, +- AR_PHY_SFCORR_EXT_M2_THRESH, m2ThreshExt); + + if (on) + REG_SET_BIT(ah, AR_PHY_SFCORR_LOW, +--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c ++++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c +@@ -42,20 +42,6 @@ static const int cycpwrThr1_table[] = + /* level: 0 1 2 3 4 5 6 7 8 */ + { -6, -4, -2, 0, 2, 4, 6, 8 }; /* lvl 0-7, default 3 */ + +-/* +- * register values to turn OFDM weak signal detection OFF +- */ +-static const int m1ThreshLow_off = 127; +-static const int m2ThreshLow_off = 127; +-static const int m1Thresh_off = 127; +-static const int m2Thresh_off = 127; +-static const int m2CountThr_off = 31; +-static const int m2CountThrLow_off = 63; +-static const int m1ThreshLowExt_off = 127; +-static const int m2ThreshLowExt_off = 127; +-static const int m1ThreshExt_off = 127; +-static const int m2ThreshExt_off = 127; +- + static const u8 ofdm2pwr[] = { + ALL_TARGET_LEGACY_6_24, + ALL_TARGET_LEGACY_6_24, +@@ -1077,11 +1063,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; +- int m1ThreshLow, m2ThreshLow; +- int m1Thresh, m2Thresh; +- int m2CountThr, m2CountThrLow; +- int m1ThreshLowExt, m2ThreshLowExt; +- int m1ThreshExt, m2ThreshExt; + s32 value, value2; + + switch (cmd & ah->ani_function) { +@@ -1095,61 +1076,6 @@ static bool ar9003_hw_ani_control(struct + */ + u32 on = param ? 1 : 0; + +- if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) +- goto skip_ws_det; +- +- m1ThreshLow = on ? +- aniState->iniDef.m1ThreshLow : m1ThreshLow_off; +- m2ThreshLow = on ? +- aniState->iniDef.m2ThreshLow : m2ThreshLow_off; +- m1Thresh = on ? +- aniState->iniDef.m1Thresh : m1Thresh_off; +- m2Thresh = on ? +- aniState->iniDef.m2Thresh : m2Thresh_off; +- m2CountThr = on ? +- aniState->iniDef.m2CountThr : m2CountThr_off; +- m2CountThrLow = on ? +- aniState->iniDef.m2CountThrLow : m2CountThrLow_off; +- m1ThreshLowExt = on ? +- aniState->iniDef.m1ThreshLowExt : m1ThreshLowExt_off; +- m2ThreshLowExt = on ? +- aniState->iniDef.m2ThreshLowExt : m2ThreshLowExt_off; +- m1ThreshExt = on ? +- aniState->iniDef.m1ThreshExt : m1ThreshExt_off; +- m2ThreshExt = on ? +- aniState->iniDef.m2ThreshExt : m2ThreshExt_off; +- +- REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, +- AR_PHY_SFCORR_LOW_M1_THRESH_LOW, +- m1ThreshLow); +- REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, +- AR_PHY_SFCORR_LOW_M2_THRESH_LOW, +- m2ThreshLow); +- REG_RMW_FIELD(ah, AR_PHY_SFCORR, +- AR_PHY_SFCORR_M1_THRESH, +- m1Thresh); +- REG_RMW_FIELD(ah, AR_PHY_SFCORR, +- AR_PHY_SFCORR_M2_THRESH, +- m2Thresh); +- REG_RMW_FIELD(ah, AR_PHY_SFCORR, +- AR_PHY_SFCORR_M2COUNT_THR, +- m2CountThr); +- REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, +- AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW, +- m2CountThrLow); +- REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, +- AR_PHY_SFCORR_EXT_M1_THRESH_LOW, +- m1ThreshLowExt); +- REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, +- AR_PHY_SFCORR_EXT_M2_THRESH_LOW, +- m2ThreshLowExt); +- REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, +- AR_PHY_SFCORR_EXT_M1_THRESH, +- m1ThreshExt); +- REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, +- AR_PHY_SFCORR_EXT_M2_THRESH, +- m2ThreshExt); +-skip_ws_det: + if (on) + REG_SET_BIT(ah, AR_PHY_SFCORR_LOW, + AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW); diff --git a/feeds/ipq40xx/mac80211/patches/ath/547-ath9k_led_defstate_fix.patch b/feeds/ipq40xx/mac80211/patches/ath/547-ath9k_led_defstate_fix.patch new file mode 100644 index 000000000..5d84cf0c4 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/ath/547-ath9k_led_defstate_fix.patch @@ -0,0 +1,29 @@ +From: Michal Cieslakiewicz +Date: Sun, 31 Jan 2016 20:48:49 +0100 +Subject: [PATCH v4 2/8] mac80211: ath9k: set default state for platform LEDs + +Support default state for platform LEDs connected to ath9k device. +Now LEDs are correctly set on or off at ath9k module initialization. +Very useful if power LED is connected to wireless chip. + +Signed-off-by: Michal Cieslakiewicz +--- + gpio.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +--- a/drivers/net/wireless/ath/ath9k/gpio.c ++++ b/drivers/net/wireless/ath/ath9k/gpio.c +@@ -74,8 +74,11 @@ static int ath_add_led(struct ath_softc + ath9k_hw_gpio_request_out(sc->sc_ah, gpio->gpio, gpio->name, + AR_GPIO_OUTPUT_MUX_AS_OUTPUT); + +- /* LED off */ +- ath9k_hw_set_gpio(sc->sc_ah, gpio->gpio, gpio->active_low); ++ /* Set default LED state */ ++ if (gpio->default_state == LEDS_GPIO_DEFSTATE_ON) ++ ath9k_hw_set_gpio(sc->sc_ah, gpio->gpio, !gpio->active_low); ++ else ++ ath9k_hw_set_gpio(sc->sc_ah, gpio->gpio, gpio->active_low); + + return 0; + } diff --git a/feeds/ipq40xx/mac80211/patches/ath/548-ath9k_enable_gpio_chip.patch b/feeds/ipq40xx/mac80211/patches/ath/548-ath9k_enable_gpio_chip.patch new file mode 100644 index 000000000..78206d286 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/ath/548-ath9k_enable_gpio_chip.patch @@ -0,0 +1,251 @@ +From: Michal Cieslakiewicz +Date: Sun, 31 Jan 2016 21:01:31 +0100 +Subject: [PATCH v4 4/8] mac80211: ath9k: enable access to GPIO + +Enable access to GPIO chip and its pins for Atheros AR92xx +wireless devices. For now AR9285 and AR9287 are supported. + +Signed-off-by: Michal Cieslakiewicz +Signed-off-by: Felix Fietkau +--- +--- a/drivers/net/wireless/ath/ath9k/ath9k.h ++++ b/drivers/net/wireless/ath/ath9k/ath9k.h +@@ -24,6 +24,7 @@ + #include + #include + #include ++#include + + #include "common.h" + #include "debug.h" +@@ -989,6 +990,14 @@ struct ath_led { + struct led_classdev cdev; + }; + ++#ifdef CONFIG_GPIOLIB ++struct ath9k_gpio_chip { ++ struct ath_softc *sc; ++ char label[32]; ++ struct gpio_chip gchip; ++}; ++#endif ++ + struct ath_softc { + struct ieee80211_hw *hw; + struct device *dev; +@@ -1044,6 +1053,9 @@ struct ath_softc { + #ifdef CPTCFG_MAC80211_LEDS + const char *led_default_trigger; + struct list_head leds; ++#ifdef CONFIG_GPIOLIB ++ struct ath9k_gpio_chip *gpiochip; ++#endif + #endif + + #ifdef CPTCFG_ATH9K_DEBUGFS +--- a/drivers/net/wireless/ath/ath9k/gpio.c ++++ b/drivers/net/wireless/ath/ath9k/gpio.c +@@ -16,13 +16,139 @@ + + #include "ath9k.h" + #include ++#include ++ ++#ifdef CPTCFG_MAC80211_LEDS ++ ++#ifdef CONFIG_GPIOLIB ++ ++/***************/ ++/* GPIO Chip */ ++/***************/ ++ ++/* gpio_chip handler : set GPIO to input */ ++static int ath9k_gpio_pin_cfg_input(struct gpio_chip *chip, unsigned offset) ++{ ++ struct ath9k_gpio_chip *gc = container_of(chip, struct ath9k_gpio_chip, ++ gchip); ++ ++ ath9k_hw_gpio_request_in(gc->sc->sc_ah, offset, "ath9k-gpio"); ++ ++ return 0; ++} ++ ++/* gpio_chip handler : set GPIO to output */ ++static int ath9k_gpio_pin_cfg_output(struct gpio_chip *chip, unsigned offset, ++ int value) ++{ ++ struct ath9k_gpio_chip *gc = container_of(chip, struct ath9k_gpio_chip, ++ gchip); ++ ++ ath9k_hw_gpio_request_out(gc->sc->sc_ah, offset, "ath9k-gpio", ++ AR_GPIO_OUTPUT_MUX_AS_OUTPUT); ++ ath9k_hw_set_gpio(gc->sc->sc_ah, offset, value); ++ ++ return 0; ++} ++ ++/* gpio_chip handler : query GPIO direction (0=out, 1=in) */ ++static int ath9k_gpio_pin_get_dir(struct gpio_chip *chip, unsigned offset) ++{ ++ struct ath9k_gpio_chip *gc = container_of(chip, struct ath9k_gpio_chip, ++ gchip); ++ struct ath_hw *ah = gc->sc->sc_ah; ++ ++ return !((REG_READ(ah, AR_GPIO_OE_OUT) >> (offset * 2)) & 3); ++} ++ ++/* gpio_chip handler : get GPIO pin value */ ++static int ath9k_gpio_pin_get(struct gpio_chip *chip, unsigned offset) ++{ ++ struct ath9k_gpio_chip *gc = container_of(chip, struct ath9k_gpio_chip, ++ gchip); ++ ++ return ath9k_hw_gpio_get(gc->sc->sc_ah, offset); ++} ++ ++/* gpio_chip handler : set GPIO pin to value */ ++static void ath9k_gpio_pin_set(struct gpio_chip *chip, unsigned offset, ++ int value) ++{ ++ struct ath9k_gpio_chip *gc = container_of(chip, struct ath9k_gpio_chip, ++ gchip); ++ ++ ath9k_hw_set_gpio(gc->sc->sc_ah, offset, value); ++} ++ ++/* register GPIO chip */ ++static void ath9k_register_gpio_chip(struct ath_softc *sc) ++{ ++ struct ath9k_gpio_chip *gc; ++ struct ath_hw *ah = sc->sc_ah; ++ ++ gc = kzalloc(sizeof(struct ath9k_gpio_chip), GFP_KERNEL); ++ if (!gc) ++ return; ++ ++ gc->sc = sc; ++ snprintf(gc->label, sizeof(gc->label), "ath9k-%s", ++ wiphy_name(sc->hw->wiphy)); ++#ifdef CONFIG_OF ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,5,0) ++ gc->gchip.parent = sc->dev; ++#else ++ gc->gchip.dev = sc->dev; ++#endif ++#endif ++ gc->gchip.label = gc->label; ++ gc->gchip.base = -1; /* determine base automatically */ ++ gc->gchip.ngpio = ah->caps.num_gpio_pins; ++ gc->gchip.direction_input = ath9k_gpio_pin_cfg_input; ++ gc->gchip.direction_output = ath9k_gpio_pin_cfg_output; ++ gc->gchip.get_direction = ath9k_gpio_pin_get_dir; ++ gc->gchip.get = ath9k_gpio_pin_get; ++ gc->gchip.set = ath9k_gpio_pin_set; ++ ++ if (gpiochip_add(&gc->gchip)) { ++ kfree(gc); ++ return; ++ } ++ ++#ifdef CONFIG_OF ++ gc->gchip.owner = NULL; ++#endif ++ sc->gpiochip = gc; ++} ++ ++/* remove GPIO chip */ ++static void ath9k_unregister_gpio_chip(struct ath_softc *sc) ++{ ++ struct ath9k_gpio_chip *gc = sc->gpiochip; ++ ++ if (!gc) ++ return; ++ ++ gpiochip_remove(&gc->gchip); ++ kfree(gc); ++ sc->gpiochip = NULL; ++} ++ ++#else /* CONFIG_GPIOLIB */ ++ ++static inline void ath9k_register_gpio_chip(struct ath_softc *sc) ++{ ++} ++ ++static inline void ath9k_unregister_gpio_chip(struct ath_softc *sc) ++{ ++} ++ ++#endif /* CONFIG_GPIOLIB */ + + /********************************/ + /* LED functions */ + /********************************/ + +-#ifdef CPTCFG_MAC80211_LEDS +- + static void ath_fill_led_pin(struct ath_softc *sc) + { + struct ath_hw *ah = sc->sc_ah; +@@ -80,6 +206,12 @@ static int ath_add_led(struct ath_softc + else + ath9k_hw_set_gpio(sc->sc_ah, gpio->gpio, gpio->active_low); + ++#ifdef CONFIG_GPIOLIB ++ /* If there is GPIO chip configured, reserve LED pin */ ++ if (sc->gpiochip) ++ gpio_request(sc->gpiochip->gchip.base + gpio->gpio, gpio->name); ++#endif ++ + return 0; + } + +@@ -136,17 +268,24 @@ void ath_deinit_leds(struct ath_softc *s + + while (!list_empty(&sc->leds)) { + led = list_first_entry(&sc->leds, struct ath_led, list); ++#ifdef CONFIG_GPIOLIB ++ /* If there is GPIO chip configured, free LED pin */ ++ if (sc->gpiochip) ++ gpio_free(sc->gpiochip->gchip.base + led->gpio->gpio); ++#endif + list_del(&led->list); + ath_led_brightness(&led->cdev, LED_OFF); + led_classdev_unregister(&led->cdev); + ath9k_hw_gpio_free(sc->sc_ah, led->gpio->gpio); + kfree(led); + } ++ ath9k_unregister_gpio_chip(sc); + } + + void ath_init_leds(struct ath_softc *sc) + { + struct ath9k_platform_data *pdata = sc->dev->platform_data; ++ struct device_node *np = sc->dev->of_node; + char led_name[32]; + const char *trigger; + int i; +@@ -156,6 +295,15 @@ void ath_init_leds(struct ath_softc *sc) + if (AR_SREV_9100(sc->sc_ah)) + return; + ++ if (!np) ++ ath9k_register_gpio_chip(sc); ++ ++ /* setup gpio controller only if requested and skip the led_pin setup */ ++ if (of_property_read_bool(np, "gpio-controller")) { ++ ath9k_register_gpio_chip(sc); ++ return; ++ } ++ + ath_fill_led_pin(sc); + + if (pdata && pdata->leds && pdata->num_leds) +@@ -180,6 +328,7 @@ void ath_init_leds(struct ath_softc *sc) + ath_create_gpio_led(sc, sc->sc_ah->led_pin, led_name, trigger, + !sc->sc_ah->config.led_active_high); + } ++ + #endif + + /*******************/ diff --git a/feeds/ipq40xx/mac80211/patches/ath/549-ath9k_enable_gpio_buttons.patch b/feeds/ipq40xx/mac80211/patches/ath/549-ath9k_enable_gpio_buttons.patch new file mode 100644 index 000000000..716e09f35 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/ath/549-ath9k_enable_gpio_buttons.patch @@ -0,0 +1,143 @@ +From: Michal Cieslakiewicz +Subject: [PATCH v5 5/8] mac80211: ath9k: enable GPIO buttons + +Enable platform-defined GPIO button support for ath9k device. +Key poller is activated for attached platform buttons. +Requires ath9k GPIO chip access. + +Signed-off-by: Michal Cieslakiewicz +Signed-off-by: Felix Fietkau +--- +--- a/drivers/net/wireless/ath/ath9k/ath9k.h ++++ b/drivers/net/wireless/ath/ath9k/ath9k.h +@@ -1055,6 +1055,7 @@ struct ath_softc { + struct list_head leds; + #ifdef CONFIG_GPIOLIB + struct ath9k_gpio_chip *gpiochip; ++ struct platform_device *btnpdev; /* gpio-keys-polled */ + #endif + #endif + +--- a/drivers/net/wireless/ath/ath9k/gpio.c ++++ b/drivers/net/wireless/ath/ath9k/gpio.c +@@ -17,6 +17,8 @@ + #include "ath9k.h" + #include + #include ++#include ++#include + + #ifdef CPTCFG_MAC80211_LEDS + +@@ -133,6 +135,67 @@ static void ath9k_unregister_gpio_chip(s + sc->gpiochip = NULL; + } + ++/******************/ ++/* GPIO Buttons */ ++/******************/ ++ ++/* add GPIO buttons */ ++static void ath9k_init_buttons(struct ath_softc *sc) ++{ ++ struct ath9k_platform_data *pdata = sc->dev->platform_data; ++ struct platform_device *pdev; ++ struct gpio_keys_platform_data gkpdata; ++ struct gpio_keys_button *bt; ++ int i; ++ ++ if (!sc->gpiochip) ++ return; ++ ++ if (!pdata || !pdata->btns || !pdata->num_btns) ++ return; ++ ++ bt = devm_kmemdup(sc->dev, pdata->btns, ++ pdata->num_btns * sizeof(struct gpio_keys_button), ++ GFP_KERNEL); ++ if (!bt) ++ return; ++ ++ for (i = 0; i < pdata->num_btns; i++) { ++ if (pdata->btns[i].gpio == sc->sc_ah->led_pin) ++ sc->sc_ah->led_pin = -1; ++ ++ ath9k_hw_gpio_request_in(sc->sc_ah, pdata->btns[i].gpio, ++ "ath9k-gpio"); ++ bt[i].gpio = sc->gpiochip->gchip.base + pdata->btns[i].gpio; ++ } ++ ++ memset(&gkpdata, 0, sizeof(struct gpio_keys_platform_data)); ++ gkpdata.buttons = bt; ++ gkpdata.nbuttons = pdata->num_btns; ++ gkpdata.poll_interval = pdata->btn_poll_interval; ++ ++ pdev = platform_device_register_data(sc->dev, "gpio-keys-polled", ++ PLATFORM_DEVID_AUTO, &gkpdata, ++ sizeof(gkpdata)); ++ if (!IS_ERR_OR_NULL(pdev)) ++ sc->btnpdev = pdev; ++ else { ++ sc->btnpdev = NULL; ++ devm_kfree(sc->dev, bt); ++ } ++} ++ ++/* remove GPIO buttons */ ++static void ath9k_deinit_buttons(struct ath_softc *sc) ++{ ++ if (!sc->gpiochip || !sc->btnpdev) ++ return; ++ ++ platform_device_unregister(sc->btnpdev); ++ ++ sc->btnpdev = NULL; ++} ++ + #else /* CONFIG_GPIOLIB */ + + static inline void ath9k_register_gpio_chip(struct ath_softc *sc) +@@ -143,6 +206,14 @@ static inline void ath9k_unregister_gpio + { + } + ++static inline void ath9k_init_buttons(struct ath_softc *sc) ++{ ++} ++ ++static inline void ath9k_deinit_buttons(struct ath_softc *sc) ++{ ++} ++ + #endif /* CONFIG_GPIOLIB */ + + /********************************/ +@@ -266,6 +337,7 @@ void ath_deinit_leds(struct ath_softc *s + { + struct ath_led *led; + ++ ath9k_deinit_buttons(sc); + while (!list_empty(&sc->leds)) { + led = list_first_entry(&sc->leds, struct ath_led, list); + #ifdef CONFIG_GPIOLIB +@@ -305,6 +377,7 @@ void ath_init_leds(struct ath_softc *sc) + } + + ath_fill_led_pin(sc); ++ ath9k_init_buttons(sc); + + 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/feeds/ipq40xx/mac80211/patches/ath/550-ath9k-disable-bands-via-dt.patch b/feeds/ipq40xx/mac80211/patches/ath/550-ath9k-disable-bands-via-dt.patch new file mode 100644 index 000000000..7d3a334c4 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/ath/550-ath9k-disable-bands-via-dt.patch @@ -0,0 +1,15 @@ +--- a/drivers/net/wireless/ath/ath9k/init.c ++++ b/drivers/net/wireless/ath/ath9k/init.c +@@ -627,6 +627,12 @@ static int ath9k_of_init(struct ath_soft + + ath_dbg(common, CONFIG, "parsing configuration from OF node\n"); + ++ if (of_property_read_bool(np, "qca,disable-2ghz")) ++ ah->disable_2ghz = true; ++ ++ if (of_property_read_bool(np, "qca,disable-5ghz")) ++ ah->disable_5ghz = true; ++ + if (of_property_read_bool(np, "qca,no-eeprom")) { + /* ath9k-eeprom--.bin */ + scnprintf(eeprom_name, sizeof(eeprom_name), diff --git a/feeds/ipq40xx/mac80211/patches/ath/551-ath9k_ubnt_uap_plus_hsr.patch b/feeds/ipq40xx/mac80211/patches/ath/551-ath9k_ubnt_uap_plus_hsr.patch new file mode 100644 index 000000000..4454baeef --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/ath/551-ath9k_ubnt_uap_plus_hsr.patch @@ -0,0 +1,418 @@ +--- a/drivers/net/wireless/ath/ath9k/channel.c ++++ b/drivers/net/wireless/ath/ath9k/channel.c +@@ -15,6 +15,8 @@ + */ + + #include "ath9k.h" ++#include ++#include "hsr.h" + + /* Set/change channels. If the channel is really being changed, it's done + * by reseting the chip. To accomplish this we must first cleanup any pending +@@ -22,6 +24,7 @@ + */ + static int ath_set_channel(struct ath_softc *sc) + { ++ struct ath9k_platform_data *pdata = sc->dev->platform_data; + struct ath_hw *ah = sc->sc_ah; + struct ath_common *common = ath9k_hw_common(ah); + struct ieee80211_hw *hw = sc->hw; +@@ -42,6 +45,11 @@ static int ath_set_channel(struct ath_so + ath_dbg(common, CONFIG, "Set channel: %d MHz width: %d\n", + chan->center_freq, chandef->width); + ++ if (pdata && pdata->ubnt_hsr) { ++ ath9k_hsr_enable(ah, chandef->width, chan->center_freq); ++ ath9k_hsr_status(ah); ++ } ++ + /* update survey stats for the old channel before switching */ + spin_lock_irqsave(&common->cc_lock, flags); + ath_update_survey_stats(sc); +--- /dev/null ++++ b/drivers/net/wireless/ath/ath9k/hsr.c +@@ -0,0 +1,247 @@ ++/* ++ * ++ * The MIT License (MIT) ++ * ++ * Copyright (c) 2015 Kirill Berezin ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to deal ++ * in the Software without restriction, including without limitation the rights ++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++ * copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ++ * SOFTWARE. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "hw.h" ++#include "ath9k.h" ++ ++#define HSR_GPIO_CSN 8 ++#define HSR_GPIO_CLK 6 ++#define HSR_GPIO_DOUT 7 ++#define HSR_GPIO_DIN 5 ++ ++/* delays are in useconds */ ++#define HSR_DELAY_HALF_TICK 100 ++#define HSR_DELAY_PRE_WRITE 75 ++#define HSR_DELAY_FINAL 20000 ++#define HSR_DELAY_TRAILING 200 ++ ++void ath9k_hsr_init(struct ath_hw *ah) ++{ ++ ath9k_hw_gpio_request_in(ah, HSR_GPIO_DIN, NULL); ++ ath9k_hw_gpio_request_out(ah, HSR_GPIO_CSN, NULL, ++ AR_GPIO_OUTPUT_MUX_AS_OUTPUT); ++ ath9k_hw_gpio_request_out(ah, HSR_GPIO_CLK, NULL, ++ AR_GPIO_OUTPUT_MUX_AS_OUTPUT); ++ ath9k_hw_gpio_request_out(ah, HSR_GPIO_DOUT, NULL, ++ AR_GPIO_OUTPUT_MUX_AS_OUTPUT); ++ ++ ath9k_hw_set_gpio(ah, HSR_GPIO_CSN, 1); ++ ath9k_hw_set_gpio(ah, HSR_GPIO_CLK, 0); ++ ath9k_hw_set_gpio(ah, HSR_GPIO_DOUT, 0); ++ ++ udelay(HSR_DELAY_TRAILING); ++} ++ ++static u32 ath9k_hsr_write_byte(struct ath_hw *ah, int delay, u32 value) ++{ ++ struct ath_common *common = ath9k_hw_common(ah); ++ int i; ++ u32 rval = 0; ++ ++ udelay(delay); ++ ++ ath9k_hw_set_gpio(ah, HSR_GPIO_CLK, 0); ++ udelay(HSR_DELAY_HALF_TICK); ++ ++ ath9k_hw_set_gpio(ah, HSR_GPIO_CSN, 0); ++ udelay(HSR_DELAY_HALF_TICK); ++ ++ for (i = 0; i < 8; ++i) { ++ rval = rval << 1; ++ ++ /* pattern is left to right, that is 7-th bit runs first */ ++ ath9k_hw_set_gpio(ah, HSR_GPIO_DOUT, (value >> (7 - i)) & 0x1); ++ udelay(HSR_DELAY_HALF_TICK); ++ ++ ath9k_hw_set_gpio(ah, HSR_GPIO_CLK, 1); ++ udelay(HSR_DELAY_HALF_TICK); ++ ++ rval |= ath9k_hw_gpio_get(ah, HSR_GPIO_DIN); ++ ++ ath9k_hw_set_gpio(ah, HSR_GPIO_CLK, 0); ++ udelay(HSR_DELAY_HALF_TICK); ++ } ++ ++ ath9k_hw_set_gpio(ah, HSR_GPIO_CSN, 1); ++ udelay(HSR_DELAY_HALF_TICK); ++ ++ ath_dbg(common, CONFIG, "ath9k_hsr_write_byte: write byte %d return value is %d %c\n", ++ value, rval, rval > 32 ? rval : '-'); ++ ++ return rval & 0xff; ++} ++ ++static int ath9k_hsr_write_a_chain(struct ath_hw *ah, char *chain, int items) ++{ ++ int status = 0; ++ int i = 0; ++ int err; ++ ++ /* a preamble */ ++ ath9k_hsr_write_byte(ah, HSR_DELAY_PRE_WRITE, 0); ++ status = ath9k_hsr_write_byte(ah, HSR_DELAY_PRE_WRITE, 0); ++ ++ /* clear HSR's reply buffer */ ++ if (status) { ++ int loop = 0; ++ ++ for (loop = 0; (loop < 42) && status; ++loop) ++ status = ath9k_hsr_write_byte(ah, HSR_DELAY_PRE_WRITE, ++ 0); ++ ++ if (loop >= 42) { ++ ATH_DBG_WARN(1, ++ "ath9k_hsr_write_a_chain: can't clear an output buffer after a 42 cycles.\n"); ++ return -1; ++ } ++ } ++ ++ for (i = 0; (i < items) && (chain[i] != 0); ++i) ++ ath9k_hsr_write_byte(ah, HSR_DELAY_PRE_WRITE, (u32)chain[i]); ++ ++ ath9k_hsr_write_byte(ah, HSR_DELAY_PRE_WRITE, 0); ++ mdelay(HSR_DELAY_FINAL / 1000); ++ ++ /* reply */ ++ memset(chain, 0, items); ++ ++ ath9k_hsr_write_byte(ah, HSR_DELAY_PRE_WRITE, 0); ++ udelay(HSR_DELAY_TRAILING); ++ ++ for (i = 0; i < (items - 1); ++i) { ++ u32 ret; ++ ++ ret = ath9k_hsr_write_byte(ah, HSR_DELAY_PRE_WRITE, 0); ++ if (ret != 0) ++ chain[i] = (char)ret; ++ else ++ break; ++ ++ udelay(HSR_DELAY_TRAILING); ++ } ++ ++ if (i <= 1) ++ return 0; ++ ++ err = kstrtoint(chain + 1, 10, &i); ++ if (err) ++ return err; ++ ++ return i; ++} ++ ++int ath9k_hsr_disable(struct ath_hw *ah) ++{ ++ char cmd[10] = {'b', '4', '0', 0, 0, 0, 0, 0, 0, 0}; ++ int ret; ++ ++ ret = ath9k_hsr_write_a_chain(ah, cmd, sizeof(cmd)); ++ if ((ret > 0) && (*cmd == 'B')) ++ return 0; ++ ++ return -1; ++} ++ ++int ath9k_hsr_enable(struct ath_hw *ah, int bw, int fq) ++{ ++ char cmd[10]; ++ int ret; ++ ++ /* Bandwidth argument is 0 sometimes. Assume default 802.11bgn ++ * 20MHz on invalid values ++ */ ++ if ((bw != 5) && (bw != 10) && (bw != 20) && (bw != 40)) ++ bw = 20; ++ ++ memset(cmd, 0, sizeof(cmd)); ++ *cmd = 'b'; ++ snprintf(cmd + 1, 3, "%02d", bw); ++ ++ ret = ath9k_hsr_write_a_chain(ah, cmd, sizeof(cmd)); ++ if ((*cmd != 'B') || (ret != bw)) { ++ ATH_DBG_WARN(1, ++ "ath9k_hsr_enable: failed changing bandwidth -> set (%d,%d) reply (%d, %d)\n", ++ 'b', bw, *cmd, ret); ++ return -1; ++ } ++ ++ memset(cmd, 0, sizeof(cmd)); ++ *cmd = 'x'; ++ ret = ath9k_hsr_write_a_chain(ah, cmd, sizeof(cmd)); ++ if (*cmd != 'X') { ++ ATH_DBG_WARN(1, ++ "ath9k_hsr_enable: failed 'x' command -> reply (%d, %d)\n", ++ *cmd, ret); ++ return -1; ++ } ++ ++ memset(cmd, 0, sizeof(cmd)); ++ *cmd = 'm'; ++ ret = ath9k_hsr_write_a_chain(ah, cmd, sizeof(cmd)); ++ if (*cmd != 'M') { ++ ATH_DBG_WARN(1, ++ "ath9k_hsr_enable: failed 'm' command -> reply (%d, %d)\n", ++ *cmd, ret); ++ return -1; ++ } ++ ++ memset(cmd, 0, sizeof(cmd)); ++ *cmd = 'f'; ++ snprintf(cmd + 1, 6, "%05d", fq); ++ ret = ath9k_hsr_write_a_chain(ah, cmd, sizeof(cmd)); ++ if ((*cmd != 'F') && (ret != fq)) { ++ ATH_DBG_WARN(1, ++ "ath9k_hsr_enable: failed set frequency -> reply (%d, %d)\n", ++ *cmd, ret); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++int ath9k_hsr_status(struct ath_hw *ah) ++{ ++ char cmd[10] = {'s', 0, 0, 0, 0, 0, 0, 0, 0, 0}; ++ int ret; ++ ++ ret = ath9k_hsr_write_a_chain(ah, cmd, sizeof(cmd)); ++ if (*cmd != 'S') { ++ ATH_DBG_WARN(1, "ath9k_hsr_status: returned %d,%d\n", *cmd, ++ ret); ++ return -1; ++ } ++ ++ return 0; ++} +--- /dev/null ++++ b/drivers/net/wireless/ath/ath9k/hsr.h +@@ -0,0 +1,48 @@ ++/* ++ * The MIT License (MIT) ++ * ++ * Copyright (c) 2015 Kirill Berezin ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to deal ++ * in the Software without restriction, including without limitation the rights ++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++ * copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ++ * SOFTWARE. ++ */ ++ ++#ifndef HSR_H ++#define HSR_H ++ ++#ifdef CPTCFG_ATH9K_UBNTHSR ++ ++void ath9k_hsr_init(struct ath_hw *ah); ++int ath9k_hsr_disable(struct ath_hw *ah); ++int ath9k_hsr_enable(struct ath_hw *ah, int bw, int fq); ++int ath9k_hsr_status(struct ath_hw *ah); ++ ++#else ++static inline void ath9k_hsr_init(struct ath_hw *ah) {} ++ ++static inline int ath9k_hsr_enable(struct ath_hw *ah, int bw, int fq) ++{ ++ return 0; ++} ++ ++static inline int ath9k_hsr_disable(struct ath_hw *ah) { return 0; } ++static inline int ath9k_hsr_status(struct ath_hw *ah) { return 0; } ++ ++#endif ++ ++#endif /* HSR_H */ +--- a/drivers/net/wireless/ath/ath9k/main.c ++++ b/drivers/net/wireless/ath/ath9k/main.c +@@ -16,8 +16,10 @@ + + #include + #include ++#include + #include "ath9k.h" + #include "btcoex.h" ++#include "hsr.h" + + u8 ath9k_parse_mpdudensity(u8 mpdudensity) + { +@@ -649,6 +651,7 @@ void ath_reset_work(struct work_struct * + static int ath9k_start(struct ieee80211_hw *hw) + { + struct ath_softc *sc = hw->priv; ++ struct ath9k_platform_data *pdata = sc->dev->platform_data; + struct ath_hw *ah = sc->sc_ah; + struct ath_common *common = ath9k_hw_common(ah); + struct ieee80211_channel *curchan = sc->cur_chan->chandef.chan; +@@ -727,6 +730,11 @@ static int ath9k_start(struct ieee80211_ + AR_GPIO_OUTPUT_MUX_AS_OUTPUT); + } + ++ if (pdata && pdata->ubnt_hsr) { ++ ath9k_hsr_init(ah); ++ ath9k_hsr_disable(ah); ++ } ++ + /* + * Reset key cache to sane defaults (all entries cleared) instead of + * semi-random values after suspend/resume. +--- a/drivers/net/wireless/ath/ath9k/Makefile ++++ b/drivers/net/wireless/ath/ath9k/Makefile +@@ -17,6 +17,7 @@ ath9k-$(CPTCFG_ATH9K_DFS_CERTIFIED) += d + ath9k-$(CPTCFG_ATH9K_TX99) += tx99.o + ath9k-$(CPTCFG_ATH9K_WOW) += wow.o + ath9k-$(CPTCFG_ATH9K_HWRNG) += rng.o ++ath9k-$(CPTCFG_ATH9K_UBNTHSR) += hsr.o + + ath9k-$(CPTCFG_ATH9K_DEBUGFS) += debug.o + +--- a/include/linux/ath9k_platform.h ++++ b/include/linux/ath9k_platform.h +@@ -53,6 +53,8 @@ struct ath9k_platform_data { + unsigned num_btns; + const struct gpio_keys_button *btns; + unsigned btn_poll_interval; ++ ++ bool ubnt_hsr; + }; + + #endif /* _LINUX_ATH9K_PLATFORM_H */ +--- a/local-symbols ++++ b/local-symbols +@@ -112,6 +112,7 @@ ATH9K_WOW= + ATH9K_RFKILL= + ATH9K_CHANNEL_CONTEXT= + ATH9K_PCOEM= ++ATH9K_UBNTHSR= + ATH9K_PCI_NO_EEPROM= + ATH9K_HTC= + ATH9K_HTC_DEBUGFS= +--- a/drivers/net/wireless/ath/ath9k/Kconfig ++++ b/drivers/net/wireless/ath/ath9k/Kconfig +@@ -60,6 +60,19 @@ config ATH9K_AHB + Say Y, if you have a SoC with a compatible built-in + wireless MAC. Say N if unsure. + ++config ATH9K_UBNTHSR ++ bool "Ubiquiti UniFi Outdoor Plus HSR support" ++ depends on ATH9K ++ ---help--- ++ This options enables code to control the HSR RF ++ filter in the receive path of the Ubiquiti UniFi ++ Outdoor Plus access point. ++ ++ Say Y if you want to use the access point. The ++ code will only be used if the device is detected, ++ so it does not harm other setup other than occupying ++ a bit of memory. ++ + config ATH9K_DEBUGFS + bool "Atheros ath9k debugging" + depends on ATH9K && DEBUG_FS diff --git a/feeds/ipq40xx/mac80211/patches/ath/552-ahb_of.patch b/feeds/ipq40xx/mac80211/patches/ath/552-ahb_of.patch new file mode 100644 index 000000000..2552bbc7a --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/ath/552-ahb_of.patch @@ -0,0 +1,337 @@ +--- a/drivers/net/wireless/ath/ath9k/ahb.c ++++ b/drivers/net/wireless/ath/ath9k/ahb.c +@@ -20,7 +20,15 @@ + #include + #include + #include ++#include + #include "ath9k.h" ++#include ++ ++#ifdef CONFIG_OF ++#include ++#include ++#include ++#endif + + static const struct platform_device_id ath9k_platform_id_table[] = { + { +@@ -69,6 +77,242 @@ static const struct ath_bus_ops ath_ahb_ + .eeprom_read = ath_ahb_eeprom_read, + }; + ++#ifdef CONFIG_OF ++ ++#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); ++ mdelay(10); ++ ++ ath79_device_reset_clear(AR913X_RESET_AMBA2WMAC); ++ mdelay(10); ++ ++ return 0; ++} ++ ++static int ar933x_wmac_reset(void) ++{ ++ int retries = 20; ++ ++ ath79_device_reset_set(AR933X_RESET_WMAC); ++ ath79_device_reset_clear(AR933X_RESET_WMAC); ++ ++ while (1) { ++ u32 bootstrap; ++ ++ bootstrap = ath79_reset_rr(AR933X_RESET_REG_BOOTSTRAP); ++ if ((bootstrap & AR933X_BOOTSTRAP_EEPBUSY) == 0) ++ return 0; ++ ++ if (retries-- == 0) ++ break; ++ ++ udelay(10000); ++ } ++ ++ pr_err("ar933x: WMAC reset timed out"); ++ return -ETIMEDOUT; ++} ++ ++static int qca955x_wmac_reset(void) ++{ ++ int i; ++ ++ /* Try to wait for WMAC DDR activity to stop */ ++ for (i = 0; i < 10; i++) { ++ if (!(__raw_readl(ath79_ddr_base + QCA955X_DDR_CTL_CONFIG) & ++ QCA955X_DDR_CTL_CONFIG_ACT_WMAC)) ++ break; ++ ++ udelay(10); ++ } ++ ++ ath79_device_reset_set(QCA955X_RESET_RTC); ++ udelay(10); ++ ath79_device_reset_clear(QCA955X_RESET_RTC); ++ udelay(10); ++ ++ return 0; ++} ++ ++enum { ++ AR913X_WMAC = 0, ++ AR933X_WMAC, ++ AR934X_WMAC, ++ QCA953X_WMAC, ++ QCA955X_WMAC, ++ QCA956X_WMAC, ++}; ++ ++static int ar9330_get_soc_revision(void) ++{ ++ if (ath79_soc_rev == 1) ++ return ath79_soc_rev; ++ ++ return 0; ++} ++ ++static int ath79_get_soc_revision(void) ++{ ++ return ath79_soc_rev; ++} ++ ++static const struct of_ath_ahb_data { ++ u16 dev_id; ++ u32 bootstrap_reg; ++ u32 bootstrap_ref; ++ ++ int (*soc_revision)(void); ++ int (*wmac_reset)(void); ++} of_ath_ahb_data[] = { ++ [AR913X_WMAC] = { ++ .dev_id = AR5416_AR9100_DEVID, ++ .wmac_reset = ar913x_wmac_reset, ++ ++ }, ++ [AR933X_WMAC] = { ++ .dev_id = AR9300_DEVID_AR9330, ++ .bootstrap_reg = AR933X_RESET_REG_BOOTSTRAP, ++ .bootstrap_ref = AR933X_BOOTSTRAP_REF_CLK_40, ++ .soc_revision = ar9330_get_soc_revision, ++ .wmac_reset = ar933x_wmac_reset, ++ }, ++ [AR934X_WMAC] = { ++ .dev_id = AR9300_DEVID_AR9340, ++ .bootstrap_reg = AR934X_RESET_REG_BOOTSTRAP, ++ .bootstrap_ref = AR934X_BOOTSTRAP_REF_CLK_40, ++ .soc_revision = ath79_get_soc_revision, ++ }, ++ [QCA953X_WMAC] = { ++ .dev_id = AR9300_DEVID_AR953X, ++ .bootstrap_reg = QCA953X_RESET_REG_BOOTSTRAP, ++ .bootstrap_ref = QCA953X_BOOTSTRAP_REF_CLK_40, ++ .soc_revision = ath79_get_soc_revision, ++ }, ++ [QCA955X_WMAC] = { ++ .dev_id = AR9300_DEVID_QCA955X, ++ .bootstrap_reg = QCA955X_RESET_REG_BOOTSTRAP, ++ .bootstrap_ref = QCA955X_BOOTSTRAP_REF_CLK_40, ++ .wmac_reset = qca955x_wmac_reset, ++ }, ++ [QCA956X_WMAC] = { ++ .dev_id = AR9300_DEVID_QCA956X, ++ .bootstrap_reg = QCA956X_RESET_REG_BOOTSTRAP, ++ .bootstrap_ref = QCA956X_BOOTSTRAP_REF_CLK_40, ++ .soc_revision = ath79_get_soc_revision, ++ }, ++}; ++ ++const struct of_device_id of_ath_ahb_match[] = { ++ { .compatible = "qca,ar9130-wmac", .data = &of_ath_ahb_data[AR913X_WMAC] }, ++ { .compatible = "qca,ar9330-wmac", .data = &of_ath_ahb_data[AR933X_WMAC] }, ++ { .compatible = "qca,ar9340-wmac", .data = &of_ath_ahb_data[AR934X_WMAC] }, ++ { .compatible = "qca,qca9530-wmac", .data = &of_ath_ahb_data[QCA953X_WMAC] }, ++ { .compatible = "qca,qca9550-wmac", .data = &of_ath_ahb_data[QCA955X_WMAC] }, ++ { .compatible = "qca,qca9560-wmac", .data = &of_ath_ahb_data[QCA956X_WMAC] }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, of_ath_ahb_match); ++ ++static int of_ath_ahb_probe(struct platform_device *pdev) ++{ ++ struct ath9k_platform_data *pdata; ++ const struct of_device_id *match; ++ const struct of_ath_ahb_data *data; ++ u8 led_pin; ++ ++ match = of_match_device(of_ath_ahb_match, &pdev->dev); ++ data = (const struct of_ath_ahb_data *)match->data; ++ ++ pdata = dev_get_platdata(&pdev->dev); ++ ++ if (!of_property_read_u8(pdev->dev.of_node, "qca,led-pin", &led_pin)) ++ pdata->led_pin = led_pin; ++ else ++ pdata->led_pin = -1; ++ ++ if (of_property_read_bool(pdev->dev.of_node, "qca,disable-2ghz")) ++ pdata->disable_2ghz = true; ++ ++ if (of_property_read_bool(pdev->dev.of_node, "qca,disable-5ghz")) ++ pdata->disable_5ghz = true; ++ ++ if (of_property_read_bool(pdev->dev.of_node, "qca,tx-gain-buffalo")) ++ pdata->tx_gain_buffalo = true; ++ ++ if (data->wmac_reset) { ++ data->wmac_reset(); ++ pdata->external_reset = data->wmac_reset; ++ } ++ ++ if (data->dev_id == AR9300_DEVID_AR953X) { ++ /* ++ * QCA953x only supports 25MHz refclk. ++ * Some vendors have an invalid bootstrap option ++ * set, which would break the WMAC here. ++ */ ++ pdata->is_clk_25mhz = true; ++ } else if (data->bootstrap_reg && data->bootstrap_ref) { ++ u32 t = ath79_reset_rr(data->bootstrap_reg); ++ if (t & data->bootstrap_ref) ++ pdata->is_clk_25mhz = false; ++ else ++ pdata->is_clk_25mhz = true; ++ } ++ ++ 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 ++ + static int ath_ahb_probe(struct platform_device *pdev) + { + void __iomem *mem; +@@ -80,6 +324,17 @@ static int ath_ahb_probe(struct platform + int ret = 0; + struct ath_hw *ah; + char hw_name[64]; ++ u16 dev_id; ++ ++ if (id) ++ dev_id = id->driver_data; ++ ++#ifdef CONFIG_OF ++ if (pdev->dev.of_node) ++ pdev->dev.platform_data = devm_kzalloc(&pdev->dev, ++ sizeof(struct ath9k_platform_data), ++ GFP_KERNEL); ++#endif + + if (!dev_get_platdata(&pdev->dev)) { + dev_err(&pdev->dev, "no platform data specified\n"); +@@ -122,13 +377,16 @@ static int ath_ahb_probe(struct platform + sc->mem = mem; + sc->irq = irq; + ++#ifdef CONFIG_OF ++ dev_id = of_ath_ahb_probe(pdev); ++#endif + ret = request_irq(irq, ath_isr, IRQF_SHARED, "ath9k", sc); + if (ret) { + dev_err(&pdev->dev, "request_irq failed\n"); + goto err_free_hw; + } + +- ret = ath9k_init_device(id->driver_data, sc, &ath_ahb_bus_ops); ++ ret = ath9k_init_device(dev_id, sc, &ath_ahb_bus_ops); + if (ret) { + dev_err(&pdev->dev, "failed to initialize device\n"); + goto err_irq; +@@ -159,6 +417,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 + + return 0; + } +@@ -168,6 +429,9 @@ static struct platform_driver ath_ahb_dr + .remove = ath_ahb_remove, + .driver = { + .name = "ath9k", ++#ifdef CONFIG_OF ++ .of_match_table = of_ath_ahb_match, ++#endif + }, + .id_table = ath9k_platform_id_table, + }; +--- a/drivers/net/wireless/ath/ath9k/ath9k.h ++++ b/drivers/net/wireless/ath/ath9k/ath9k.h +@@ -25,6 +25,7 @@ + #include + #include + #include ++#include + + #include "common.h" + #include "debug.h" +@@ -1011,6 +1012,9 @@ struct ath_softc { + struct ath_hw *sc_ah; + void __iomem *mem; + int irq; ++#ifdef CONFIG_OF ++ struct reset_control *reset; ++#endif + spinlock_t sc_serial_rw; + spinlock_t sc_pm_lock; + spinlock_t sc_pcu_lock; diff --git a/feeds/ipq40xx/mac80211/patches/ath/553-ath9k_of_gpio_mask.patch b/feeds/ipq40xx/mac80211/patches/ath/553-ath9k_of_gpio_mask.patch new file mode 100644 index 000000000..72b99050c --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/ath/553-ath9k_of_gpio_mask.patch @@ -0,0 +1,25 @@ +--- a/drivers/net/wireless/ath/ath9k/init.c ++++ b/drivers/net/wireless/ath/ath9k/init.c +@@ -654,6 +654,12 @@ static int ath9k_of_init(struct ath_soft + return 0; + } + ++static void ath9k_of_gpio_mask(struct ath_softc *sc) ++{ ++ of_property_read_u32(sc->dev->of_node, "qca,gpio-mask", ++ &sc->sc_ah->caps.gpio_mask); ++} ++ + static int ath9k_init_softc(u16 devid, struct ath_softc *sc, + const struct ath_bus_ops *bus_ops) + { +@@ -758,6 +764,9 @@ static int ath9k_init_softc(u16 devid, s + if (ret) + goto err_hw; + ++ /* GPIO mask quirk */ ++ ath9k_of_gpio_mask(sc); ++ + ret = ath9k_init_queues(sc); + if (ret) + goto err_queues; diff --git a/feeds/ipq40xx/mac80211/patches/ath/921-ath10k_init_devices_synchronously.patch b/feeds/ipq40xx/mac80211/patches/ath/921-ath10k_init_devices_synchronously.patch new file mode 100644 index 000000000..4e59bb00e --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/ath/921-ath10k_init_devices_synchronously.patch @@ -0,0 +1,33 @@ +From: Sven Eckelmann +Date: Tue, 18 Nov 2014 12:29:28 +0100 +Subject: [PATCH] ath10k: Don't initialize devices asynchronously + +OpenWrt requires all PHYs to be initialized to create the configuration files +during bootup. ath10k violates this because it delays the creation of the PHY +to a not well defined point in the future. + +Forcing the work to be done immediately works around this problem but may also +delay the boot when firmware images cannot be found. + +Signed-off-by: Sven Eckelmann +--- + +--- a/drivers/net/wireless/ath/ath10k/core.c ++++ b/drivers/net/wireless/ath/ath10k/core.c +@@ -3172,6 +3172,16 @@ int ath10k_core_register(struct ath10k * + + queue_work(ar->workqueue, &ar->register_work); + ++ /* OpenWrt requires all PHYs to be initialized to create the ++ * configuration files during bootup. ath10k violates this ++ * because it delays the creation of the PHY to a not well defined ++ * point in the future. ++ * ++ * 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); ++ + return 0; + } + EXPORT_SYMBOL(ath10k_core_register); diff --git a/feeds/ipq40xx/mac80211/patches/ath/922-ath10k-increase-rx-buffer-size-to-2048.patch b/feeds/ipq40xx/mac80211/patches/ath/922-ath10k-increase-rx-buffer-size-to-2048.patch new file mode 100644 index 000000000..abce36167 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/ath/922-ath10k-increase-rx-buffer-size-to-2048.patch @@ -0,0 +1,37 @@ +From: Linus Lüssing +Date: Wed, 5 Feb 2020 20:10:43 +0100 +Subject: ath10k: increase rx buffer size to 2048 + +Before, only frames with a maximum size of 1528 bytes could be +transmitted between two 802.11s nodes. + +For batman-adv for instance, which adds its own header to each frame, +we typically need an MTU of at least 1532 bytes to be able to transmit +without fragmentation. + +This patch now increases the maxmimum frame size from 1528 to 1656 +bytes. + +Tested with two ath10k devices in 802.11s mode, as well as with +batman-adv on top of 802.11s with forwarding disabled. + +Fix originally found and developed by Ben Greear. + +Link: https://github.com/greearb/ath10k-ct/issues/89 +Link: https://github.com/greearb/ath10k-ct/commit/9e5ab25027e0971fa24ccf93373324c08c4e992d +Cc: Ben Greear +Signed-off-by: Linus Lüssing + +Forwarded: https://patchwork.kernel.org/patch/11367055/ + +--- a/drivers/net/wireless/ath/ath10k/htt.h ++++ b/drivers/net/wireless/ath/ath10k/htt.h +@@ -2242,7 +2242,7 @@ struct htt_rx_chan_info { + * Should be: sizeof(struct htt_host_rx_desc) + max rx MSDU size, + * rounded up to a cache line size. + */ +-#define HTT_RX_BUF_SIZE 1920 ++#define HTT_RX_BUF_SIZE 2048 + #define HTT_RX_MSDU_SIZE (HTT_RX_BUF_SIZE - (int)sizeof(struct htt_rx_desc)) + + /* Refill a bunch of RX buffers for each refill round so that FW/HW can handle diff --git a/feeds/ipq40xx/mac80211/patches/ath/930-ath10k_add_tpt_led_trigger.patch b/feeds/ipq40xx/mac80211/patches/ath/930-ath10k_add_tpt_led_trigger.patch new file mode 100644 index 000000000..2b36a559d --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/ath/930-ath10k_add_tpt_led_trigger.patch @@ -0,0 +1,37 @@ +--- a/drivers/net/wireless/ath/ath10k/mac.c ++++ b/drivers/net/wireless/ath/ath10k/mac.c +@@ -9053,6 +9053,21 @@ static int ath10k_mac_init_rd(struct ath + return 0; + } + ++#ifdef CPTCFG_MAC80211_LEDS ++static const struct ieee80211_tpt_blink ath10k_tpt_blink[] = { ++ { .throughput = 0 * 1024, .blink_time = 334 }, ++ { .throughput = 1 * 1024, .blink_time = 260 }, ++ { .throughput = 2 * 1024, .blink_time = 220 }, ++ { .throughput = 5 * 1024, .blink_time = 190 }, ++ { .throughput = 10 * 1024, .blink_time = 170 }, ++ { .throughput = 25 * 1024, .blink_time = 150 }, ++ { .throughput = 54 * 1024, .blink_time = 130 }, ++ { .throughput = 120 * 1024, .blink_time = 110 }, ++ { .throughput = 265 * 1024, .blink_time = 80 }, ++ { .throughput = 586 * 1024, .blink_time = 50 }, ++}; ++#endif ++ + int ath10k_mac_register(struct ath10k *ar) + { + static const u32 cipher_suites[] = { +@@ -9380,6 +9395,12 @@ int ath10k_mac_register(struct ath10k *a + + ar->hw->weight_multiplier = ATH10K_AIRTIME_WEIGHT_MULTIPLIER; + ++#ifdef CPTCFG_MAC80211_LEDS ++ ieee80211_create_tpt_led_trigger(ar->hw, ++ IEEE80211_TPT_LEDTRIG_FL_RADIO, ath10k_tpt_blink, ++ ARRAY_SIZE(ath10k_tpt_blink)); ++#endif ++ + ret = ieee80211_register_hw(ar->hw); + if (ret) { + ath10k_err(ar, "failed to register ieee80211: %d\n", ret); diff --git a/feeds/ipq40xx/mac80211/patches/ath/974-ath10k_add-LED-and-GPIO-controlling-support-for-various-chipsets.patch b/feeds/ipq40xx/mac80211/patches/ath/974-ath10k_add-LED-and-GPIO-controlling-support-for-various-chipsets.patch new file mode 100644 index 000000000..74a3028a8 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/ath/974-ath10k_add-LED-and-GPIO-controlling-support-for-various-chipsets.patch @@ -0,0 +1,609 @@ +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. + + +Signed-off-by: Sebastian Gottschall +Reviewed-by: Steve deRosier +[kvalo: major reorg and cleanup] +Signed-off-by: Kalle Valo +Signed-off-by: Ansuel Smith +--- + +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 +@@ -70,6 +70,16 @@ config ATH10K_DEBUGFS + + If unsure, say Y to make it easier to debug problems. + ++config ATH10K_LEDS ++ bool "Atheros ath10k LED support" ++ depends on ATH10K ++ 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" + depends on ATH10K_DEBUGFS +--- a/drivers/net/wireless/ath/ath10k/Makefile ++++ b/drivers/net/wireless/ath/ath10k/Makefile +@@ -19,6 +19,7 @@ ath10k_core-$(CPTCFG_ATH10K_SPECTRAL) += + ath10k_core-$(CPTCFG_NL80211_TESTMODE) += testmode.o + ath10k_core-$(CPTCFG_ATH10K_TRACING) += trace.o + ath10k_core-$(CPTCFG_ATH10K_THERMAL) += thermal.o ++ath10k_core-$(CPTCFG_ATH10K_LEDS) += leds.o + ath10k_core-$(CPTCFG_MAC80211_DEBUGFS) += debugfs_sta.o + ath10k_core-$(CONFIG_PM) += wow.o + ath10k_core-$(CONFIG_DEV_COREDUMP) += coredump.o +--- a/local-symbols ++++ b/local-symbols +@@ -145,6 +145,7 @@ ATH10K_DEBUG= + ATH10K_DEBUGFS= + ATH10K_SPECTRAL= + ATH10K_THERMAL= ++ATH10K_LEDS= + ATH10K_TRACING= + ATH10K_DFS_CERTIFIED= + WCN36XX= +--- a/drivers/net/wireless/ath/ath10k/core.c ++++ b/drivers/net/wireless/ath/ath10k/core.c +@@ -25,6 +25,7 @@ + #include "testmode.h" + #include "wmi-ops.h" + #include "coredump.h" ++#include "leds.h" + + unsigned int ath10k_debug_mask; + EXPORT_SYMBOL(ath10k_debug_mask); +@@ -61,6 +62,7 @@ static const struct ath10k_hw_params ath + .dev_id = QCA988X_2_0_DEVICE_ID, + .bus = ATH10K_BUS_PCI, + .name = "qca988x hw2.0", ++ .led_pin = 1, + .patch_load_addr = QCA988X_HW_2_0_PATCH_LOAD_ADDR, + .uart_pin = 7, + .cc_wraparound_type = ATH10K_HW_CC_WRAP_SHIFTED_ALL, +@@ -131,6 +133,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, + .cc_wraparound_type = ATH10K_HW_CC_WRAP_SHIFTED_ALL, +@@ -340,6 +343,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, + .otp_exe_param = 0x00000700, +@@ -381,6 +385,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, + .cc_wraparound_type = ATH10K_HW_CC_WRAP_SHIFTED_EACH, +@@ -429,6 +434,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, + .cc_wraparound_type = ATH10K_HW_CC_WRAP_SHIFTED_EACH, +@@ -2887,6 +2893,10 @@ int ath10k_core_start(struct ath10k *ar, + goto err_hif_stop; + } + ++ status = ath10k_leds_start(ar); ++ if (status) ++ goto err_hif_stop; ++ + return 0; + + err_hif_stop: +@@ -3145,9 +3155,18 @@ static void ath10k_core_register_work(st + goto err_spectral_destroy; + } + ++ status = ath10k_leds_register(ar); ++ if (status) { ++ ath10k_err(ar, "could not register leds: %d\n", ++ status); ++ goto err_thermal_unregister; ++ } ++ + set_bit(ATH10K_FLAG_CORE_REGISTERED, &ar->dev_flags); + return; + ++err_thermal_unregister: ++ ath10k_thermal_unregister(ar); + err_spectral_destroy: + ath10k_spectral_destroy(ar); + err_debug_destroy: +@@ -3193,6 +3212,8 @@ void ath10k_core_unregister(struct ath10 + if (!test_bit(ATH10K_FLAG_CORE_REGISTERED, &ar->dev_flags)) + return; + ++ ath10k_leds_unregister(ar); ++ + ath10k_thermal_unregister(ar); + /* Stop spectral before unregistering from mac80211 to remove the + * 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 +@@ -14,6 +14,7 @@ + #include + #include + #include ++#include + + #include "htt.h" + #include "htc.h" +@@ -1216,6 +1217,13 @@ struct ath10k { + } testmode; + + struct { ++ struct gpio_led wifi_led; ++ struct led_classdev cdev; ++ char label[48]; ++ u32 gpio_state_pin; ++ } leds; ++ ++ struct { + /* protected by data_lock */ + u32 rx_crc_err_drop; + u32 fw_crash_counter; +--- a/drivers/net/wireless/ath/ath10k/hw.h ++++ b/drivers/net/wireless/ath/ath10k/hw.h +@@ -517,6 +517,7 @@ struct ath10k_hw_params { + const char *name; + u32 patch_load_addr; + int uart_pin; ++ int led_pin; + u32 otp_exe_param; + + /* Type of hw cycle counter wraparound logic, for more info +--- /dev/null ++++ b/drivers/net/wireless/ath/ath10k/leds.c +@@ -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. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ++ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ++ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++ ++#include "core.h" ++#include "wmi.h" ++#include "wmi-ops.h" ++ ++#include "leds.h" ++ ++static int ath10k_leds_set_brightness_blocking(struct led_classdev *led_cdev, ++ enum led_brightness brightness) ++{ ++ struct ath10k *ar = container_of(led_cdev, struct ath10k, ++ leds.cdev); ++ struct gpio_led *led = &ar->leds.wifi_led; ++ ++ mutex_lock(&ar->conf_mutex); ++ ++ if (ar->state != ATH10K_STATE_ON) ++ goto out; ++ ++ ar->leds.gpio_state_pin = (brightness != LED_OFF) ^ led->active_low; ++ ath10k_wmi_gpio_output(ar, led->gpio, ar->leds.gpio_state_pin); ++ ++out: ++ mutex_unlock(&ar->conf_mutex); ++ ++ return 0; ++} ++ ++int ath10k_leds_start(struct ath10k *ar) ++{ ++ if (ar->hw_params.led_pin == 0) ++ /* leds not supported */ ++ return 0; ++ ++ /* under some circumstances, the gpio pin gets reconfigured ++ * to default state by the firmware, so we need to ++ * reconfigure it this behaviour has only ben seen on ++ * QCA9984 and QCA99XX devices so far ++ */ ++ ath10k_wmi_gpio_config(ar, ar->hw_params.led_pin, 0, ++ WMI_GPIO_PULL_NONE, WMI_GPIO_INTTYPE_DISABLE); ++ ath10k_wmi_gpio_output(ar, ar->hw_params.led_pin, 1); ++ ++ return 0; ++} ++ ++int ath10k_leds_register(struct ath10k *ar) ++{ ++ int ret; ++ ++ if (ar->hw_params.led_pin == 0) ++ /* leds not supported */ ++ return 0; ++ ++ snprintf(ar->leds.label, sizeof(ar->leds.label), "ath10k-%s", ++ wiphy_name(ar->hw->wiphy)); ++ ar->leds.wifi_led.active_low = 1; ++ ar->leds.wifi_led.gpio = ar->hw_params.led_pin; ++ ar->leds.wifi_led.name = ar->leds.label; ++ ar->leds.wifi_led.default_state = LEDS_GPIO_DEFSTATE_KEEP; ++ ++ 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); ++ if (ret) ++ return ret; ++ ++ return 0; ++} ++ ++void ath10k_leds_unregister(struct ath10k *ar) ++{ ++ if (ar->hw_params.led_pin == 0) ++ /* leds not supported */ ++ return; ++ ++ led_classdev_unregister(&ar->leds.cdev); ++} ++ +--- /dev/null ++++ b/drivers/net/wireless/ath/ath10k/leds.h +@@ -0,0 +1,41 @@ ++/* ++ * 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_ ++ ++#include "core.h" ++ ++#ifdef CPTCFG_ATH10K_LEDS ++void ath10k_leds_unregister(struct ath10k *ar); ++int ath10k_leds_start(struct ath10k *ar); ++int ath10k_leds_register(struct ath10k *ar); ++#else ++static inline void ath10k_leds_unregister(struct ath10k *ar) ++{ ++} ++ ++static inline int ath10k_leds_start(struct ath10k *ar) ++{ ++ return 0; ++} ++ ++static inline int ath10k_leds_register(struct ath10k *ar) ++{ ++ return 0; ++} ++ ++#endif ++#endif /* _LEDS_H_ */ +--- a/drivers/net/wireless/ath/ath10k/mac.c ++++ b/drivers/net/wireless/ath/ath10k/mac.c +@@ -24,6 +24,7 @@ + #include "wmi-tlv.h" + #include "wmi-ops.h" + #include "wow.h" ++#include "leds.h" + + /*********/ + /* Rates */ +--- a/drivers/net/wireless/ath/ath10k/wmi-ops.h ++++ b/drivers/net/wireless/ath/ath10k/wmi-ops.h +@@ -224,7 +224,10 @@ struct wmi_ops { + struct sk_buff *(*gen_bb_timing) + (struct ath10k *ar, + const struct wmi_bb_timing_cfg_arg *arg); ++ struct sk_buff *(*gen_gpio_config)(struct ath10k *ar, u32 gpio_num, ++ u32 input, u32 pull_type, u32 intr_mode); + ++ struct sk_buff *(*gen_gpio_output)(struct ath10k *ar, u32 gpio_num, u32 set); + }; + + int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id); +@@ -1120,6 +1123,35 @@ ath10k_wmi_force_fw_hang(struct ath10k * + return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->force_fw_hang_cmdid); + } + ++static inline int ath10k_wmi_gpio_config(struct ath10k *ar, u32 gpio_num, ++ u32 input, u32 pull_type, u32 intr_mode) ++{ ++ struct sk_buff *skb; ++ ++ if (!ar->wmi.ops->gen_gpio_config) ++ return -EOPNOTSUPP; ++ ++ skb = ar->wmi.ops->gen_gpio_config(ar, gpio_num, input, pull_type, intr_mode); ++ if (IS_ERR(skb)) ++ return PTR_ERR(skb); ++ ++ return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->gpio_config_cmdid); ++} ++ ++static inline int ath10k_wmi_gpio_output(struct ath10k *ar, u32 gpio_num, u32 set) ++{ ++ struct sk_buff *skb; ++ ++ if (!ar->wmi.ops->gen_gpio_config) ++ return -EOPNOTSUPP; ++ ++ skb = ar->wmi.ops->gen_gpio_output(ar, gpio_num, set); ++ if (IS_ERR(skb)) ++ return PTR_ERR(skb); ++ ++ return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->gpio_output_cmdid); ++} ++ + static inline int + ath10k_wmi_dbglog_cfg(struct ath10k *ar, u64 module_enable, u32 log_level) + { +--- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c ++++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c +@@ -4583,6 +4583,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, ++ /* .gen_gpio_config not implemented */ ++ /* .gen_gpio_output not implemented */ + }; + + 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 +@@ -7471,6 +7471,49 @@ ath10k_wmi_op_gen_peer_set_param(struct + return skb; + } + ++static struct sk_buff *ath10k_wmi_op_gen_gpio_config(struct ath10k *ar, ++ u32 gpio_num, u32 input, ++ u32 pull_type, u32 intr_mode) ++{ ++ struct wmi_gpio_config_cmd *cmd; ++ struct sk_buff *skb; ++ ++ skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd)); ++ if (!skb) ++ return ERR_PTR(-ENOMEM); ++ ++ cmd = (struct wmi_gpio_config_cmd *)skb->data; ++ cmd->pull_type = __cpu_to_le32(pull_type); ++ cmd->gpio_num = __cpu_to_le32(gpio_num); ++ cmd->input = __cpu_to_le32(input); ++ cmd->intr_mode = __cpu_to_le32(intr_mode); ++ ++ ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi gpio_config gpio_num 0x%08x input 0x%08x pull_type 0x%08x intr_mode 0x%08x\n", ++ gpio_num, input, pull_type, intr_mode); ++ ++ return skb; ++} ++ ++static struct sk_buff *ath10k_wmi_op_gen_gpio_output(struct ath10k *ar, ++ u32 gpio_num, u32 set) ++{ ++ struct wmi_gpio_output_cmd *cmd; ++ struct sk_buff *skb; ++ ++ skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd)); ++ if (!skb) ++ return ERR_PTR(-ENOMEM); ++ ++ cmd = (struct wmi_gpio_output_cmd *)skb->data; ++ cmd->gpio_num = __cpu_to_le32(gpio_num); ++ cmd->set = __cpu_to_le32(set); ++ ++ ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi gpio_output gpio_num 0x%08x set 0x%08x\n", ++ gpio_num, set); ++ ++ return skb; ++} ++ + static struct sk_buff * + ath10k_wmi_op_gen_set_psmode(struct ath10k *ar, u32 vdev_id, + enum wmi_sta_ps_mode psmode) +@@ -9129,6 +9172,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, ++ .gen_gpio_config = ath10k_wmi_op_gen_gpio_config, ++ .gen_gpio_output = ath10k_wmi_op_gen_gpio_output, ++ + /* .gen_bcn_tmpl not implemented */ + /* .gen_prb_tmpl not implemented */ + /* .gen_p2p_go_bcn_ie not implemented */ +@@ -9199,6 +9245,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, ++ .gen_gpio_config = ath10k_wmi_op_gen_gpio_config, ++ .gen_gpio_output = ath10k_wmi_op_gen_gpio_output, + /* .gen_bcn_tmpl not implemented */ + /* .gen_prb_tmpl not implemented */ + /* .gen_p2p_go_bcn_ie not implemented */ +@@ -9271,6 +9319,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, ++ .gen_gpio_config = ath10k_wmi_op_gen_gpio_config, ++ .gen_gpio_output = ath10k_wmi_op_gen_gpio_output, + /* .gen_pdev_enable_adaptive_cca not implemented */ + }; + +@@ -9342,6 +9392,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, ++ .gen_gpio_config = ath10k_wmi_op_gen_gpio_config, ++ .gen_gpio_output = ath10k_wmi_op_gen_gpio_output, + /* .gen_bcn_tmpl not implemented */ + /* .gen_prb_tmpl not implemented */ + /* .gen_p2p_go_bcn_ie not implemented */ +@@ -9422,6 +9474,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, ++ .gen_gpio_config = ath10k_wmi_op_gen_gpio_config, ++ .gen_gpio_output = ath10k_wmi_op_gen_gpio_output, + }; + + int ath10k_wmi_attach(struct ath10k *ar) +--- a/drivers/net/wireless/ath/ath10k/wmi.h ++++ b/drivers/net/wireless/ath/ath10k/wmi.h +@@ -3016,6 +3016,41 @@ enum wmi_10_4_feature_mask { + + }; + ++/* WMI_GPIO_CONFIG_CMDID */ ++enum { ++ WMI_GPIO_PULL_NONE, ++ WMI_GPIO_PULL_UP, ++ WMI_GPIO_PULL_DOWN, ++}; ++ ++enum { ++ WMI_GPIO_INTTYPE_DISABLE, ++ WMI_GPIO_INTTYPE_RISING_EDGE, ++ WMI_GPIO_INTTYPE_FALLING_EDGE, ++ WMI_GPIO_INTTYPE_BOTH_EDGE, ++ WMI_GPIO_INTTYPE_LEVEL_LOW, ++ WMI_GPIO_INTTYPE_LEVEL_HIGH ++}; ++ ++/* WMI_GPIO_CONFIG_CMDID */ ++struct wmi_gpio_config_cmd { ++ __le32 gpio_num; /* GPIO number to be setup */ ++ __le32 input; /* 0 - Output/ 1 - Input */ ++ __le32 pull_type; /* Pull type defined above */ ++ __le32 intr_mode; /* Interrupt mode defined above (Input) */ ++} __packed; ++ ++/* WMI_GPIO_OUTPUT_CMDID */ ++struct wmi_gpio_output_cmd { ++ __le32 gpio_num; /* GPIO number to be setup */ ++ __le32 set; /* Set the GPIO pin*/ ++} __packed; ++ ++/* WMI_GPIO_INPUT_EVENTID */ ++struct wmi_gpio_input_event { ++ __le32 gpio_num; /* GPIO number which changed state */ ++} __packed; ++ + struct wmi_ext_resource_config_10_4_cmd { + /* contains enum wmi_host_platform_type */ + __le32 host_platform_config; diff --git a/feeds/ipq40xx/mac80211/patches/ath/975-ath10k-use-tpt-trigger-by-default.patch b/feeds/ipq40xx/mac80211/patches/ath/975-ath10k-use-tpt-trigger-by-default.patch new file mode 100644 index 000000000..db9a88e00 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/ath/975-ath10k-use-tpt-trigger-by-default.patch @@ -0,0 +1,53 @@ +From 79c9d7aabae1d1da9eea97d83b61e1517a8a2221 Mon Sep 17 00:00:00 2001 +From: Mathias Kresin +Date: Fri, 22 Jun 2018 18:59:44 +0200 +Subject: [PATCH] ath10k: use tpt LED trigger by default + +Use the tpt LED trigger for each created phy led. Ths way LEDs attached +to the ath10k GPIO pins are indicating the phy status and blink on +traffic. + +Signed-off-by: Mathias Kresin +--- + drivers/net/wireless/ath/ath10k/core.h | 4 ++++ + drivers/net/wireless/ath/ath10k/leds.c | 4 +--- + drivers/net/wireless/ath/ath10k/mac.c | 2 +- + 3 files changed, 6 insertions(+), 4 deletions(-) + +--- a/drivers/net/wireless/ath/ath10k/core.h ++++ b/drivers/net/wireless/ath/ath10k/core.h +@@ -1269,6 +1269,10 @@ struct ath10k { + bool coex_support; + int coex_gpio_pin; + ++#ifdef CPTCFG_MAC80211_LEDS ++ const char *led_default_trigger; ++#endif ++ + /* must be last */ + u8 drv_priv[] __aligned(sizeof(void *)); + }; +--- a/drivers/net/wireless/ath/ath10k/leds.c ++++ b/drivers/net/wireless/ath/ath10k/leds.c +@@ -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; + + ret = led_classdev_register(wiphy_dev(ar->hw->wiphy), &ar->leds.cdev); + if (ret) +--- a/drivers/net/wireless/ath/ath10k/mac.c ++++ b/drivers/net/wireless/ath/ath10k/mac.c +@@ -9397,7 +9397,7 @@ int ath10k_mac_register(struct ath10k *a + ar->hw->weight_multiplier = ATH10K_AIRTIME_WEIGHT_MULTIPLIER; + + #ifdef CPTCFG_MAC80211_LEDS +- ieee80211_create_tpt_led_trigger(ar->hw, ++ ar->led_default_trigger = ieee80211_create_tpt_led_trigger(ar->hw, + IEEE80211_TPT_LEDTRIG_FL_RADIO, ath10k_tpt_blink, + ARRAY_SIZE(ath10k_tpt_blink)); + #endif diff --git a/feeds/ipq40xx/mac80211/patches/ath/980-ath10k-fix-max-antenna-gain-unit.patch b/feeds/ipq40xx/mac80211/patches/ath/980-ath10k-fix-max-antenna-gain-unit.patch new file mode 100644 index 000000000..9498e0246 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/ath/980-ath10k-fix-max-antenna-gain-unit.patch @@ -0,0 +1,49 @@ +From: Sven Eckelmann +Date: Tue, 11 Jun 2019 13:58:35 +0200 +Subject: ath10k: fix max antenna gain unit + +Most of the txpower for the ath10k firmware is stored as twicepower (0.5 dB +steps). This isn't the case for max_antenna_gain - which is still expected +by the firmware as dB. + +The firmware is converting it from dB to the internal (twicepower) +representation when it calculates the limits of a channel. This can be seen +in tpc_stats when configuring "12" as max_antenna_gain. Instead of the +expected 12 (6 dB), the tpc_stats shows 24 (12 dB). + +Tested on QCA9888 and IPQ4019 with firmware 10.4-3.5.3-00057. + +Fixes: 02256930d9b8 ("ath10k: use proper tx power unit") +Signed-off-by: Sven Eckelmann + +Forwarded: https://patchwork.kernel.org/patch/10986723/ + +--- a/drivers/net/wireless/ath/ath10k/mac.c ++++ b/drivers/net/wireless/ath/ath10k/mac.c +@@ -1043,7 +1043,7 @@ 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; +- arg.channel.max_antenna_gain = channel->max_antenna_gain * 2; ++ arg.channel.max_antenna_gain = channel->max_antenna_gain; + + reinit_completion(&ar->vdev_setup_done); + reinit_completion(&ar->vdev_delete_done); +@@ -1489,7 +1489,7 @@ 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; +- arg.channel.max_antenna_gain = chandef->chan->max_antenna_gain * 2; ++ arg.channel.max_antenna_gain = chandef->chan->max_antenna_gain; + + if (arvif->vdev_type == WMI_VDEV_TYPE_AP) { + arg.ssid = arvif->u.ap.ssid; +@@ -3194,7 +3194,7 @@ 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; +- ch->max_antenna_gain = channel->max_antenna_gain * 2; ++ ch->max_antenna_gain = channel->max_antenna_gain; + ch->reg_class_id = 0; /* FIXME */ + + /* FIXME: why use only legacy modes, why not any diff --git a/feeds/ipq40xx/mac80211/patches/ath/981-ath10k-adjust-tx-power-reduction-for-US-regulatory-d.patch b/feeds/ipq40xx/mac80211/patches/ath/981-ath10k-adjust-tx-power-reduction-for-US-regulatory-d.patch new file mode 100644 index 000000000..fbb6fad66 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/ath/981-ath10k-adjust-tx-power-reduction-for-US-regulatory-d.patch @@ -0,0 +1,101 @@ +From: Sven Eckelmann +Date: Wed, 28 Nov 2018 16:16:27 +0100 +Subject: ath10k: adjust tx power reduction for US regulatory domain + +FCC allows maximum antenna gain of 6 dBi. 15.247(b)(4): + +> (4) The conducted output power limit +> specified in paragraph (b) of this section +> is based on the use of antennas +> with directional gains that do not exceed +> 6 dBi. Except as shown in paragraph +> (c) of this section, if transmitting +> antennas of directional gain greater +> than 6 dBi are used, the conducted +> output power from the intentional radiator +> shall be reduced below the stated +> values in paragraphs (b)(1), (b)(2), +> and (b)(3) of this section, as appropriate, +> by the amount in dB that the +> directional gain of the antenna exceeds +> 6 dBi. + +https://www.gpo.gov/fdsys/pkg/CFR-2013-title47-vol1/pdf/CFR-2013-title47-vol1-sec15-247.pdf + +Signed-off-by: Sven Eckelmann + +Forwarded: no + +--- a/drivers/net/wireless/ath/ath10k/mac.c ++++ b/drivers/net/wireless/ath/ath10k/mac.c +@@ -1011,6 +1011,40 @@ static inline int ath10k_vdev_setup_sync + return ar->last_wmi_vdev_start_status; + } + ++static u32 ath10k_get_max_antenna_gain(struct ath10k *ar, ++ u32 ch_max_antenna_gain) ++{ ++ u32 max_antenna_gain; ++ ++ if (ar->dfs_detector && ar->dfs_detector->region == NL80211_DFS_FCC) { ++ /* FCC allows maximum antenna gain of 6 dBi. 15.247(b)(4): ++ * ++ * > (4) The conducted output power limit ++ * > specified in paragraph (b) of this section ++ * > is based on the use of antennas ++ * > with directional gains that do not exceed ++ * > 6 dBi. Except as shown in paragraph ++ * > (c) of this section, if transmitting ++ * > antennas of directional gain greater ++ * > than 6 dBi are used, the conducted ++ * > output power from the intentional radiator ++ * > shall be reduced below the stated ++ * > values in paragraphs (b)(1), (b)(2), ++ * > and (b)(3) of this section, as appropriate, ++ * > by the amount in dB that the ++ * > directional gain of the antenna exceeds ++ * > 6 dBi. ++ * ++ * https://www.gpo.gov/fdsys/pkg/CFR-2013-title47-vol1/pdf/CFR-2013-title47-vol1-sec15-247.pdf ++ */ ++ max_antenna_gain = 6; ++ } else { ++ max_antenna_gain = 0; ++ } ++ ++ return max(ch_max_antenna_gain, max_antenna_gain); ++} ++ + static int ath10k_monitor_vdev_start(struct ath10k *ar, int vdev_id) + { + struct cfg80211_chan_def *chandef = NULL; +@@ -1043,7 +1077,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; +- arg.channel.max_antenna_gain = channel->max_antenna_gain; ++ arg.channel.max_antenna_gain = ath10k_get_max_antenna_gain(ar, ++ channel->max_antenna_gain); + + reinit_completion(&ar->vdev_setup_done); + reinit_completion(&ar->vdev_delete_done); +@@ -1489,7 +1524,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; +- arg.channel.max_antenna_gain = chandef->chan->max_antenna_gain; ++ arg.channel.max_antenna_gain = ath10k_get_max_antenna_gain(ar, ++ chandef->chan->max_antenna_gain); + + if (arvif->vdev_type == WMI_VDEV_TYPE_AP) { + arg.ssid = arvif->u.ap.ssid; +@@ -3194,7 +3230,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; +- ch->max_antenna_gain = channel->max_antenna_gain; ++ ch->max_antenna_gain = ath10k_get_max_antenna_gain(ar, ++ channel->max_antenna_gain); + ch->reg_class_id = 0; /* FIXME */ + + /* FIXME: why use only legacy modes, why not any diff --git a/feeds/ipq40xx/mac80211/patches/brcm/040-brcmutil_option.patch b/feeds/ipq40xx/mac80211/patches/brcm/040-brcmutil_option.patch new file mode 100644 index 000000000..3e8505b5b --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/brcm/040-brcmutil_option.patch @@ -0,0 +1,10 @@ +--- a/drivers/net/wireless/broadcom/brcm80211/Kconfig ++++ b/drivers/net/wireless/broadcom/brcm80211/Kconfig +@@ -1,6 +1,6 @@ + # SPDX-License-Identifier: GPL-2.0-only + config BRCMUTIL +- tristate ++ tristate "Broadcom 802.11 driver utility functions" + depends on m + + config BRCMSMAC diff --git a/feeds/ipq40xx/mac80211/patches/brcm/810-b43-gpio-mask-module-option.patch b/feeds/ipq40xx/mac80211/patches/brcm/810-b43-gpio-mask-module-option.patch new file mode 100644 index 000000000..b3f30943a --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/brcm/810-b43-gpio-mask-module-option.patch @@ -0,0 +1,37 @@ +--- a/drivers/net/wireless/broadcom/b43/b43.h ++++ b/drivers/net/wireless/broadcom/b43/b43.h +@@ -840,6 +840,7 @@ struct b43_wldev { + bool qos_enabled; /* TRUE, if QoS is used. */ + bool hwcrypto_enabled; /* TRUE, if HW crypto acceleration is enabled. */ + bool use_pio; /* TRUE if next init should use PIO */ ++ int gpiomask; /* GPIO LED mask as a module parameter */ + + /* PHY/Radio device. */ + struct b43_phy phy; +--- a/drivers/net/wireless/broadcom/b43/main.c ++++ b/drivers/net/wireless/broadcom/b43/main.c +@@ -72,6 +72,11 @@ MODULE_FIRMWARE("b43/ucode40.fw"); + MODULE_FIRMWARE("b43/ucode42.fw"); + MODULE_FIRMWARE("b43/ucode9.fw"); + ++static int modparam_gpiomask = 0x000F; ++module_param_named(gpiomask, modparam_gpiomask, int, 0444); ++MODULE_PARM_DESC(gpiomask, ++ "GPIO mask for LED control (default 0x000F)"); ++ + static int modparam_bad_frames_preempt; + module_param_named(bad_frames_preempt, modparam_bad_frames_preempt, int, 0444); + MODULE_PARM_DESC(bad_frames_preempt, +@@ -2867,10 +2872,10 @@ static int b43_gpio_init(struct b43_wlde + u32 mask, set; + + b43_maskset32(dev, B43_MMIO_MACCTL, ~B43_MACCTL_GPOUTSMSK, 0); +- b43_maskset16(dev, B43_MMIO_GPIO_MASK, ~0, 0xF); ++ b43_maskset16(dev, B43_MMIO_GPIO_MASK, ~0, modparam_gpiomask); + + mask = 0x0000001F; +- set = 0x0000000F; ++ set = modparam_gpiomask; + if (dev->dev->chip_id == 0x4301) { + mask |= 0x0060; + set |= 0x0060; diff --git a/feeds/ipq40xx/mac80211/patches/brcm/811-b43_no_pio.patch b/feeds/ipq40xx/mac80211/patches/brcm/811-b43_no_pio.patch new file mode 100644 index 000000000..a8dbefb5d --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/brcm/811-b43_no_pio.patch @@ -0,0 +1,86 @@ +--- a/drivers/net/wireless/broadcom/b43/Makefile ++++ b/drivers/net/wireless/broadcom/b43/Makefile +@@ -18,7 +18,7 @@ b43-$(CPTCFG_B43_PHY_AC) += phy_ac.o + b43-y += sysfs.o + b43-y += xmit.o + b43-y += dma.o +-b43-y += pio.o ++b43-$(CPTCFG_B43_PIO) += pio.o + b43-y += rfkill.o + b43-y += ppr.o + b43-$(CPTCFG_B43_LEDS) += leds.o +--- a/drivers/net/wireless/broadcom/b43/main.c ++++ b/drivers/net/wireless/broadcom/b43/main.c +@@ -2000,10 +2000,12 @@ static void b43_do_interrupt_thread(stru + dma_reason[0], dma_reason[1], + dma_reason[2], dma_reason[3], + dma_reason[4], dma_reason[5]); ++#ifdef CPTCFG_B43_PIO + b43err(dev->wl, "This device does not support DMA " + "on your system. It will now be switched to PIO.\n"); + /* Fall back to PIO transfers if we get fatal DMA errors! */ + dev->use_pio = true; ++#endif + b43_controller_restart(dev, "DMA error"); + return; + } +--- a/drivers/net/wireless/broadcom/b43/pio.h ++++ b/drivers/net/wireless/broadcom/b43/pio.h +@@ -151,7 +151,7 @@ static inline void b43_piorx_write32(str + b43_write32(q->dev, q->mmio_base + offset, value); + } + +- ++#ifdef CPTCFG_B43_PIO + int b43_pio_init(struct b43_wldev *dev); + void b43_pio_free(struct b43_wldev *dev); + +@@ -162,5 +162,37 @@ void b43_pio_rx(struct b43_pio_rxqueue * + + void b43_pio_tx_suspend(struct b43_wldev *dev); + void b43_pio_tx_resume(struct b43_wldev *dev); ++#else ++static inline int b43_pio_init(struct b43_wldev *dev) ++{ ++ return 0; ++} ++ ++static inline void b43_pio_free(struct b43_wldev *dev) ++{ ++} ++ ++static inline int b43_pio_tx(struct b43_wldev *dev, struct sk_buff *skb) ++{ ++ return 0; ++} ++ ++static inline void b43_pio_handle_txstatus(struct b43_wldev *dev, ++ const struct b43_txstatus *status) ++{ ++} ++ ++static inline void b43_pio_rx(struct b43_pio_rxqueue *q) ++{ ++} ++ ++static inline void b43_pio_tx_suspend(struct b43_wldev *dev) ++{ ++} ++ ++static inline void b43_pio_tx_resume(struct b43_wldev *dev) ++{ ++} ++#endif /* CPTCFG_B43_PIO */ + + #endif /* B43_PIO_H_ */ +--- a/drivers/net/wireless/broadcom/b43/Kconfig ++++ b/drivers/net/wireless/broadcom/b43/Kconfig +@@ -100,7 +100,7 @@ config B43_BCMA_PIO + default y + + config B43_PIO +- bool ++ bool "Broadcom 43xx PIO support" + depends on B43 && B43_SSB + depends on SSB_BLOCKIO + default y diff --git a/feeds/ipq40xx/mac80211/patches/brcm/812-b43-add-antenna-control.patch b/feeds/ipq40xx/mac80211/patches/brcm/812-b43-add-antenna-control.patch new file mode 100644 index 000000000..cd7b7583c --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/brcm/812-b43-add-antenna-control.patch @@ -0,0 +1,131 @@ +--- a/drivers/net/wireless/broadcom/b43/main.c ++++ b/drivers/net/wireless/broadcom/b43/main.c +@@ -1642,7 +1642,7 @@ static void b43_write_beacon_template(st + len, ram_offset, shm_size_offset, rate); + + /* Write the PHY TX control parameters. */ +- antenna = B43_ANTENNA_DEFAULT; ++ antenna = dev->tx_antenna; + 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. */ +@@ -3282,8 +3282,8 @@ static int b43_chip_init(struct b43_wlde + + /* Select the antennae */ + if (phy->ops->set_rx_antenna) +- phy->ops->set_rx_antenna(dev, B43_ANTENNA_DEFAULT); +- b43_mgmtframe_txantenna(dev, B43_ANTENNA_DEFAULT); ++ phy->ops->set_rx_antenna(dev, dev->rx_antenna); ++ b43_mgmtframe_txantenna(dev, dev->tx_antenna); + + if (phy->type == B43_PHYTYPE_B) { + value16 = b43_read16(dev, 0x005E); +@@ -3983,7 +3983,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; +- int antenna; + int err = 0; + + mutex_lock(&wl->mutex); +@@ -4026,11 +4025,9 @@ static int b43_op_config(struct ieee8021 + } + + /* Antennas for RX and management frame TX. */ +- antenna = B43_ANTENNA_DEFAULT; +- b43_mgmtframe_txantenna(dev, antenna); +- antenna = B43_ANTENNA_DEFAULT; ++ b43_mgmtframe_txantenna(dev, dev->tx_antenna); + if (phy->ops->set_rx_antenna) +- phy->ops->set_rx_antenna(dev, antenna); ++ phy->ops->set_rx_antenna(dev, dev->rx_antenna); + + if (wl->radio_enabled != phy->radio_on) { + if (wl->radio_enabled) { +@@ -5174,6 +5171,47 @@ static int b43_op_get_survey(struct ieee + return 0; + } + ++static int b43_op_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant) ++{ ++ struct b43_wl *wl = hw_to_b43_wl(hw); ++ struct b43_wldev *dev = wl->current_dev; ++ ++ if (tx_ant == 1 && rx_ant == 1) { ++ dev->tx_antenna = B43_ANTENNA0; ++ dev->rx_antenna = B43_ANTENNA0; ++ } ++ else if (tx_ant == 2 && rx_ant == 2) { ++ dev->tx_antenna = B43_ANTENNA1; ++ dev->rx_antenna = B43_ANTENNA1; ++ } ++ else if ((tx_ant & 3) == 3 && (rx_ant & 3) == 3) { ++ dev->tx_antenna = B43_ANTENNA_DEFAULT; ++ dev->rx_antenna = B43_ANTENNA_DEFAULT; ++ } ++ else { ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++ ++static int b43_op_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant) ++{ ++ struct b43_wl *wl = hw_to_b43_wl(hw); ++ struct b43_wldev *dev = wl->current_dev; ++ ++ switch (dev->tx_antenna) { ++ case B43_ANTENNA0: ++ *tx_ant = 1; *rx_ant = 1; break; ++ case B43_ANTENNA1: ++ *tx_ant = 2; *rx_ant = 2; break; ++ case B43_ANTENNA_DEFAULT: ++ *tx_ant = 3; *rx_ant = 3; break; ++ } ++ return 0; ++} ++ + static const struct ieee80211_ops b43_hw_ops = { + .tx = b43_op_tx, + .conf_tx = b43_op_conf_tx, +@@ -5195,6 +5233,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, ++ .set_antenna = b43_op_set_antenna, ++ .get_antenna = b43_op_get_antenna, + }; + + /* Hard-reset the chip. Do not call this directly. +@@ -5496,6 +5536,8 @@ static int b43_one_core_attach(struct b4 + if (!wldev) + goto out; + ++ wldev->rx_antenna = B43_ANTENNA_DEFAULT; ++ wldev->tx_antenna = B43_ANTENNA_DEFAULT; + wldev->use_pio = b43_modparam_pio; + wldev->dev = dev; + wldev->wl = wl; +@@ -5590,6 +5632,9 @@ static struct b43_wl *b43_wireless_init( + + wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST); + ++ hw->wiphy->available_antennas_rx = 0x3; ++ hw->wiphy->available_antennas_tx = 0x3; ++ + wl->hw_registered = false; + hw->max_rates = 2; + SET_IEEE80211_DEV(hw, dev->dev); +--- a/drivers/net/wireless/broadcom/b43/b43.h ++++ b/drivers/net/wireless/broadcom/b43/b43.h +@@ -841,6 +841,8 @@ struct b43_wldev { + bool hwcrypto_enabled; /* TRUE, if HW crypto acceleration is enabled. */ + bool use_pio; /* TRUE if next init should use PIO */ + int gpiomask; /* GPIO LED mask as a module parameter */ ++ int rx_antenna; /* Used RX antenna (B43_ANTENNAxxx) */ ++ int tx_antenna; /* Used TX antenna (B43_ANTENNAxxx) */ + + /* PHY/Radio device. */ + struct b43_phy phy; diff --git a/feeds/ipq40xx/mac80211/patches/brcm/813-b43-reduce-number-of-RX-slots.patch b/feeds/ipq40xx/mac80211/patches/brcm/813-b43-reduce-number-of-RX-slots.patch new file mode 100644 index 000000000..85c52c028 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/brcm/813-b43-reduce-number-of-RX-slots.patch @@ -0,0 +1,11 @@ +--- a/drivers/net/wireless/broadcom/b43/dma.h ++++ b/drivers/net/wireless/broadcom/b43/dma.h +@@ -170,7 +170,7 @@ struct b43_dmadesc_generic { + + /* DMA engine tuning knobs */ + #define B43_TXRING_SLOTS 256 +-#define B43_RXRING_SLOTS 256 ++#define B43_RXRING_SLOTS 32 + #define B43_DMA0_RX_FW598_BUFSIZE (B43_DMA0_RX_FW598_FO + IEEE80211_MAX_FRAME_LEN) + #define B43_DMA0_RX_FW351_BUFSIZE (B43_DMA0_RX_FW351_FO + IEEE80211_MAX_FRAME_LEN) + diff --git a/feeds/ipq40xx/mac80211/patches/brcm/814-b43-only-use-gpio-0-1-for-led.patch b/feeds/ipq40xx/mac80211/patches/brcm/814-b43-only-use-gpio-0-1-for-led.patch new file mode 100644 index 000000000..2aa761287 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/brcm/814-b43-only-use-gpio-0-1-for-led.patch @@ -0,0 +1,17 @@ +--- a/drivers/net/wireless/broadcom/b43/main.c ++++ b/drivers/net/wireless/broadcom/b43/main.c +@@ -2884,6 +2884,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 */ ++ } else if (dev->dev->chip_id == BCMA_CHIP_ID_BCM4716 || ++ dev->dev->chip_id == BCMA_CHIP_ID_BCM47162 || ++ dev->dev->chip_id == BCMA_CHIP_ID_BCM5356 || ++ dev->dev->chip_id == BCMA_CHIP_ID_BCM5357 || ++ dev->dev->chip_id == BCMA_CHIP_ID_BCM53572) { ++ /* just use gpio 0 and 1 for 2.4 GHz wifi led */ ++ set &= 0x3; ++ mask &= 0x3; + } + + if (0 /* FIXME: conditional unknown */ ) { diff --git a/feeds/ipq40xx/mac80211/patches/brcm/815-b43-always-take-overlapping-devs.patch b/feeds/ipq40xx/mac80211/patches/brcm/815-b43-always-take-overlapping-devs.patch new file mode 100644 index 000000000..a8eae1941 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/brcm/815-b43-always-take-overlapping-devs.patch @@ -0,0 +1,11 @@ +--- a/drivers/net/wireless/broadcom/b43/main.c ++++ b/drivers/net/wireless/broadcom/b43/main.c +@@ -114,7 +114,7 @@ static int b43_modparam_pio = 0; + module_param_named(pio, b43_modparam_pio, int, 0644); + MODULE_PARM_DESC(pio, "Use PIO accesses by default: 0=DMA, 1=PIO"); + +-static int modparam_allhwsupport = !IS_ENABLED(CPTCFG_BRCMSMAC); ++static int modparam_allhwsupport = 1; + module_param_named(allhwsupport, modparam_allhwsupport, int, 0444); + MODULE_PARM_DESC(allhwsupport, "Enable support for all hardware (even it if overlaps with the brcmsmac driver)"); + diff --git a/feeds/ipq40xx/mac80211/patches/brcm/850-brcmsmac-remove-extra-regulation-restriction.patch b/feeds/ipq40xx/mac80211/patches/brcm/850-brcmsmac-remove-extra-regulation-restriction.patch new file mode 100644 index 000000000..3c93386b3 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/brcm/850-brcmsmac-remove-extra-regulation-restriction.patch @@ -0,0 +1,27 @@ +--- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/channel.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/channel.c +@@ -58,19 +58,12 @@ + (((c) < 149) ? 3 : 4)))) + + #define BRCM_2GHZ_2412_2462 REG_RULE(2412-10, 2462+10, 40, 0, 19, 0) +-#define BRCM_2GHZ_2467_2472 REG_RULE(2467-10, 2472+10, 20, 0, 19, \ +- NL80211_RRF_NO_IR) ++#define BRCM_2GHZ_2467_2472 REG_RULE(2467-10, 2472+10, 20, 0, 19, 0) + +-#define BRCM_5GHZ_5180_5240 REG_RULE(5180-10, 5240+10, 40, 0, 21, \ +- NL80211_RRF_NO_IR) +-#define BRCM_5GHZ_5260_5320 REG_RULE(5260-10, 5320+10, 40, 0, 21, \ +- NL80211_RRF_DFS | \ +- NL80211_RRF_NO_IR) +-#define BRCM_5GHZ_5500_5700 REG_RULE(5500-10, 5700+10, 40, 0, 21, \ +- NL80211_RRF_DFS | \ +- NL80211_RRF_NO_IR) +-#define BRCM_5GHZ_5745_5825 REG_RULE(5745-10, 5825+10, 40, 0, 21, \ +- NL80211_RRF_NO_IR) ++#define BRCM_5GHZ_5180_5240 REG_RULE(5180-10, 5240+10, 40, 0, 21, 0) ++#define BRCM_5GHZ_5260_5320 REG_RULE(5260-10, 5320+10, 40, 0, 21, 0) ++#define BRCM_5GHZ_5500_5700 REG_RULE(5500-10, 5700+10, 40, 0, 21, 0) ++#define BRCM_5GHZ_5745_5825 REG_RULE(5745-10, 5825+10, 40, 0, 21, 0) + + static const struct ieee80211_regdomain brcms_regdom_x2 = { + .n_reg_rules = 6, diff --git a/feeds/ipq40xx/mac80211/patches/brcm/860-brcmfmac-register-wiphy-s-during-module_init.patch b/feeds/ipq40xx/mac80211/patches/brcm/860-brcmfmac-register-wiphy-s-during-module_init.patch new file mode 100644 index 000000000..1b965087d --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/brcm/860-brcmfmac-register-wiphy-s-during-module_init.patch @@ -0,0 +1,74 @@ +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/core.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c +@@ -1551,6 +1551,7 @@ int __init brcmf_core_init(void) + { + if (!schedule_work(&brcmf_driver_work)) + return -EBUSY; ++ flush_work(&brcmf_driver_work); + + return 0; + } +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c +@@ -431,6 +431,7 @@ struct brcmf_fw { + struct brcmf_fw_request *req; + u32 curpos; + void (*done)(struct device *dev, int err, struct brcmf_fw_request *req); ++ struct completion *completion; + }; + + static void brcmf_fw_request_done(const struct firmware *fw, void *ctx); +@@ -638,6 +639,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); + } + +@@ -662,6 +665,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; + int ret; + + brcmf_dbg(TRACE, "enter: dev=%s\n", dev_name(dev)); +@@ -678,6 +683,9 @@ int brcmf_fw_get_firmwares(struct device + fwctx->dev = dev; + fwctx->req = req; + fwctx->done = fw_cb; ++ ++ init_completion(&completion); ++ fwctx->completion = &completion; + + ret = request_firmware_nowait(THIS_MODULE, true, first->path, + fwctx->dev, GFP_KERNEL, fwctx, +@@ -685,6 +693,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/feeds/ipq40xx/mac80211/patches/brcm/861-brcmfmac-workaround-bug-with-some-inconsistent-BSSes.patch b/feeds/ipq40xx/mac80211/patches/brcm/861-brcmfmac-workaround-bug-with-some-inconsistent-BSSes.patch new file mode 100644 index 000000000..069aab824 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/brcm/861-brcmfmac-workaround-bug-with-some-inconsistent-BSSes.patch @@ -0,0 +1,49 @@ +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Thu, 9 Jul 2015 00:07:59 +0200 +Subject: [PATCH] brcmfmac: workaround bug with some inconsistent BSSes state +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Rafał Miłecki +--- + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +@@ -712,8 +712,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; ++ struct net_device *dev; + int err; + ++ /* ++ * There is a bug with in-firmware BSS management. When adding virtual ++ * interface brcmfmac first tells firmware to create new BSS and then ++ * it creates new struct net_device. ++ * ++ * If creating/registering netdev(ice) fails, BSS remains in some bugged ++ * state. It conflicts with existing BSSes by overtaking their auth ++ * requests. ++ * ++ * It results in one BSS (addresss X) sending beacons and another BSS ++ * (address Y) replying to authentication requests. This makes interface ++ * unusable as AP. ++ * ++ * To workaround this bug we may try to guess if register_netdev(ice) ++ * will fail. The most obvious case is using interface name that already ++ * exists. This is actually quite likely with brcmfmac & some user space ++ * scripts as brcmfmac doesn't allow deleting virtual interfaces. ++ * So this bug can be triggered even by something trivial like: ++ * iw dev wlan0 delete ++ * iw phy phy0 interface add wlan0 type __ap ++ */ ++ dev = dev_get_by_name(&init_net, name); ++ if (dev) { ++ dev_put(dev); ++ return ERR_PTR(-ENFILE); ++ } ++ + brcmf_dbg(TRACE, "enter: %s type %d\n", name, type); + err = brcmf_vif_add_validate(wiphy_to_cfg(wiphy), type); + if (err) { diff --git a/feeds/ipq40xx/mac80211/patches/brcm/862-brcmfmac-Disable-power-management.patch b/feeds/ipq40xx/mac80211/patches/brcm/862-brcmfmac-Disable-power-management.patch new file mode 100644 index 000000000..8a20ae133 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/brcm/862-brcmfmac-Disable-power-management.patch @@ -0,0 +1,27 @@ +From 66ae1b1750720a33e29792a177b1e696f4f005fb Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Wed, 9 Mar 2016 17:25:59 +0000 +Subject: [PATCH] brcmfmac: Disable power management + +Disable wireless power saving in the brcmfmac WLAN driver. This is a +temporary measure until the connectivity loss resulting from power +saving is resolved. + +Signed-off-by: Phil Elwell +--- + drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +@@ -2953,6 +2953,10 @@ brcmf_cfg80211_set_power_mgmt(struct wip + * preference in cfg struct to apply this to + * FW later while initializing the dongle + */ ++#if defined(CONFIG_ARCH_BCM2835) ++ brcmf_dbg(INFO, "power management disabled\n"); ++ enabled = false; ++#endif + cfg->pwr_save = enabled; + if (!check_vif_up(ifp->vif)) { + diff --git a/feeds/ipq40xx/mac80211/patches/brcm/863-brcmfmac-add-in-driver-tables-with-country-codes.patch b/feeds/ipq40xx/mac80211/patches/brcm/863-brcmfmac-add-in-driver-tables-with-country-codes.patch new file mode 100644 index 000000000..2613171a8 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/brcm/863-brcmfmac-add-in-driver-tables-with-country-codes.patch @@ -0,0 +1,60 @@ +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Subject: [PATCH] brcmfmac: add in-driver tables with country codes +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This adds early support for changing region. Ideally this data should +be stored in DT as all these mappings are devices specific. + +Signed-off-by: Rafał Miłecki +--- + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c +@@ -12,6 +12,36 @@ + #include "common.h" + #include "of.h" + ++/* TODO: FIXME: Use DT */ ++static void brcmf_of_probe_cc(struct device *dev, ++ struct brcmf_mp_device *settings) ++{ ++ static struct brcmfmac_pd_cc_entry netgear_r8000_cc_ent[] = { ++ { "JP", "JP", 78 }, ++ { "US", "Q2", 86 }, ++ }; ++ struct brcmfmac_pd_cc_entry *cc_ent = NULL; ++ int table_size = 0; ++ ++ if (of_machine_is_compatible("netgear,r8000")) { ++ cc_ent = netgear_r8000_cc_ent; ++ table_size = ARRAY_SIZE(netgear_r8000_cc_ent); ++ } ++ ++ if (cc_ent && table_size) { ++ struct brcmfmac_pd_cc *cc; ++ size_t memsize; ++ ++ memsize = table_size * sizeof(struct brcmfmac_pd_cc_entry); ++ cc = devm_kzalloc(dev, sizeof(*cc) + memsize, GFP_KERNEL); ++ if (!cc) ++ return; ++ cc->table_size = table_size; ++ memcpy(cc->table, cc_ent, memsize); ++ settings->country_codes = cc; ++ } ++} ++ + void brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type, + struct brcmf_mp_device *settings) + { +@@ -30,6 +60,8 @@ void brcmf_of_probe(struct device *dev, + of_node_put(root); + } + ++ brcmf_of_probe_cc(dev, settings); ++ + if (!np || bus_type != BRCMF_BUSTYPE_SDIO || + !of_device_is_compatible(np, "brcm,bcm4329-fmac")) + return; diff --git a/feeds/ipq40xx/mac80211/patches/brcm/864-brcmfmac-do-not-use-internal-roaming-engine-by-default.patch b/feeds/ipq40xx/mac80211/patches/brcm/864-brcmfmac-do-not-use-internal-roaming-engine-by-default.patch new file mode 100644 index 000000000..fe79c40c1 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/brcm/864-brcmfmac-do-not-use-internal-roaming-engine-by-default.patch @@ -0,0 +1,23 @@ +brcmfmac: do not use internal roaming engine by default + +Some evidence of curing disconnects with this disabled, so make it a default. +Can be overridden with module parameter roamoff=0 +See: http://projectable.me/optimize-my-pi-wi-fi/ + +Signed-off-by: Phil Elwell +--- + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c +@@ -59,7 +59,11 @@ static int brcmf_fcmode; + module_param_named(fcmode, brcmf_fcmode, int, 0); + MODULE_PARM_DESC(fcmode, "Mode of firmware signalled flow control"); + ++#if defined(CONFIG_ARCH_BCM2835) ++static int brcmf_roamoff = 1; ++#else + static int brcmf_roamoff; ++#endif + module_param_named(roamoff, brcmf_roamoff, int, 0400); + MODULE_PARM_DESC(roamoff, "Do not use internal roaming engine"); + diff --git a/feeds/ipq40xx/mac80211/patches/brcm/998-survey.patch b/feeds/ipq40xx/mac80211/patches/brcm/998-survey.patch new file mode 100644 index 000000000..bcab2e3f3 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/brcm/998-survey.patch @@ -0,0 +1,148 @@ +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +@@ -2905,6 +2905,63 @@ done: + } + + static int ++brcmf_cfg80211_dump_survey(struct wiphy *wiphy, struct net_device *ndev, ++ int idx, struct survey_info *survey) ++{ ++ struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); ++ struct brcmf_if *ifp = netdev_priv(ndev); ++ struct brcmu_chan ch; ++ enum nl80211_band band = 0; ++ s32 err = 0; ++ int noise; ++ u32 freq; ++ u32 chanspec; ++ ++ memset(survey, 0, sizeof(struct survey_info)); ++ if (idx != 0) { ++ if (idx >= cfg->pub->num_chan_stats || cfg->pub->chan_stats == NULL) ++ return -ENOENT; ++ if (cfg->pub->chan_stats[idx].freq == 0) ++ return -ENOENT; ++ survey->filled = SURVEY_INFO_NOISE_DBM; ++ survey->channel = ieee80211_get_channel(wiphy, cfg->pub->chan_stats[idx].freq); ++ survey->noise = cfg->pub->chan_stats[idx].noise; ++ return 0; ++ } ++ ++ err = brcmf_fil_iovar_int_get(ifp, "chanspec", &chanspec); ++ if (err) { ++ brcmf_err("chanspec failed (%d)\n", err); ++ return err; ++ } ++ ++ ch.chspec = chanspec; ++ cfg->d11inf.decchspec(&ch); ++ ++ switch (ch.band) { ++ case BRCMU_CHAN_BAND_2G: ++ band = NL80211_BAND_2GHZ; ++ break; ++ case BRCMU_CHAN_BAND_5G: ++ band = NL80211_BAND_5GHZ; ++ break; ++ } ++ ++ freq = ieee80211_channel_to_frequency(ch.control_ch_num, band); ++ survey->channel = ieee80211_get_channel(wiphy, freq); ++ ++ err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_PHY_NOISE, &noise); ++ if (err) { ++ brcmf_err("Could not get noise (%d)\n", err); ++ return err; ++ } ++ ++ survey->filled = SURVEY_INFO_NOISE_DBM | SURVEY_INFO_IN_USE; ++ survey->noise = le32_to_cpu(noise); ++ return 0; ++} ++ ++static int + brcmf_cfg80211_dump_station(struct wiphy *wiphy, struct net_device *ndev, + int idx, u8 *mac, struct station_info *sinfo) + { +@@ -2994,6 +3051,7 @@ static s32 brcmf_inform_single_bss(struc + struct brcmu_chan ch; + u16 channel; + u32 freq; ++ int i; + u16 notify_capability; + u16 notify_interval; + u8 *notify_ie; +@@ -3018,6 +3076,17 @@ static s32 brcmf_inform_single_bss(struc + band = NL80211_BAND_5GHZ; + + freq = ieee80211_channel_to_frequency(channel, band); ++ for (i = 0;i < cfg->pub->num_chan_stats;i++) { ++ if (freq == cfg->pub->chan_stats[i].freq) ++ break; ++ if (cfg->pub->chan_stats[i].freq == 0) ++ break; ++ } ++ if (i < cfg->pub->num_chan_stats) { ++ cfg->pub->chan_stats[i].freq = freq; ++ cfg->pub->chan_stats[i].noise = bi->phy_noise; ++ } ++ + bss_data.chan = ieee80211_get_channel(wiphy, freq); + bss_data.scan_width = NL80211_BSS_CHAN_WIDTH_20; + bss_data.boottime_ns = ktime_to_ns(ktime_get_boottime()); +@@ -5470,6 +5539,7 @@ static struct cfg80211_ops brcmf_cfg8021 + .leave_ibss = brcmf_cfg80211_leave_ibss, + .get_station = brcmf_cfg80211_get_station, + .dump_station = brcmf_cfg80211_dump_station, ++ .dump_survey = brcmf_cfg80211_dump_survey, + .set_tx_power = brcmf_cfg80211_set_tx_power, + .get_tx_power = brcmf_cfg80211_get_tx_power, + .add_key = brcmf_cfg80211_add_key, +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c +@@ -1349,6 +1349,8 @@ int brcmf_attach(struct device *dev) + + /* Link to bus module */ + drvr->hdrlen = 0; ++ drvr->chan_stats = vzalloc(256 * sizeof(struct brcmf_chan_stats)); ++ drvr->num_chan_stats = 256; + + /* Attach and link in the protocol */ + ret = brcmf_proto_attach(drvr); +@@ -1431,6 +1433,12 @@ void brcmf_detach(struct device *dev) + if (drvr == NULL) + return; + ++ drvr->num_chan_stats = 0; ++ if (drvr->chan_stats) { ++ vfree(drvr->chan_stats); ++ drvr->chan_stats = NULL; ++ } ++ + #ifdef CONFIG_INET + unregister_inetaddr_notifier(&drvr->inetaddr_notifier); + #endif +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h +@@ -91,6 +91,11 @@ struct brcmf_rev_info { + u32 nvramrev; + }; + ++struct brcmf_chan_stats { ++ u32 freq; ++ int noise; ++}; ++ + /* Common structure for module and instance linkage */ + struct brcmf_pub { + /* Linkage ponters */ +@@ -100,6 +105,9 @@ struct brcmf_pub { + struct cfg80211_ops *ops; + struct brcmf_cfg80211_info *config; + ++ int num_chan_stats; ++ struct brcmf_chan_stats *chan_stats; ++ + /* Internal brcmf items */ + uint hdrlen; /* Total BRCMF header length (proto + bus) */ + diff --git a/feeds/ipq40xx/mac80211/patches/build/000-fix_kconfig.patch b/feeds/ipq40xx/mac80211/patches/build/000-fix_kconfig.patch new file mode 100644 index 000000000..3987aae4f --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/build/000-fix_kconfig.patch @@ -0,0 +1,14 @@ +--- a/kconf/Makefile ++++ b/kconf/Makefile +@@ -1,9 +1,9 @@ +-CFLAGS=-Wall -Wmissing-prototypes -Wstrict-prototypes -O2 -fomit-frame-pointer ++CFLAGS=-Wall -Wmissing-prototypes -Wstrict-prototypes -O2 -fomit-frame-pointer -DKBUILD_NO_NLS + + LXDIALOG := lxdialog/checklist.o lxdialog/inputbox.o lxdialog/menubox.o lxdialog/textbox.o lxdialog/util.o lxdialog/yesno.o + + conf: conf.o zconf.tab.o +-mconf_CFLAGS := $(shell ./lxdialog/check-lxdialog.sh -ccflags) -DLOCALE ++mconf_CFLAGS := $(shell ./lxdialog/check-lxdialog.sh -ccflags) + mconf_LDFLAGS := $(shell ./lxdialog/check-lxdialog.sh -ldflags $(CC)) + mconf: CFLAGS += $(mconf_CFLAGS) + diff --git a/feeds/ipq40xx/mac80211/patches/build/001-fix_build.patch b/feeds/ipq40xx/mac80211/patches/build/001-fix_build.patch new file mode 100644 index 000000000..e57ca190e --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/build/001-fix_build.patch @@ -0,0 +1,169 @@ +--- a/Makefile ++++ b/Makefile +@@ -5,7 +5,7 @@ + ifeq ($(KERNELRELEASE),) + + MAKEFLAGS += --no-print-directory +-SHELL := /bin/bash ++SHELL := /usr/bin/env bash + BACKPORT_DIR := $(shell pwd) + + KMODDIR ?= updates +@@ -19,6 +19,7 @@ KLIB_BUILD ?= $(KLIB)/build/ + KERNEL_CONFIG := $(KLIB_BUILD)/.config + KERNEL_MAKEFILE := $(KLIB_BUILD)/Makefile + CONFIG_MD5 := $(shell md5sum $(KERNEL_CONFIG) 2>/dev/null | sed 's/\s.*//') ++STAMP_KERNEL_CONFIG := .kernel_config_md5_$(CONFIG_MD5) + + export KLIB KLIB_BUILD BACKPORT_DIR KMODDIR KMODPATH_ARG + +@@ -36,7 +37,8 @@ mrproper: + @rm -f .kernel_config_md5 Kconfig.versions Kconfig.kernel + @rm -f backport-include/backport/autoconf.h + +-.DEFAULT: ++.SILENT: $(STAMP_KERNEL_CONFIG) ++$(STAMP_KERNEL_CONFIG): + @set -e ; test -f local-symbols || ( \ + echo "/--------------" ;\ + echo "| You shouldn't run make in the backports tree, but only in" ;\ +@@ -60,58 +62,62 @@ mrproper: + echo "| (that isn't currently running.)" ;\ + echo "\\--" ;\ + false) +- @set -e ; if [ "$$(cat .kernel_config_md5 2>/dev/null)" != "$(CONFIG_MD5)" ] ;\ +- then \ +- echo -n "Generating local configuration database from kernel ..." ;\ +- grep -v -f local-symbols $(KERNEL_CONFIG) | grep = | ( \ +- while read l ; do \ +- if [ "$${l:0:7}" != "CONFIG_" ] ; then \ +- continue ;\ +- fi ;\ +- l=$${l:7} ;\ +- n=$${l%%=*} ;\ +- v=$${l#*=} ;\ +- if [ "$$v" = "m" ] ; then \ +- echo config $$n ;\ +- echo ' tristate' ;\ +- elif [ "$$v" = "y" ] ; then \ +- echo config $$n ;\ +- echo ' bool' ;\ +- else \ +- continue ;\ +- fi ;\ +- echo " default $$v" ;\ +- echo "" ;\ +- done \ +- ) > Kconfig.kernel ;\ +- kver=$$($(MAKE) --no-print-directory -C $(KLIB_BUILD) 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 99 | sed 's/^/5./')" ;\ +- print=0 ;\ +- for v in $$kvers ; do \ +- if [ "$$print" = "1" ] ; then \ +- echo config KERNEL_$$(echo $$v | tr . _) ;\ +- 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) | \ +- sed 's/.*=\s*\([0-9]*\)/\1/;t;d') ;\ +- RHEL_MINOR=$$(grep '^RHEL_MINOR' $(KERNEL_MAKEFILE) | \ +- sed 's/.*=\s*\([0-9]*\)/\1/;t;d') ;\ +- for v in $$(seq 0 $$RHEL_MINOR) ; do \ +- echo config BACKPORT_RHEL_KERNEL_$${RHEL_MAJOR}_$$v ;\ +- echo " def_bool y" ;\ +- done >> Kconfig.versions ;\ +- echo " done." ;\ +- fi ;\ +- echo "$(CONFIG_MD5)" > .kernel_config_md5 ++ @rm -f .kernel_config_md5_* ++ @touch $@ ++ ++Kconfig.kernel: $(STAMP_KERNEL_CONFIG) local-symbols ++ @printf "Generating local configuration database from kernel ..." ++ @grep -v -f local-symbols $(KERNEL_CONFIG) | grep = | ( \ ++ while read l ; do \ ++ if [ "$${l:0:7}" != "CONFIG_" ] ; then \ ++ continue ;\ ++ fi ;\ ++ l=$${l:7} ;\ ++ n=$${l%%=*} ;\ ++ v=$${l#*=} ;\ ++ if [ "$$v" = "m" ] ; then \ ++ echo config $$n ;\ ++ echo ' tristate' ;\ ++ elif [ "$$v" = "y" ] ; then \ ++ echo config $$n ;\ ++ echo ' bool' ;\ ++ else \ ++ continue ;\ ++ fi ;\ ++ echo " default $$v" ;\ ++ echo "" ;\ ++ done \ ++ ) > $@ ++ @echo " done." ++ ++Kconfig.versions: Kconfig.kernel ++ @kver=$$($(MAKE) --no-print-directory -C $(KLIB_BUILD) 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 99 | sed 's/^/5./')" ;\ ++ print=0 ;\ ++ for v in $$kvers ; do \ ++ if [ "$$print" = "1" ] ; then \ ++ echo config KERNEL_$$(echo $$v | tr . _) ;\ ++ echo " def_bool y" ;\ ++ fi ;\ ++ if [ "$$v" = "$$kver" ] ; then print=1 ; fi ;\ ++ 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') ;\ ++ for v in $$(seq 0 $$RHEL_MINOR) ; do \ ++ echo config BACKPORT_RHEL_KERNEL_$${RHEL_MAJOR}_$$v ;\ ++ echo " def_bool y" ;\ ++ done >> $@ ++ ++.DEFAULT: ++ @$(MAKE) Kconfig.versions + @$(MAKE) -f Makefile.real "$@" + + .PHONY: defconfig-help +--- a/Makefile.real ++++ b/Makefile.real +@@ -59,7 +59,7 @@ defconfig-%:: + + backport-include/backport/autoconf.h: .config Kconfig.versions Kconfig.kernel + @$(MAKE) oldconfig +- @echo -n "Building backport-include/backport/autoconf.h ..." ++ @printf "Building backport-include/backport/autoconf.h ..." + @grep -f local-symbols .config | ( \ + echo "#ifndef COMPAT_AUTOCONF_INCLUDED" ;\ + echo "#define COMPAT_AUTOCONF_INCLUDED" ;\ +@@ -80,7 +80,12 @@ backport-include/backport/autoconf.h: .c + esac ;\ + done ;\ + echo "#endif /* COMPAT_AUTOCONF_INCLUDED */" ;\ +- ) > backport-include/backport/autoconf.h ++ ) > $@.new ++ @if cmp -s $@ $@.new; then \ ++ rm -f $@.new; \ ++ else \ ++ mv $@.new $@; \ ++ fi + @echo " done." + + .PHONY: modules diff --git a/feeds/ipq40xx/mac80211/patches/build/002-change_allconfig.patch b/feeds/ipq40xx/mac80211/patches/build/002-change_allconfig.patch new file mode 100644 index 000000000..368725d0c --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/build/002-change_allconfig.patch @@ -0,0 +1,64 @@ +--- a/kconf/conf.c ++++ b/kconf/conf.c +@@ -598,40 +598,12 @@ int main(int ac, char **av) + case oldconfig: + case listnewconfig: + case olddefconfig: +- conf_read(NULL); +- break; + case allnoconfig: + case allyesconfig: + case allmodconfig: + case alldefconfig: + case randconfig: +- name = getenv("KCONFIG_ALLCONFIG"); +- if (!name) +- break; +- if ((strcmp(name, "") != 0) && (strcmp(name, "1") != 0)) { +- if (conf_read_simple(name, S_DEF_USER)) { +- fprintf(stderr, +- _("*** Can't read seed configuration \"%s\"!\n"), +- name); +- exit(1); +- } +- break; +- } +- switch (input_mode) { +- case allnoconfig: name = "allno.config"; break; +- case allyesconfig: name = "allyes.config"; break; +- case allmodconfig: name = "allmod.config"; break; +- case alldefconfig: name = "alldef.config"; break; +- case randconfig: name = "allrandom.config"; break; +- default: break; +- } +- if (conf_read_simple(name, S_DEF_USER) && +- conf_read_simple("all.config", S_DEF_USER)) { +- fprintf(stderr, +- _("*** KCONFIG_ALLCONFIG set, but no \"%s\" or \"all.config\" file found\n"), +- name); +- exit(1); +- } ++ conf_read(NULL); + break; + default: + break; +--- a/kconf/confdata.c ++++ b/kconf/confdata.c +@@ -1170,6 +1170,8 @@ bool conf_set_all_new_symbols(enum conf_ + } + bool has_changed = false; + ++ sym_clear_all_valid(); ++ + for_all_symbols(i, sym) { + if (sym_has_value(sym) || (sym->flags & SYMBOL_VALID)) + continue; +@@ -1213,8 +1215,6 @@ bool conf_set_all_new_symbols(enum conf_ + + } + +- sym_clear_all_valid(); +- + /* + * We have different type of choice blocks. + * If curr.tri equals to mod then we can select several diff --git a/feeds/ipq40xx/mac80211/patches/build/003-remove_bogus_modparams.patch b/feeds/ipq40xx/mac80211/patches/build/003-remove_bogus_modparams.patch new file mode 100644 index 000000000..8fa465a7e --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/build/003-remove_bogus_modparams.patch @@ -0,0 +1,34 @@ +--- a/compat/main.c ++++ b/compat/main.c +@@ -20,31 +20,6 @@ MODULE_LICENSE("GPL"); + #error "You need a CPTCFG_VERSION" + #endif + +-static char *backported_kernel_name = CPTCFG_KERNEL_NAME; +- +-module_param(backported_kernel_name, charp, 0400); +-MODULE_PARM_DESC(backported_kernel_name, +- "The kernel tree name that was used for this backport (" CPTCFG_KERNEL_NAME ")"); +- +-#ifdef BACKPORTS_GIT_TRACKED +-static char *backports_tracker_id = BACKPORTS_GIT_TRACKED; +-module_param(backports_tracker_id, charp, 0400); +-MODULE_PARM_DESC(backports_tracker_id, +- "The version of the tree containing this backport (" BACKPORTS_GIT_TRACKED ")"); +-#else +-static char *backported_kernel_version = CPTCFG_KERNEL_VERSION; +-static char *backports_version = CPTCFG_VERSION; +- +-module_param(backported_kernel_version, charp, 0400); +-MODULE_PARM_DESC(backported_kernel_version, +- "The kernel version that was used for this backport (" CPTCFG_KERNEL_VERSION ")"); +- +-module_param(backports_version, charp, 0400); +-MODULE_PARM_DESC(backports_version, +- "The git version of the backports tree used to generate this backport (" CPTCFG_VERSION ")"); +- +-#endif +- + void backport_dependency_symbol(void) + { + } diff --git a/feeds/ipq40xx/mac80211/patches/build/004-kconfig_backport_fix.patch b/feeds/ipq40xx/mac80211/patches/build/004-kconfig_backport_fix.patch new file mode 100644 index 000000000..2c9572ec9 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/build/004-kconfig_backport_fix.patch @@ -0,0 +1,28 @@ +--- a/backport-include/linux/kconfig.h ++++ b/backport-include/linux/kconfig.h +@@ -5,6 +5,8 @@ + #include_next + #endif + ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0) ++ + #ifndef __ARG_PLACEHOLDER_1 + #define __ARG_PLACEHOLDER_1 0, + #define config_enabled(cfg) _config_enabled(cfg) +@@ -16,6 +18,7 @@ + * 3.1 - 3.3 had a broken version of this, so undef + * (they didn't have __ARG_PLACEHOLDER_1) + */ ++ + #undef IS_ENABLED + #define IS_ENABLED(option) \ + (config_enabled(option) || config_enabled(option##_MODULE)) +@@ -31,6 +34,8 @@ + #undef IS_BUILTIN + #define IS_BUILTIN(option) config_enabled(option) + ++#endif ++ + #ifndef IS_REACHABLE + /* + * IS_REACHABLE(CONFIG_FOO) evaluates to 1 if the currently compiled diff --git a/feeds/ipq40xx/mac80211/patches/build/010-disable_rfkill.patch b/feeds/ipq40xx/mac80211/patches/build/010-disable_rfkill.patch new file mode 100644 index 000000000..d5253063c --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/build/010-disable_rfkill.patch @@ -0,0 +1,15 @@ +--- a/backport-include/linux/rfkill.h ++++ b/backport-include/linux/rfkill.h +@@ -2,6 +2,12 @@ + #define __COMPAT_RFKILL_H + #include + ++#undef CONFIG_RFKILL ++#undef CONFIG_RFKILL_FULL ++#undef CONFIG_RFKILL_LEDS ++#undef CONFIG_RFKILL_MODULE ++#undef CONFIG_RFKILL_FULL_MODULE ++ + #if LINUX_VERSION_IS_GEQ(3,10,0) + #include_next + #else diff --git a/feeds/ipq40xx/mac80211/patches/build/012-kernel_build_check.patch b/feeds/ipq40xx/mac80211/patches/build/012-kernel_build_check.patch new file mode 100644 index 000000000..d225ba182 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/build/012-kernel_build_check.patch @@ -0,0 +1,11 @@ +--- a/Makefile ++++ b/Makefile +@@ -2,7 +2,7 @@ + # Makefile for the output source package + # + +-ifeq ($(KERNELRELEASE),) ++ifeq ($(KERNELVERSION),) + + MAKEFLAGS += --no-print-directory + SHELL := /usr/bin/env bash diff --git a/feeds/ipq40xx/mac80211/patches/build/015-ipw200-mtu.patch b/feeds/ipq40xx/mac80211/patches/build/015-ipw200-mtu.patch new file mode 100644 index 000000000..68db4f72d --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/build/015-ipw200-mtu.patch @@ -0,0 +1,34 @@ +--- a/drivers/net/wireless/intel/ipw2x00/ipw2200.c ++++ b/drivers/net/wireless/intel/ipw2x00/ipw2200.c +@@ -11470,6 +11470,15 @@ static const struct attribute_group ipw_ + .attrs = ipw_sysfs_entries, + }; + ++#if LINUX_VERSION_IS_LESS(4,10,0) ++static int __change_mtu(struct net_device *ndev, int new_mtu){ ++ if (new_mtu < 68 || new_mtu > LIBIPW_DATA_LEN) ++ return -EINVAL; ++ ndev->mtu = new_mtu; ++ return 0; ++} ++#endif ++ + #ifdef CPTCFG_IPW2200_PROMISCUOUS + static int ipw_prom_open(struct net_device *dev) + { +@@ -11518,15 +11527,6 @@ static netdev_tx_t ipw_prom_hard_start_x + return NETDEV_TX_OK; + } + +-#if LINUX_VERSION_IS_LESS(4,10,0) +-static int __change_mtu(struct net_device *ndev, int new_mtu){ +- if (new_mtu < 68 || new_mtu > LIBIPW_DATA_LEN) +- return -EINVAL; +- ndev->mtu = new_mtu; +- return 0; +-} +-#endif +- + static const struct net_device_ops ipw_prom_netdev_ops = { + #if LINUX_VERSION_IS_LESS(4,10,0) + .ndo_change_mtu = __change_mtu, diff --git a/feeds/ipq40xx/mac80211/patches/build/050-lib80211_option.patch b/feeds/ipq40xx/mac80211/patches/build/050-lib80211_option.patch new file mode 100644 index 000000000..c6174449c --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/build/050-lib80211_option.patch @@ -0,0 +1,33 @@ +--- a/net/wireless/Kconfig ++++ b/net/wireless/Kconfig +@@ -187,7 +187,7 @@ config CFG80211_WEXT_EXPORT + endif # CFG80211 + + config LIB80211 +- tristate ++ tristate "lib80211" + depends on m + default n + help +@@ -197,18 +197,18 @@ 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_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/feeds/ipq40xx/mac80211/patches/build/060-no_local_ssb_bcma.patch b/feeds/ipq40xx/mac80211/patches/build/060-no_local_ssb_bcma.patch new file mode 100644 index 000000000..c00ab7c78 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/build/060-no_local_ssb_bcma.patch @@ -0,0 +1,335 @@ +--- a/local-symbols ++++ b/local-symbols +@@ -424,43 +424,6 @@ USB_SIERRA_NET= + USB_VL600= + USB_NET_CH9200= + USB_NET_AQC111= +-SSB_POSSIBLE= +-SSB= +-SSB_SPROM= +-SSB_BLOCKIO= +-SSB_PCIHOST_POSSIBLE= +-SSB_PCIHOST= +-SSB_B43_PCI_BRIDGE= +-SSB_PCMCIAHOST_POSSIBLE= +-SSB_PCMCIAHOST= +-SSB_SDIOHOST_POSSIBLE= +-SSB_SDIOHOST= +-SSB_HOST_SOC= +-SSB_SERIAL= +-SSB_DRIVER_PCICORE_POSSIBLE= +-SSB_DRIVER_PCICORE= +-SSB_PCICORE_HOSTMODE= +-SSB_DRIVER_MIPS= +-SSB_SFLASH= +-SSB_EMBEDDED= +-SSB_DRIVER_EXTIF= +-SSB_DRIVER_GIGE= +-SSB_DRIVER_GPIO= +-BCMA_POSSIBLE= +-BCMA= +-BCMA_BLOCKIO= +-BCMA_HOST_PCI_POSSIBLE= +-BCMA_HOST_PCI= +-BCMA_HOST_SOC= +-BCMA_DRIVER_PCI= +-BCMA_DRIVER_PCI_HOSTMODE= +-BCMA_DRIVER_MIPS= +-BCMA_PFLASH= +-BCMA_SFLASH= +-BCMA_NFLASH= +-BCMA_DRIVER_GMAC_CMN= +-BCMA_DRIVER_GPIO= +-BCMA_DEBUG= + USB_ACM= + USB_PRINTER= + USB_WDM= +--- a/drivers/net/wireless/broadcom/b43/Kconfig ++++ b/drivers/net/wireless/broadcom/b43/Kconfig +@@ -63,21 +63,21 @@ endchoice + config B43_PCI_AUTOSELECT + bool + depends on B43 && SSB_PCIHOST_POSSIBLE +- select SSB_PCIHOST +- select SSB_B43_PCI_BRIDGE ++ depends on SSB_PCIHOST ++ depends on SSB_B43_PCI_BRIDGE + default y + + # Auto-select SSB PCICORE driver, if possible + config B43_PCICORE_AUTOSELECT + bool + depends on B43 && SSB_DRIVER_PCICORE_POSSIBLE +- select SSB_DRIVER_PCICORE ++ depends on SSB_DRIVER_PCICORE + default y + + config B43_SDIO + bool "Broadcom 43xx SDIO device support" + depends on B43 && B43_SSB && SSB_SDIOHOST_POSSIBLE +- select SSB_SDIOHOST ++ depends on SSB_SDIOHOST + help + Broadcom 43xx device support for Soft-MAC SDIO devices. + +@@ -96,13 +96,13 @@ config B43_SDIO + config B43_BCMA_PIO + bool + depends on B43 && B43_BCMA +- select BCMA_BLOCKIO ++ depends on BCMA_BLOCKIO + default y + + config B43_PIO + bool + depends on B43 && B43_SSB +- select SSB_BLOCKIO ++ depends on SSB_BLOCKIO + default y + + config B43_PHY_G +--- a/drivers/net/wireless/broadcom/b43/main.c ++++ b/drivers/net/wireless/broadcom/b43/main.c +@@ -2851,7 +2851,7 @@ static struct ssb_device *b43_ssb_gpio_d + { + struct ssb_bus *bus = dev->dev->sdev->bus; + +-#ifdef CPTCFG_SSB_DRIVER_PCICORE ++#ifdef CONFIG_SSB_DRIVER_PCICORE + return (bus->chipco.dev ? bus->chipco.dev : bus->pcicore.dev); + #else + return bus->chipco.dev; +@@ -4868,7 +4868,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. */ +-#if defined(CPTCFG_B43_SSB) && defined(CPTCFG_SSB_DRIVER_PCICORE) ++#if defined(CPTCFG_B43_SSB) && defined(CONFIG_SSB_DRIVER_PCICORE) + if (dev->dev->bus_type == B43_BUS_SSB && + dev->dev->sdev->bus->bustype == SSB_BUSTYPE_PCI && + dev->dev->sdev->bus->pcicore.dev->id.revision <= 10) +--- a/drivers/net/wireless/broadcom/b43legacy/Kconfig ++++ b/drivers/net/wireless/broadcom/b43legacy/Kconfig +@@ -3,7 +3,7 @@ config B43LEGACY + tristate "Broadcom 43xx-legacy wireless support (mac80211 stack)" + depends on m + depends on SSB_POSSIBLE && MAC80211 && HAS_DMA +- select SSB ++ depends on SSB + depends on FW_LOADER + help + b43legacy is a driver for 802.11b devices from Broadcom (BCM4301 and +@@ -25,15 +25,15 @@ config B43LEGACY + config B43LEGACY_PCI_AUTOSELECT + bool + depends on B43LEGACY && SSB_PCIHOST_POSSIBLE +- select SSB_PCIHOST +- select SSB_B43_PCI_BRIDGE ++ depends on SSB_PCIHOST ++ depends on SSB_B43_PCI_BRIDGE + default y + + # Auto-select SSB PCICORE driver, if possible + config B43LEGACY_PCICORE_AUTOSELECT + bool + depends on B43LEGACY && SSB_DRIVER_PCICORE_POSSIBLE +- select SSB_DRIVER_PCICORE ++ depends on SSB_DRIVER_PCICORE + default y + + # LED support +--- a/drivers/net/wireless/broadcom/b43legacy/main.c ++++ b/drivers/net/wireless/broadcom/b43legacy/main.c +@@ -1906,7 +1906,7 @@ static int b43legacy_gpio_init(struct b4 + if (dev->dev->id.revision >= 2) + mask |= 0x0010; /* FIXME: This is redundant. */ + +-#ifdef CPTCFG_SSB_DRIVER_PCICORE ++#ifdef CONFIG_SSB_DRIVER_PCICORE + pcidev = bus->pcicore.dev; + #endif + gpiodev = bus->chipco.dev ? : pcidev; +@@ -1925,7 +1925,7 @@ static void b43legacy_gpio_cleanup(struc + struct ssb_bus *bus = dev->dev->bus; + struct ssb_device *gpiodev, *pcidev = NULL; + +-#ifdef CPTCFG_SSB_DRIVER_PCICORE ++#ifdef CONFIG_SSB_DRIVER_PCICORE + pcidev = bus->pcicore.dev; + #endif + gpiodev = bus->chipco.dev ? : pcidev; +--- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/led.h ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/led.h +@@ -22,7 +22,7 @@ struct brcms_led { + bool active_low; + }; + +-#ifdef CPTCFG_BCMA_DRIVER_GPIO ++#ifdef CONFIG_BCMA_DRIVER_GPIO + void brcms_led_unregister(struct brcms_info *wl); + int brcms_led_register(struct brcms_info *wl); + #else +--- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/Makefile ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/Makefile +@@ -42,6 +42,6 @@ brcmsmac-y := \ + brcms_trace_events.o \ + debug.o + +-brcmsmac-$(CPTCFG_BCMA_DRIVER_GPIO) += led.o ++brcmsmac-$(CONFIG_BCMA_DRIVER_GPIO) += led.o + + obj-$(CPTCFG_BRCMSMAC) += brcmsmac.o +--- a/drivers/net/wireless/broadcom/brcm80211/Kconfig ++++ b/drivers/net/wireless/broadcom/brcm80211/Kconfig +@@ -8,7 +8,7 @@ config BRCMSMAC + depends on m + depends on MAC80211 + depends on BCMA_POSSIBLE +- select BCMA ++ depends on BCMA + select NEW_LEDS if BCMA_DRIVER_GPIO + select LEDS_CLASS if BCMA_DRIVER_GPIO + select BRCMUTIL +--- a/Kconfig.local ++++ b/Kconfig.local +@@ -1276,117 +1276,6 @@ config BACKPORTED_USB_NET_CH9200 + config BACKPORTED_USB_NET_AQC111 + tristate + default USB_NET_AQC111 +-config BACKPORTED_SSB_POSSIBLE +- tristate +- default SSB_POSSIBLE +-config BACKPORTED_SSB +- tristate +- default SSB +-config BACKPORTED_SSB_SPROM +- tristate +- default SSB_SPROM +-config BACKPORTED_SSB_BLOCKIO +- tristate +- default SSB_BLOCKIO +-config BACKPORTED_SSB_PCIHOST_POSSIBLE +- tristate +- default SSB_PCIHOST_POSSIBLE +-config BACKPORTED_SSB_PCIHOST +- tristate +- default SSB_PCIHOST +-config BACKPORTED_SSB_B43_PCI_BRIDGE +- tristate +- default SSB_B43_PCI_BRIDGE +-config BACKPORTED_SSB_PCMCIAHOST_POSSIBLE +- tristate +- default SSB_PCMCIAHOST_POSSIBLE +-config BACKPORTED_SSB_PCMCIAHOST +- tristate +- default SSB_PCMCIAHOST +-config BACKPORTED_SSB_SDIOHOST_POSSIBLE +- tristate +- default SSB_SDIOHOST_POSSIBLE +-config BACKPORTED_SSB_SDIOHOST +- tristate +- default SSB_SDIOHOST +-config BACKPORTED_SSB_HOST_SOC +- tristate +- default SSB_HOST_SOC +-config BACKPORTED_SSB_SERIAL +- tristate +- default SSB_SERIAL +-config BACKPORTED_SSB_DRIVER_PCICORE_POSSIBLE +- tristate +- default SSB_DRIVER_PCICORE_POSSIBLE +-config BACKPORTED_SSB_DRIVER_PCICORE +- tristate +- default SSB_DRIVER_PCICORE +-config BACKPORTED_SSB_PCICORE_HOSTMODE +- tristate +- default SSB_PCICORE_HOSTMODE +-config BACKPORTED_SSB_DRIVER_MIPS +- tristate +- default SSB_DRIVER_MIPS +-config BACKPORTED_SSB_SFLASH +- tristate +- default SSB_SFLASH +-config BACKPORTED_SSB_EMBEDDED +- tristate +- default SSB_EMBEDDED +-config BACKPORTED_SSB_DRIVER_EXTIF +- tristate +- default SSB_DRIVER_EXTIF +-config BACKPORTED_SSB_DRIVER_GIGE +- tristate +- default SSB_DRIVER_GIGE +-config BACKPORTED_SSB_DRIVER_GPIO +- tristate +- default SSB_DRIVER_GPIO +-config BACKPORTED_BCMA_POSSIBLE +- tristate +- default BCMA_POSSIBLE +-config BACKPORTED_BCMA +- tristate +- default BCMA +-config BACKPORTED_BCMA_BLOCKIO +- tristate +- default BCMA_BLOCKIO +-config BACKPORTED_BCMA_HOST_PCI_POSSIBLE +- tristate +- default BCMA_HOST_PCI_POSSIBLE +-config BACKPORTED_BCMA_HOST_PCI +- tristate +- default BCMA_HOST_PCI +-config BACKPORTED_BCMA_HOST_SOC +- tristate +- default BCMA_HOST_SOC +-config BACKPORTED_BCMA_DRIVER_PCI +- tristate +- default BCMA_DRIVER_PCI +-config BACKPORTED_BCMA_DRIVER_PCI_HOSTMODE +- tristate +- default BCMA_DRIVER_PCI_HOSTMODE +-config BACKPORTED_BCMA_DRIVER_MIPS +- tristate +- default BCMA_DRIVER_MIPS +-config BACKPORTED_BCMA_PFLASH +- tristate +- default BCMA_PFLASH +-config BACKPORTED_BCMA_SFLASH +- tristate +- default BCMA_SFLASH +-config BACKPORTED_BCMA_NFLASH +- tristate +- default BCMA_NFLASH +-config BACKPORTED_BCMA_DRIVER_GMAC_CMN +- tristate +- default BCMA_DRIVER_GMAC_CMN +-config BACKPORTED_BCMA_DRIVER_GPIO +- tristate +- default BCMA_DRIVER_GPIO +-config BACKPORTED_BCMA_DEBUG +- tristate +- default BCMA_DEBUG + config BACKPORTED_USB_ACM + tristate + default USB_ACM +--- a/Kconfig.sources ++++ b/Kconfig.sources +@@ -7,9 +7,6 @@ source "$BACKPORT_DIR/net/mac80211/Kconf + source "$BACKPORT_DIR/drivers/net/wireless/Kconfig" + source "$BACKPORT_DIR/drivers/net/usb/Kconfig" + +-source "$BACKPORT_DIR/drivers/ssb/Kconfig" +-source "$BACKPORT_DIR/drivers/bcma/Kconfig" +- + source "$BACKPORT_DIR/drivers/usb/class/Kconfig" + + source "$BACKPORT_DIR/drivers/staging/Kconfig" +--- a/Makefile.kernel ++++ b/Makefile.kernel +@@ -40,8 +40,6 @@ obj-y += compat/ + obj-$(CPTCFG_CFG80211) += net/wireless/ + obj-$(CPTCFG_MAC80211) += net/mac80211/ + obj-$(CPTCFG_WLAN) += drivers/net/wireless/ +-obj-$(CPTCFG_SSB) += drivers/ssb/ +-obj-$(CPTCFG_BCMA) += drivers/bcma/ + obj-$(CPTCFG_USB_NET_RNDIS_WLAN) += drivers/net/usb/ + + obj-$(CPTCFG_USB_WDM) += drivers/usb/class/ diff --git a/feeds/ipq40xx/mac80211/patches/mwl/700-mwl8k-missing-pci-id-for-WNR854T.patch b/feeds/ipq40xx/mac80211/patches/mwl/700-mwl8k-missing-pci-id-for-WNR854T.patch new file mode 100644 index 000000000..cfa40e1bd --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/mwl/700-mwl8k-missing-pci-id-for-WNR854T.patch @@ -0,0 +1,10 @@ +--- a/drivers/net/wireless/marvell/mwl8k.c ++++ b/drivers/net/wireless/marvell/mwl8k.c +@@ -5694,6 +5694,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[] = { ++ { PCI_VDEVICE(MARVELL, 0x2a02), .driver_data = MWL8363, }, + { PCI_VDEVICE(MARVELL, 0x2a0a), .driver_data = MWL8363, }, + { PCI_VDEVICE(MARVELL, 0x2a0c), .driver_data = MWL8363, }, + { PCI_VDEVICE(MARVELL, 0x2a24), .driver_data = MWL8363, }, diff --git a/feeds/ipq40xx/mac80211/patches/mwl/801-libertas-configure-sysfs-links.patch b/feeds/ipq40xx/mac80211/patches/mwl/801-libertas-configure-sysfs-links.patch new file mode 100644 index 000000000..dfa0e502f --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/mwl/801-libertas-configure-sysfs-links.patch @@ -0,0 +1,21 @@ +--- a/drivers/net/wireless/marvell/libertas/cfg.c ++++ b/drivers/net/wireless/marvell/libertas/cfg.c +@@ -2053,6 +2053,8 @@ struct wireless_dev *lbs_cfg_alloc(struc + goto err_wiphy_new; + } + ++ set_wiphy_dev(wdev->wiphy, dev); ++ + return wdev; + + err_wiphy_new: +--- a/drivers/net/wireless/marvell/libertas/main.c ++++ b/drivers/net/wireless/marvell/libertas/main.c +@@ -935,6 +935,7 @@ struct lbs_private *lbs_add_card(void *c + goto err_adapter; + } + ++ dev_net_set(dev, wiphy_net(wdev->wiphy)); + dev->ieee80211_ptr = wdev; + dev->ml_priv = priv; + SET_NETDEV_DEV(dev, dmdev); diff --git a/feeds/ipq40xx/mac80211/patches/mwl/802-libertas-set-wireless-macaddr.patch b/feeds/ipq40xx/mac80211/patches/mwl/802-libertas-set-wireless-macaddr.patch new file mode 100644 index 000000000..c2d0a5890 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/mwl/802-libertas-set-wireless-macaddr.patch @@ -0,0 +1,11 @@ +--- a/drivers/net/wireless/marvell/libertas/cfg.c ++++ b/drivers/net/wireless/marvell/libertas/cfg.c +@@ -2129,6 +2129,8 @@ int lbs_cfg_register(struct lbs_private + wdev->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); + wdev->wiphy->reg_notifier = lbs_reg_notifier; + ++ memcpy(wdev->wiphy->perm_addr, priv->current_addr, ETH_ALEN); ++ + ret = wiphy_register(wdev->wiphy); + if (ret < 0) + pr_err("cannot register wiphy device\n"); diff --git a/feeds/ipq40xx/mac80211/patches/mwl/940-mwl8k_init_devices_synchronously.patch b/feeds/ipq40xx/mac80211/patches/mwl/940-mwl8k_init_devices_synchronously.patch new file mode 100644 index 000000000..f3130f7ae --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/mwl/940-mwl8k_init_devices_synchronously.patch @@ -0,0 +1,20 @@ +--- a/drivers/net/wireless/marvell/mwl8k.c ++++ b/drivers/net/wireless/marvell/mwl8k.c +@@ -6279,6 +6279,8 @@ static int mwl8k_probe(struct pci_dev *p + + priv->running_bsses = 0; + ++ wait_for_completion(&priv->firmware_loading_complete); ++ + return rc; + + err_stop_firmware: +@@ -6312,8 +6314,6 @@ static void mwl8k_remove(struct pci_dev + return; + priv = hw->priv; + +- wait_for_completion(&priv->firmware_loading_complete); +- + if (priv->fw_state == FW_STATE_ERROR) { + mwl8k_hw_reset(priv); + goto unmap; diff --git a/feeds/ipq40xx/mac80211/patches/rt2x00/002-rt2x00-define-RF5592-in-init_eeprom-routine.patch b/feeds/ipq40xx/mac80211/patches/rt2x00/002-rt2x00-define-RF5592-in-init_eeprom-routine.patch new file mode 100644 index 000000000..a50a19528 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/rt2x00/002-rt2x00-define-RF5592-in-init_eeprom-routine.patch @@ -0,0 +1,51 @@ +From patchwork Thu Dec 27 14:05:26 2018 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 8bit +X-Patchwork-Submitter: Tom Psyborg +X-Patchwork-Id: 10743707 +X-Patchwork-Delegate: kvalo@adurom.com +From: =?utf-8?q?Tomislav_Po=C5=BEega?= +To: linux-wireless@vger.kernel.org +Cc: kvalo@codeaurora.org, hauke@hauke-m.de, nbd@nbd.name, + john@phrozen.org, sgruszka@redhat.com, daniel@makrotopia.org +Subject: [PATCH 2/2] rt2x00: define RF5592 in init_eeprom routine +Date: Thu, 27 Dec 2018 15:05:26 +0100 +Message-Id: <1545919526-4074-2-git-send-email-pozega.tomislav@gmail.com> +X-Mailer: git-send-email 1.7.0.4 +In-Reply-To: <1545919526-4074-1-git-send-email-pozega.tomislav@gmail.com> +References: <1545919526-4074-1-git-send-email-pozega.tomislav@gmail.com> +MIME-Version: 1.0 +Sender: linux-wireless-owner@vger.kernel.org +Precedence: bulk +List-ID: +X-Mailing-List: linux-wireless@vger.kernel.org +X-Virus-Scanned: ClamAV using ClamSMTP + +This patch fixes following crash on Linksys EA2750 during 5GHz wifi +init: + +[ 7.955153] rt2800pci 0000:01:00.0: card - bus=0x1, slot = 0x0 irq=4 +[ 7.962259] rt2800pci 0000:01:00.0: loaded eeprom from mtd device "Factory" +[ 7.969435] ieee80211 phy0: rt2x00_set_rt: Info - RT chipset 5592, rev 0222 detected +[ 7.977348] ieee80211 phy0: rt2800_init_eeprom: Error - Invalid RF chipset 0x0000 detected +[ 7.985793] ieee80211 phy0: rt2x00lib_probe_dev: Error - Failed to allocate device +[ 7.993569] CPU 0 Unable to handle kernel paging request at virtual address 00000024, epc == 800c8f54, ra == 80249ff8 +[ 8.004408] Oops[#1]: + +Signed-off-by: Tomislav Požega +--- + drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 2 ++ + 1 files changed, 2 insertions(+), 0 deletions(-) + +--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +@@ -9416,6 +9416,8 @@ static int rt2800_init_eeprom(struct rt2 + rf = RF3853; + else if (rt2x00_rt(rt2x00dev, RT5350)) + rf = RF5350; ++ else if (rt2x00_rt(rt2x00dev, RT5592)) ++ rf = RF5592; + else + rf = rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RF_TYPE); + diff --git a/feeds/ipq40xx/mac80211/patches/rt2x00/100-rt2x00_options.patch b/feeds/ipq40xx/mac80211/patches/rt2x00/100-rt2x00_options.patch new file mode 100644 index 000000000..295904c64 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/rt2x00/100-rt2x00_options.patch @@ -0,0 +1,47 @@ +--- a/drivers/net/wireless/ralink/rt2x00/Kconfig ++++ b/drivers/net/wireless/ralink/rt2x00/Kconfig +@@ -226,36 +226,37 @@ config RT2800SOC + + + config RT2800_LIB +- tristate ++ tristate "RT2800 USB/PCI support" + depends on m + + config RT2800_LIB_MMIO +- tristate ++ tristate "RT2800 MMIO support" + depends on m + select RT2X00_LIB_MMIO + select RT2800_LIB + + config RT2X00_LIB_MMIO +- tristate ++ tristate "RT2x00 MMIO support" + depends on m + + config RT2X00_LIB_PCI +- tristate ++ tristate "RT2x00 PCI support" + depends on m + select RT2X00_LIB + + config RT2X00_LIB_SOC +- tristate ++ tristate "RT2x00 SoC support" ++ depends on SOC_RT288X || SOC_RT305X || SOC_MT7620 + depends on m + select RT2X00_LIB + + config RT2X00_LIB_USB +- tristate ++ tristate "RT2x00 USB support" + depends on m + select RT2X00_LIB + + config RT2X00_LIB +- tristate ++ tristate "RT2x00 support" + depends on m + + config RT2X00_LIB_FIRMWARE diff --git a/feeds/ipq40xx/mac80211/patches/rt2x00/501-rt2x00-allow-to-build-rt2800soc-module-for-RT3883.patch b/feeds/ipq40xx/mac80211/patches/rt2x00/501-rt2x00-allow-to-build-rt2800soc-module-for-RT3883.patch new file mode 100644 index 000000000..b4106b019 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/rt2x00/501-rt2x00-allow-to-build-rt2800soc-module-for-RT3883.patch @@ -0,0 +1,30 @@ +From 91094ed065f7794886b4a5490fd6de942f036bb4 Mon Sep 17 00:00:00 2001 +From: Gabor Juhos +Date: Sun, 24 Mar 2013 19:26:26 +0100 +Subject: [PATCH] rt2x00: allow to build rt2800soc module for RT3883 + +Signed-off-by: Gabor Juhos +--- + drivers/net/wireless/ralink/rt2x00/Kconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/wireless/ralink/rt2x00/Kconfig ++++ b/drivers/net/wireless/ralink/rt2x00/Kconfig +@@ -211,7 +211,7 @@ endif + config RT2800SOC + tristate "Ralink WiSoC support" + depends on m +- depends on SOC_RT288X || SOC_RT305X || SOC_MT7620 ++ depends on SOC_RT288X || SOC_RT305X || SOC_RT3883 || SOC_MT7620 + select RT2X00_LIB_SOC + select RT2X00_LIB_MMIO + select RT2X00_LIB_CRYPTO +@@ -246,7 +246,7 @@ config RT2X00_LIB_PCI + + config RT2X00_LIB_SOC + tristate "RT2x00 SoC support" +- depends on SOC_RT288X || SOC_RT305X || SOC_MT7620 ++ depends on SOC_RT288X || SOC_RT305X || SOC_RT3883 || SOC_MT7620 + depends on m + select RT2X00_LIB + diff --git a/feeds/ipq40xx/mac80211/patches/rt2x00/601-rt2x00-introduce-rt2x00_platform_h.patch b/feeds/ipq40xx/mac80211/patches/rt2x00/601-rt2x00-introduce-rt2x00_platform_h.patch new file mode 100644 index 000000000..1e6211a47 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/rt2x00/601-rt2x00-introduce-rt2x00_platform_h.patch @@ -0,0 +1,32 @@ +--- /dev/null ++++ b/include/linux/rt2x00_platform.h +@@ -0,0 +1,19 @@ ++/* ++ * Platform data definition for the rt2x00 driver ++ * ++ * Copyright (C) 2011 Gabor Juhos ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ * ++ */ ++ ++#ifndef _RT2X00_PLATFORM_H ++#define _RT2X00_PLATFORM_H ++ ++struct rt2x00_platform_data { ++ char *eeprom_file_name; ++}; ++ ++#endif /* _RT2X00_PLATFORM_H */ +--- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h ++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h +@@ -28,6 +28,7 @@ + #include + #include + #include ++#include + + #include + diff --git a/feeds/ipq40xx/mac80211/patches/rt2x00/602-rt2x00-introduce-rt2x00eeprom.patch b/feeds/ipq40xx/mac80211/patches/rt2x00/602-rt2x00-introduce-rt2x00eeprom.patch new file mode 100644 index 000000000..da76b34fa --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/rt2x00/602-rt2x00-introduce-rt2x00eeprom.patch @@ -0,0 +1,296 @@ +--- a/local-symbols ++++ b/local-symbols +@@ -321,6 +321,7 @@ RT2X00_LIB_FIRMWARE= + RT2X00_LIB_CRYPTO= + RT2X00_LIB_LEDS= + RT2X00_LIB_DEBUGFS= ++RT2X00_LIB_EEPROM= + RT2X00_DEBUG= + WLAN_VENDOR_REALTEK= + RTL8180= +--- a/drivers/net/wireless/ralink/rt2x00/Kconfig ++++ b/drivers/net/wireless/ralink/rt2x00/Kconfig +@@ -70,6 +70,7 @@ config RT2800PCI + select RT2X00_LIB_MMIO + select RT2X00_LIB_PCI + select RT2X00_LIB_FIRMWARE ++ select RT2X00_LIB_EEPROM + select RT2X00_LIB_CRYPTO + depends on CRC_CCITT + depends on EEPROM_93CX6 +@@ -216,6 +217,7 @@ config RT2800SOC + select RT2X00_LIB_MMIO + select RT2X00_LIB_CRYPTO + select RT2X00_LIB_FIRMWARE ++ select RT2X00_LIB_EEPROM + select RT2800_LIB + select RT2800_LIB_MMIO + help +@@ -266,6 +268,9 @@ config RT2X00_LIB_FIRMWARE + config RT2X00_LIB_CRYPTO + bool + ++config RT2X00_LIB_EEPROM ++ bool ++ + config RT2X00_LIB_LEDS + bool + default y if (RT2X00_LIB=y && LEDS_CLASS=y) || (RT2X00_LIB=m && LEDS_CLASS!=n) +--- a/drivers/net/wireless/ralink/rt2x00/Makefile ++++ b/drivers/net/wireless/ralink/rt2x00/Makefile +@@ -8,6 +8,7 @@ rt2x00lib-$(CPTCFG_RT2X00_LIB_DEBUGFS) + + rt2x00lib-$(CPTCFG_RT2X00_LIB_CRYPTO) += rt2x00crypto.o + rt2x00lib-$(CPTCFG_RT2X00_LIB_FIRMWARE) += rt2x00firmware.o + rt2x00lib-$(CPTCFG_RT2X00_LIB_LEDS) += rt2x00leds.o ++rt2x00lib-$(CPTCFG_RT2X00_LIB_EEPROM) += rt2x00eeprom.o + + 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 +@@ -37,6 +37,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); +@@ -135,6 +137,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 + return retval; + } + +-static int rt2800soc_read_eeprom(struct rt2x00_dev *rt2x00dev) +-{ +- void __iomem *base_addr = ioremap(0x1F040000, EEPROM_SIZE); +- +- if (!base_addr) +- return -ENOMEM; +- +- memcpy_fromio(rt2x00dev->eeprom, base_addr, EEPROM_SIZE); +- +- iounmap(base_addr); +- return 0; +-} +- + /* Firmware functions */ + static char *rt2800soc_get_firmware_name(struct rt2x00_dev *rt2x00dev) + { +@@ -167,7 +154,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, + .hwcrypt_disabled = rt2800soc_hwcrypt_disabled, + .drv_write_firmware = rt2800soc_write_firmware, + .drv_init_registers = rt2800mmio_init_registers, +--- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h ++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h +@@ -694,6 +694,7 @@ enum rt2x00_capability_flags { + REQUIRE_HT_TX_DESC, + REQUIRE_PS_AUTOWAKE, + REQUIRE_DELAYED_RFKILL, ++ REQUIRE_EEPROM_FILE, + + /* + * Capabilities +@@ -970,6 +971,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 +@@ -1407,6 +1407,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. + */ +@@ -1550,6 +1554,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,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. ++ */ ++ ++#include ++#include ++ ++#include "rt2x00.h" ++#include "rt2x00lib.h" ++ ++static const char * ++rt2x00lib_get_eeprom_file_name(struct rt2x00_dev *rt2x00dev) ++{ ++ struct rt2x00_platform_data *pdata = rt2x00dev->dev->platform_data; ++ ++ if (pdata && pdata->eeprom_file_name) ++ return pdata->eeprom_file_name; ++ ++ return NULL ++} ++ ++static int rt2x00lib_request_eeprom_file(struct rt2x00_dev *rt2x00dev) ++{ ++ const struct firmware *ee; ++ const char *ee_name; ++ int retval; ++ ++ 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."); ++ return -EINVAL; ++ } ++ ++ if (!ee_name) ++ return 0; ++ ++ rt2x00_info(rt2x00dev, "Loading EEPROM data from '%s'.\n", ee_name); ++ ++ retval = request_firmware(&ee, ee_name, rt2x00dev->dev); ++ if (retval) { ++ rt2x00_err(rt2x00dev, "Failed to request EEPROM.\n"); ++ return retval; ++ } ++ ++ if (!ee || !ee->size || !ee->data) { ++ rt2x00_err(rt2x00dev, "Failed to read EEPROM file.\n"); ++ retval = -ENOENT; ++ goto err_exit; ++ } ++ ++ if (ee->size != rt2x00dev->ops->eeprom_size) { ++ rt2x00_err(rt2x00dev, ++ "EEPROM file size is invalid, it should be %d bytes\n", ++ rt2x00dev->ops->eeprom_size); ++ retval = -EINVAL; ++ goto err_release_ee; ++ } ++ ++ rt2x00dev->eeprom_file = ee; ++ return 0; ++ ++err_release_ee: ++ release_firmware(ee); ++err_exit: ++ return retval; ++} ++ ++int rt2x00lib_load_eeprom_file(struct rt2x00_dev *rt2x00dev) ++{ ++ int retval; ++ ++ retval = rt2x00lib_request_eeprom_file(rt2x00dev); ++ if (retval) ++ return retval; ++ ++ return 0; ++} ++ ++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 + if (IS_ERR(rt2x00dev->clk)) + rt2x00dev->clk = NULL; + ++ set_bit(REQUIRE_EEPROM_FILE, &rt2x00dev->cap_flags); + rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_SOC); + + retval = rt2x00soc_alloc_reg(rt2x00dev); diff --git a/feeds/ipq40xx/mac80211/patches/rt2x00/603-rt2x00-of_load_eeprom_filename.patch b/feeds/ipq40xx/mac80211/patches/rt2x00/603-rt2x00-of_load_eeprom_filename.patch new file mode 100644 index 000000000..9dffef181 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/rt2x00/603-rt2x00-of_load_eeprom_filename.patch @@ -0,0 +1,33 @@ +--- 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,11 +35,21 @@ 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; + +- return NULL ++#ifdef CONFIG_OF ++ np = rt2x00dev->dev->of_node; ++ if (np && of_property_read_string(np, "ralink,eeprom", &eep) == 0) ++ return eep; ++#endif ++ ++ return NULL; + } + + static int rt2x00lib_request_eeprom_file(struct rt2x00_dev *rt2x00dev) diff --git a/feeds/ipq40xx/mac80211/patches/rt2x00/604-rt2x00-load-eeprom-on-SoC-from-a-mtd-device-defines-.patch b/feeds/ipq40xx/mac80211/patches/rt2x00/604-rt2x00-load-eeprom-on-SoC-from-a-mtd-device-defines-.patch new file mode 100644 index 000000000..7338eb15b --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/rt2x00/604-rt2x00-load-eeprom-on-SoC-from-a-mtd-device-defines-.patch @@ -0,0 +1,113 @@ +From 339fe73f340161a624cc08e738d2244814852c3e Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Sun, 17 Mar 2013 00:55:04 +0100 +Subject: [PATCH] rt2x00: load eeprom on SoC from a mtd device defines inside + OF + +Signed-off-by: John Crispin +--- + 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 +@@ -220,6 +220,7 @@ config RT2800SOC + select RT2X00_LIB_EEPROM + select RT2800_LIB + select RT2800_LIB_MMIO ++ select MTD if SOC_RT288X || SOC_RT305X + help + This adds support for Ralink WiSoC devices. + Supported chips: RT2880, RT3050, RT3052, RT3350, RT3352. +--- a/drivers/net/wireless/ralink/rt2x00/rt2x00eeprom.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00eeprom.c +@@ -26,11 +26,76 @@ + + #include + #include ++#if IS_ENABLED(CONFIG_MTD) ++#include ++#include ++#endif + #include + + #include "rt2x00.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; ++ 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; ++ ++ list = of_get_property(np, "ralink,mtd-eeprom", &size); ++ if (!list) ++ return -ENOENT; ++ ++ phandle = be32_to_cpup(list++); ++ if (phandle) ++ mtd_np = of_find_node_by_phandle(phandle); ++ if (!mtd_np) { ++ dev_err(rt2x00dev->dev, "failed to load mtd phandle\n"); ++ return -EINVAL; ++ } ++ ++ part = of_get_property(mtd_np, "label", NULL); ++ if (!part) ++ part = mtd_np->name; ++ ++ mtd = get_mtd_device_nm(part); ++ if (IS_ERR(mtd)) { ++ dev_err(rt2x00dev->dev, "failed to get mtd device \"%s\"\n", part); ++ return PTR_ERR(mtd); ++ } ++ ++ if (size > sizeof(*list)) ++ offset = be32_to_cpup(list); ++ ++ ret = mtd_read(mtd, offset, len, &retlen, (u_char *) rt2x00dev->eeprom); ++ put_mtd_device(mtd); ++ ++ 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 ++ ++ return ret; ++} ++#endif ++ + static const char * + rt2x00lib_get_eeprom_file_name(struct rt2x00_dev *rt2x00dev) + { +@@ -58,6 +123,11 @@ static int rt2x00lib_request_eeprom_file + const char *ee_name; + int retval; + ++#if IS_ENABLED(CONFIG_MTD) ++ if (!rt2800lib_read_eeprom_mtd(rt2x00dev)) ++ return 0; ++#endif ++ + 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/feeds/ipq40xx/mac80211/patches/rt2x00/606-rt2x00-allow_disabling_bands_through_platform_data.patch b/feeds/ipq40xx/mac80211/patches/rt2x00/606-rt2x00-allow_disabling_bands_through_platform_data.patch new file mode 100644 index 000000000..6a8e594d5 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/rt2x00/606-rt2x00-allow_disabling_bands_through_platform_data.patch @@ -0,0 +1,47 @@ +--- a/include/linux/rt2x00_platform.h ++++ b/include/linux/rt2x00_platform.h +@@ -14,6 +14,9 @@ + + struct rt2x00_platform_data { + char *eeprom_file_name; ++ ++ int disable_2ghz; ++ int disable_5ghz; + }; + + #endif /* _RT2X00_PLATFORM_H */ +--- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c +@@ -1012,6 +1012,22 @@ static int rt2x00lib_probe_hw_modes(stru + unsigned int num_rates; + unsigned int i; + ++ if (rt2x00dev->dev->platform_data) { ++ struct rt2x00_platform_data *pdata; ++ ++ pdata = rt2x00dev->dev->platform_data; ++ if (pdata->disable_2ghz) ++ spec->supported_bands &= ~SUPPORT_BAND_2GHZ; ++ if (pdata->disable_5ghz) ++ spec->supported_bands &= ~SUPPORT_BAND_5GHZ; ++ } ++ ++ if ((spec->supported_bands & SUPPORT_BAND_BOTH) == 0) { ++ rt2x00_err(rt2x00dev, "No supported bands\n"); ++ return -EINVAL; ++ } ++ ++ + num_rates = 0; + if (spec->supported_rates & SUPPORT_RATE_CCK) + num_rates += 4; +--- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h ++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h +@@ -399,6 +399,7 @@ struct hw_mode_spec { + unsigned int supported_bands; + #define SUPPORT_BAND_2GHZ 0x00000001 + #define SUPPORT_BAND_5GHZ 0x00000002 ++#define SUPPORT_BAND_BOTH (SUPPORT_BAND_2GHZ | SUPPORT_BAND_5GHZ) + + unsigned int supported_rates; + #define SUPPORT_RATE_CCK 0x00000001 diff --git a/feeds/ipq40xx/mac80211/patches/rt2x00/607-rt2x00-add_platform_data_mac_addr.patch b/feeds/ipq40xx/mac80211/patches/rt2x00/607-rt2x00-add_platform_data_mac_addr.patch new file mode 100644 index 000000000..b5b2c6103 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/rt2x00/607-rt2x00-add_platform_data_mac_addr.patch @@ -0,0 +1,26 @@ +--- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c +@@ -990,8 +990,13 @@ static void rt2x00lib_rate(struct ieee80 + + void rt2x00lib_set_mac_address(struct rt2x00_dev *rt2x00dev, u8 *eeprom_mac_addr) + { ++ struct rt2x00_platform_data *pdata; + const char *mac_addr; + ++ pdata = rt2x00dev->dev->platform_data; ++ if (pdata && pdata->mac_address) ++ ether_addr_copy(eeprom_mac_addr, pdata->mac_address); ++ + mac_addr = of_get_mac_address(rt2x00dev->dev->of_node); + if (!IS_ERR(mac_addr)) + ether_addr_copy(eeprom_mac_addr, mac_addr); +--- a/include/linux/rt2x00_platform.h ++++ b/include/linux/rt2x00_platform.h +@@ -14,6 +14,7 @@ + + struct rt2x00_platform_data { + char *eeprom_file_name; ++ const u8 *mac_address; + + int disable_2ghz; + int disable_5ghz; diff --git a/feeds/ipq40xx/mac80211/patches/rt2x00/608-rt2x00-allow_disabling_bands_through_dts.patch b/feeds/ipq40xx/mac80211/patches/rt2x00/608-rt2x00-allow_disabling_bands_through_dts.patch new file mode 100644 index 000000000..ff8b2c947 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/rt2x00/608-rt2x00-allow_disabling_bands_through_dts.patch @@ -0,0 +1,19 @@ +--- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c +@@ -1016,6 +1016,16 @@ static int rt2x00lib_probe_hw_modes(stru + struct ieee80211_rate *rates; + unsigned int num_rates; + unsigned int i; ++#ifdef CONFIG_OF ++ struct device_node *np = rt2x00dev->dev->of_node; ++ unsigned int enabled; ++ if (!of_property_read_u32(np, "ralink,2ghz", ++ &enabled) && !enabled) ++ spec->supported_bands &= ~SUPPORT_BAND_2GHZ; ++ if (!of_property_read_u32(np, "ralink,5ghz", ++ &enabled) && !enabled) ++ spec->supported_bands &= ~SUPPORT_BAND_5GHZ; ++#endif /* CONFIG_OF */ + + if (rt2x00dev->dev->platform_data) { + struct rt2x00_platform_data *pdata; diff --git a/feeds/ipq40xx/mac80211/patches/rt2x00/609-rt2x00-make-wmac-loadable-via-OF-on-rt288x-305x-SoC.patch b/feeds/ipq40xx/mac80211/patches/rt2x00/609-rt2x00-make-wmac-loadable-via-OF-on-rt288x-305x-SoC.patch new file mode 100644 index 000000000..38f8b7717 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/rt2x00/609-rt2x00-make-wmac-loadable-via-OF-on-rt288x-305x-SoC.patch @@ -0,0 +1,33 @@ +From 04dbd87265f6ba4a373b211ba324b437d224fb2d Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Sun, 17 Mar 2013 00:03:31 +0100 +Subject: [PATCH 21/38] rt2x00: make wmac loadable via OF on rt288x/305x SoC + +This patch ads the match table to allow loading the wmac support from a +devicetree. + +Signed-off-by: John Crispin +--- + drivers/net/wireless/ralink/rt2x00/rt2800pci.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/drivers/net/wireless/ralink/rt2x00/rt2800soc.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2800soc.c +@@ -224,10 +224,17 @@ static int rt2800soc_probe(struct platfo + return rt2x00soc_probe(pdev, &rt2800soc_ops); + } + ++static const struct of_device_id rt2880_wmac_match[] = { ++ { .compatible = "ralink,rt2880-wmac" }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, rt2880_wmac_match); ++ + static struct platform_driver rt2800soc_driver = { + .driver = { + .name = "rt2800_wmac", + .mod_name = KBUILD_MODNAME, ++ .of_match_table = rt2880_wmac_match, + }, + .probe = rt2800soc_probe, + .remove = rt2x00soc_remove, diff --git a/feeds/ipq40xx/mac80211/patches/rt2x00/610-rt2x00-change-led-polarity-from-OF.patch b/feeds/ipq40xx/mac80211/patches/rt2x00/610-rt2x00-change-led-polarity-from-OF.patch new file mode 100644 index 000000000..039c6f6af --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/rt2x00/610-rt2x00-change-led-polarity-from-OF.patch @@ -0,0 +1,40 @@ +--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +@@ -25,6 +25,7 @@ + #include + #include + #include ++#include + + #include "rt2x00.h" + #include "rt2800lib.h" +@@ -9530,6 +9531,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); + ++ { ++ struct device_node *np = rt2x00dev->dev->of_node; ++ unsigned int led_polarity; ++ ++ /* Allow overriding polarity from OF */ ++ if (!of_property_read_u32(np, "ralink,led-polarity", ++ &led_polarity)) ++ rt2x00_set_field16(&eeprom, EEPROM_FREQ_LED_POLARITY, ++ led_polarity); ++ } ++ + rt2x00dev->led_mcu_reg = eeprom; + #endif /* CPTCFG_RT2X00_LIB_LEDS */ + +--- a/drivers/net/wireless/ralink/rt2x00/rt2x00leds.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00leds.c +@@ -98,6 +98,9 @@ static int rt2x00leds_register_led(struc + led->led_dev.name = name; + led->led_dev.brightness = LED_OFF; + ++ if (rt2x00_is_soc(rt2x00dev)) ++ led->led_dev.brightness_set(&led->led_dev, LED_OFF); ++ + retval = led_classdev_register(device, &led->led_dev); + if (retval) { + rt2x00_err(rt2x00dev, "Failed to register led handler\n"); diff --git a/feeds/ipq40xx/mac80211/patches/rt2x00/611-rt2x00-add-AP+STA-support.patch b/feeds/ipq40xx/mac80211/patches/rt2x00/611-rt2x00-add-AP+STA-support.patch new file mode 100644 index 000000000..15f46fc98 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/rt2x00/611-rt2x00-add-AP+STA-support.patch @@ -0,0 +1,11 @@ +--- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c +@@ -1345,7 +1345,7 @@ static inline void rt2x00lib_set_if_comb + */ + if_limit = &rt2x00dev->if_limits_ap; + if_limit->max = rt2x00dev->ops->max_ap_intf; +- if_limit->types = BIT(NL80211_IFTYPE_AP); ++ if_limit->types = BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_STATION); + #ifdef CPTCFG_MAC80211_MESH + if_limit->types |= BIT(NL80211_IFTYPE_MESH_POINT); + #endif diff --git a/feeds/ipq40xx/mac80211/patches/rt2x00/612-rt2x00-led-tpt-trigger-support.patch b/feeds/ipq40xx/mac80211/patches/rt2x00/612-rt2x00-led-tpt-trigger-support.patch new file mode 100644 index 000000000..70f8d06e2 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/rt2x00/612-rt2x00-led-tpt-trigger-support.patch @@ -0,0 +1,44 @@ +From: David Bauer +Date: Mon, 16 Dec 2019 20:47:06 +0100 +Subject: [PATCH] rt2x00: add throughput LED trigger + +This adds a (currently missing) throughput LED trigger for the rt2x00 +driver. Previously, LED triggers had to be assigned to the netdev, which +was limited to a single VAP. + +Signed-off-by: David Bauer +Tested-by: Christoph Krapp + +--- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c +@@ -1129,6 +1129,19 @@ static void rt2x00lib_remove_hw(struct r + kfree(rt2x00dev->spec.channels_info); + } + ++static const struct ieee80211_tpt_blink rt2x00_tpt_blink[] = { ++ { .throughput = 0 * 1024, .blink_time = 334 }, ++ { .throughput = 1 * 1024, .blink_time = 260 }, ++ { .throughput = 2 * 1024, .blink_time = 220 }, ++ { .throughput = 5 * 1024, .blink_time = 190 }, ++ { .throughput = 10 * 1024, .blink_time = 170 }, ++ { .throughput = 25 * 1024, .blink_time = 150 }, ++ { .throughput = 54 * 1024, .blink_time = 130 }, ++ { .throughput = 120 * 1024, .blink_time = 110 }, ++ { .throughput = 265 * 1024, .blink_time = 80 }, ++ { .throughput = 586 * 1024, .blink_time = 50 }, ++}; ++ + static int rt2x00lib_probe_hw(struct rt2x00_dev *rt2x00dev) + { + struct hw_mode_spec *spec = &rt2x00dev->spec; +@@ -1211,6 +1224,10 @@ static int rt2x00lib_probe_hw(struct rt2 + + #undef RT2X00_TASKLET_INIT + ++ ieee80211_create_tpt_led_trigger(rt2x00dev->hw, ++ IEEE80211_TPT_LEDTRIG_FL_RADIO, rt2x00_tpt_blink, ++ ARRAY_SIZE(rt2x00_tpt_blink)); ++ + /* + * Register HW. + */ diff --git a/feeds/ipq40xx/mac80211/patches/rt2x00/650-rt2x00-add-support-for-external-PA-on-MT7620.patch b/feeds/ipq40xx/mac80211/patches/rt2x00/650-rt2x00-add-support-for-external-PA-on-MT7620.patch new file mode 100644 index 000000000..20452cd8a --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/rt2x00/650-rt2x00-add-support-for-external-PA-on-MT7620.patch @@ -0,0 +1,107 @@ +From 9782a7f7488443568fa4d6088b73c9aff7eb8510 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Wed, 19 Apr 2017 16:14:53 +0200 +Subject: [PATCH] rt2x00: add support for external PA on MT7620 +To: Stanislaw Gruszka +Cc: Helmut Schaa , + linux-wireless@vger.kernel.org, + Kalle Valo +Content-Type: text/plain; charset="UTF-8" +Content-Transfer-Encoding: quoted-printable + +Signed-off-by: Daniel Golle +Signed-off-by: Tomislav Po=C5=BEega +[pozega.tomislav@gmail.com: use chanreg and dccal helpers.] + +--- + drivers/net/wireless/ralink/rt2x00/rt2800.h | 1 + + drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 70 +++++++++++++++++++++++++- + 2 files changed, 70 insertions(+), 1 deletion(-) + +--- a/drivers/net/wireless/ralink/rt2x00/rt2800.h ++++ b/drivers/net/wireless/ralink/rt2x00/rt2800.h +@@ -2739,6 +2739,7 @@ enum rt2800_eeprom_word { + #define EEPROM_NIC_CONF2_RX_STREAM FIELD16(0x000f) + #define EEPROM_NIC_CONF2_TX_STREAM FIELD16(0x00f0) + #define EEPROM_NIC_CONF2_CRYSTAL FIELD16(0x0600) ++#define EEPROM_NIC_CONF2_EXTERNAL_PA FIELD16(0xc000) + + /* + * EEPROM LNA +--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +@@ -4356,6 +4356,45 @@ static void rt2800_config_channel(struct + rt2800_iq_calibrate(rt2x00dev, rf->channel); + } + ++ if (rt2x00_rt(rt2x00dev, RT6352)) { ++ if (test_bit(CAPABILITY_EXTERNAL_PA_TX0, ++ &rt2x00dev->cap_flags)) { ++ rt2x00_warn(rt2x00dev, "Using incomplete support for " \ ++ "external PA\n"); ++ 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, 43, 0x73); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 44, 0x73); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 45, 0x73); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 46, 0x27); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 47, 0xC8); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 48, 0xA4); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 49, 0x05); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 54, 0x27); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 55, 0xC8); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 56, 0xA4); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 57, 0x05); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 58, 0x27); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 59, 0xC8); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 60, 0xA4); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 61, 0x05); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 05, 0x00); ++ ++ rt2800_register_write(rt2x00dev, TX0_RF_GAIN_CORRECT, ++ 0x36303636); ++ rt2800_register_write(rt2x00dev, TX0_RF_GAIN_ATTEN, ++ 0x6C6C6B6C); ++ rt2800_register_write(rt2x00dev, TX1_RF_GAIN_ATTEN, ++ 0x6C6C6B6C); ++ } ++ } ++ + bbp = rt2800_bbp_read(rt2x00dev, 4); + rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 2 * conf_is_ht40(conf)); + rt2800_bbp_write(rt2x00dev, 4, bbp); +@@ -9559,7 +9598,8 @@ static int rt2800_init_eeprom(struct rt2 + */ + eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1); + +- if (rt2x00_rt(rt2x00dev, RT3352)) { ++ if (rt2x00_rt(rt2x00dev, RT3352) || ++ rt2x00_rt(rt2x00dev, RT6352)) { + if (rt2x00_get_field16(eeprom, + EEPROM_NIC_CONF1_EXTERNAL_TX0_PA_3352)) + __set_bit(CAPABILITY_EXTERNAL_PA_TX0, +@@ -9570,6 +9610,18 @@ static int rt2800_init_eeprom(struct rt2 + &rt2x00dev->cap_flags); + } + ++ eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF2); ++ ++ if (rt2x00_rt(rt2x00dev, RT6352) && eeprom != 0 && eeprom != 0xffff) { ++ if (rt2x00_get_field16(eeprom, ++ EEPROM_NIC_CONF2_EXTERNAL_PA)) { ++ __set_bit(CAPABILITY_EXTERNAL_PA_TX0, ++ &rt2x00dev->cap_flags); ++ __set_bit(CAPABILITY_EXTERNAL_PA_TX1, ++ &rt2x00dev->cap_flags); ++ } ++ } ++ + return 0; + } + diff --git a/feeds/ipq40xx/mac80211/patches/rt2x00/982-rt2x00-add-rf-self-txdc-calibration.patch b/feeds/ipq40xx/mac80211/patches/rt2x00/982-rt2x00-add-rf-self-txdc-calibration.patch new file mode 100644 index 000000000..6be847478 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/rt2x00/982-rt2x00-add-rf-self-txdc-calibration.patch @@ -0,0 +1,67 @@ +--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +@@ -8419,6 +8419,56 @@ static void rt2800_init_rfcsr_5592(struc + rt2800_led_open_drain_enable(rt2x00dev); + } + ++static void rt2800_rf_self_txdc_cal(struct rt2x00_dev *rt2x00dev) ++{ ++ u8 rfb5r1_org, rfb7r1_org, rfvalue; ++ u32 mac0518, mac051c, mac0528, mac052c; ++ u8 i; ++ ++ rt2x00_info(rt2x00dev, "RF Tx self calibration start\n"); ++ mac0518 = rt2800_register_read(rt2x00dev, RF_CONTROL0); ++ mac051c = rt2800_register_read(rt2x00dev, RF_BYPASS0); ++ mac0528 = rt2800_register_read(rt2x00dev, RF_CONTROL2); ++ mac052c = rt2800_register_read(rt2x00dev, RF_BYPASS2); ++ ++ rt2800_register_write(rt2x00dev, RF_BYPASS0, 0x0); ++ rt2800_register_write(rt2x00dev, RF_BYPASS2, 0x0); ++ ++ rt2800_register_write(rt2x00dev, RF_CONTROL0, 0xC); ++ rt2800_register_write(rt2x00dev, RF_BYPASS0, 0x3306); ++ rt2800_register_write(rt2x00dev, RF_CONTROL2, 0x3330); ++ rt2800_register_write(rt2x00dev, RF_BYPASS2, 0xfffff); ++ rfb5r1_org = rt2800_rfcsr_read_bank(rt2x00dev, 5, 1); ++ rfb7r1_org = rt2800_rfcsr_read_bank(rt2x00dev, 7, 1); ++ ++ rt2800_rfcsr_write_bank(rt2x00dev, 5, 1, 0x4); ++ for (i = 0; i < 100; i = i + 1) { ++ udelay(50); ++ rfvalue = rt2800_rfcsr_read_bank(rt2x00dev, 5, 1); ++ if((rfvalue & 0x04) != 0x4) ++ break; ++ } ++ rt2800_rfcsr_write_bank(rt2x00dev, 5, 1, rfb5r1_org); ++ ++ rt2800_rfcsr_write_bank(rt2x00dev, 7, 1, 0x4); ++ for (i = 0; i < 100; i = i + 1) { ++ udelay(50); ++ rfvalue = rt2800_rfcsr_read_bank(rt2x00dev, 7, 1); ++ if((rfvalue & 0x04) != 0x4) ++ break; ++ } ++ rt2800_rfcsr_write_bank(rt2x00dev, 7, 1, rfb7r1_org); ++ ++ rt2800_register_write(rt2x00dev, RF_BYPASS0, 0x0); ++ rt2800_register_write(rt2x00dev, RF_BYPASS2, 0x0); ++ rt2800_register_write(rt2x00dev, RF_CONTROL0, mac0518); ++ rt2800_register_write(rt2x00dev, RF_BYPASS0, mac051c); ++ rt2800_register_write(rt2x00dev, RF_CONTROL2, mac0528); ++ rt2800_register_write(rt2x00dev, RF_BYPASS2, mac052c); ++ ++ rt2x00_info(rt2x00dev, "RF Tx self calibration end\n"); ++} ++ + static void rt2800_bbp_core_soft_reset(struct rt2x00_dev *rt2x00dev, + bool set_bw, bool is_ht40) + { +@@ -9026,6 +9076,7 @@ static void rt2800_init_rfcsr_6352(struc + rt2800_rfcsr_write_dccal(rt2x00dev, 5, 0x00); + rt2800_rfcsr_write_dccal(rt2x00dev, 17, 0x7C); + ++ rt2800_rf_self_txdc_cal(rt2x00dev); + rt2800_bw_filter_calibration(rt2x00dev, true); + rt2800_bw_filter_calibration(rt2x00dev, false); + } diff --git a/feeds/ipq40xx/mac80211/patches/rt2x00/983-rt2x00-add-r-calibration.patch b/feeds/ipq40xx/mac80211/patches/rt2x00/983-rt2x00-add-r-calibration.patch new file mode 100644 index 000000000..3ed0ff7ef --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/rt2x00/983-rt2x00-add-r-calibration.patch @@ -0,0 +1,166 @@ +--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +@@ -8469,6 +8469,155 @@ static void rt2800_rf_self_txdc_cal(stru + rt2x00_info(rt2x00dev, "RF Tx self calibration end\n"); + } + ++static int rt2800_calcrcalibrationcode(struct rt2x00_dev *rt2x00dev, int d1, int d2) ++{ ++ int calcode; ++ calcode = ((d2 - d1) * 1000) / 43; ++ if ((calcode%10) >= 5) ++ calcode += 10; ++ calcode = (calcode / 10); ++ ++ return calcode; ++} ++ ++static void rt2800_r_calibration(struct rt2x00_dev *rt2x00dev) ++{ ++ u32 savemacsysctrl; ++ u8 saverfb0r1, saverfb0r34, saverfb0r35; ++ u8 saverfb5r4, saverfb5r17, saverfb5r18; ++ u8 saverfb5r19, saverfb5r20; ++ u8 savebbpr22, savebbpr47, savebbpr49; ++ u8 bytevalue = 0; ++ int rcalcode; ++ u8 r_cal_code = 0; ++ char d1 = 0, d2 = 0; ++ u8 rfvalue; ++ u32 MAC_RF_BYPASS0, MAC_RF_CONTROL0, MAC_PWR_PIN_CFG; ++ u32 maccfg, macstatus; ++ int i; ++ ++ saverfb0r1 = rt2800_rfcsr_read_bank(rt2x00dev, 0, 1); ++ saverfb0r34 = rt2800_rfcsr_read_bank(rt2x00dev, 0, 34); ++ saverfb0r35 = rt2800_rfcsr_read_bank(rt2x00dev, 0, 35); ++ saverfb5r4 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 4); ++ saverfb5r17 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 17); ++ saverfb5r18 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 18); ++ saverfb5r19 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 19); ++ saverfb5r20 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 20); ++ ++ savebbpr22 = rt2800_bbp_read(rt2x00dev, 22); ++ savebbpr47 = rt2800_bbp_read(rt2x00dev, 47); ++ savebbpr49 = rt2800_bbp_read(rt2x00dev, 49); ++ ++ savemacsysctrl = rt2800_register_read(rt2x00dev, MAC_SYS_CTRL); ++ MAC_RF_BYPASS0 = rt2800_register_read(rt2x00dev, RF_BYPASS0); ++ MAC_RF_CONTROL0 = rt2800_register_read(rt2x00dev, RF_CONTROL0); ++ MAC_PWR_PIN_CFG = rt2800_register_read(rt2x00dev, PWR_PIN_CFG); ++ ++ maccfg = rt2800_register_read(rt2x00dev, MAC_SYS_CTRL); ++ maccfg &= (~0x04); ++ rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, maccfg); ++ ++ for (i = 0; i < 10000; i++) { ++ macstatus = rt2800_register_read(rt2x00dev, MAC_STATUS_CFG); ++ if (macstatus & 0x1) ++ udelay(50); ++ else ++ break; ++ } ++ ++ if (i == 10000) ++ rt2x00_warn(rt2x00dev, "Wait MAC Tx Status to MAX !!!\n"); ++ ++ maccfg = rt2800_register_read(rt2x00dev, MAC_SYS_CTRL); ++ maccfg &= (~0x04); ++ rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, maccfg); ++ ++ for (i = 0; i < 10000; i++) { ++ macstatus = rt2800_register_read(rt2x00dev, MAC_STATUS_CFG); ++ if (macstatus & 0x2) ++ udelay(50); ++ else ++ break; ++ } ++ ++ if (i == 10000) ++ rt2x00_warn(rt2x00dev, "Wait MAC Rx Status to MAX !!!\n"); ++ ++ rfvalue = (MAC_RF_BYPASS0 | 0x3004); ++ rt2800_register_write(rt2x00dev, RF_BYPASS0, rfvalue); ++ rfvalue = (MAC_RF_CONTROL0 | (~0x3002)); ++ rt2800_register_write(rt2x00dev, RF_CONTROL0, rfvalue); ++ ++ rt2800_rfcsr_write_bank(rt2x00dev, 5, 4, 0x27); ++ rt2800_rfcsr_write_bank(rt2x00dev, 5, 17, 0x80); ++ rt2800_rfcsr_write_bank(rt2x00dev, 5, 18, 0x83); ++ rt2800_rfcsr_write_bank(rt2x00dev, 5, 19, 0x00); ++ rt2800_rfcsr_write_bank(rt2x00dev, 5, 20, 0x20); ++ ++ rt2800_rfcsr_write_bank(rt2x00dev, 0, 1, 0x00); ++ rt2800_rfcsr_write_bank(rt2x00dev, 0, 34, 0x13); ++ rt2800_rfcsr_write_bank(rt2x00dev, 0, 35, 0x00); ++ ++ rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0x1); ++ ++ rt2800_bbp_write(rt2x00dev, 47, 0x04); ++ rt2800_bbp_write(rt2x00dev, 22, 0x80); ++ udelay(100); ++ bytevalue = rt2800_bbp_read(rt2x00dev, 49); ++ if (bytevalue > 128) ++ d1 = bytevalue - 256; ++ else ++ d1 = (char)bytevalue; ++ rt2800_bbp_write(rt2x00dev, 22, 0x0); ++ rt2800_rfcsr_write_bank(rt2x00dev, 0, 35, 0x01); ++ ++ rt2800_bbp_write(rt2x00dev, 22, 0x80); ++ udelay(100); ++ bytevalue = rt2800_bbp_read(rt2x00dev, 49); ++ if (bytevalue > 128) ++ d2 = bytevalue - 256; ++ else ++ d2 = (char)bytevalue; ++ rt2800_bbp_write(rt2x00dev, 22, 0x0); ++ ++ rcalcode = rt2800_calcrcalibrationcode(rt2x00dev, d1, d2); ++ if (rcalcode < 0) ++ r_cal_code = 256 + rcalcode; ++ else ++ r_cal_code = (u8)rcalcode; ++ ++ rt2800_rfcsr_write_bank(rt2x00dev, 0, 7, r_cal_code); ++ ++ rt2800_bbp_write(rt2x00dev, 22, 0x0); ++ ++ bytevalue = rt2800_bbp_read(rt2x00dev, 21); ++ bytevalue |= 0x1; ++ rt2800_bbp_write(rt2x00dev, 21, bytevalue); ++ bytevalue = rt2800_bbp_read(rt2x00dev, 21); ++ bytevalue &= (~0x1); ++ rt2800_bbp_write(rt2x00dev, 21, bytevalue); ++ ++ rt2800_rfcsr_write_bank(rt2x00dev, 0, 1, saverfb0r1); ++ rt2800_rfcsr_write_bank(rt2x00dev, 0, 34, saverfb0r34); ++ rt2800_rfcsr_write_bank(rt2x00dev, 0, 35, saverfb0r35); ++ rt2800_rfcsr_write_bank(rt2x00dev, 5, 4, saverfb5r4); ++ rt2800_rfcsr_write_bank(rt2x00dev, 5, 17, saverfb5r17); ++ rt2800_rfcsr_write_bank(rt2x00dev, 5, 18, saverfb5r18); ++ rt2800_rfcsr_write_bank(rt2x00dev, 5, 19, saverfb5r19); ++ rt2800_rfcsr_write_bank(rt2x00dev, 5, 20, saverfb5r20); ++ ++ rt2800_bbp_write(rt2x00dev, 22, savebbpr22); ++ rt2800_bbp_write(rt2x00dev, 47, savebbpr47); ++ rt2800_bbp_write(rt2x00dev, 49, savebbpr49); ++ ++ rt2800_register_write(rt2x00dev, RF_BYPASS0, MAC_RF_BYPASS0); ++ rt2800_register_write(rt2x00dev, RF_CONTROL0, MAC_RF_CONTROL0); ++ ++ rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, savemacsysctrl); ++ rt2800_register_write(rt2x00dev, PWR_PIN_CFG, MAC_PWR_PIN_CFG); ++} ++ + static void rt2800_bbp_core_soft_reset(struct rt2x00_dev *rt2x00dev, + bool set_bw, bool is_ht40) + { +@@ -9076,6 +9225,7 @@ static void rt2800_init_rfcsr_6352(struc + rt2800_rfcsr_write_dccal(rt2x00dev, 5, 0x00); + rt2800_rfcsr_write_dccal(rt2x00dev, 17, 0x7C); + ++ rt2800_r_calibration(rt2x00dev); + rt2800_rf_self_txdc_cal(rt2x00dev); + rt2800_bw_filter_calibration(rt2x00dev, true); + rt2800_bw_filter_calibration(rt2x00dev, false); diff --git a/feeds/ipq40xx/mac80211/patches/rt2x00/984-rt2x00-add-rxdcoc-calibration.patch b/feeds/ipq40xx/mac80211/patches/rt2x00/984-rt2x00-add-rxdcoc-calibration.patch new file mode 100644 index 000000000..77be986d1 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/rt2x00/984-rt2x00-add-rxdcoc-calibration.patch @@ -0,0 +1,81 @@ +--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +@@ -8618,6 +8618,70 @@ static void rt2800_r_calibration(struct + rt2800_register_write(rt2x00dev, PWR_PIN_CFG, MAC_PWR_PIN_CFG); + } + ++static void rt2800_rxdcoc_calibration(struct rt2x00_dev *rt2x00dev) ++{ ++ u8 bbpreg = 0; ++ u32 macvalue = 0, macvalue1 = 0; ++ u8 saverfb0r2, saverfb5r4, saverfb7r4, rfvalue; ++ int i; ++ ++ saverfb0r2 = rt2800_rfcsr_read_bank(rt2x00dev, 0, 2); ++ rfvalue = saverfb0r2; ++ rfvalue |= 0x03; ++ rt2800_rfcsr_write_bank(rt2x00dev, 0, 2, rfvalue); ++ ++ rt2800_bbp_write(rt2x00dev, 158, 141); ++ bbpreg = rt2800_bbp_read(rt2x00dev, 159); ++ bbpreg |= 0x10; ++ rt2800_bbp_write(rt2x00dev, 159, bbpreg); ++ ++ macvalue = rt2800_register_read(rt2x00dev, MAC_SYS_CTRL); ++ rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, 0x8); ++ ++ for (i = 0; i < 10000; i++) { ++ macvalue1 = rt2800_register_read(rt2x00dev, MAC_STATUS_CFG); ++ if (macvalue1 & 0x1) ++ udelay(50); ++ else ++ break; ++ } ++ ++ saverfb5r4 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 0); ++ saverfb7r4 = rt2800_rfcsr_read_bank(rt2x00dev, 7, 4); ++ saverfb5r4 = saverfb5r4 & (~0x40); ++ saverfb7r4 = saverfb7r4 & (~0x40); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 4, 0x64); ++ rt2800_rfcsr_write_bank(rt2x00dev, 5, 4, saverfb5r4); ++ rt2800_rfcsr_write_bank(rt2x00dev, 7, 4, saverfb7r4); ++ ++ rt2800_bbp_write(rt2x00dev, 158, 141); ++ bbpreg = rt2800_bbp_read(rt2x00dev, 159); ++ bbpreg = bbpreg & (~0x40); ++ rt2800_bbp_write(rt2x00dev, 159, bbpreg); ++ bbpreg |= 0x48; ++ rt2800_bbp_write(rt2x00dev, 159, bbpreg); ++ ++ for (i = 0; i < 10000; i++) { ++ bbpreg = rt2800_bbp_read(rt2x00dev, 159); ++ if ((bbpreg & 0x40)==0) ++ break; ++ udelay(50); ++ } ++ ++ bbpreg = rt2800_bbp_read(rt2x00dev, 159); ++ bbpreg = bbpreg & (~0x40); ++ rt2800_bbp_write(rt2x00dev, 159, bbpreg); ++ ++ rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, macvalue); ++ ++ rt2800_bbp_write(rt2x00dev, 158, 141); ++ bbpreg = rt2800_bbp_read(rt2x00dev, 159); ++ bbpreg &= (~0x10); ++ rt2800_bbp_write(rt2x00dev, 159, bbpreg); ++ ++ rt2800_rfcsr_write_bank(rt2x00dev, 0, 2, saverfb0r2); ++} ++ + static void rt2800_bbp_core_soft_reset(struct rt2x00_dev *rt2x00dev, + bool set_bw, bool is_ht40) + { +@@ -9227,6 +9291,7 @@ static void rt2800_init_rfcsr_6352(struc + + rt2800_r_calibration(rt2x00dev); + rt2800_rf_self_txdc_cal(rt2x00dev); ++ rt2800_rxdcoc_calibration(rt2x00dev); + rt2800_bw_filter_calibration(rt2x00dev, true); + rt2800_bw_filter_calibration(rt2x00dev, false); + } diff --git a/feeds/ipq40xx/mac80211/patches/rt2x00/985-rt2x00-add-rxiq-calibration.patch b/feeds/ipq40xx/mac80211/patches/rt2x00/985-rt2x00-add-rxiq-calibration.patch new file mode 100644 index 000000000..7352ad036 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/rt2x00/985-rt2x00-add-rxiq-calibration.patch @@ -0,0 +1,395 @@ +--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +@@ -8682,6 +8682,384 @@ static void rt2800_rxdcoc_calibration(st + rt2800_rfcsr_write_bank(rt2x00dev, 0, 2, saverfb0r2); + } + ++static u32 rt2800_do_sqrt_accumulation(u32 si) { ++ u32 root, root_pre, bit; ++ char i; ++ bit = 1 << 15; ++ root = 0; ++ for (i = 15; i >= 0; i = i - 1) { ++ root_pre = root + bit; ++ if ((root_pre*root_pre) <= si) ++ root = root_pre; ++ bit = bit >> 1; ++ } ++ ++ return root; ++} ++ ++static void rt2800_rxiq_calibration(struct rt2x00_dev *rt2x00dev) { ++ u8 rfb0r1, rfb0r2, rfb0r42; ++ u8 rfb4r0, rfb4r19; ++ u8 rfb5r3, rfb5r4, rfb5r17, rfb5r18, rfb5r19, rfb5r20; ++ u8 rfb6r0, rfb6r19; ++ u8 rfb7r3, rfb7r4, rfb7r17, rfb7r18, rfb7r19, rfb7r20; ++ ++ u8 bbp1, bbp4; ++ u8 bbpr241, bbpr242; ++ u32 i; ++ u8 ch_idx; ++ u8 bbpval; ++ u8 rfval, vga_idx = 0; ++ int mi = 0, mq = 0, si = 0, sq = 0, riq = 0; ++ int sigma_i, sigma_q, r_iq, g_rx; ++ int g_imb; ++ int ph_rx; ++ u32 savemacsysctrl = 0; ++ u32 orig_RF_CONTROL0 = 0; ++ u32 orig_RF_BYPASS0 = 0; ++ u32 orig_RF_CONTROL1 = 0; ++ u32 orig_RF_BYPASS1 = 0; ++ u32 orig_RF_CONTROL3 = 0; ++ u32 orig_RF_BYPASS3 = 0; ++ u32 macstatus, bbpval1 = 0; ++ u8 rf_vga_table[] = {0x20, 0x21, 0x22, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f}; ++ ++ savemacsysctrl = rt2800_register_read(rt2x00dev, MAC_SYS_CTRL); ++ orig_RF_CONTROL0 = rt2800_register_read(rt2x00dev, RF_CONTROL0); ++ orig_RF_BYPASS0 = rt2800_register_read(rt2x00dev, RF_BYPASS0); ++ orig_RF_CONTROL1 = rt2800_register_read(rt2x00dev, RF_CONTROL1); ++ orig_RF_BYPASS1 = rt2800_register_read(rt2x00dev, RF_BYPASS1); ++ orig_RF_CONTROL3 = rt2800_register_read(rt2x00dev, RF_CONTROL3); ++ orig_RF_BYPASS3 = rt2800_register_read(rt2x00dev, RF_BYPASS3); ++ ++ bbp1 = rt2800_bbp_read(rt2x00dev, 1); ++ bbp4 = rt2800_bbp_read(rt2x00dev, 4); ++ ++ rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, 0x0); ++ ++ for (i = 0; i < 10000; i++) { ++ macstatus = rt2800_register_read(rt2x00dev, MAC_STATUS_CFG); ++ if (macstatus & 0x3) ++ udelay(50); ++ else ++ break; ++ } ++ ++ if (i == 10000) ++ rt2x00_warn(rt2x00dev, "Wait MAC Status to MAX !!!\n"); ++ ++ bbpval = bbp4 & (~0x18); ++ bbpval = bbp4 | 0x00; ++ rt2800_bbp_write(rt2x00dev, 4, bbpval); ++ ++ bbpval = rt2800_bbp_read(rt2x00dev, 21); ++ bbpval = bbpval | 1; ++ rt2800_bbp_write(rt2x00dev, 21, bbpval); ++ bbpval = bbpval & 0xfe; ++ rt2800_bbp_write(rt2x00dev, 21, bbpval); ++ ++ rt2800_register_write(rt2x00dev, RF_CONTROL1, 0x00000202); ++ rt2800_register_write(rt2x00dev, RF_BYPASS1, 0x00000303); ++ if (test_bit(CAPABILITY_EXTERNAL_PA_TX0, &rt2x00dev->cap_flags)) ++ rt2800_register_write(rt2x00dev, RF_CONTROL3, 0x0101); ++ else ++ rt2800_register_write(rt2x00dev, RF_CONTROL3, 0x0000); ++ ++ rt2800_register_write(rt2x00dev, RF_BYPASS3, 0xf1f1); ++ ++ rfb0r1 = rt2800_rfcsr_read_bank(rt2x00dev, 0, 1); ++ rfb0r2 = rt2800_rfcsr_read_bank(rt2x00dev, 0, 2); ++ rfb0r42 = rt2800_rfcsr_read_bank(rt2x00dev, 0, 42); ++ rfb4r0 = rt2800_rfcsr_read_bank(rt2x00dev, 4, 0); ++ rfb4r19 = rt2800_rfcsr_read_bank(rt2x00dev, 4, 19); ++ rfb5r3 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 3); ++ rfb5r4 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 4); ++ rfb5r17 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 17); ++ rfb5r18 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 18); ++ rfb5r19 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 19); ++ rfb5r20 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 20); ++ ++ rfb6r0 = rt2800_rfcsr_read_bank(rt2x00dev, 6, 0); ++ rfb6r19 = rt2800_rfcsr_read_bank(rt2x00dev, 6, 19); ++ rfb7r3 = rt2800_rfcsr_read_bank(rt2x00dev, 7, 3); ++ rfb7r4 = rt2800_rfcsr_read_bank(rt2x00dev, 7, 4); ++ rfb7r17 = rt2800_rfcsr_read_bank(rt2x00dev, 7, 17); ++ rfb7r18 = rt2800_rfcsr_read_bank(rt2x00dev, 7, 18); ++ rfb7r19 = rt2800_rfcsr_read_bank(rt2x00dev, 7, 19); ++ rfb7r20 = rt2800_rfcsr_read_bank(rt2x00dev, 7, 20); ++ ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 0, 0x87); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 19, 0x27); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 3, 0x38); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 4, 0x38); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 17, 0x80); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 18, 0xC1); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 19, 0x60); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 20, 0x00); ++ ++ rt2800_bbp_write(rt2x00dev, 23, 0x0); ++ rt2800_bbp_write(rt2x00dev, 24, 0x0); ++ ++ rt2800_bbp_dcoc_write(rt2x00dev, 5, 0x0); ++ ++ bbpr241 = rt2800_bbp_read(rt2x00dev, 241); ++ bbpr242 = rt2800_bbp_read(rt2x00dev, 242); ++ ++ rt2800_bbp_write(rt2x00dev, 241, 0x10); ++ rt2800_bbp_write(rt2x00dev, 242, 0x84); ++ rt2800_bbp_write(rt2x00dev, 244, 0x31); ++ ++ bbpval = rt2800_bbp_dcoc_read(rt2x00dev, 3); ++ bbpval = bbpval & (~0x7); ++ rt2800_bbp_dcoc_write(rt2x00dev, 3, bbpval); ++ ++ rt2800_register_write(rt2x00dev, RF_CONTROL0, 0x00000004); ++ udelay(1); ++ rt2800_register_write(rt2x00dev, RF_CONTROL0, 0x00000006); ++ usleep_range(1, 200); ++ rt2800_register_write(rt2x00dev, RF_BYPASS0, 0x00003376); ++ rt2800_register_write(rt2x00dev, RF_CONTROL0, 0x00001006); ++ udelay(1); ++ if (test_bit(CAPABILITY_EXTERNAL_PA_TX0, &rt2x00dev->cap_flags)) { ++ rt2800_bbp_write(rt2x00dev, 23, 0x06); ++ rt2800_bbp_write(rt2x00dev, 24, 0x06); ++ } else { ++ rt2800_bbp_write(rt2x00dev, 23, 0x02); ++ rt2800_bbp_write(rt2x00dev, 24, 0x02); ++ } ++ ++ for (ch_idx = 0; ch_idx < 2; ch_idx = ch_idx + 1) { ++ if (ch_idx == 0) { ++ rfval = rfb0r1 & (~0x3); ++ rfval = rfb0r1 | 0x1; ++ rt2800_rfcsr_write_bank(rt2x00dev, 0, 1, rfval); ++ rfval = rfb0r2 & (~0x33); ++ rfval = rfb0r2 | 0x11; ++ rt2800_rfcsr_write_bank(rt2x00dev, 0, 2, rfval); ++ rfval = rfb0r42 & (~0x50); ++ rfval = rfb0r42 | 0x10; ++ rt2800_rfcsr_write_bank(rt2x00dev, 0, 42, rfval); ++ ++ rt2800_register_write(rt2x00dev, RF_CONTROL0, 0x00001006); ++ udelay(1); ++ ++ bbpval = bbp1 & (~ 0x18); ++ bbpval = bbpval | 0x00; ++ rt2800_bbp_write(rt2x00dev, 1, bbpval); ++ ++ rt2800_bbp_dcoc_write(rt2x00dev, 1, 0x00); ++ } else { ++ rfval = rfb0r1 & (~0x3); ++ rfval = rfb0r1 | 0x2; ++ rt2800_rfcsr_write_bank(rt2x00dev, 0, 1, rfval); ++ rfval = rfb0r2 & (~0x33); ++ rfval = rfb0r2 | 0x22; ++ rt2800_rfcsr_write_bank(rt2x00dev, 0, 2, rfval); ++ rfval = rfb0r42 & (~0x50); ++ rfval = rfb0r42 | 0x40; ++ rt2800_rfcsr_write_bank(rt2x00dev, 0, 42, rfval); ++ ++ rt2800_register_write(rt2x00dev, RF_CONTROL0, 0x00002006); ++ udelay(1); ++ ++ bbpval = bbp1 & (~ 0x18); ++ bbpval = bbpval | 0x08; ++ rt2800_bbp_write(rt2x00dev, 1, bbpval); ++ ++ rt2800_bbp_dcoc_write(rt2x00dev, 1, 0x01); ++ } ++ udelay(500); ++ ++ vga_idx = 0; ++ while (vga_idx < 11) { ++ rt2800_rfcsr_write_dccal(rt2x00dev, 3, rf_vga_table[vga_idx]); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 4, rf_vga_table[vga_idx]); ++ ++ rt2800_bbp_dcoc_write(rt2x00dev, 0, 0x93); ++ ++ for (i = 0; i < 10000; i++) { ++ bbpval = rt2800_bbp_read(rt2x00dev, 159); ++ if ((bbpval & 0xff) == 0x93) ++ udelay(50); ++ else ++ break; ++ } ++ ++ if ((bbpval & 0xff) == 0x93) { ++ rt2x00_warn(rt2x00dev, "Fatal Error: Calibration doesn't finish"); ++ goto restore_value; ++ } ++ ++ for (i = 0; i < 5; i++) { ++ u32 bbptemp = 0; ++ u8 value = 0; ++ int result = 0; ++ ++ rt2800_bbp_write(rt2x00dev, 158, 0x1e); ++ rt2800_bbp_write(rt2x00dev, 159, i); ++ rt2800_bbp_write(rt2x00dev, 158, 0x22); ++ value = rt2800_bbp_read(rt2x00dev, 159); ++ bbptemp = bbptemp + (value << 24); ++ rt2800_bbp_write(rt2x00dev, 158, 0x21); ++ value = rt2800_bbp_read(rt2x00dev, 159); ++ bbptemp = bbptemp + (value << 16); ++ rt2800_bbp_write(rt2x00dev, 158, 0x20); ++ value = rt2800_bbp_read(rt2x00dev, 159); ++ bbptemp = bbptemp + (value << 8); ++ rt2800_bbp_write(rt2x00dev, 158, 0x1f); ++ value = rt2800_bbp_read(rt2x00dev, 159); ++ bbptemp = bbptemp + value; ++ ++ if ((i < 2) && (bbptemp & 0x800000)) ++ result = (bbptemp & 0xffffff) - 0x1000000; ++ else if (i == 4) ++ result = bbptemp; ++ else ++ result = bbptemp; ++ ++ if (i == 0) ++ mi = result/4096; ++ else if (i == 1) ++ mq = result/4096; ++ else if (i == 2) ++ si = bbptemp/4096; ++ else if (i == 3) ++ sq = bbptemp/4096; ++ else ++ riq = result/4096; ++ } ++ ++ bbpval1 = si - mi*mi; ++ rt2x00_dbg(rt2x00dev, "RXIQ si=%d, sq=%d, riq=%d, bbpval %d, vga_idx %d", si, sq, riq, bbpval1, vga_idx); ++ ++ if (bbpval1 >= (100*100)) ++ break; ++ ++ if (bbpval1 <= 100) ++ vga_idx = vga_idx + 9; ++ else if (bbpval1 <= 158) ++ vga_idx = vga_idx + 8; ++ else if (bbpval1 <= 251) ++ vga_idx = vga_idx + 7; ++ else if (bbpval1 <= 398) ++ vga_idx = vga_idx + 6; ++ else if (bbpval1 <= 630) ++ vga_idx = vga_idx + 5; ++ else if (bbpval1 <= 1000) ++ vga_idx = vga_idx + 4; ++ else if (bbpval1 <= 1584) ++ vga_idx = vga_idx + 3; ++ else if (bbpval1 <= 2511) ++ vga_idx = vga_idx + 2; ++ else ++ vga_idx = vga_idx + 1; ++ } ++ ++ sigma_i = rt2800_do_sqrt_accumulation(100*(si - mi*mi)); ++ sigma_q = rt2800_do_sqrt_accumulation(100*(sq - mq*mq)); ++ r_iq = 10*(riq-(mi*mq)); ++ ++ rt2x00_dbg(rt2x00dev, "Sigma_i=%d, Sigma_q=%d, R_iq=%d", sigma_i, sigma_q, r_iq); ++ ++ if (((sigma_i <= 1400 ) && (sigma_i >= 1000)) ++ && ((sigma_i - sigma_q) <= 112) ++ && ((sigma_i - sigma_q) >= -112) ++ && ((mi <= 32) && (mi >= -32)) ++ && ((mq <= 32) && (mq >= -32))) { ++ r_iq = 10*(riq-(mi*mq)); ++ rt2x00_dbg(rt2x00dev, "RXIQ Sigma_i=%d, Sigma_q=%d, R_iq=%d\n", sigma_i, sigma_q, r_iq); ++ ++ g_rx = (1000 * sigma_q) / sigma_i; ++ g_imb = ((-2) * 128 * (1000 - g_rx)) / (1000 + g_rx); ++ ph_rx = (r_iq * 2292) / (sigma_i * sigma_q); ++ rt2x00_info(rt2x00dev, "RXIQ G_imb=%d, Ph_rx=%d\n", g_imb, ph_rx); ++ ++ if ((ph_rx > 20) || (ph_rx < -20)) { ++ ph_rx = 0; ++ rt2x00_warn(rt2x00dev, "RXIQ calibration FAIL"); ++ } ++ ++ if ((g_imb > 12) || (g_imb < -12)) { ++ g_imb = 0; ++ rt2x00_warn(rt2x00dev, "RXIQ calibration FAIL"); ++ } ++ } ++ else { ++ g_imb = 0; ++ ph_rx = 0; ++ rt2x00_dbg(rt2x00dev, "RXIQ Sigma_i=%d, Sigma_q=%d, R_iq=%d\n", sigma_i, sigma_q, r_iq); ++ rt2x00_warn(rt2x00dev, "RXIQ calibration FAIL"); ++ } ++ ++ if (ch_idx == 0) { ++ rt2800_bbp_write(rt2x00dev, 158, 0x37); ++ rt2800_bbp_write(rt2x00dev, 159, g_imb & 0x3f); ++ rt2800_bbp_write(rt2x00dev, 158, 0x35); ++ rt2800_bbp_write(rt2x00dev, 159, ph_rx & 0x3f); ++ } else { ++ rt2800_bbp_write(rt2x00dev, 158, 0x55); ++ rt2800_bbp_write(rt2x00dev, 159, g_imb & 0x3f); ++ rt2800_bbp_write(rt2x00dev, 158, 0x53); ++ rt2800_bbp_write(rt2x00dev, 159, ph_rx & 0x3f); ++ } ++ } ++ ++restore_value: ++ rt2800_bbp_write(rt2x00dev, 158, 0x3); ++ bbpval = rt2800_bbp_read(rt2x00dev, 159); ++ rt2800_bbp_write(rt2x00dev, 159, (bbpval | 0x07)); ++ ++ rt2800_bbp_write(rt2x00dev, 158, 0x00); ++ rt2800_bbp_write(rt2x00dev, 159, 0x00); ++ rt2800_bbp_write(rt2x00dev, 1, bbp1); ++ rt2800_bbp_write(rt2x00dev, 4, bbp4); ++ rt2800_bbp_write(rt2x00dev, 241, bbpr241); ++ rt2800_bbp_write(rt2x00dev, 242, bbpr242); ++ ++ rt2800_bbp_write(rt2x00dev, 244, 0x00); ++ bbpval = rt2800_bbp_read(rt2x00dev, 21); ++ bbpval |= 0x1; ++ rt2800_bbp_write(rt2x00dev, 21, bbpval); ++ usleep_range(10, 200); ++ bbpval &= 0xfe; ++ rt2800_bbp_write(rt2x00dev, 21, bbpval); ++ ++ rt2800_rfcsr_write_bank(rt2x00dev, 0, 1, rfb0r1); ++ rt2800_rfcsr_write_bank(rt2x00dev, 0, 2, rfb0r2); ++ rt2800_rfcsr_write_bank(rt2x00dev, 0, 42, rfb0r42); ++ ++ rt2800_rfcsr_write_bank(rt2x00dev, 4, 0, rfb4r0); ++ rt2800_rfcsr_write_bank(rt2x00dev, 4, 19, rfb4r19); ++ rt2800_rfcsr_write_bank(rt2x00dev, 5, 3, rfb5r3); ++ rt2800_rfcsr_write_bank(rt2x00dev, 5, 4, rfb5r4); ++ rt2800_rfcsr_write_bank(rt2x00dev, 5, 17, rfb5r17); ++ rt2800_rfcsr_write_bank(rt2x00dev, 5, 18, rfb5r18); ++ rt2800_rfcsr_write_bank(rt2x00dev, 5, 19, rfb5r19); ++ rt2800_rfcsr_write_bank(rt2x00dev, 5, 20, rfb5r20); ++ ++ rt2800_rfcsr_write_bank(rt2x00dev, 6, 0, rfb6r0); ++ rt2800_rfcsr_write_bank(rt2x00dev, 6, 19, rfb6r19); ++ rt2800_rfcsr_write_bank(rt2x00dev, 7, 3, rfb7r3); ++ rt2800_rfcsr_write_bank(rt2x00dev, 7, 4, rfb7r4); ++ rt2800_rfcsr_write_bank(rt2x00dev, 7, 17, rfb7r17); ++ rt2800_rfcsr_write_bank(rt2x00dev, 7, 18, rfb7r18); ++ rt2800_rfcsr_write_bank(rt2x00dev, 7, 19, rfb7r19); ++ rt2800_rfcsr_write_bank(rt2x00dev, 7, 20, rfb7r20); ++ ++ rt2800_register_write(rt2x00dev, RF_CONTROL0, 0x00000006); ++ udelay(1); ++ rt2800_register_write(rt2x00dev, RF_CONTROL0, 0x00000004); ++ udelay(1); ++ rt2800_register_write(rt2x00dev, RF_CONTROL0, orig_RF_CONTROL0); ++ udelay(1); ++ rt2800_register_write(rt2x00dev, RF_BYPASS0, orig_RF_BYPASS0); ++ rt2800_register_write(rt2x00dev, RF_CONTROL1, orig_RF_CONTROL1); ++ rt2800_register_write(rt2x00dev, RF_BYPASS1, orig_RF_BYPASS1); ++ rt2800_register_write(rt2x00dev, RF_CONTROL3, orig_RF_CONTROL3); ++ rt2800_register_write(rt2x00dev, RF_BYPASS3, orig_RF_BYPASS3); ++ rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, savemacsysctrl); ++} ++ + static void rt2800_bbp_core_soft_reset(struct rt2x00_dev *rt2x00dev, + bool set_bw, bool is_ht40) + { +@@ -9294,6 +9672,7 @@ static void rt2800_init_rfcsr_6352(struc + rt2800_rxdcoc_calibration(rt2x00dev); + rt2800_bw_filter_calibration(rt2x00dev, true); + rt2800_bw_filter_calibration(rt2x00dev, false); ++ rt2800_rxiq_calibration(rt2x00dev); + } + + static void rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) diff --git a/feeds/ipq40xx/mac80211/patches/rt2x00/986-rt2x00-add-TX-LOFT-calibration.patch b/feeds/ipq40xx/mac80211/patches/rt2x00/986-rt2x00-add-TX-LOFT-calibration.patch new file mode 100644 index 000000000..fe0961baa --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/rt2x00/986-rt2x00-add-TX-LOFT-calibration.patch @@ -0,0 +1,973 @@ +--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +@@ -9060,6 +9060,943 @@ restore_value: + rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, savemacsysctrl); + } + ++static void rt2800_rf_configstore(struct rt2x00_dev *rt2x00dev, rf_reg_pair rf_reg_record[][13], u8 chain) ++{ ++ u8 rfvalue = 0; ++ ++ if (chain == CHAIN_0) { ++ rfvalue = rt2800_rfcsr_read_bank(rt2x00dev, 0, 1); ++ rf_reg_record[CHAIN_0][0].bank = 0; ++ rf_reg_record[CHAIN_0][0].reg = 1; ++ rf_reg_record[CHAIN_0][0].value = rfvalue; ++ rfvalue = rt2800_rfcsr_read_bank(rt2x00dev, 0, 2); ++ rf_reg_record[CHAIN_0][1].bank = 0; ++ rf_reg_record[CHAIN_0][1].reg = 2; ++ rf_reg_record[CHAIN_0][1].value = rfvalue; ++ rfvalue = rt2800_rfcsr_read_bank(rt2x00dev, 0, 35); ++ rf_reg_record[CHAIN_0][2].bank = 0; ++ rf_reg_record[CHAIN_0][2].reg = 35; ++ rf_reg_record[CHAIN_0][2].value = rfvalue; ++ rfvalue = rt2800_rfcsr_read_bank(rt2x00dev, 0, 42); ++ rf_reg_record[CHAIN_0][3].bank = 0; ++ rf_reg_record[CHAIN_0][3].reg = 42; ++ rf_reg_record[CHAIN_0][3].value = rfvalue; ++ rfvalue = rt2800_rfcsr_read_bank(rt2x00dev, 4, 0); ++ rf_reg_record[CHAIN_0][4].bank = 4; ++ rf_reg_record[CHAIN_0][4].reg = 0; ++ rf_reg_record[CHAIN_0][4].value = rfvalue; ++ rfvalue = rt2800_rfcsr_read_bank(rt2x00dev, 4, 2); ++ rf_reg_record[CHAIN_0][5].bank = 4; ++ rf_reg_record[CHAIN_0][5].reg = 2; ++ rf_reg_record[CHAIN_0][5].value = rfvalue; ++ rfvalue = rt2800_rfcsr_read_bank(rt2x00dev, 4, 34); ++ rf_reg_record[CHAIN_0][6].bank = 4; ++ rf_reg_record[CHAIN_0][6].reg = 34; ++ rf_reg_record[CHAIN_0][6].value = rfvalue; ++ rfvalue = rt2800_rfcsr_read_bank(rt2x00dev, 5, 3); ++ rf_reg_record[CHAIN_0][7].bank = 5; ++ rf_reg_record[CHAIN_0][7].reg = 3; ++ rf_reg_record[CHAIN_0][7].value = rfvalue; ++ rfvalue = rt2800_rfcsr_read_bank(rt2x00dev, 5, 4); ++ rf_reg_record[CHAIN_0][8].bank = 5; ++ rf_reg_record[CHAIN_0][8].reg = 4; ++ rf_reg_record[CHAIN_0][8].value = rfvalue; ++ rfvalue = rt2800_rfcsr_read_bank(rt2x00dev, 5, 17); ++ rf_reg_record[CHAIN_0][9].bank = 5; ++ rf_reg_record[CHAIN_0][9].reg = 17; ++ rf_reg_record[CHAIN_0][9].value = rfvalue; ++ rfvalue = rt2800_rfcsr_read_bank(rt2x00dev, 5, 18); ++ rf_reg_record[CHAIN_0][10].bank = 5; ++ rf_reg_record[CHAIN_0][10].reg = 18; ++ rf_reg_record[CHAIN_0][10].value = rfvalue; ++ rfvalue = rt2800_rfcsr_read_bank(rt2x00dev, 5, 19); ++ rf_reg_record[CHAIN_0][11].bank = 5; ++ rf_reg_record[CHAIN_0][11].reg = 19; ++ rf_reg_record[CHAIN_0][11].value = rfvalue; ++ rfvalue = rt2800_rfcsr_read_bank(rt2x00dev, 5, 20); ++ rf_reg_record[CHAIN_0][12].bank = 5; ++ rf_reg_record[CHAIN_0][12].reg = 20; ++ rf_reg_record[CHAIN_0][12].value = rfvalue; ++ } else if (chain == CHAIN_1) { ++ rfvalue = rt2800_rfcsr_read_bank(rt2x00dev, 0, 1); ++ rf_reg_record[CHAIN_1][0].bank = 0; ++ rf_reg_record[CHAIN_1][0].reg = 1; ++ rf_reg_record[CHAIN_1][0].value = rfvalue; ++ rfvalue = rt2800_rfcsr_read_bank(rt2x00dev, 0, 2); ++ rf_reg_record[CHAIN_1][1].bank = 0; ++ rf_reg_record[CHAIN_1][1].reg = 2; ++ rf_reg_record[CHAIN_1][1].value = rfvalue; ++ rfvalue = rt2800_rfcsr_read_bank(rt2x00dev, 0, 35); ++ rf_reg_record[CHAIN_1][2].bank = 0; ++ rf_reg_record[CHAIN_1][2].reg = 35; ++ rf_reg_record[CHAIN_1][2].value = rfvalue; ++ rfvalue = rt2800_rfcsr_read_bank(rt2x00dev, 0, 42); ++ rf_reg_record[CHAIN_1][3].bank = 0; ++ rf_reg_record[CHAIN_1][3].reg = 42; ++ rf_reg_record[CHAIN_1][3].value = rfvalue; ++ rfvalue = rt2800_rfcsr_read_bank(rt2x00dev, 6, 0); ++ rf_reg_record[CHAIN_1][4].bank = 6; ++ rf_reg_record[CHAIN_1][4].reg = 0; ++ rf_reg_record[CHAIN_1][4].value = rfvalue; ++ rfvalue = rt2800_rfcsr_read_bank(rt2x00dev, 6, 2); ++ rf_reg_record[CHAIN_1][5].bank = 6; ++ rf_reg_record[CHAIN_1][5].reg = 2; ++ rf_reg_record[CHAIN_1][5].value = rfvalue; ++ rfvalue = rt2800_rfcsr_read_bank(rt2x00dev, 6, 34); ++ rf_reg_record[CHAIN_1][6].bank = 6; ++ rf_reg_record[CHAIN_1][6].reg = 34; ++ rf_reg_record[CHAIN_1][6].value = rfvalue; ++ rfvalue = rt2800_rfcsr_read_bank(rt2x00dev, 7, 3); ++ rf_reg_record[CHAIN_1][7].bank = 7; ++ rf_reg_record[CHAIN_1][7].reg = 3; ++ rf_reg_record[CHAIN_1][7].value = rfvalue; ++ rfvalue = rt2800_rfcsr_read_bank(rt2x00dev, 7, 4); ++ rf_reg_record[CHAIN_1][8].bank = 7; ++ rf_reg_record[CHAIN_1][8].reg = 4; ++ rf_reg_record[CHAIN_1][8].value = rfvalue; ++ rfvalue = rt2800_rfcsr_read_bank(rt2x00dev, 7, 17); ++ rf_reg_record[CHAIN_1][9].bank = 7; ++ rf_reg_record[CHAIN_1][9].reg = 17; ++ rf_reg_record[CHAIN_1][9].value = rfvalue; ++ rfvalue = rt2800_rfcsr_read_bank(rt2x00dev, 7, 18); ++ rf_reg_record[CHAIN_1][10].bank = 7; ++ rf_reg_record[CHAIN_1][10].reg = 18; ++ rf_reg_record[CHAIN_1][10].value = rfvalue; ++ rfvalue = rt2800_rfcsr_read_bank(rt2x00dev, 7, 19); ++ rf_reg_record[CHAIN_1][11].bank = 7; ++ rf_reg_record[CHAIN_1][11].reg = 19; ++ rf_reg_record[CHAIN_1][11].value = rfvalue; ++ rfvalue = rt2800_rfcsr_read_bank(rt2x00dev, 7, 20); ++ rf_reg_record[CHAIN_1][12].bank = 7; ++ rf_reg_record[CHAIN_1][12].reg = 20; ++ rf_reg_record[CHAIN_1][12].value = rfvalue; ++ } else { ++ rt2x00_warn(rt2x00dev, "Unknown chain = %u\n", chain); ++ return; ++ } ++ ++ return; ++} ++ ++static void rt2800_rf_configrecover(struct rt2x00_dev *rt2x00dev, rf_reg_pair rf_record[][13]) ++{ ++ u8 chain_index = 0, record_index = 0; ++ u8 bank = 0, rf_register = 0, value = 0; ++ ++ for (chain_index = 0; chain_index < 2; chain_index++) { ++ for (record_index = 0; record_index < 13; record_index++) { ++ bank = rf_record[chain_index][record_index].bank; ++ rf_register = rf_record[chain_index][record_index].reg; ++ value = rf_record[chain_index][record_index].value; ++ rt2800_rfcsr_write_bank(rt2x00dev, bank, rf_register, value); ++ rt2x00_dbg(rt2x00dev, "bank: %d, rf_register: %d, value: %x\n", bank, rf_register, value); ++ } ++ } ++ ++ return; ++} ++ ++static void rt2800_setbbptonegenerator(struct rt2x00_dev *rt2x00dev) ++{ ++ rt2800_bbp_write(rt2x00dev, 158, 0xAA); ++ rt2800_bbp_write(rt2x00dev, 159, 0x00); ++ ++ rt2800_bbp_write(rt2x00dev, 158, 0xAB); ++ rt2800_bbp_write(rt2x00dev, 159, 0x0A); ++ ++ rt2800_bbp_write(rt2x00dev, 158, 0xAC); ++ rt2800_bbp_write(rt2x00dev, 159, 0x3F); ++ ++ rt2800_bbp_write(rt2x00dev, 158, 0xAD); ++ rt2800_bbp_write(rt2x00dev, 159, 0x3F); ++ ++ rt2800_bbp_write(rt2x00dev, 244, 0x40); ++ ++ return; ++} ++ ++static u32 rt2800_do_fft_accumulation(struct rt2x00_dev *rt2x00dev, u8 tidx, u8 read_neg) ++{ ++ u32 macvalue = 0; ++ int fftout_i = 0, fftout_q = 0; ++ u32 ptmp=0, pint = 0; ++ u8 bbp = 0; ++ u8 tidxi; ++ ++ rt2800_bbp_write(rt2x00dev, 158, 0x00); ++ rt2800_bbp_write(rt2x00dev, 159, 0x9b); ++ ++ bbp = 0x9b; ++ ++ while (bbp == 0x9b) { ++ udelay(10); ++ bbp = rt2800_bbp_read(rt2x00dev, 159); ++ bbp = bbp & 0xff; ++ } ++ ++ rt2800_bbp_write(rt2x00dev, 158, 0xba); ++ rt2800_bbp_write(rt2x00dev, 159, tidx); ++ rt2800_bbp_write(rt2x00dev, 159, tidx); ++ rt2800_bbp_write(rt2x00dev, 159, tidx); ++ ++ macvalue = rt2800_register_read(rt2x00dev, 0x057C); ++ ++ fftout_i = (macvalue >> 16); ++ fftout_i = (fftout_i & 0x8000) ? (fftout_i - 0x10000) : fftout_i; ++ fftout_q = (macvalue & 0xffff); ++ fftout_q = (fftout_q & 0x8000) ? (fftout_q - 0x10000) : fftout_q; ++ ptmp = (fftout_i * fftout_i); ++ ptmp = ptmp + (fftout_q * fftout_q); ++ pint = ptmp; ++ rt2x00_dbg(rt2x00dev, "I = %d, Q = %d, power = %x\n", fftout_i, fftout_q, pint); ++ if (read_neg) { ++ pint = pint >> 1; ++ tidxi = 0x40 - tidx; ++ tidxi = tidxi & 0x3f; ++ ++ rt2800_bbp_write(rt2x00dev, 158, 0xba); ++ rt2800_bbp_write(rt2x00dev, 159, tidxi); ++ rt2800_bbp_write(rt2x00dev, 159, tidxi); ++ rt2800_bbp_write(rt2x00dev, 159, tidxi); ++ ++ macvalue = rt2800_register_read(rt2x00dev, 0x057C); ++ ++ fftout_i = (macvalue >> 16); ++ fftout_i = (fftout_i & 0x8000) ? (fftout_i - 0x10000) : fftout_i; ++ fftout_q = (macvalue & 0xffff); ++ fftout_q = (fftout_q & 0x8000) ? (fftout_q - 0x10000) : fftout_q; ++ ptmp = (fftout_i * fftout_i); ++ ptmp = ptmp + (fftout_q * fftout_q); ++ ptmp = ptmp >> 1; ++ pint = pint + ptmp; ++ } ++ ++ return pint; ++} ++ ++static u32 rt2800_read_fft_accumulation(struct rt2x00_dev *rt2x00dev, u8 tidx) { ++ u32 macvalue = 0; ++ int fftout_i = 0, fftout_q = 0; ++ u32 ptmp=0, pint = 0; ++ ++ rt2800_bbp_write(rt2x00dev, 158, 0xBA); ++ rt2800_bbp_write(rt2x00dev, 159, tidx); ++ rt2800_bbp_write(rt2x00dev, 159, tidx); ++ rt2800_bbp_write(rt2x00dev, 159, tidx); ++ ++ macvalue = rt2800_register_read(rt2x00dev, 0x057C); ++ ++ fftout_i = (macvalue >> 16); ++ fftout_i = (fftout_i & 0x8000) ? (fftout_i - 0x10000) : fftout_i; ++ fftout_q = (macvalue & 0xffff); ++ fftout_q = (fftout_q & 0x8000) ? (fftout_q - 0x10000) : fftout_q; ++ ptmp = (fftout_i * fftout_i); ++ ptmp = ptmp + (fftout_q * fftout_q); ++ pint = ptmp; ++ rt2x00_info(rt2x00dev, "I = %d, Q = %d, power = %x\n", fftout_i, fftout_q, pint); ++ ++ return pint; ++} ++ ++static void rt2800_write_dc(struct rt2x00_dev *rt2x00dev, u8 ch_idx, u8 alc, u8 iorq, u8 dc) ++{ ++ u8 bbp = 0; ++ ++ rt2800_bbp_write(rt2x00dev, 158, 0xb0); ++ bbp = alc | 0x80; ++ rt2800_bbp_write(rt2x00dev, 159, bbp); ++ ++ if (ch_idx == 0) ++ bbp = (iorq == 0) ? 0xb1: 0xb2; ++ else ++ bbp = (iorq == 0) ? 0xb8: 0xb9; ++ ++ rt2800_bbp_write(rt2x00dev, 158, bbp); ++ bbp = dc; ++ rt2800_bbp_write(rt2x00dev, 159, bbp); ++ ++ return; ++} ++ ++static void rt2800_loft_search(struct rt2x00_dev *rt2x00dev, u8 ch_idx, u8 alc_idx, u8 dc_result[][RF_ALC_NUM][2]) ++{ ++ u32 p0 = 0, p1 = 0, pf = 0; ++ char idx0 = 0, idx1 = 0; ++ u8 idxf[] = {0x00, 0x00}; ++ u8 ibit = 0x20; ++ u8 iorq; ++ char bidx; ++ ++ rt2800_bbp_write(rt2x00dev, 158, 0xb0); ++ rt2800_bbp_write(rt2x00dev, 159, 0x80); ++ ++ for (bidx = 5; bidx >= 0; bidx--) { ++ for (iorq = 0; iorq <= 1; iorq++) { ++ rt2x00_dbg(rt2x00dev, "\n========================================================\n"); ++ ++ if (idxf[iorq] == 0x20) { ++ idx0 = 0x20; ++ p0 = pf; ++ } else { ++ idx0 = idxf[iorq] - ibit; ++ idx0 = idx0 & 0x3F; ++ rt2800_write_dc(rt2x00dev, ch_idx, 0, iorq, idx0); ++ p0 = rt2800_do_fft_accumulation(rt2x00dev, 0x0A, 0); ++ } ++ ++ idx1 = idxf[iorq] + ((bidx == 5) ? 0 : ibit); ++ idx1 = idx1 & 0x3F; ++ rt2800_write_dc(rt2x00dev, ch_idx, 0, iorq, idx1); ++ p1 = rt2800_do_fft_accumulation(rt2x00dev, 0x0A, 0); ++ ++ rt2x00_dbg(rt2x00dev, "alc=%u, IorQ=%u, idx_final=%2x\n", alc_idx, iorq, idxf[iorq]); ++ rt2x00_dbg(rt2x00dev, "p0=%x, p1=%x, pf=%x, idx_0=%x, idx_1=%x, ibit=%x !\n", p0, p1, pf, idx0, idx1, ibit); ++ ++ if ((bidx != 5) && (pf <= p0) && (pf < p1)) { ++ pf = pf; ++ idxf[iorq] = idxf[iorq]; ++ } else if (p0 < p1) { ++ pf = p0; ++ idxf[iorq] = idx0 & 0x3F; ++ } else { ++ pf = p1; ++ idxf[iorq] = idx1 & 0x3F; ++ } ++ rt2x00_dbg(rt2x00dev, "IorQ=%u, idx_final[%u]:%x, pf:%8x\n", iorq, iorq, idxf[iorq], pf); ++ ++ rt2800_write_dc(rt2x00dev, ch_idx, 0, iorq, idxf[iorq]); ++ ++ } ++ ibit = ibit >> 1; ++ } ++ dc_result[ch_idx][alc_idx][0] = idxf[0]; ++ dc_result[ch_idx][alc_idx][1] = idxf[1]; ++ ++ return; ++} ++ ++static void rt2800_iq_search(struct rt2x00_dev *rt2x00dev, u8 ch_idx, u8 *ges, u8 *pes) ++{ ++ u32 p0 = 0, p1 = 0, pf = 0; ++ char perr = 0, gerr = 0, iq_err = 0; ++ char pef = 0, gef = 0; ++ char psta, pend; ++ char gsta, gend; ++ ++ u8 ibit = 0x20; ++ u8 first_search = 0x00, touch_neg_max = 0x00; ++ char idx0 = 0, idx1 = 0; ++ u8 gop; ++ u8 bbp = 0; ++ char bidx; ++ ++ rt2x00_info(rt2x00dev, "IQCalibration Start!\n"); ++ for (bidx = 5; bidx >= 1; bidx--) { ++ for (gop = 0; gop < 2; gop++) { ++ rt2x00_dbg(rt2x00dev, "\n========================================================\n"); ++ ++ if ((gop == 1) || (bidx < 4)) { ++ if (gop == 0) ++ iq_err = gerr; ++ else ++ iq_err = perr; ++ ++ first_search = (gop == 0) ? (bidx == 3) : (bidx == 5); ++ touch_neg_max = (gop) ? ((iq_err & 0x0F) == 0x08) : ((iq_err & 0x3F) == 0x20); ++ ++ if (touch_neg_max) { ++ p0 = pf; ++ idx0 = iq_err; ++ } else { ++ idx0 = iq_err - ibit; ++ bbp = (ch_idx == 0) ? ((gop == 0) ? 0x28 : 0x29): ((gop == 0) ? 0x46 : 0x47); ++ ++ rt2800_bbp_write(rt2x00dev, 158, bbp); ++ rt2800_bbp_write(rt2x00dev, 159, idx0); ++ ++ p0 = rt2800_do_fft_accumulation(rt2x00dev, 0x14, 1); ++ } ++ ++ idx1 = iq_err + (first_search ? 0 : ibit); ++ idx1 = (gop == 0) ? (idx1 & 0x0F) : (idx1 & 0x3F); ++ ++ bbp = (ch_idx == 0) ? (gop == 0) ? 0x28 : 0x29 : (gop == 0) ? 0x46 : 0x47; ++ ++ rt2800_bbp_write(rt2x00dev, 158, bbp); ++ rt2800_bbp_write(rt2x00dev, 159, idx1); ++ ++ p1 = rt2800_do_fft_accumulation(rt2x00dev, 0x14, 1); ++ ++ rt2x00_dbg(rt2x00dev, "p0=%x, p1=%x, pwer_final=%x, idx0=%x, idx1=%x, iq_err=%x, gop=%d, ibit=%x !\n", p0, p1, pf, idx0, idx1, iq_err, gop, ibit); ++ ++ if ((!first_search) && (pf <= p0) && (pf < p1)) { ++ pf = pf; ++ } else if (p0 < p1) { ++ pf = p0; ++ iq_err = idx0; ++ } else { ++ pf = p1; ++ iq_err = idx1; ++ } ++ ++ bbp = (ch_idx == 0) ? (gop == 0) ? 0x28 : 0x29 : (gop == 0) ? 0x46 : 0x47; ++ ++ rt2800_bbp_write(rt2x00dev, 158, bbp); ++ rt2800_bbp_write(rt2x00dev, 159, iq_err); ++ ++ if (gop == 0) ++ gerr = iq_err; ++ else ++ perr = iq_err; ++ ++ rt2x00_dbg(rt2x00dev, "IQCalibration pf=%8x (%2x, %2x) !\n", pf, gerr & 0x0F, perr & 0x3F); ++ ++ } ++ } ++ ++ if (bidx > 0) ++ ibit = (ibit >> 1); ++ } ++ gerr = (gerr & 0x08) ? (gerr & 0x0F) - 0x10 : (gerr & 0x0F); ++ perr = (perr & 0x20) ? (perr & 0x3F) - 0x40 : (perr & 0x3F); ++ ++ gerr = (gerr < -0x07) ? -0x07 : (gerr > 0x05) ? 0x05 : gerr; ++ gsta = gerr - 1; ++ gend = gerr + 2; ++ ++ perr = (perr < -0x1f) ? -0x1f : (perr > 0x1d) ? 0x1d : perr; ++ psta = perr - 1; ++ pend = perr + 2; ++ ++ for (gef = gsta; gef <= gend; gef = gef + 1) ++ for (pef = psta; pef <= pend; pef = pef + 1) { ++ bbp = (ch_idx == 0) ? 0x28 : 0x46; ++ rt2800_bbp_write(rt2x00dev, 158, bbp); ++ rt2800_bbp_write(rt2x00dev, 159, gef & 0x0F); ++ ++ bbp = (ch_idx == 0) ? 0x29 : 0x47; ++ rt2800_bbp_write(rt2x00dev, 158, bbp); ++ rt2800_bbp_write(rt2x00dev, 159, pef & 0x3F); ++ ++ p1 = rt2800_do_fft_accumulation(rt2x00dev, 0x14, 1); ++ if ((gef == gsta) && (pef == psta)) { ++ pf = p1; ++ gerr = gef; ++ perr = pef; ++ } ++ else if (pf > p1){ ++ pf = p1; ++ gerr = gef; ++ perr = pef; ++ } ++ rt2x00_dbg(rt2x00dev, "Fine IQCalibration p1=%8x pf=%8x (%2x, %2x) !\n", p1, pf, gef & 0x0F, pef & 0x3F); ++ } ++ ++ ges[ch_idx] = gerr & 0x0F; ++ pes[ch_idx] = perr & 0x3F; ++ ++ rt2x00_info(rt2x00dev, "IQCalibration Done! CH = %u, (gain=%2x, phase=%2x)\n", ch_idx, gerr & 0x0F, perr & 0x3F); ++ ++ return; ++} ++ ++static void rt2800_rf_aux_tx0_loopback(struct rt2x00_dev *rt2x00dev) ++{ ++ rt2800_rfcsr_write_bank(rt2x00dev, 0, 1, 0x21); ++ rt2800_rfcsr_write_bank(rt2x00dev, 0, 2, 0x10); ++ rt2800_rfcsr_write_bank(rt2x00dev, 0, 35, 0x00); ++ rt2800_rfcsr_write_bank(rt2x00dev, 0, 42, 0x1b); ++ rt2800_rfcsr_write_bank(rt2x00dev, 4, 0, 0x81); ++ rt2800_rfcsr_write_bank(rt2x00dev, 4, 2, 0x81); ++ rt2800_rfcsr_write_bank(rt2x00dev, 4, 34, 0xee); ++ rt2800_rfcsr_write_bank(rt2x00dev, 5, 3, 0x2d); ++ rt2800_rfcsr_write_bank(rt2x00dev, 5, 4, 0x2d); ++ rt2800_rfcsr_write_bank(rt2x00dev, 5, 17, 0x80); ++ rt2800_rfcsr_write_bank(rt2x00dev, 5, 18, 0xd7); ++ rt2800_rfcsr_write_bank(rt2x00dev, 5, 19, 0xa2); ++ rt2800_rfcsr_write_bank(rt2x00dev, 5, 20, 0x20); ++} ++ ++static void rt2800_rf_aux_tx1_loopback(struct rt2x00_dev *rt2x00dev) ++{ ++ rt2800_rfcsr_write_bank(rt2x00dev, 0, 1, 0x22); ++ rt2800_rfcsr_write_bank(rt2x00dev, 0, 2, 0x20); ++ rt2800_rfcsr_write_bank(rt2x00dev, 0, 35, 0x00); ++ rt2800_rfcsr_write_bank(rt2x00dev, 0, 42, 0x4b); ++ rt2800_rfcsr_write_bank(rt2x00dev, 6, 0, 0x81); ++ rt2800_rfcsr_write_bank(rt2x00dev, 6, 2, 0x81); ++ rt2800_rfcsr_write_bank(rt2x00dev, 6, 34, 0xee); ++ rt2800_rfcsr_write_bank(rt2x00dev, 7, 3, 0x2d); ++ rt2800_rfcsr_write_bank(rt2x00dev, 7, 4, 0x2d); ++ rt2800_rfcsr_write_bank(rt2x00dev, 7, 17, 0x80); ++ rt2800_rfcsr_write_bank(rt2x00dev, 7, 18, 0xd7); ++ rt2800_rfcsr_write_bank(rt2x00dev, 7, 19, 0xa2); ++ rt2800_rfcsr_write_bank(rt2x00dev, 7, 20, 0x20); ++} ++ ++void rt2800_loft_iq_calibration(struct rt2x00_dev *rt2x00dev) ++{ ++ rf_reg_pair rf_store[CHAIN_NUM][13]; ++ u32 macorg1 = 0; ++ u32 macorg2 = 0; ++ u32 macorg3 = 0; ++ u32 macorg4 = 0; ++ u32 macorg5 = 0; ++ u32 orig528 = 0; ++ u32 orig52c = 0; ++ ++ u32 savemacsysctrl = 0, mtxcycle = 0; ++ u32 macvalue = 0; ++ u32 mac13b8 = 0; ++ u32 p0 = 0, p1 = 0; ++ u32 p0_idx10 = 0, p1_idx10 = 0; ++ ++ u8 rfvalue; ++ u8 loft_dc_search_result[CHAIN_NUM][RF_ALC_NUM][2]; ++ u8 ger[CHAIN_NUM], per[CHAIN_NUM]; ++ u8 rf_gain[] = {0x00, 0x01, 0x02, 0x04, 0x08, 0x0c}; ++ u8 rfvga_gain_table[] = {0x24, 0x25, 0x26, 0x27, 0x28, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3F}; ++ ++ u8 vga_gain[] = {14, 14}; ++ u8 bbp_2324gain[] = {0x16, 0x14, 0x12, 0x10, 0x0c, 0x08}; ++ u8 bbp = 0, ch_idx = 0, rf_alc_idx = 0, idx = 0; ++ u8 bbpr30, rfb0r39, rfb0r42; ++ u8 bbpr1; ++ u8 bbpr4; ++ u8 bbpr241, bbpr242; ++ u8 count_step; ++ ++ savemacsysctrl = rt2800_register_read(rt2x00dev, MAC_SYS_CTRL); ++ macorg1 = rt2800_register_read(rt2x00dev, TX_PIN_CFG); ++ macorg2 = rt2800_register_read(rt2x00dev, RF_CONTROL0); ++ macorg3 = rt2800_register_read(rt2x00dev, RF_BYPASS0); ++ macorg4 = rt2800_register_read(rt2x00dev, RF_CONTROL3); ++ macorg5 = rt2800_register_read(rt2x00dev, RF_BYPASS3); ++ mac13b8 = rt2800_register_read(rt2x00dev, 0x13b8); ++ orig528 = rt2800_register_read(rt2x00dev, RF_CONTROL2); ++ orig52c = rt2800_register_read(rt2x00dev, RF_BYPASS2); ++ ++ macvalue = rt2800_register_read(rt2x00dev, MAC_SYS_CTRL); ++ macvalue &= (~0x04); ++ rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, macvalue); ++ ++ for (mtxcycle = 0; mtxcycle < 10000; mtxcycle++) { ++ macvalue = rt2800_register_read(rt2x00dev, MAC_STATUS_CFG); ++ if (macvalue & 0x01) ++ udelay(50); ++ else ++ break; ++ } ++ ++ macvalue = rt2800_register_read(rt2x00dev, MAC_SYS_CTRL); ++ macvalue &= (~0x08); ++ rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, macvalue); ++ ++ for (mtxcycle = 0; mtxcycle < 10000; mtxcycle++) { ++ macvalue = rt2800_register_read(rt2x00dev, MAC_STATUS_CFG); ++ if (macvalue & 0x02) ++ udelay(50); ++ else ++ break; ++ } ++ ++ for (ch_idx = 0; ch_idx < 2; ch_idx++) { ++ rt2800_rf_configstore(rt2x00dev, rf_store, ch_idx); ++ } ++ ++ bbpr30 = rt2800_bbp_read(rt2x00dev, 30); ++ rfb0r39 = rt2800_rfcsr_read_bank(rt2x00dev, 0, 39); ++ rfb0r42 = rt2800_rfcsr_read_bank(rt2x00dev, 0, 42); ++ ++ rt2800_bbp_write(rt2x00dev, 30, 0x1F); ++ rt2800_rfcsr_write_bank(rt2x00dev, 0, 39, 0x80); ++ rt2800_rfcsr_write_bank(rt2x00dev, 0, 42, 0x5B); ++ ++ rt2800_bbp_write(rt2x00dev, 23, 0x00); ++ rt2800_bbp_write(rt2x00dev, 24, 0x00); ++ ++ rt2800_setbbptonegenerator(rt2x00dev); ++ ++ for (ch_idx = 0; ch_idx < 2; ch_idx ++) { ++ rt2800_bbp_write(rt2x00dev, 23, 0x00); ++ rt2800_bbp_write(rt2x00dev, 24, 0x00); ++ rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00); ++ rt2800_register_write(rt2x00dev, TX_PIN_CFG, 0x0000000F); ++ rt2800_register_write(rt2x00dev, RF_CONTROL0, 0x00000004); ++ rt2800_register_write(rt2x00dev, RF_BYPASS0, 0x00003306); ++ rt2800_register_write(rt2x00dev, 0x13b8, 0x10); ++ udelay(1); ++ ++ if (ch_idx == 0) { ++ rt2800_rf_aux_tx0_loopback(rt2x00dev); ++ } else { ++ rt2800_rf_aux_tx1_loopback(rt2x00dev); ++ } ++ udelay(1); ++ ++ if (ch_idx == 0) { ++ rt2800_register_write(rt2x00dev, RF_CONTROL0, 0x00001004); ++ } else { ++ rt2800_register_write(rt2x00dev, RF_CONTROL0, 0x00002004); ++ } ++ ++ rt2800_bbp_write(rt2x00dev, 158, 0x05); ++ rt2800_bbp_write(rt2x00dev, 159, 0x00); ++ ++ rt2800_bbp_write(rt2x00dev, 158, 0x01); ++ if (ch_idx == 0) ++ rt2800_bbp_write(rt2x00dev, 159, 0x00); ++ else ++ rt2800_bbp_write(rt2x00dev, 159, 0x01); ++ ++ vga_gain[ch_idx] = 18; ++ for (rf_alc_idx = 0; rf_alc_idx < 3; rf_alc_idx++) { ++ rt2800_bbp_write(rt2x00dev, 23, bbp_2324gain[rf_alc_idx]); ++ rt2800_bbp_write(rt2x00dev, 24, bbp_2324gain[rf_alc_idx]); ++ ++ macvalue = rt2800_register_read(rt2x00dev, RF_CONTROL3); ++ macvalue &= (~0x0000F1F1); ++ macvalue |= (rf_gain[rf_alc_idx] << 4); ++ macvalue |= (rf_gain[rf_alc_idx] << 12); ++ rt2800_register_write(rt2x00dev, RF_CONTROL3, macvalue); ++ macvalue = (0x0000F1F1); ++ rt2800_register_write(rt2x00dev, RF_BYPASS3, macvalue); ++ ++ if (rf_alc_idx == 0) { ++ rt2800_write_dc(rt2x00dev, ch_idx, 0, 1, 0x21); ++ for (;vga_gain[ch_idx] > 0;vga_gain[ch_idx] = vga_gain[ch_idx] - 2) { ++ rfvalue = rfvga_gain_table[vga_gain[ch_idx]]; ++ rt2800_rfcsr_write_dccal(rt2x00dev, 3, rfvalue); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 4, rfvalue); ++ rt2800_write_dc(rt2x00dev, ch_idx, 0, 1, 0x00); ++ rt2800_write_dc(rt2x00dev, ch_idx, 0, 0, 0x00); ++ p0 = rt2800_do_fft_accumulation(rt2x00dev, 0x0A, 0); ++ rt2800_write_dc(rt2x00dev, ch_idx, 0, 0, 0x21); ++ p1 = rt2800_do_fft_accumulation(rt2x00dev, 0x0A, 0); ++ rt2x00_dbg(rt2x00dev, "LOFT AGC %d %d\n", p0, p1); ++ if ((p0 < 7000*7000) && (p1 < (7000*7000))) { ++ break; ++ } ++ } ++ ++ rt2800_write_dc(rt2x00dev, ch_idx, 0, 0, 0x00); ++ rt2800_write_dc(rt2x00dev, ch_idx, 0, 1, 0x00); ++ ++ rt2x00_dbg(rt2x00dev, "Used VGA %d %x\n",vga_gain[ch_idx], rfvga_gain_table[vga_gain[ch_idx]]); ++ ++ if (vga_gain[ch_idx] < 0) ++ vga_gain[ch_idx] = 0; ++ } ++ ++ rfvalue = rfvga_gain_table[vga_gain[ch_idx]]; ++ ++ rt2800_rfcsr_write_dccal(rt2x00dev, 3, rfvalue); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 4, rfvalue); ++ ++ rt2800_loft_search(rt2x00dev, ch_idx, rf_alc_idx, loft_dc_search_result); ++ } ++ } ++ ++ for (rf_alc_idx = 0; rf_alc_idx < 3; rf_alc_idx++) { ++ for (idx = 0; idx < 4; idx++) { ++ rt2800_bbp_write(rt2x00dev, 158, 0xB0); ++ bbp = (idx<<2) + rf_alc_idx; ++ rt2800_bbp_write(rt2x00dev, 159, bbp); ++ rt2x00_dbg(rt2x00dev, " ALC %2x,", bbp); ++ ++ rt2800_bbp_write(rt2x00dev, 158, 0xb1); ++ bbp = loft_dc_search_result[CHAIN_0][rf_alc_idx][0x00]; ++ bbp = bbp & 0x3F; ++ rt2800_bbp_write(rt2x00dev, 159, bbp); ++ rt2x00_dbg(rt2x00dev, " I0 %2x,", bbp); ++ ++ rt2800_bbp_write(rt2x00dev, 158, 0xb2); ++ bbp = loft_dc_search_result[CHAIN_0][rf_alc_idx][0x01]; ++ bbp = bbp & 0x3F; ++ rt2800_bbp_write(rt2x00dev, 159, bbp); ++ rt2x00_dbg(rt2x00dev, " Q0 %2x,", bbp); ++ ++ rt2800_bbp_write(rt2x00dev, 158, 0xb8); ++ bbp = loft_dc_search_result[CHAIN_1][rf_alc_idx][0x00]; ++ bbp = bbp & 0x3F; ++ rt2800_bbp_write(rt2x00dev, 159, bbp); ++ rt2x00_dbg(rt2x00dev, " I1 %2x,", bbp); ++ ++ rt2800_bbp_write(rt2x00dev, 158, 0xb9); ++ bbp = loft_dc_search_result[CHAIN_1][rf_alc_idx][0x01]; ++ bbp = bbp & 0x3F; ++ rt2800_bbp_write(rt2x00dev, 159, bbp); ++ rt2x00_dbg(rt2x00dev, " Q1 %2x\n", bbp); ++ } ++ } ++ ++ rt2800_bbp_write(rt2x00dev, 23, 0x00); ++ rt2800_bbp_write(rt2x00dev, 24, 0x00); ++ ++ rt2800_register_write(rt2x00dev, RF_CONTROL0, 0x04); ++ ++ rt2800_bbp_write(rt2x00dev, 158, 0x00); ++ rt2800_bbp_write(rt2x00dev, 159, 0x00); ++ ++ bbp = 0x00; ++ rt2800_bbp_write(rt2x00dev, 244, 0x00); ++ ++ rt2800_bbp_write(rt2x00dev, 21, 0x01); ++ udelay(1); ++ rt2800_bbp_write(rt2x00dev, 21, 0x00); ++ ++ rt2800_rf_configrecover(rt2x00dev, rf_store); ++ ++ rt2800_register_write(rt2x00dev, TX_PIN_CFG, macorg1); ++ rt2800_register_write(rt2x00dev, RF_CONTROL0, 0x04); ++ rt2800_register_write(rt2x00dev, RF_CONTROL0, 0x00); ++ rt2800_register_write(rt2x00dev, RF_BYPASS0, 0x00); ++ rt2800_register_write(rt2x00dev, RF_CONTROL0, macorg2); ++ udelay(1); ++ rt2800_register_write(rt2x00dev, RF_BYPASS0, macorg3); ++ rt2800_register_write(rt2x00dev, RF_CONTROL3, macorg4); ++ rt2800_register_write(rt2x00dev, RF_BYPASS3, macorg5); ++ rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, savemacsysctrl); ++ rt2800_register_write(rt2x00dev, RF_CONTROL2, orig528); ++ rt2800_register_write(rt2x00dev, RF_BYPASS2, orig52c); ++ rt2800_register_write(rt2x00dev, 0x13b8, mac13b8); ++ ++ rt2x00_info(rt2x00dev, "LOFT Calibration Done!\n"); ++ ++ savemacsysctrl = rt2800_register_read(rt2x00dev, MAC_SYS_CTRL); ++ macorg1 = rt2800_register_read(rt2x00dev, TX_PIN_CFG); ++ macorg2 = rt2800_register_read(rt2x00dev, RF_CONTROL0); ++ macorg3 = rt2800_register_read(rt2x00dev, RF_BYPASS0); ++ macorg4 = rt2800_register_read(rt2x00dev, RF_CONTROL3); ++ macorg5 = rt2800_register_read(rt2x00dev, RF_BYPASS3); ++ ++ bbpr1 = rt2800_bbp_read(rt2x00dev, 1); ++ bbpr4 = rt2800_bbp_read(rt2x00dev, 4); ++ bbpr241 = rt2800_bbp_read(rt2x00dev, 241); ++ bbpr242 = rt2800_bbp_read(rt2x00dev, 242); ++ mac13b8 = rt2800_register_read(rt2x00dev, 0x13b8); ++ ++ macvalue = rt2800_register_read(rt2x00dev, MAC_SYS_CTRL); ++ macvalue &= (~0x04); ++ rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, macvalue); ++ for (mtxcycle = 0; mtxcycle < 10000; mtxcycle++) { ++ macvalue = rt2800_register_read(rt2x00dev, MAC_STATUS_CFG); ++ if (macvalue & 0x01) ++ udelay(50); ++ else ++ break; ++ } ++ ++ macvalue = rt2800_register_read(rt2x00dev, MAC_SYS_CTRL); ++ macvalue &= (~0x08); ++ rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, macvalue); ++ for (mtxcycle = 0; mtxcycle < 10000; mtxcycle++) { ++ macvalue = rt2800_register_read(rt2x00dev, MAC_STATUS_CFG); ++ if (macvalue & 0x02) ++ udelay(50); ++ else ++ break; ++ } ++ ++ if (test_bit(CAPABILITY_EXTERNAL_PA_TX0, &rt2x00dev->cap_flags)) { ++ rt2800_register_write(rt2x00dev, RF_CONTROL3, 0x00000101); ++ rt2800_register_write(rt2x00dev, RF_BYPASS3, 0x0000F1F1); ++ } ++ ++ rt2800_bbp_write(rt2x00dev, 23, 0x00); ++ rt2800_bbp_write(rt2x00dev, 24, 0x00); ++ ++ if (test_bit(CAPABILITY_EXTERNAL_PA_TX0, &rt2x00dev->cap_flags)) { ++ rt2800_bbp_write(rt2x00dev, 4, bbpr4 & (~0x18)); ++ rt2800_bbp_write(rt2x00dev, 21, 0x01); ++ udelay(1); ++ rt2800_bbp_write(rt2x00dev, 21, 0x00); ++ ++ rt2800_bbp_write(rt2x00dev, 241, 0x14); ++ rt2800_bbp_write(rt2x00dev, 242, 0x80); ++ rt2800_bbp_write(rt2x00dev, 244, 0x31); ++ } else { ++ rt2800_setbbptonegenerator(rt2x00dev); ++ } ++ ++ rt2800_register_write(rt2x00dev, RF_CONTROL0, 0x00000004); ++ rt2800_register_write(rt2x00dev, RF_BYPASS0, 0x00003306); ++ udelay(1); ++ ++ rt2800_register_write(rt2x00dev, TX_PIN_CFG, 0x0000000F); ++ ++ if (!test_bit(CAPABILITY_EXTERNAL_PA_TX0, &rt2x00dev->cap_flags)) { ++ rt2800_register_write(rt2x00dev, RF_CONTROL3, 0x00000000); ++ rt2800_register_write(rt2x00dev, RF_BYPASS3, 0x0000F1F1); ++ } ++ ++ rt2800_register_write(rt2x00dev, 0x13b8, 0x00000010); ++ ++ for (ch_idx = 0; ch_idx < 2; ch_idx++) { ++ rt2800_rf_configstore(rt2x00dev, rf_store, ch_idx); ++ } ++ ++ rt2800_rfcsr_write_dccal(rt2x00dev, 3, 0x3B); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 4, 0x3B); ++ ++ rt2800_bbp_write(rt2x00dev, 158, 0x03); ++ rt2800_bbp_write(rt2x00dev, 159, 0x60); ++ rt2800_bbp_write(rt2x00dev, 158, 0xB0); ++ rt2800_bbp_write(rt2x00dev, 159, 0x80); ++ ++ for (ch_idx = 0; ch_idx < 2; ch_idx ++) { ++ rt2800_bbp_write(rt2x00dev, 23, 0x00); ++ rt2800_bbp_write(rt2x00dev, 24, 0x00); ++ ++ if (ch_idx == 0) { ++ rt2800_bbp_write(rt2x00dev, 158, 0x01); ++ rt2800_bbp_write(rt2x00dev, 159, 0x00); ++ if (test_bit(CAPABILITY_EXTERNAL_PA_TX0, &rt2x00dev->cap_flags)) { ++ bbp = bbpr1 & (~0x18); ++ bbp = bbp | 0x00; ++ rt2800_bbp_write(rt2x00dev, 1, bbp); ++ } ++ rt2800_rf_aux_tx0_loopback(rt2x00dev); ++ rt2800_register_write(rt2x00dev, RF_CONTROL0, 0x00001004); ++ } else { ++ rt2800_bbp_write(rt2x00dev, 158, 0x01); ++ rt2800_bbp_write(rt2x00dev, 159, 0x01); ++ if (test_bit(CAPABILITY_EXTERNAL_PA_TX1, &rt2x00dev->cap_flags)) { ++ bbp = bbpr1 & (~0x18); ++ bbp = bbp | 0x08; ++ rt2800_bbp_write(rt2x00dev, 1, bbp); ++ } ++ rt2800_rf_aux_tx1_loopback(rt2x00dev); ++ rt2800_register_write(rt2x00dev, RF_CONTROL0, 0x00002004); ++ } ++ ++ rt2800_bbp_write(rt2x00dev, 158, 0x05); ++ rt2800_bbp_write(rt2x00dev, 159, 0x04); ++ ++ bbp = (ch_idx == 0) ? 0x28 : 0x46; ++ rt2800_bbp_write(rt2x00dev, 158, bbp); ++ rt2800_bbp_write(rt2x00dev, 159, 0x00); ++ ++ if (test_bit(CAPABILITY_EXTERNAL_PA_TX0, &rt2x00dev->cap_flags)) { ++ rt2800_bbp_write(rt2x00dev, 23, 0x06); ++ rt2800_bbp_write(rt2x00dev, 24, 0x06); ++ count_step = 1; ++ } else { ++ rt2800_bbp_write(rt2x00dev, 23, 0x1F); ++ rt2800_bbp_write(rt2x00dev, 24, 0x1F); ++ count_step = 2; ++ } ++ ++ for (;vga_gain[ch_idx] < 19; vga_gain[ch_idx]=(vga_gain[ch_idx] + count_step)) { ++ rfvalue = rfvga_gain_table[vga_gain[ch_idx]]; ++ rt2800_rfcsr_write_dccal(rt2x00dev, 3, rfvalue); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 4, rfvalue); ++ ++ bbp = (ch_idx == 0) ? 0x29 : 0x47; ++ rt2800_bbp_write(rt2x00dev, 158, bbp); ++ rt2800_bbp_write(rt2x00dev, 159, 0x00); ++ p0 = rt2800_do_fft_accumulation(rt2x00dev, 0x14, 0); ++ if (test_bit(CAPABILITY_EXTERNAL_PA_TX0, &rt2x00dev->cap_flags)) { ++ p0_idx10 = rt2800_read_fft_accumulation(rt2x00dev, 0x0A); ++ } ++ ++ bbp = (ch_idx == 0) ? 0x29 : 0x47; ++ rt2800_bbp_write(rt2x00dev, 158, bbp); ++ rt2800_bbp_write(rt2x00dev, 159, 0x21); ++ p1 = rt2800_do_fft_accumulation(rt2x00dev, 0x14, 0); ++ if (test_bit(CAPABILITY_EXTERNAL_PA_TX1, &rt2x00dev->cap_flags)) { ++ p1_idx10 = rt2800_read_fft_accumulation(rt2x00dev, 0x0A); ++ } ++ ++ rt2x00_dbg(rt2x00dev, "IQ AGC %d %d\n", p0, p1); ++ ++ if (test_bit(CAPABILITY_EXTERNAL_PA_TX0, &rt2x00dev->cap_flags)) { ++ rt2x00_dbg(rt2x00dev, "IQ AGC IDX 10 %d %d\n", p0_idx10, p1_idx10); ++ if ((p0_idx10 > 7000*7000) || (p1_idx10 > 7000*7000)) { ++ if (vga_gain[ch_idx]!=0) ++ vga_gain[ch_idx] = vga_gain[ch_idx]-1; ++ break; ++ } ++ } ++ ++ if ((p0 > 2500*2500) || (p1 > 2500*2500)) { ++ break; ++ } ++ } ++ ++ if (vga_gain[ch_idx] > 18) ++ vga_gain[ch_idx] = 18; ++ rt2x00_dbg(rt2x00dev, "Used VGA %d %x\n",vga_gain[ch_idx], rfvga_gain_table[vga_gain[ch_idx]]); ++ ++ bbp = (ch_idx == 0) ? 0x29 : 0x47; ++ rt2800_bbp_write(rt2x00dev, 158, bbp); ++ rt2800_bbp_write(rt2x00dev, 159, 0x00); ++ ++ rt2800_iq_search(rt2x00dev, ch_idx, ger, per); ++ } ++ ++ rt2800_bbp_write(rt2x00dev, 23, 0x00); ++ rt2800_bbp_write(rt2x00dev, 24, 0x00); ++ rt2800_register_write(rt2x00dev, RF_CONTROL0, 0x04); ++ ++ rt2800_bbp_write(rt2x00dev, 158, 0x28); ++ bbp = ger[CHAIN_0] & 0x0F; ++ rt2800_bbp_write(rt2x00dev, 159, bbp); ++ ++ rt2800_bbp_write(rt2x00dev, 158, 0x29); ++ bbp = per[CHAIN_0] & 0x3F; ++ rt2800_bbp_write(rt2x00dev, 159, bbp); ++ ++ rt2800_bbp_write(rt2x00dev, 158, 0x46); ++ bbp = ger[CHAIN_1] & 0x0F; ++ rt2800_bbp_write(rt2x00dev, 159, bbp); ++ ++ rt2800_bbp_write(rt2x00dev, 158, 0x47); ++ bbp = per[CHAIN_1] & 0x3F; ++ rt2800_bbp_write(rt2x00dev, 159, bbp); ++ ++ if (test_bit(CAPABILITY_EXTERNAL_PA_TX0, &rt2x00dev->cap_flags)) { ++ rt2800_bbp_write(rt2x00dev, 1, bbpr1); ++ rt2800_bbp_write(rt2x00dev, 241, bbpr241); ++ rt2800_bbp_write(rt2x00dev, 242, bbpr242); ++ } ++ rt2800_bbp_write(rt2x00dev, 244, 0x00); ++ ++ rt2800_bbp_write(rt2x00dev, 158, 0x00); ++ rt2800_bbp_write(rt2x00dev, 159, 0x00); ++ rt2800_bbp_write(rt2x00dev, 158, 0xB0); ++ rt2800_bbp_write(rt2x00dev, 159, 0x00); ++ ++ rt2800_bbp_write(rt2x00dev, 30, bbpr30); ++ rt2800_rfcsr_write_bank(rt2x00dev, 0, 39, rfb0r39); ++ rt2800_rfcsr_write_bank(rt2x00dev, 0, 42, rfb0r42); ++ ++ if (test_bit(CAPABILITY_EXTERNAL_PA_TX0, &rt2x00dev->cap_flags)) { ++ rt2800_bbp_write(rt2x00dev, 4, bbpr4); ++ } ++ ++ rt2800_bbp_write(rt2x00dev, 21, 0x01); ++ udelay(1); ++ rt2800_bbp_write(rt2x00dev, 21, 0x00); ++ ++ rt2800_rf_configrecover(rt2x00dev, rf_store); ++ ++ rt2800_register_write(rt2x00dev, TX_PIN_CFG, macorg1); ++ rt2800_register_write(rt2x00dev, RF_CONTROL0, 0x00); ++ rt2800_register_write(rt2x00dev, RF_BYPASS0, 0x00); ++ rt2800_register_write(rt2x00dev, RF_CONTROL0, macorg2); ++ udelay(1); ++ rt2800_register_write(rt2x00dev, RF_BYPASS0, macorg3); ++ rt2800_register_write(rt2x00dev, RF_CONTROL3, macorg4); ++ rt2800_register_write(rt2x00dev, RF_BYPASS3, macorg5); ++ rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, savemacsysctrl); ++ rt2800_register_write(rt2x00dev, 0x13b8, mac13b8); ++ ++ rt2x00_info(rt2x00dev, "TX IQ Calibration Done!\n"); ++ ++ return; ++} ++ + static void rt2800_bbp_core_soft_reset(struct rt2x00_dev *rt2x00dev, + bool set_bw, bool is_ht40) + { +@@ -9672,6 +10609,7 @@ static void rt2800_init_rfcsr_6352(struc + rt2800_rxdcoc_calibration(rt2x00dev); + rt2800_bw_filter_calibration(rt2x00dev, true); + rt2800_bw_filter_calibration(rt2x00dev, false); ++ rt2800_loft_iq_calibration(rt2x00dev); + rt2800_rxiq_calibration(rt2x00dev); + } + +--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h ++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h +@@ -17,6 +17,16 @@ + #define WCID_START 33 + #define WCID_END 222 + #define STA_IDS_SIZE (WCID_END - WCID_START + 2) ++#define CHAIN_0 0x0 ++#define CHAIN_1 0x1 ++#define RF_ALC_NUM 6 ++#define CHAIN_NUM 2 ++ ++typedef struct rf_reg_pair { ++ u8 bank; ++ u8 reg; ++ u8 value; ++} rf_reg_pair; + + /* RT2800 driver data structure */ + struct rt2800_drv_data { diff --git a/feeds/ipq40xx/mac80211/patches/subsys/070-backports-add-netif_receive_skb_list.patch b/feeds/ipq40xx/mac80211/patches/subsys/070-backports-add-netif_receive_skb_list.patch new file mode 100644 index 000000000..b26a6bc38 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/subsys/070-backports-add-netif_receive_skb_list.patch @@ -0,0 +1,30 @@ +From: Felix Fietkau +Date: Fri, 14 Aug 2020 16:13:45 +0200 +Subject: [PATCH] backports: add netif_receive_skb_list + +It will be needed by pending mac80211 changes + +Signed-off-by: Felix Fietkau +--- + +--- a/backport-include/linux/netdevice.h ++++ b/backport-include/linux/netdevice.h +@@ -372,6 +372,18 @@ static inline int _bp_netdev_upper_dev_l + macro_dispatcher(netdev_upper_dev_link, __VA_ARGS__)(__VA_ARGS__) + #endif + ++#if LINUX_VERSION_IS_LESS(4,19,0) ++static inline void netif_receive_skb_list(struct list_head *head) ++{ ++ struct sk_buff *skb, *next; ++ ++ list_for_each_entry_safe(skb, next, head, list) { ++ skb_list_del_init(skb); ++ netif_receive_skb(skb); ++ } ++} ++#endif ++ + #if LINUX_VERSION_IS_LESS(5,0,0) + static inline int backport_dev_open(struct net_device *dev, struct netlink_ext_ack *extack) + { diff --git a/feeds/ipq40xx/mac80211/patches/subsys/071-backports-add-skb_list_del_init.patch b/feeds/ipq40xx/mac80211/patches/subsys/071-backports-add-skb_list_del_init.patch new file mode 100644 index 000000000..ee7e63498 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/subsys/071-backports-add-skb_list_del_init.patch @@ -0,0 +1,24 @@ +From: Felix Fietkau +Date: Fri, 14 Aug 2020 16:13:55 +0200 +Subject: [PATCH] backports: add skb_list_del_init + +It will be needed by pending mac80211 changes + +Signed-off-by: Felix Fietkau +--- + +--- a/backport-include/linux/skbuff.h ++++ b/backport-include/linux/skbuff.h +@@ -384,6 +384,12 @@ static inline void skb_mark_not_on_list( + { + skb->next = NULL; + } ++ ++static inline void skb_list_del_init(struct sk_buff *skb) ++{ ++ __list_del_entry(&skb->list); ++ skb_mark_not_on_list(skb); ++} + #endif /* 4.19.10 <= x < 4.20 */ + #endif + diff --git a/feeds/ipq40xx/mac80211/patches/subsys/100-remove-cryptoapi-dependencies.patch b/feeds/ipq40xx/mac80211/patches/subsys/100-remove-cryptoapi-dependencies.patch new file mode 100644 index 000000000..a94f9d8fd --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/subsys/100-remove-cryptoapi-dependencies.patch @@ -0,0 +1,698 @@ +--- a/net/mac80211/Makefile ++++ b/net/mac80211/Makefile +@@ -7,7 +7,6 @@ mac80211-y := \ + driver-ops.o \ + sta_info.o \ + wep.o \ +- aead_api.o \ + wpa.o \ + scan.o offchannel.o \ + ht.o agg-tx.o agg-rx.o \ +@@ -18,8 +17,8 @@ mac80211-y := \ + rate.o \ + michael.o \ + tkip.o \ ++ aes_ccm.o \ + aes_cmac.o \ +- aes_gmac.o \ + fils_aead.o \ + cfg.o \ + ethtool.o \ +--- a/net/mac80211/aead_api.c ++++ /dev/null +@@ -1,112 +0,0 @@ +-// SPDX-License-Identifier: GPL-2.0-only +-/* +- * Copyright 2003-2004, Instant802 Networks, Inc. +- * Copyright 2005-2006, Devicescape Software, Inc. +- * Copyright 2014-2015, Qualcomm Atheros, Inc. +- * +- * Rewrite: Copyright (C) 2013 Linaro Ltd +- */ +- +-#include +-#include +-#include +-#include +-#include +- +-#include "aead_api.h" +- +-int aead_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, size_t aad_len, +- u8 *data, size_t data_len, u8 *mic) +-{ +- size_t mic_len = crypto_aead_authsize(tfm); +- struct scatterlist sg[3]; +- struct aead_request *aead_req; +- int reqsize = sizeof(*aead_req) + crypto_aead_reqsize(tfm); +- u8 *__aad; +- +- aead_req = kzalloc(reqsize + aad_len, GFP_ATOMIC); +- if (!aead_req) +- return -ENOMEM; +- +- __aad = (u8 *)aead_req + reqsize; +- memcpy(__aad, aad, aad_len); +- +- sg_init_table(sg, 3); +- sg_set_buf(&sg[0], __aad, aad_len); +- sg_set_buf(&sg[1], data, data_len); +- sg_set_buf(&sg[2], mic, mic_len); +- +- aead_request_set_tfm(aead_req, tfm); +- aead_request_set_crypt(aead_req, sg, sg, data_len, b_0); +- aead_request_set_ad(aead_req, sg[0].length); +- +- crypto_aead_encrypt(aead_req); +- kzfree(aead_req); +- +- return 0; +-} +- +-int aead_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, size_t aad_len, +- u8 *data, size_t data_len, u8 *mic) +-{ +- size_t mic_len = crypto_aead_authsize(tfm); +- struct scatterlist sg[3]; +- struct aead_request *aead_req; +- int reqsize = sizeof(*aead_req) + crypto_aead_reqsize(tfm); +- u8 *__aad; +- int err; +- +- if (data_len == 0) +- return -EINVAL; +- +- aead_req = kzalloc(reqsize + aad_len, GFP_ATOMIC); +- if (!aead_req) +- return -ENOMEM; +- +- __aad = (u8 *)aead_req + reqsize; +- memcpy(__aad, aad, aad_len); +- +- sg_init_table(sg, 3); +- sg_set_buf(&sg[0], __aad, aad_len); +- sg_set_buf(&sg[1], data, data_len); +- sg_set_buf(&sg[2], mic, mic_len); +- +- aead_request_set_tfm(aead_req, tfm); +- aead_request_set_crypt(aead_req, sg, sg, data_len + mic_len, b_0); +- aead_request_set_ad(aead_req, sg[0].length); +- +- err = crypto_aead_decrypt(aead_req); +- kzfree(aead_req); +- +- return err; +-} +- +-struct crypto_aead * +-aead_key_setup_encrypt(const char *alg, const u8 key[], +- size_t key_len, size_t mic_len) +-{ +- struct crypto_aead *tfm; +- int err; +- +- tfm = crypto_alloc_aead(alg, 0, CRYPTO_ALG_ASYNC); +- if (IS_ERR(tfm)) +- return tfm; +- +- err = crypto_aead_setkey(tfm, key, key_len); +- if (err) +- goto free_aead; +- err = crypto_aead_setauthsize(tfm, mic_len); +- if (err) +- goto free_aead; +- +- return tfm; +- +-free_aead: +- crypto_free_aead(tfm); +- return ERR_PTR(err); +-} +- +-void aead_key_free(struct crypto_aead *tfm) +-{ +- crypto_free_aead(tfm); +-} +--- a/net/mac80211/aead_api.h ++++ /dev/null +@@ -1,23 +0,0 @@ +-/* SPDX-License-Identifier: GPL-2.0-only */ +- +-#ifndef _AEAD_API_H +-#define _AEAD_API_H +- +-#include +-#include +- +-struct crypto_aead * +-aead_key_setup_encrypt(const char *alg, const u8 key[], +- size_t key_len, size_t mic_len); +- +-int aead_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, +- size_t aad_len, u8 *data, +- size_t data_len, u8 *mic); +- +-int aead_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, +- size_t aad_len, u8 *data, +- size_t data_len, u8 *mic); +- +-void aead_key_free(struct crypto_aead *tfm); +- +-#endif /* _AEAD_API_H */ +--- a/net/mac80211/aes_ccm.h ++++ b/net/mac80211/aes_ccm.h +@@ -7,39 +7,17 @@ + #ifndef AES_CCM_H + #define AES_CCM_H + +-#include "aead_api.h" ++#include + +-#define CCM_AAD_LEN 32 +- +-static inline struct crypto_aead * +-ieee80211_aes_key_setup_encrypt(const u8 key[], size_t key_len, size_t mic_len) +-{ +- return aead_key_setup_encrypt("ccm(aes)", key, key_len, mic_len); +-} +- +-static inline int +-ieee80211_aes_ccm_encrypt(struct crypto_aead *tfm, +- u8 *b_0, u8 *aad, u8 *data, +- size_t data_len, u8 *mic) +-{ +- return aead_encrypt(tfm, b_0, aad + 2, +- be16_to_cpup((__be16 *)aad), +- data, data_len, mic); +-} +- +-static inline int +-ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, +- u8 *b_0, u8 *aad, u8 *data, +- size_t data_len, u8 *mic) +-{ +- return aead_decrypt(tfm, b_0, aad + 2, +- be16_to_cpup((__be16 *)aad), +- data, data_len, mic); +-} +- +-static inline void ieee80211_aes_key_free(struct crypto_aead *tfm) +-{ +- return aead_key_free(tfm); +-} ++struct crypto_cipher *ieee80211_aes_key_setup_encrypt(const u8 key[], ++ size_t key_len, ++ size_t mic_len); ++void ieee80211_aes_ccm_encrypt(struct crypto_cipher *tfm, u8 *b_0, u8 *aad, ++ u8 *data, size_t data_len, u8 *mic, ++ size_t mic_len); ++int ieee80211_aes_ccm_decrypt(struct crypto_cipher *tfm, u8 *b_0, u8 *aad, ++ u8 *data, size_t data_len, u8 *mic, ++ size_t mic_len); ++void ieee80211_aes_key_free(struct crypto_cipher *tfm); + + #endif /* AES_CCM_H */ +--- /dev/null ++++ b/net/mac80211/aes_gcm.c +@@ -0,0 +1,109 @@ ++/* ++ * Copyright 2014-2015, Qualcomm Atheros, Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include "key.h" ++#include "aes_gcm.h" ++ ++int ieee80211_aes_gcm_encrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad, ++ u8 *data, size_t data_len, u8 *mic) ++{ ++ struct scatterlist sg[3]; ++ struct aead_request *aead_req; ++ int reqsize = sizeof(*aead_req) + crypto_aead_reqsize(tfm); ++ u8 *__aad; ++ ++ aead_req = kzalloc(reqsize + GCM_AAD_LEN, GFP_ATOMIC); ++ if (!aead_req) ++ return -ENOMEM; ++ ++ __aad = (u8 *)aead_req + reqsize; ++ memcpy(__aad, aad, GCM_AAD_LEN); ++ ++ sg_init_table(sg, 3); ++ sg_set_buf(&sg[0], &__aad[2], be16_to_cpup((__be16 *)__aad)); ++ sg_set_buf(&sg[1], data, data_len); ++ sg_set_buf(&sg[2], mic, IEEE80211_GCMP_MIC_LEN); ++ ++ aead_request_set_tfm(aead_req, tfm); ++ aead_request_set_crypt(aead_req, sg, sg, data_len, j_0); ++ aead_request_set_ad(aead_req, sg[0].length); ++ ++ crypto_aead_encrypt(aead_req); ++ kzfree(aead_req); ++ return 0; ++} ++ ++int ieee80211_aes_gcm_decrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad, ++ u8 *data, size_t data_len, u8 *mic) ++{ ++ struct scatterlist sg[3]; ++ struct aead_request *aead_req; ++ int reqsize = sizeof(*aead_req) + crypto_aead_reqsize(tfm); ++ u8 *__aad; ++ int err; ++ ++ if (data_len == 0) ++ return -EINVAL; ++ ++ aead_req = kzalloc(reqsize + GCM_AAD_LEN, GFP_ATOMIC); ++ if (!aead_req) ++ return -ENOMEM; ++ ++ __aad = (u8 *)aead_req + reqsize; ++ memcpy(__aad, aad, GCM_AAD_LEN); ++ ++ sg_init_table(sg, 3); ++ sg_set_buf(&sg[0], &__aad[2], be16_to_cpup((__be16 *)__aad)); ++ sg_set_buf(&sg[1], data, data_len); ++ sg_set_buf(&sg[2], mic, IEEE80211_GCMP_MIC_LEN); ++ ++ aead_request_set_tfm(aead_req, tfm); ++ aead_request_set_crypt(aead_req, sg, sg, ++ data_len + IEEE80211_GCMP_MIC_LEN, j_0); ++ aead_request_set_ad(aead_req, sg[0].length); ++ ++ err = crypto_aead_decrypt(aead_req); ++ kzfree(aead_req); ++ ++ return err; ++} ++ ++struct crypto_aead *ieee80211_aes_gcm_key_setup_encrypt(const u8 key[], ++ size_t key_len) ++{ ++ struct crypto_aead *tfm; ++ int err; ++ ++ tfm = crypto_alloc_aead("gcm(aes)", 0, CRYPTO_ALG_ASYNC); ++ if (IS_ERR(tfm)) ++ return tfm; ++ ++ err = crypto_aead_setkey(tfm, key, key_len); ++ if (err) ++ goto free_aead; ++ err = crypto_aead_setauthsize(tfm, IEEE80211_GCMP_MIC_LEN); ++ if (err) ++ goto free_aead; ++ ++ return tfm; ++ ++free_aead: ++ crypto_free_aead(tfm); ++ return ERR_PTR(err); ++} ++ ++void ieee80211_aes_gcm_key_free(struct crypto_aead *tfm) ++{ ++ crypto_free_aead(tfm); ++} +--- a/net/mac80211/aes_gcm.h ++++ b/net/mac80211/aes_gcm.h +@@ -6,38 +6,30 @@ + #ifndef AES_GCM_H + #define AES_GCM_H + +-#include "aead_api.h" ++#include + +-#define GCM_AAD_LEN 32 +- +-static inline int ieee80211_aes_gcm_encrypt(struct crypto_aead *tfm, +- u8 *j_0, u8 *aad, u8 *data, +- size_t data_len, u8 *mic) ++static inline void ++ieee80211_aes_gcm_encrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad, ++ u8 *data, size_t data_len, u8 *mic) + { +- return aead_encrypt(tfm, j_0, aad + 2, +- be16_to_cpup((__be16 *)aad), +- data, data_len, mic); + } + +-static inline int ieee80211_aes_gcm_decrypt(struct crypto_aead *tfm, +- u8 *j_0, u8 *aad, u8 *data, +- size_t data_len, u8 *mic) ++static inline int ++ieee80211_aes_gcm_decrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad, ++ u8 *data, size_t data_len, u8 *mic) + { +- return aead_decrypt(tfm, j_0, aad + 2, +- be16_to_cpup((__be16 *)aad), +- data, data_len, mic); ++ return -EOPNOTSUPP; + } + + static inline struct crypto_aead * + ieee80211_aes_gcm_key_setup_encrypt(const u8 key[], size_t key_len) + { +- return aead_key_setup_encrypt("gcm(aes)", key, +- key_len, IEEE80211_GCMP_MIC_LEN); ++ return NULL; + } + +-static inline void ieee80211_aes_gcm_key_free(struct crypto_aead *tfm) ++static inline void ++ieee80211_aes_gcm_key_free(struct crypto_aead *tfm) + { +- return aead_key_free(tfm); + } + + #endif /* AES_GCM_H */ +--- a/net/mac80211/wpa.c ++++ b/net/mac80211/wpa.c +@@ -311,7 +311,8 @@ ieee80211_crypto_tkip_decrypt(struct iee + } + + +-static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *b_0, u8 *aad) ++static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *b_0, u8 *aad, ++ u16 data_len) + { + __le16 mask_fc; + int a4_included, mgmt; +@@ -341,14 +342,8 @@ static void ccmp_special_blocks(struct s + else + qos_tid = 0; + +- /* In CCM, the initial vectors (IV) used for CTR mode encryption and CBC +- * mode authentication are not allowed to collide, yet both are derived +- * from this vector b_0. We only set L := 1 here to indicate that the +- * data size can be represented in (L+1) bytes. The CCM layer will take +- * care of storing the data length in the top (L+1) bytes and setting +- * and clearing the other bits as is required to derive the two IVs. +- */ +- b_0[0] = 0x1; ++ /* First block, b_0 */ ++ b_0[0] = 0x59; /* flags: Adata: 1, M: 011, L: 001 */ + + /* Nonce: Nonce Flags | A2 | PN + * Nonce Flags: Priority (b0..b3) | Management (b4) | Reserved (b5..b7) +@@ -356,6 +351,8 @@ static void ccmp_special_blocks(struct s + b_0[1] = qos_tid | (mgmt << 4); + memcpy(&b_0[2], hdr->addr2, ETH_ALEN); + memcpy(&b_0[8], pn, IEEE80211_CCMP_PN_LEN); ++ /* l(m) */ ++ put_unaligned_be16(data_len, &b_0[14]); + + /* AAD (extra authenticate-only data) / masked 802.11 header + * FC | A1 | A2 | A3 | SC | [A4] | [QC] */ +@@ -412,7 +409,7 @@ static int ccmp_encrypt_skb(struct ieee8 + u8 *pos; + u8 pn[6]; + u64 pn64; +- u8 aad[CCM_AAD_LEN]; ++ u8 aad[2 * AES_BLOCK_SIZE]; + u8 b_0[AES_BLOCK_SIZE]; + + if (info->control.hw_key && +@@ -467,9 +464,11 @@ static int ccmp_encrypt_skb(struct ieee8 + return 0; + + pos += IEEE80211_CCMP_HDR_LEN; +- ccmp_special_blocks(skb, pn, b_0, aad); +- return ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, b_0, aad, pos, len, +- skb_put(skb, mic_len)); ++ ccmp_special_blocks(skb, pn, b_0, aad, len); ++ ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, b_0, aad, pos, len, ++ skb_put(skb, mic_len), mic_len); ++ ++ return 0; + } + + +@@ -542,13 +541,13 @@ ieee80211_crypto_ccmp_decrypt(struct iee + u8 aad[2 * AES_BLOCK_SIZE]; + u8 b_0[AES_BLOCK_SIZE]; + /* hardware didn't decrypt/verify MIC */ +- ccmp_special_blocks(skb, pn, b_0, aad); ++ ccmp_special_blocks(skb, pn, b_0, aad, data_len); + + if (ieee80211_aes_ccm_decrypt( + key->u.ccmp.tfm, b_0, aad, + skb->data + hdrlen + IEEE80211_CCMP_HDR_LEN, + data_len, +- skb->data + skb->len - mic_len)) ++ skb->data + skb->len - mic_len, mic_len)) + return RX_DROP_UNUSABLE; + } + +@@ -643,7 +642,7 @@ static int gcmp_encrypt_skb(struct ieee8 + u8 *pos; + u8 pn[6]; + u64 pn64; +- u8 aad[GCM_AAD_LEN]; ++ u8 aad[2 * AES_BLOCK_SIZE]; + u8 j_0[AES_BLOCK_SIZE]; + + if (info->control.hw_key && +@@ -700,8 +699,10 @@ static int gcmp_encrypt_skb(struct ieee8 + + pos += IEEE80211_GCMP_HDR_LEN; + gcmp_special_blocks(skb, pn, j_0, aad); +- return ieee80211_aes_gcm_encrypt(key->u.gcmp.tfm, j_0, aad, pos, len, +- skb_put(skb, IEEE80211_GCMP_MIC_LEN)); ++ ieee80211_aes_gcm_encrypt(key->u.gcmp.tfm, j_0, aad, pos, len, ++ skb_put(skb, IEEE80211_GCMP_MIC_LEN)); ++ ++ return 0; + } + + ieee80211_tx_result +@@ -1128,9 +1129,9 @@ ieee80211_crypto_aes_gmac_encrypt(struct + struct ieee80211_key *key = tx->key; + struct ieee80211_mmie_16 *mmie; + struct ieee80211_hdr *hdr; +- u8 aad[GMAC_AAD_LEN]; ++ u8 aad[20]; + u64 pn64; +- u8 nonce[GMAC_NONCE_LEN]; ++ u8 nonce[12]; + + if (WARN_ON(skb_queue_len(&tx->skbs) != 1)) + return TX_DROP; +@@ -1176,7 +1177,7 @@ ieee80211_crypto_aes_gmac_decrypt(struct + struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); + struct ieee80211_key *key = rx->key; + struct ieee80211_mmie_16 *mmie; +- u8 aad[GMAC_AAD_LEN], *mic, ipn[6], nonce[GMAC_NONCE_LEN]; ++ u8 aad[20], *mic, ipn[6], nonce[12]; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + + if (!ieee80211_is_mgmt(hdr->frame_control)) +--- /dev/null ++++ b/net/mac80211/aes_ccm.c +@@ -0,0 +1,144 @@ ++/* ++ * Copyright 2003-2004, Instant802 Networks, Inc. ++ * Copyright 2005-2006, Devicescape Software, Inc. ++ * ++ * Rewrite: Copyright (C) 2013 Linaro Ltd ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include "key.h" ++#include "aes_ccm.h" ++ ++static void aes_ccm_prepare(struct crypto_cipher *tfm, u8 *b_0, u8 *aad, u8 *s_0, ++ u8 *a, u8 *b) ++{ ++ int i; ++ ++ crypto_cipher_encrypt_one(tfm, b, b_0); ++ ++ /* Extra Authenticate-only data (always two AES blocks) */ ++ for (i = 0; i < AES_BLOCK_SIZE; i++) ++ aad[i] ^= b[i]; ++ crypto_cipher_encrypt_one(tfm, b, aad); ++ ++ aad += AES_BLOCK_SIZE; ++ ++ for (i = 0; i < AES_BLOCK_SIZE; i++) ++ aad[i] ^= b[i]; ++ crypto_cipher_encrypt_one(tfm, a, aad); ++ ++ /* Mask out bits from auth-only-b_0 */ ++ b_0[0] &= 0x07; ++ ++ /* S_0 is used to encrypt T (= MIC) */ ++ b_0[14] = 0; ++ b_0[15] = 0; ++ crypto_cipher_encrypt_one(tfm, s_0, b_0); ++} ++ ++ ++void ieee80211_aes_ccm_encrypt(struct crypto_cipher *tfm, u8 *b_0, u8 *aad, ++ u8 *data, size_t data_len, u8 *mic, ++ size_t mic_len) ++{ ++ int i, j, last_len, num_blocks; ++ u8 b[AES_BLOCK_SIZE]; ++ u8 s_0[AES_BLOCK_SIZE]; ++ u8 e[AES_BLOCK_SIZE]; ++ u8 *pos, *cpos; ++ ++ num_blocks = DIV_ROUND_UP(data_len, AES_BLOCK_SIZE); ++ last_len = data_len % AES_BLOCK_SIZE; ++ aes_ccm_prepare(tfm, b_0, aad, s_0, b, b); ++ ++ /* Process payload blocks */ ++ pos = data; ++ cpos = data; ++ for (j = 1; j <= num_blocks; j++) { ++ int blen = (j == num_blocks && last_len) ? ++ last_len : AES_BLOCK_SIZE; ++ ++ /* Authentication followed by encryption */ ++ for (i = 0; i < blen; i++) ++ b[i] ^= pos[i]; ++ crypto_cipher_encrypt_one(tfm, b, b); ++ ++ b_0[14] = (j >> 8) & 0xff; ++ b_0[15] = j & 0xff; ++ crypto_cipher_encrypt_one(tfm, e, b_0); ++ for (i = 0; i < blen; i++) ++ *cpos++ = *pos++ ^ e[i]; ++ } ++ ++ for (i = 0; i < mic_len; i++) ++ mic[i] = b[i] ^ s_0[i]; ++} ++ ++int ieee80211_aes_ccm_decrypt(struct crypto_cipher *tfm, u8 *b_0, u8 *aad, ++ u8 *data, size_t data_len, u8 *mic, ++ size_t mic_len) ++{ ++ int i, j, last_len, num_blocks; ++ u8 *pos, *cpos; ++ u8 a[AES_BLOCK_SIZE]; ++ u8 b[AES_BLOCK_SIZE]; ++ u8 s_0[AES_BLOCK_SIZE]; ++ ++ num_blocks = DIV_ROUND_UP(data_len, AES_BLOCK_SIZE); ++ last_len = data_len % AES_BLOCK_SIZE; ++ aes_ccm_prepare(tfm, b_0, aad, s_0, a, b); ++ ++ /* Process payload blocks */ ++ cpos = data; ++ pos = data; ++ for (j = 1; j <= num_blocks; j++) { ++ int blen = (j == num_blocks && last_len) ? ++ last_len : AES_BLOCK_SIZE; ++ ++ /* Decryption followed by authentication */ ++ b_0[14] = (j >> 8) & 0xff; ++ b_0[15] = j & 0xff; ++ crypto_cipher_encrypt_one(tfm, b, b_0); ++ for (i = 0; i < blen; i++) { ++ *pos = *cpos++ ^ b[i]; ++ a[i] ^= *pos++; ++ } ++ crypto_cipher_encrypt_one(tfm, a, a); ++ } ++ ++ for (i = 0; i < mic_len; i++) { ++ if ((mic[i] ^ s_0[i]) != a[i]) ++ return -1; ++ } ++ ++ return 0; ++} ++ ++struct crypto_cipher *ieee80211_aes_key_setup_encrypt(const u8 key[], ++ size_t key_len, ++ size_t mic_len) ++{ ++ struct crypto_cipher *tfm; ++ ++ tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC); ++ if (!IS_ERR(tfm)) ++ crypto_cipher_setkey(tfm, key, key_len); ++ ++ return tfm; ++} ++ ++ ++void ieee80211_aes_key_free(struct crypto_cipher *tfm) ++{ ++ crypto_free_cipher(tfm); ++} +--- a/net/mac80211/Kconfig ++++ b/net/mac80211/Kconfig +@@ -6,8 +6,6 @@ config MAC80211 + depends on CRYPTO + select BPAUTO_CRYPTO_LIB_ARC4 + depends on CRYPTO_AES +- depends on CRYPTO_CCM +- depends on CRYPTO_GCM + depends on CRYPTO_CMAC + depends on CRC32 + help +--- a/net/mac80211/aes_gmac.h ++++ b/net/mac80211/aes_gmac.h +@@ -12,10 +12,22 @@ + #define GMAC_MIC_LEN 16 + #define GMAC_NONCE_LEN 12 + +-struct crypto_aead *ieee80211_aes_gmac_key_setup(const u8 key[], +- size_t key_len); +-int ieee80211_aes_gmac(struct crypto_aead *tfm, const u8 *aad, u8 *nonce, +- const u8 *data, size_t data_len, u8 *mic); +-void ieee80211_aes_gmac_key_free(struct crypto_aead *tfm); ++static inline struct crypto_aead * ++ieee80211_aes_gmac_key_setup(const u8 key[], size_t key_len) ++{ ++ return NULL; ++} ++ ++static inline int ++ieee80211_aes_gmac(struct crypto_aead *tfm, const u8 *aad, u8 *nonce, ++ const u8 *data, size_t data_len, u8 *mic) ++{ ++ return -EOPNOTSUPP; ++} ++ ++static inline void ++ieee80211_aes_gmac_key_free(struct crypto_aead *tfm) ++{ ++} + + #endif /* AES_GMAC_H */ +--- a/net/mac80211/key.h ++++ b/net/mac80211/key.h +@@ -89,7 +89,7 @@ struct ieee80211_key { + * Management frames. + */ + u8 rx_pn[IEEE80211_NUM_TIDS + 1][IEEE80211_CCMP_PN_LEN]; +- struct crypto_aead *tfm; ++ struct crypto_cipher *tfm; + u32 replays; /* dot11RSNAStatsCCMPReplays */ + } ccmp; + struct { diff --git a/feeds/ipq40xx/mac80211/patches/subsys/110-mac80211_keep_keys_on_stop_ap.patch b/feeds/ipq40xx/mac80211/patches/subsys/110-mac80211_keep_keys_on_stop_ap.patch new file mode 100644 index 000000000..e56055caf --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/subsys/110-mac80211_keep_keys_on_stop_ap.patch @@ -0,0 +1,12 @@ +Used for AP+STA support in OpenWrt - preserve AP mode keys across STA reconnects + +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -1197,7 +1197,6 @@ static int ieee80211_stop_ap(struct wiph + sdata->vif.bss_conf.ftmr_params = NULL; + + __sta_info_flush(sdata, true); +- ieee80211_free_keys(sdata, true); + + sdata->vif.bss_conf.enable_beacon = false; + sdata->beacon_rate_set = false; diff --git a/feeds/ipq40xx/mac80211/patches/subsys/120-cfg80211_allow_perm_addr_change.patch b/feeds/ipq40xx/mac80211/patches/subsys/120-cfg80211_allow_perm_addr_change.patch new file mode 100644 index 000000000..172e5b04f --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/subsys/120-cfg80211_allow_perm_addr_change.patch @@ -0,0 +1,43 @@ +--- a/net/wireless/sysfs.c ++++ b/net/wireless/sysfs.c +@@ -23,18 +23,35 @@ static inline struct cfg80211_registered + return container_of(dev, struct cfg80211_registered_device, wiphy.dev); + } + +-#define SHOW_FMT(name, fmt, member) \ ++#define SHOW_FMT(name, fmt, member, mode) \ + static ssize_t name ## _show(struct device *dev, \ + struct device_attribute *attr, \ + char *buf) \ + { \ + return sprintf(buf, fmt "\n", dev_to_rdev(dev)->member); \ + } \ +-static DEVICE_ATTR_RO(name) ++static DEVICE_ATTR_##mode(name) + +-SHOW_FMT(index, "%d", wiphy_idx); +-SHOW_FMT(macaddress, "%pM", wiphy.perm_addr); +-SHOW_FMT(address_mask, "%pM", wiphy.addr_mask); ++static ssize_t macaddress_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t len) ++{ ++ u8 mac[ETH_ALEN]; ++ ++ if (!mac_pton(buf, mac)) ++ return -EINVAL; ++ ++ if (buf[3 * ETH_ALEN - 1] && buf[3 * ETH_ALEN - 1] != '\n') ++ return -EINVAL; ++ ++ memcpy(dev_to_rdev(dev)->wiphy.perm_addr, mac, ETH_ALEN); ++ ++ return strnlen(buf, len); ++} ++ ++SHOW_FMT(index, "%d", wiphy_idx, RO); ++SHOW_FMT(macaddress, "%pM", wiphy.perm_addr, RW); ++SHOW_FMT(address_mask, "%pM", wiphy.addr_mask, RO); + + static ssize_t name_show(struct device *dev, + struct device_attribute *attr, diff --git a/feeds/ipq40xx/mac80211/patches/subsys/131-Revert-mac80211-aes-cmac-switch-to-shash-CMAC-driver.patch b/feeds/ipq40xx/mac80211/patches/subsys/131-Revert-mac80211-aes-cmac-switch-to-shash-CMAC-driver.patch new file mode 100644 index 000000000..c3bf7ccc7 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/subsys/131-Revert-mac80211-aes-cmac-switch-to-shash-CMAC-driver.patch @@ -0,0 +1,230 @@ +From: Felix Fietkau +Date: Sat, 7 Oct 2017 09:37:28 +0200 +Subject: [PATCH] Revert "mac80211: aes-cmac: switch to shash CMAC + driver" + +This reverts commit 26717828b75dd5c46e97f7f4a9b937d038bb2852. +Reduces mac80211 dependencies for LEDE + +Signed-off-by: Felix Fietkau +--- + +--- a/net/mac80211/aes_cmac.c ++++ b/net/mac80211/aes_cmac.c +@@ -19,67 +19,151 @@ + #define CMAC_TLEN_256 16 /* CMAC TLen = 128 bits (16 octets) */ + #define AAD_LEN 20 + +-static const u8 zero[CMAC_TLEN_256]; + +-void ieee80211_aes_cmac(struct crypto_shash *tfm, const u8 *aad, ++void gf_mulx(u8 *pad) ++{ ++ int i, carry; ++ ++ carry = pad[0] & 0x80; ++ for (i = 0; i < AES_BLOCK_SIZE - 1; i++) ++ pad[i] = (pad[i] << 1) | (pad[i + 1] >> 7); ++ pad[AES_BLOCK_SIZE - 1] <<= 1; ++ if (carry) ++ pad[AES_BLOCK_SIZE - 1] ^= 0x87; ++} ++ ++void aes_cmac_vector(struct crypto_cipher *tfm, size_t num_elem, ++ const u8 *addr[], const size_t *len, u8 *mac, ++ size_t mac_len) ++{ ++ u8 cbc[AES_BLOCK_SIZE], pad[AES_BLOCK_SIZE]; ++ const u8 *pos, *end; ++ size_t i, e, left, total_len; ++ ++ memset(cbc, 0, AES_BLOCK_SIZE); ++ ++ total_len = 0; ++ for (e = 0; e < num_elem; e++) ++ total_len += len[e]; ++ left = total_len; ++ ++ e = 0; ++ pos = addr[0]; ++ end = pos + len[0]; ++ ++ while (left >= AES_BLOCK_SIZE) { ++ for (i = 0; i < AES_BLOCK_SIZE; i++) { ++ cbc[i] ^= *pos++; ++ if (pos >= end) { ++ e++; ++ pos = addr[e]; ++ end = pos + len[e]; ++ } ++ } ++ if (left > AES_BLOCK_SIZE) ++ crypto_cipher_encrypt_one(tfm, cbc, cbc); ++ left -= AES_BLOCK_SIZE; ++ } ++ ++ memset(pad, 0, AES_BLOCK_SIZE); ++ crypto_cipher_encrypt_one(tfm, pad, pad); ++ gf_mulx(pad); ++ ++ if (left || total_len == 0) { ++ for (i = 0; i < left; i++) { ++ cbc[i] ^= *pos++; ++ if (pos >= end) { ++ e++; ++ pos = addr[e]; ++ end = pos + len[e]; ++ } ++ } ++ cbc[left] ^= 0x80; ++ gf_mulx(pad); ++ } ++ ++ for (i = 0; i < AES_BLOCK_SIZE; i++) ++ pad[i] ^= cbc[i]; ++ crypto_cipher_encrypt_one(tfm, pad, pad); ++ memcpy(mac, pad, mac_len); ++} ++ ++ ++void ieee80211_aes_cmac(struct crypto_cipher *tfm, const u8 *aad, + const u8 *data, size_t data_len, u8 *mic) + { +- SHASH_DESC_ON_STACK(desc, tfm); +- u8 out[AES_BLOCK_SIZE]; ++ const u8 *addr[4]; ++ size_t len[4]; ++ u8 zero[CMAC_TLEN]; + const __le16 *fc; + +- desc->tfm = tfm; +- +- crypto_shash_init(desc); +- crypto_shash_update(desc, aad, AAD_LEN); ++ memset(zero, 0, CMAC_TLEN); ++ addr[0] = aad; ++ len[0] = AAD_LEN; + fc = (const __le16 *)aad; + if (ieee80211_is_beacon(*fc)) { + /* mask Timestamp field to zero */ +- crypto_shash_update(desc, zero, 8); +- crypto_shash_update(desc, data + 8, data_len - 8 - CMAC_TLEN); ++ addr[1] = zero; ++ len[1] = 8; ++ addr[2] = data + 8; ++ len[2] = data_len - 8 - CMAC_TLEN; ++ addr[3] = zero; ++ len[3] = CMAC_TLEN; ++ aes_cmac_vector(tfm, 4, addr, len, mic, CMAC_TLEN); + } else { +- crypto_shash_update(desc, data, data_len - CMAC_TLEN); ++ addr[1] = data; ++ len[1] = data_len - CMAC_TLEN; ++ addr[2] = zero; ++ len[2] = CMAC_TLEN; ++ aes_cmac_vector(tfm, 3, addr, len, mic, CMAC_TLEN); + } +- crypto_shash_finup(desc, zero, CMAC_TLEN, out); +- +- memcpy(mic, out, CMAC_TLEN); + } + +-void ieee80211_aes_cmac_256(struct crypto_shash *tfm, const u8 *aad, ++void ieee80211_aes_cmac_256(struct crypto_cipher *tfm, const u8 *aad, + const u8 *data, size_t data_len, u8 *mic) + { +- SHASH_DESC_ON_STACK(desc, tfm); ++ const u8 *addr[4]; ++ size_t len[4]; ++ u8 zero[CMAC_TLEN_256]; + const __le16 *fc; + +- desc->tfm = tfm; +- +- crypto_shash_init(desc); +- crypto_shash_update(desc, aad, AAD_LEN); ++ memset(zero, 0, CMAC_TLEN_256); ++ addr[0] = aad; ++ len[0] = AAD_LEN; ++ addr[1] = data; + fc = (const __le16 *)aad; + if (ieee80211_is_beacon(*fc)) { + /* mask Timestamp field to zero */ +- crypto_shash_update(desc, zero, 8); +- crypto_shash_update(desc, data + 8, +- data_len - 8 - CMAC_TLEN_256); ++ addr[1] = zero; ++ len[1] = 8; ++ addr[2] = data + 8; ++ len[2] = data_len - 8 - CMAC_TLEN_256; ++ addr[3] = zero; ++ len[3] = CMAC_TLEN_256; ++ aes_cmac_vector(tfm, 4, addr, len, mic, CMAC_TLEN_256); + } else { +- crypto_shash_update(desc, data, data_len - CMAC_TLEN_256); ++ addr[1] = data; ++ len[1] = data_len - CMAC_TLEN_256; ++ addr[2] = zero; ++ len[2] = CMAC_TLEN_256; ++ aes_cmac_vector(tfm, 3, addr, len, mic, CMAC_TLEN_256); + } +- crypto_shash_finup(desc, zero, CMAC_TLEN_256, mic); + } + +-struct crypto_shash *ieee80211_aes_cmac_key_setup(const u8 key[], +- size_t key_len) ++struct crypto_cipher *ieee80211_aes_cmac_key_setup(const u8 key[], ++ size_t key_len) + { +- struct crypto_shash *tfm; ++ struct crypto_cipher *tfm; + +- tfm = crypto_alloc_shash("cmac(aes)", 0, 0); ++ tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC); + if (!IS_ERR(tfm)) +- crypto_shash_setkey(tfm, key, key_len); ++ crypto_cipher_setkey(tfm, key, key_len); + + return tfm; + } + +-void ieee80211_aes_cmac_key_free(struct crypto_shash *tfm) ++ ++void ieee80211_aes_cmac_key_free(struct crypto_cipher *tfm) + { +- crypto_free_shash(tfm); ++ crypto_free_cipher(tfm); + } +--- a/net/mac80211/aes_cmac.h ++++ b/net/mac80211/aes_cmac.h +@@ -7,14 +7,13 @@ + #define AES_CMAC_H + + #include +-#include + +-struct crypto_shash *ieee80211_aes_cmac_key_setup(const u8 key[], +- size_t key_len); +-void ieee80211_aes_cmac(struct crypto_shash *tfm, const u8 *aad, ++struct crypto_cipher *ieee80211_aes_cmac_key_setup(const u8 key[], ++ size_t key_len); ++void ieee80211_aes_cmac(struct crypto_cipher *tfm, const u8 *aad, + const u8 *data, size_t data_len, u8 *mic); +-void ieee80211_aes_cmac_256(struct crypto_shash *tfm, const u8 *aad, ++void ieee80211_aes_cmac_256(struct crypto_cipher *tfm, const u8 *aad, + const u8 *data, size_t data_len, u8 *mic); +-void ieee80211_aes_cmac_key_free(struct crypto_shash *tfm); ++void ieee80211_aes_cmac_key_free(struct crypto_cipher *tfm); + + #endif /* AES_CMAC_H */ +--- a/net/mac80211/key.h ++++ b/net/mac80211/key.h +@@ -94,7 +94,7 @@ struct ieee80211_key { + } ccmp; + struct { + u8 rx_pn[IEEE80211_CMAC_PN_LEN]; +- struct crypto_shash *tfm; ++ struct crypto_cipher *tfm; + u32 replays; /* dot11RSNAStatsCMACReplays */ + u32 icverrors; /* dot11RSNAStatsCMACICVErrors */ + } aes_cmac; diff --git a/feeds/ipq40xx/mac80211/patches/subsys/132-mac80211-remove-cmac-dependency.patch b/feeds/ipq40xx/mac80211/patches/subsys/132-mac80211-remove-cmac-dependency.patch new file mode 100644 index 000000000..df67d2f10 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/subsys/132-mac80211-remove-cmac-dependency.patch @@ -0,0 +1,10 @@ +--- a/net/mac80211/Kconfig ++++ b/net/mac80211/Kconfig +@@ -6,7 +6,6 @@ config MAC80211 + depends on CRYPTO + select BPAUTO_CRYPTO_LIB_ARC4 + depends on CRYPTO_AES +- depends on CRYPTO_CMAC + depends on CRC32 + help + This option enables the hardware independent IEEE 802.11 diff --git a/feeds/ipq40xx/mac80211/patches/subsys/150-disable_addr_notifier.patch b/feeds/ipq40xx/mac80211/patches/subsys/150-disable_addr_notifier.patch new file mode 100644 index 000000000..8a717558a --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/subsys/150-disable_addr_notifier.patch @@ -0,0 +1,67 @@ +--- a/net/mac80211/main.c ++++ b/net/mac80211/main.c +@@ -321,7 +321,7 @@ void ieee80211_restart_hw(struct ieee802 + } + EXPORT_SYMBOL(ieee80211_restart_hw); + +-#ifdef CONFIG_INET ++#ifdef __disabled__CONFIG_INET + static int ieee80211_ifa_changed(struct notifier_block *nb, + unsigned long data, void *arg) + { +@@ -380,7 +380,7 @@ static int ieee80211_ifa_changed(struct + } + #endif + +-#if IS_ENABLED(CONFIG_IPV6) ++#if IS_ENABLED(__disabled__CONFIG_IPV6) + static int ieee80211_ifa6_changed(struct notifier_block *nb, + unsigned long data, void *arg) + { +@@ -1301,14 +1301,14 @@ int ieee80211_register_hw(struct ieee802 + + rtnl_unlock(); + +-#ifdef CONFIG_INET ++#ifdef __disabled__CONFIG_INET + local->ifa_notifier.notifier_call = ieee80211_ifa_changed; + result = register_inetaddr_notifier(&local->ifa_notifier); + if (result) + goto fail_ifa; + #endif + +-#if IS_ENABLED(CONFIG_IPV6) ++#if IS_ENABLED(__disabled__CONFIG_IPV6) + local->ifa6_notifier.notifier_call = ieee80211_ifa6_changed; + result = register_inet6addr_notifier(&local->ifa6_notifier); + if (result) +@@ -1317,13 +1317,13 @@ int ieee80211_register_hw(struct ieee802 + + return 0; + +-#if IS_ENABLED(CONFIG_IPV6) ++#if IS_ENABLED(__disabled__CONFIG_IPV6) + fail_ifa6: +-#ifdef CONFIG_INET ++#ifdef __disabled__CONFIG_INET + unregister_inetaddr_notifier(&local->ifa_notifier); + #endif + #endif +-#if defined(CONFIG_INET) || defined(CONFIG_IPV6) ++#if defined(__disabled__CONFIG_INET) || defined(__disabled__CONFIG_IPV6) + fail_ifa: + #endif + wiphy_unregister(local->hw.wiphy); +@@ -1351,10 +1351,10 @@ void ieee80211_unregister_hw(struct ieee + tasklet_kill(&local->tx_pending_tasklet); + tasklet_kill(&local->tasklet); + +-#ifdef CONFIG_INET ++#ifdef __disabled__CONFIG_INET + unregister_inetaddr_notifier(&local->ifa_notifier); + #endif +-#if IS_ENABLED(CONFIG_IPV6) ++#if IS_ENABLED(__disabled__CONFIG_IPV6) + unregister_inet6addr_notifier(&local->ifa6_notifier); + #endif + diff --git a/feeds/ipq40xx/mac80211/patches/subsys/210-ap_scan.patch b/feeds/ipq40xx/mac80211/patches/subsys/210-ap_scan.patch new file mode 100644 index 000000000..8ccab8cf6 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/subsys/210-ap_scan.patch @@ -0,0 +1,11 @@ +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -2345,7 +2345,7 @@ static int ieee80211_scan(struct wiphy * + * the frames sent while scanning on other channel will be + * lost) + */ +- if (sdata->u.ap.beacon && ++ if (0 && sdata->u.ap.beacon && + (!(wiphy->features & NL80211_FEATURE_AP_SCAN) || + !(req->flags & NL80211_SCAN_FLAG_AP))) + return -EOPNOTSUPP; diff --git a/feeds/ipq40xx/mac80211/patches/subsys/300-mac80211-optimize-skb-resizing.patch b/feeds/ipq40xx/mac80211/patches/subsys/300-mac80211-optimize-skb-resizing.patch new file mode 100644 index 000000000..bcdfa22ff --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/subsys/300-mac80211-optimize-skb-resizing.patch @@ -0,0 +1,201 @@ +From: Felix Fietkau +Date: Sun, 17 Mar 2019 18:11:30 +0100 +Subject: [PATCH] mac80211: optimize skb resizing + +When forwarding unicast packets from ethernet to batman-adv over 802.11s +(with forwarding disabled), the typical required headroom to transmit +encrypted packets on mt76 is 32 (802.11) + 6 (802.11s) + 8 (CCMP) + +2 (padding) + 6 (LLC) + 18 (batman-adv) - 14 (old ethernet header) = 58 bytes. + +On systems where NET_SKB_PAD is 64 this leads to a call to pskb_expand_head +for every packet, since mac80211 also tries to allocate 16 bytes status +headroom for radiotap headers. + +This patch fixes these unnecessary reallocations by only requiring the extra +status headroom in ieee80211_tx_monitor() +If however a reallocation happens before that call, the status headroom gets +added there as well, in order to avoid double reallocation. + +The patch also cleans up the code by moving the headroom calculation to +ieee80211_skb_resize. + +Signed-off-by: Felix Fietkau +--- + +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -1809,6 +1809,9 @@ int ieee80211_tx_control_port(struct wip + u64 *cookie); + int ieee80211_probe_mesh_link(struct wiphy *wiphy, struct net_device *dev, + const u8 *buf, size_t len); ++int ieee80211_skb_resize(struct ieee80211_local *local, ++ struct ieee80211_sub_if_data *sdata, ++ struct sk_buff *skb, int hdrlen, int hdr_add); + + /* HT */ + void ieee80211_apply_htcap_overrides(struct ieee80211_sub_if_data *sdata, +--- a/net/mac80211/status.c ++++ b/net/mac80211/status.c +@@ -843,6 +843,11 @@ void ieee80211_tx_monitor(struct ieee802 + struct net_device *prev_dev = NULL; + int rtap_len; + ++ if (ieee80211_skb_resize(local, NULL, skb, 0, 0)) { ++ dev_kfree_skb(skb); ++ return; ++ } ++ + /* send frame to monitor interfaces now */ + rtap_len = ieee80211_tx_radiotap_len(info, status); + if (WARN_ON_ONCE(skb_headroom(skb) < rtap_len)) { +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -1937,37 +1937,53 @@ static bool ieee80211_tx(struct ieee8021 + } + + /* device xmit handlers */ +- +-static int ieee80211_skb_resize(struct ieee80211_sub_if_data *sdata, +- struct sk_buff *skb, +- int head_need, bool may_encrypt) ++int ieee80211_skb_resize(struct ieee80211_local *local, ++ struct ieee80211_sub_if_data *sdata, ++ struct sk_buff *skb, int hdr_len, int hdr_extra) + { +- struct ieee80211_local *local = sdata->local; ++ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ieee80211_hdr *hdr; +- bool enc_tailroom; +- int tail_need = 0; +- +- hdr = (struct ieee80211_hdr *) skb->data; +- enc_tailroom = may_encrypt && +- (sdata->crypto_tx_tailroom_needed_cnt || +- ieee80211_is_mgmt(hdr->frame_control)); +- +- if (enc_tailroom) { +- tail_need = IEEE80211_ENCRYPT_TAILROOM; +- tail_need -= skb_tailroom(skb); +- tail_need = max_t(int, tail_need, 0); ++ int head_need, head_max; ++ int tail_need, tail_max; ++ bool enc_tailroom = false; ++ ++ if (sdata && !hdr_len && ++ !(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT)) { ++ hdr = (struct ieee80211_hdr *) skb->data; ++ enc_tailroom = (sdata->crypto_tx_tailroom_needed_cnt || ++ ieee80211_is_mgmt(hdr->frame_control)); ++ hdr_len += sdata->encrypt_headroom; ++ } ++ ++ head_need = head_max = hdr_len; ++ tail_need = tail_max = 0; ++ if (!sdata) { ++ head_need = head_max = local->tx_headroom; ++ } else { ++ head_max += hdr_extra; ++ head_max += max_t(int, local->tx_headroom, ++ local->hw.extra_tx_headroom); ++ head_need += local->hw.extra_tx_headroom; ++ ++ tail_max = IEEE80211_ENCRYPT_TAILROOM; ++ if (enc_tailroom) ++ tail_need = tail_max; + } + + if (skb_cloned(skb) && + (!ieee80211_hw_check(&local->hw, SUPPORTS_CLONED_SKBS) || + !skb_clone_writable(skb, ETH_HLEN) || enc_tailroom)) + I802_DEBUG_INC(local->tx_expand_skb_head_cloned); +- else if (head_need || tail_need) ++ else if (head_need > skb_headroom(skb) || ++ tail_need > skb_tailroom(skb)) + I802_DEBUG_INC(local->tx_expand_skb_head); + else + return 0; + +- if (pskb_expand_head(skb, head_need, tail_need, GFP_ATOMIC)) { ++ head_max = max_t(int, 0, head_max - skb_headroom(skb)); ++ tail_max = max_t(int, 0, tail_max - skb_tailroom(skb)); ++ ++ if (pskb_expand_head(skb, head_max, tail_max, GFP_ATOMIC)) { + wiphy_debug(local->hw.wiphy, + "failed to reallocate TX buffer\n"); + return -ENOMEM; +@@ -1983,18 +1999,8 @@ void ieee80211_xmit(struct ieee80211_sub + struct ieee80211_local *local = sdata->local; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ieee80211_hdr *hdr; +- int headroom; +- bool may_encrypt; +- +- may_encrypt = !(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT); + +- headroom = local->tx_headroom; +- if (may_encrypt) +- headroom += sdata->encrypt_headroom; +- headroom -= skb_headroom(skb); +- headroom = max_t(int, 0, headroom); +- +- if (ieee80211_skb_resize(sdata, skb, headroom, may_encrypt)) { ++ if (ieee80211_skb_resize(local, sdata, skb, 0, 0)) { + ieee80211_free_txskb(&local->hw, skb); + return; + } +@@ -2809,29 +2815,13 @@ static struct sk_buff *ieee80211_build_h + } + + skb_pull(skb, skip_header_bytes); +- head_need = hdrlen + encaps_len + meshhdrlen - skb_headroom(skb); ++ head_need = hdrlen + encaps_len + meshhdrlen; + +- /* +- * So we need to modify the skb header and hence need a copy of +- * that. The head_need variable above doesn't, so far, include +- * the needed header space that we don't need right away. If we +- * can, then we don't reallocate right now but only after the +- * frame arrives at the master device (if it does...) +- * +- * If we cannot, however, then we will reallocate to include all +- * the ever needed space. Also, if we need to reallocate it anyway, +- * make it big enough for everything we may ever need. +- */ +- +- if (head_need > 0 || skb_cloned(skb)) { +- head_need += sdata->encrypt_headroom; +- head_need += local->tx_headroom; +- head_need = max_t(int, 0, head_need); +- if (ieee80211_skb_resize(sdata, skb, head_need, true)) { +- ieee80211_free_txskb(&local->hw, skb); +- skb = NULL; +- return ERR_PTR(-ENOMEM); +- } ++ if (ieee80211_skb_resize(local, sdata, skb, head_need, ++ sdata->encrypt_headroom)) { ++ ieee80211_free_txskb(&local->hw, skb); ++ skb = NULL; ++ return ERR_PTR(-ENOMEM); + } + + if (encaps_data) +@@ -3446,7 +3436,6 @@ static bool ieee80211_xmit_fast(struct i + 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; +@@ -3498,10 +3487,7 @@ static bool ieee80211_xmit_fast(struct i + * as the may-encrypt argument for the resize to not account for + * more room than we already have in 'extra_head' + */ +- if (unlikely(ieee80211_skb_resize(sdata, skb, +- max_t(int, extra_head + hw_headroom - +- skb_headroom(skb), 0), +- false))) { ++ if (unlikely(ieee80211_skb_resize(local, sdata, skb, extra_head, 0))) { + kfree_skb(skb); + return true; + } diff --git a/feeds/ipq40xx/mac80211/patches/subsys/304-mac80211-sta-randomize-BA-session-dialog-token-alloc.patch b/feeds/ipq40xx/mac80211/patches/subsys/304-mac80211-sta-randomize-BA-session-dialog-token-alloc.patch new file mode 100644 index 000000000..10d8ad8d7 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/subsys/304-mac80211-sta-randomize-BA-session-dialog-token-alloc.patch @@ -0,0 +1,38 @@ +From b478e06a16a8baa00c5ecc87c1d636981f2206d5 Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Tue, 29 Oct 2019 10:25:25 +0100 +Subject: [PATCH] mac80211: sta: randomize BA session dialog token allocator + +We currently always start the dialog token generator at zero, +so the first dialog token we use is always 1. This would be +OK if we had a perfect guarantee that we always do a proper +deauth/re-auth handshake, but in IBSS mode this doesn't always +happen properly. + +To make problems with block ack (aggregation) sessions getting +stuck less likely, randomize the dialog token so if we start a +new session but the peer still has old state for us, it can +better detect this. + +This is really just a workaround to make things a bit more +robust than they are now - a better fix would be to do a full +authentication handshake in IBSS mode upon having discovered a +new station, and on the receiver resetting the state (removing +and re-adding the station) on receiving the authentication +packet. + +Signed-off-by: Johannes Berg +--- + net/mac80211/sta_info.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/net/mac80211/sta_info.c ++++ b/net/mac80211/sta_info.c +@@ -339,6 +339,7 @@ struct sta_info *sta_info_alloc(struct i + INIT_WORK(&sta->drv_deliver_wk, sta_deliver_ps_frames); + 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); + #ifdef CPTCFG_MAC80211_MESH + if (ieee80211_vif_is_mesh(&sdata->vif)) { + sta->mesh = kzalloc(sizeof(*sta->mesh), gfp); diff --git a/feeds/ipq40xx/mac80211/patches/subsys/305-mac80211-improve-AQL-tx-airtime-estimation.patch b/feeds/ipq40xx/mac80211/patches/subsys/305-mac80211-improve-AQL-tx-airtime-estimation.patch new file mode 100644 index 000000000..bee43a60f --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/subsys/305-mac80211-improve-AQL-tx-airtime-estimation.patch @@ -0,0 +1,81 @@ +From: Felix Fietkau +Date: Fri, 24 Jul 2020 20:25:07 +0200 +Subject: [PATCH] mac80211: improve AQL tx airtime estimation + +AQL does not take into account that most HT/VHT/HE traffic is A-MPDU aggregated. +Because of that, the per-packet airtime overhead is vastly overestimated. +Improve it by assuming an average aggregation length of 16 for non-legacy +traffic if not using the VO AC queue. +This should improve performance with high data rates, especially with multiple +stations + +Signed-off-by: Felix Fietkau +--- + +--- a/net/mac80211/airtime.c ++++ b/net/mac80211/airtime.c +@@ -551,7 +551,7 @@ EXPORT_SYMBOL_GPL(ieee80211_calc_tx_airt + u32 ieee80211_calc_expected_tx_airtime(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *pubsta, +- int len) ++ int len, bool ampdu) + { + struct ieee80211_supported_band *sband; + struct ieee80211_chanctx_conf *conf; +@@ -572,10 +572,26 @@ u32 ieee80211_calc_expected_tx_airtime(s + if (pubsta) { + struct sta_info *sta = container_of(pubsta, struct sta_info, + sta); ++ struct ieee80211_tx_rate *rate = &sta->tx_stats.last_rate; ++ u32 airtime; + +- return ieee80211_calc_tx_airtime_rate(hw, +- &sta->tx_stats.last_rate, +- band, len); ++ if (!(rate->flags & (IEEE80211_TX_RC_VHT_MCS | ++ IEEE80211_TX_RC_MCS))) ++ ampdu = false; ++ ++ /* ++ * Assume that HT/VHT transmission on any AC except VO will ++ * use aggregation. Since we don't have reliable reporting ++ * of aggregation length, assume an average of 16. ++ * This will not be very accurate, but much better than simply ++ * assuming un-aggregated tx. ++ */ ++ airtime = ieee80211_calc_tx_airtime_rate(hw, rate, band, ++ ampdu ? len * 16 : len); ++ if (ampdu) ++ airtime /= 16; ++ ++ return airtime; + } + + if (!conf) +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -2294,7 +2294,7 @@ extern const struct ethtool_ops ieee8021 + u32 ieee80211_calc_expected_tx_airtime(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *pubsta, +- int len); ++ int len, bool ampdu); + #ifdef CPTCFG_MAC80211_NOINLINE + #define debug_noinline noinline + #else +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -3707,10 +3707,11 @@ encap_out: + + if (vif && + wiphy_ext_feature_isset(local->hw.wiphy, NL80211_EXT_FEATURE_AQL)) { ++ bool ampdu = txq->ac != IEEE80211_AC_VO; + u32 airtime; + + airtime = ieee80211_calc_expected_tx_airtime(hw, vif, txq->sta, +- skb->len); ++ skb->len, ampdu); + if (airtime) { + airtime = ieee80211_info_set_tx_time_est(info, airtime); + ieee80211_sta_update_pending_airtime(local, tx.sta, diff --git a/feeds/ipq40xx/mac80211/patches/subsys/307-mac80211-add-a-function-for-running-rx-without-passi.patch b/feeds/ipq40xx/mac80211/patches/subsys/307-mac80211-add-a-function-for-running-rx-without-passi.patch new file mode 100644 index 000000000..1bcb41461 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/subsys/307-mac80211-add-a-function-for-running-rx-without-passi.patch @@ -0,0 +1,186 @@ +From: Felix Fietkau +Date: Sat, 25 Jul 2020 20:53:23 +0200 +Subject: [PATCH] mac80211: add a function for running rx without passing skbs + to the stack + +This can be used to run mac80211 rx processing on a batch of frames in NAPI +poll before passing them to the network stack in a large batch. +This can improve icache footprint, or it can be used to pass frames via +netif_receive_skb_list. + +Signed-off-by: Felix Fietkau +--- + +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -4358,6 +4358,31 @@ void ieee80211_free_hw(struct ieee80211_ + void ieee80211_restart_hw(struct ieee80211_hw *hw); + + /** ++ * ieee80211_rx_list - receive frame and store processed skbs in a list ++ * ++ * Use this function to hand received frames to mac80211. The receive ++ * buffer in @skb must start with an IEEE 802.11 header. In case of a ++ * paged @skb is used, the driver is recommended to put the ieee80211 ++ * header of the frame on the linear part of the @skb to avoid memory ++ * allocation and/or memcpy by the stack. ++ * ++ * This function may not be called in IRQ context. Calls to this function ++ * for a single hardware must be synchronized against each other. Calls to ++ * this function, ieee80211_rx_ni() and ieee80211_rx_irqsafe() may not be ++ * mixed for a single hardware. Must not run concurrently with ++ * ieee80211_tx_status() or ieee80211_tx_status_ni(). ++ * ++ * This function must be called with BHs disabled and RCU read lock ++ * ++ * @hw: the hardware this frame came in on ++ * @sta: the station the frame was received from, or %NULL ++ * @skb: the buffer to receive, owned by mac80211 after this call ++ * @list: the destination list ++ */ ++void ieee80211_rx_list(struct ieee80211_hw *hw, struct ieee80211_sta *sta, ++ struct sk_buff *skb, struct list_head *list); ++ ++/** + * ieee80211_rx_napi - receive frame from NAPI context + * + * Use this function to hand received frames to mac80211. The receive +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -218,7 +218,7 @@ enum ieee80211_rx_flags { + }; + + struct ieee80211_rx_data { +- struct napi_struct *napi; ++ struct list_head *list; + struct sk_buff *skb; + struct ieee80211_local *local; + struct ieee80211_sub_if_data *sdata; +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -2578,8 +2578,8 @@ static void ieee80211_deliver_skb_to_loc + memset(skb->cb, 0, sizeof(skb->cb)); + + /* deliver to local stack */ +- if (rx->napi) +- napi_gro_receive(rx->napi, skb); ++ if (rx->list) ++ list_add_tail(&skb->list, rx->list); + else + netif_receive_skb(skb); + } +@@ -3869,7 +3869,6 @@ void ieee80211_release_reorder_timeout(s + /* This is OK -- must be QoS data frame */ + .security_idx = tid, + .seqno_idx = tid, +- .napi = NULL, /* must be NULL to not have races */ + }; + struct tid_ampdu_rx *tid_agg_rx; + +@@ -4479,8 +4478,8 @@ static bool ieee80211_invoke_fast_rx(str + /* deliver to local stack */ + skb->protocol = eth_type_trans(skb, fast_rx->dev); + memset(skb->cb, 0, sizeof(skb->cb)); +- if (rx->napi) +- napi_gro_receive(rx->napi, skb); ++ if (rx->list) ++ list_add_tail(&skb->list, rx->list); + else + netif_receive_skb(skb); + +@@ -4547,7 +4546,7 @@ static bool ieee80211_prepare_and_rx_han + static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, + struct ieee80211_sta *pubsta, + struct sk_buff *skb, +- struct napi_struct *napi) ++ struct list_head *list) + { + struct ieee80211_local *local = hw_to_local(hw); + struct ieee80211_sub_if_data *sdata; +@@ -4562,7 +4561,7 @@ static void __ieee80211_rx_handle_packet + memset(&rx, 0, sizeof(rx)); + rx.skb = skb; + rx.local = local; +- rx.napi = napi; ++ rx.list = list; + + if (ieee80211_is_data(fc) || ieee80211_is_mgmt(fc)) + I802_DEBUG_INC(local->dot11ReceivedFragmentCount); +@@ -4670,8 +4669,8 @@ static void __ieee80211_rx_handle_packet + * This is the receive path handler. It is called by a low level driver when an + * 802.11 MPDU is received from the hardware. + */ +-void ieee80211_rx_napi(struct ieee80211_hw *hw, struct ieee80211_sta *pubsta, +- struct sk_buff *skb, struct napi_struct *napi) ++void ieee80211_rx_list(struct ieee80211_hw *hw, struct ieee80211_sta *pubsta, ++ struct sk_buff *skb, struct list_head *list) + { + struct ieee80211_local *local = hw_to_local(hw); + struct ieee80211_rate *rate = NULL; +@@ -4763,36 +4762,53 @@ void ieee80211_rx_napi(struct ieee80211_ + status->rx_flags = 0; + + /* +- * key references and virtual interfaces are protected using RCU +- * and this requires that we are in a read-side RCU section during +- * receive processing +- */ +- rcu_read_lock(); +- +- /* + * Frames with failed FCS/PLCP checksum are not returned, + * all other frames are returned without radiotap header + * if it was previously present. + * Also, frames with less than 16 bytes are dropped. + */ + skb = ieee80211_rx_monitor(local, skb, rate); +- if (!skb) { +- rcu_read_unlock(); ++ if (!skb) + return; +- } + + ieee80211_tpt_led_trig_rx(local, + ((struct ieee80211_hdr *)skb->data)->frame_control, + skb->len); + +- __ieee80211_rx_handle_packet(hw, pubsta, skb, napi); +- +- rcu_read_unlock(); ++ __ieee80211_rx_handle_packet(hw, pubsta, skb, list); + + return; + drop: + kfree_skb(skb); + } ++EXPORT_SYMBOL(ieee80211_rx_list); ++ ++void ieee80211_rx_napi(struct ieee80211_hw *hw, struct ieee80211_sta *pubsta, ++ struct sk_buff *skb, struct napi_struct *napi) ++{ ++ struct sk_buff *tmp; ++ LIST_HEAD(list); ++ ++ ++ /* ++ * key references and virtual interfaces are protected using RCU ++ * and this requires that we are in a read-side RCU section during ++ * receive processing ++ */ ++ rcu_read_lock(); ++ ieee80211_rx_list(hw, pubsta, skb, &list); ++ rcu_read_unlock(); ++ ++ if (!napi) { ++ netif_receive_skb_list(&list); ++ return; ++ } ++ ++ list_for_each_entry_safe(skb, tmp, &list, list) { ++ skb_list_del_init(skb); ++ napi_gro_receive(napi, skb); ++ } ++} + EXPORT_SYMBOL(ieee80211_rx_napi); + + /* This is a version of the rx handler that can be called from hard irq diff --git a/feeds/ipq40xx/mac80211/patches/subsys/308-net-fq_impl-use-skb_get_hash-instead-of-skb_get_hash.patch b/feeds/ipq40xx/mac80211/patches/subsys/308-net-fq_impl-use-skb_get_hash-instead-of-skb_get_hash.patch new file mode 100644 index 000000000..77ecc8230 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/subsys/308-net-fq_impl-use-skb_get_hash-instead-of-skb_get_hash.patch @@ -0,0 +1,55 @@ +From: Felix Fietkau +Date: Sun, 26 Jul 2020 14:37:02 +0200 +Subject: [PATCH] net/fq_impl: use skb_get_hash instead of + skb_get_hash_perturb + +This avoids unnecessary regenerating of the skb flow hash + +Signed-off-by: Felix Fietkau +--- + +--- a/include/net/fq.h ++++ b/include/net/fq.h +@@ -69,15 +69,6 @@ struct fq { + struct list_head backlogs; + spinlock_t lock; + u32 flows_cnt; +-#if LINUX_VERSION_IS_GEQ(5,3,10) || \ +- LINUX_VERSION_IN_RANGE(4,19,83, 4,20,0) || \ +- LINUX_VERSION_IN_RANGE(4,14,153, 4,15,0) || \ +- LINUX_VERSION_IN_RANGE(4,9,200, 4,10,0) || \ +- LINUX_VERSION_IN_RANGE(4,4,200, 4,5,0) +- siphash_key_t perturbation; +-#else +- u32 perturbation; +-#endif + u32 limit; + u32 memory_limit; + u32 memory_usage; +--- a/include/net/fq_impl.h ++++ b/include/net/fq_impl.h +@@ -108,15 +108,7 @@ begin: + + static u32 fq_flow_idx(struct fq *fq, struct sk_buff *skb) + { +-#if LINUX_VERSION_IS_GEQ(5,3,10) || \ +- LINUX_VERSION_IN_RANGE(4,19,83, 4,20,0) || \ +- LINUX_VERSION_IN_RANGE(4,14,153, 4,15,0) || \ +- LINUX_VERSION_IN_RANGE(4,9,200, 4,10,0) || \ +- LINUX_VERSION_IN_RANGE(4,4,200, 4,5,0) +- u32 hash = skb_get_hash_perturb(skb, &fq->perturbation); +-#else +- u32 hash = skb_get_hash_perturb(skb, fq->perturbation); +-#endif ++ u32 hash = skb_get_hash(skb); + + return reciprocal_scale(hash, fq->flows_cnt); + } +@@ -316,7 +308,6 @@ static int fq_init(struct fq *fq, int fl + INIT_LIST_HEAD(&fq->backlogs); + spin_lock_init(&fq->lock); + fq->flows_cnt = max_t(u32, flows_cnt, 1); +- get_random_bytes(&fq->perturbation, sizeof(fq->perturbation)); + fq->quantum = 300; + fq->limit = 8192; + fq->memory_limit = 16 << 20; /* 16 MBytes */ diff --git a/feeds/ipq40xx/mac80211/patches/subsys/309-mac80211-calculcate-skb-hash-early-when-using-itxq.patch b/feeds/ipq40xx/mac80211/patches/subsys/309-mac80211-calculcate-skb-hash-early-when-using-itxq.patch new file mode 100644 index 000000000..92b136279 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/subsys/309-mac80211-calculcate-skb-hash-early-when-using-itxq.patch @@ -0,0 +1,19 @@ +From: Felix Fietkau +Date: Sun, 26 Jul 2020 14:42:58 +0200 +Subject: [PATCH] mac80211: calculcate skb hash early when using itxq + +This avoids flow separation issues when using software encryption + +Signed-off-by: Felix Fietkau +--- + +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -3937,6 +3937,7 @@ void __ieee80211_subif_start_xmit(struct + if (local->ops->wake_tx_queue) { + u16 queue = __ieee80211_select_queue(sdata, sta, skb); + skb_set_queue_mapping(skb, queue); ++ skb_get_hash(skb); + } + + if (sta) { diff --git a/feeds/ipq40xx/mac80211/patches/subsys/310-mac80211-reduce-packet-loss-event-false-positives.patch b/feeds/ipq40xx/mac80211/patches/subsys/310-mac80211-reduce-packet-loss-event-false-positives.patch new file mode 100644 index 000000000..62f2419dd --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/subsys/310-mac80211-reduce-packet-loss-event-false-positives.patch @@ -0,0 +1,116 @@ +From: Felix Fietkau +Date: Sat, 8 Aug 2020 19:20:02 +0200 +Subject: [PATCH] mac80211: reduce packet loss event false positives + +When running a large number of packets per second with a high data rate +and long A-MPDUs, the packet loss threshold can be reached very quickly +when the link conditions change. This frequently shows up as spurious +disconnects. +Mitigate false positives by using a similar logic for regular stations +as the one being used for TDLS, though with a more aggressive timeout. +Packet loss events are only reported if no ACK was received for a second. + +Signed-off-by: Felix Fietkau +--- + +--- a/net/mac80211/sta_info.h ++++ b/net/mac80211/sta_info.h +@@ -522,7 +522,7 @@ struct ieee80211_sta_rx_stats { + * @status_stats.retry_failed: # of frames that failed after retry + * @status_stats.retry_count: # of retries attempted + * @status_stats.lost_packets: # of lost packets +- * @status_stats.last_tdls_pkt_time: timestamp of last TDLS packet ++ * @status_stats.last_pkt_time: timestamp of last ACKed packet + * @status_stats.msdu_retries: # of MSDU retries + * @status_stats.msdu_failed: # of failed MSDUs + * @status_stats.last_ack: last ack timestamp (jiffies) +@@ -595,7 +595,7 @@ struct sta_info { + unsigned long filtered; + unsigned long retry_failed, retry_count; + unsigned int lost_packets; +- unsigned long last_tdls_pkt_time; ++ unsigned long last_pkt_time; + u64 msdu_retries[IEEE80211_NUM_TIDS + 1]; + u64 msdu_failed[IEEE80211_NUM_TIDS + 1]; + unsigned long last_ack; +--- a/net/mac80211/status.c ++++ b/net/mac80211/status.c +@@ -757,12 +757,16 @@ static void ieee80211_report_used_skb(st + * - current throughput (higher value for higher tpt)? + */ + #define STA_LOST_PKT_THRESHOLD 50 ++#define STA_LOST_PKT_TIME HZ /* 1 sec since last ACK */ + #define STA_LOST_TDLS_PKT_THRESHOLD 10 + #define STA_LOST_TDLS_PKT_TIME (10*HZ) /* 10secs since last ACK */ + + static void ieee80211_lost_packet(struct sta_info *sta, + struct ieee80211_tx_info *info) + { ++ unsigned long pkt_time = STA_LOST_PKT_TIME; ++ unsigned int pkt_thr = STA_LOST_PKT_THRESHOLD; ++ + /* If driver relies on its own algorithm for station kickout, skip + * mac80211 packet loss mechanism. + */ +@@ -775,21 +779,20 @@ static void ieee80211_lost_packet(struct + return; + + sta->status_stats.lost_packets++; +- if (!sta->sta.tdls && +- sta->status_stats.lost_packets < STA_LOST_PKT_THRESHOLD) +- return; ++ if (sta->sta.tdls) { ++ pkt_time = STA_LOST_TDLS_PKT_TIME; ++ pkt_thr = STA_LOST_PKT_THRESHOLD; ++ } + + /* + * If we're in TDLS mode, make sure that all STA_LOST_TDLS_PKT_THRESHOLD + * of the last packets were lost, and that no ACK was received in the + * last STA_LOST_TDLS_PKT_TIME ms, before triggering the CQM packet-loss + * mechanism. ++ * For non-TDLS, use STA_LOST_PKT_THRESHOLD and STA_LOST_PKT_TIME + */ +- if (sta->sta.tdls && +- (sta->status_stats.lost_packets < STA_LOST_TDLS_PKT_THRESHOLD || +- time_before(jiffies, +- sta->status_stats.last_tdls_pkt_time + +- STA_LOST_TDLS_PKT_TIME))) ++ if (sta->status_stats.lost_packets < pkt_thr || ++ !time_after(jiffies, sta->status_stats.last_pkt_time + pkt_time)) + return; + + cfg80211_cqm_pktloss_notify(sta->sdata->dev, sta->sta.addr, +@@ -1042,9 +1045,7 @@ static void __ieee80211_tx_status(struct + sta->status_stats.lost_packets = 0; + + /* Track when last TDLS packet was ACKed */ +- if (test_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH)) +- sta->status_stats.last_tdls_pkt_time = +- jiffies; ++ sta->status_stats.last_pkt_time = jiffies; + } else if (noack_success) { + /* nothing to do here, do not account as lost */ + } else { +@@ -1177,9 +1178,8 @@ void ieee80211_tx_status_ext(struct ieee + if (sta->status_stats.lost_packets) + sta->status_stats.lost_packets = 0; + +- /* Track when last TDLS packet was ACKed */ +- if (test_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH)) +- sta->status_stats.last_tdls_pkt_time = jiffies; ++ /* Track when last packet was ACKed */ ++ sta->status_stats.last_pkt_time = jiffies; + } else if (test_sta_flag(sta, WLAN_STA_PS_STA)) { + return; + } else if (noack_success) { +@@ -1268,8 +1268,7 @@ void ieee80211_tx_status_8023(struct iee + if (sta->status_stats.lost_packets) + sta->status_stats.lost_packets = 0; + +- if (test_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH)) +- sta->status_stats.last_tdls_pkt_time = jiffies; ++ sta->status_stats.last_pkt_time = jiffies; + } else { + ieee80211_lost_packet(sta, info); + } diff --git a/feeds/ipq40xx/mac80211/patches/subsys/311-mac80211-use-rate-provided-via-status-rate-on-ieee80.patch b/feeds/ipq40xx/mac80211/patches/subsys/311-mac80211-use-rate-provided-via-status-rate-on-ieee80.patch new file mode 100644 index 000000000..ee1db716e --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/subsys/311-mac80211-use-rate-provided-via-status-rate-on-ieee80.patch @@ -0,0 +1,151 @@ +From: Felix Fietkau +Date: Wed, 12 Aug 2020 17:04:22 +0200 +Subject: [PATCH] mac80211: use rate provided via status->rate on + ieee80211_tx_status_ext for AQL + +Since ieee80211_tx_info does not have enough room to encode HE rates, HE +drivers use status->rate to provide rate info. +Store it in struct sta_info and use it for AQL. + +Signed-off-by: Felix Fietkau +--- + +--- a/net/mac80211/airtime.c ++++ b/net/mac80211/airtime.c +@@ -487,14 +487,61 @@ u32 ieee80211_calc_rx_airtime(struct iee + } + EXPORT_SYMBOL_GPL(ieee80211_calc_rx_airtime); + ++static bool ieee80211_fill_rate_info(struct ieee80211_hw *hw, ++ struct ieee80211_rx_status *stat, u8 band, ++ struct rate_info *ri) ++{ ++ struct ieee80211_supported_band *sband = hw->wiphy->bands[band]; ++ int i; ++ ++ if (!ri || !sband) ++ return false; ++ ++ stat->bw = ri->bw; ++ stat->nss = ri->nss; ++ stat->rate_idx = ri->mcs; ++ ++ if (ri->flags & RATE_INFO_FLAGS_HE_MCS) ++ stat->encoding = RX_ENC_HE; ++ else if (ri->flags & RATE_INFO_FLAGS_VHT_MCS) ++ stat->encoding = RX_ENC_VHT; ++ else if (ri->flags & RATE_INFO_FLAGS_MCS) ++ stat->encoding = RX_ENC_HT; ++ else ++ stat->encoding = RX_ENC_LEGACY; ++ ++ if (ri->flags & RATE_INFO_FLAGS_SHORT_GI) ++ stat->enc_flags |= RX_ENC_FLAG_SHORT_GI; ++ ++ stat->he_gi = ri->he_gi; ++ ++ if (stat->encoding != RX_ENC_LEGACY) ++ return true; ++ ++ stat->rate_idx = 0; ++ for (i = 0; i < sband->n_bitrates; i++) { ++ if (ri->legacy != sband->bitrates[i].bitrate) ++ continue; ++ ++ stat->rate_idx = i; ++ return true; ++ } ++ ++ return false; ++} ++ + static u32 ieee80211_calc_tx_airtime_rate(struct ieee80211_hw *hw, + struct ieee80211_tx_rate *rate, ++ struct rate_info *ri, + u8 band, int len) + { + struct ieee80211_rx_status stat = { + .band = band, + }; + ++ if (ieee80211_fill_rate_info(hw, &stat, band, ri)) ++ goto out; ++ + if (rate->idx < 0 || !rate->count) + return 0; + +@@ -522,6 +569,7 @@ static u32 ieee80211_calc_tx_airtime_rat + stat.encoding = RX_ENC_LEGACY; + } + ++out: + return ieee80211_calc_rx_airtime(hw, &stat, len); + } + +@@ -536,7 +584,7 @@ u32 ieee80211_calc_tx_airtime(struct iee + struct ieee80211_tx_rate *rate = &info->status.rates[i]; + u32 cur_duration; + +- cur_duration = ieee80211_calc_tx_airtime_rate(hw, rate, ++ cur_duration = ieee80211_calc_tx_airtime_rate(hw, rate, NULL, + info->band, len); + if (!cur_duration) + break; +@@ -573,6 +621,7 @@ u32 ieee80211_calc_expected_tx_airtime(s + struct sta_info *sta = container_of(pubsta, struct sta_info, + sta); + struct ieee80211_tx_rate *rate = &sta->tx_stats.last_rate; ++ struct rate_info *ri = &sta->tx_stats.last_rate_info; + u32 airtime; + + if (!(rate->flags & (IEEE80211_TX_RC_VHT_MCS | +@@ -586,7 +635,7 @@ u32 ieee80211_calc_expected_tx_airtime(s + * This will not be very accurate, but much better than simply + * assuming un-aggregated tx. + */ +- airtime = ieee80211_calc_tx_airtime_rate(hw, rate, band, ++ airtime = ieee80211_calc_tx_airtime_rate(hw, rate, ri, band, + ampdu ? len * 16 : len); + if (ampdu) + airtime /= 16; +--- a/net/mac80211/sta_info.h ++++ b/net/mac80211/sta_info.h +@@ -609,6 +609,7 @@ struct sta_info { + u64 packets[IEEE80211_NUM_ACS]; + u64 bytes[IEEE80211_NUM_ACS]; + struct ieee80211_tx_rate last_rate; ++ struct rate_info last_rate_info; + u64 msdu[IEEE80211_NUM_TIDS + 1]; + } tx_stats; + u16 tid_seq[IEEE80211_QOS_CTL_TID_MASK + 1]; +--- a/net/mac80211/status.c ++++ b/net/mac80211/status.c +@@ -1147,9 +1147,17 @@ void ieee80211_tx_status_ext(struct ieee + struct ieee80211_tx_info *info = status->info; + struct ieee80211_sta *pubsta = status->sta; + struct ieee80211_supported_band *sband; ++ struct sta_info *sta; + int retry_count; + bool acked, noack_success; + ++ if (pubsta) { ++ sta = container_of(pubsta, struct sta_info, sta); ++ ++ if (status->rate) ++ sta->tx_stats.last_rate_info = *status->rate; ++ } ++ + if (status->skb) + return __ieee80211_tx_status(hw, status); + +@@ -1164,10 +1172,6 @@ void ieee80211_tx_status_ext(struct ieee + noack_success = !!(info->flags & IEEE80211_TX_STAT_NOACK_TRANSMITTED); + + if (pubsta) { +- struct sta_info *sta; +- +- sta = container_of(pubsta, struct sta_info, sta); +- + if (!acked && !noack_success) + sta->status_stats.retry_failed++; + sta->status_stats.retry_count += retry_count; diff --git a/feeds/ipq40xx/mac80211/patches/subsys/312-mac80211-factor-out-code-to-look-up-the-average-pack.patch b/feeds/ipq40xx/mac80211/patches/subsys/312-mac80211-factor-out-code-to-look-up-the-average-pack.patch new file mode 100644 index 000000000..06db852c3 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/subsys/312-mac80211-factor-out-code-to-look-up-the-average-pack.patch @@ -0,0 +1,187 @@ +From: Felix Fietkau +Date: Wed, 12 Aug 2020 17:06:12 +0200 +Subject: [PATCH] mac80211: factor out code to look up the average packet + length duration for a rate + +This will be used to enhance AQL estimated aggregation length + +Signed-off-by: Felix Fietkau +--- + +--- a/net/mac80211/airtime.c ++++ b/net/mac80211/airtime.c +@@ -405,18 +405,14 @@ ieee80211_calc_legacy_rate_duration(u16 + return duration; + } + +-u32 ieee80211_calc_rx_airtime(struct ieee80211_hw *hw, +- struct ieee80211_rx_status *status, +- int len) ++static u32 ieee80211_get_rate_duration(struct ieee80211_hw *hw, ++ struct ieee80211_rx_status *status, ++ u32 *overhead) + { +- struct ieee80211_supported_band *sband; +- const struct ieee80211_rate *rate; + bool sgi = status->enc_flags & RX_ENC_FLAG_SHORT_GI; +- bool sp = status->enc_flags & RX_ENC_FLAG_SHORTPRE; + int bw, streams; + int group, idx; + u32 duration; +- bool cck; + + switch (status->bw) { + case RATE_INFO_BW_20: +@@ -437,20 +433,6 @@ u32 ieee80211_calc_rx_airtime(struct iee + } + + switch (status->encoding) { +- case RX_ENC_LEGACY: +- if (WARN_ON_ONCE(status->band > NL80211_BAND_5GHZ)) +- return 0; +- +- sband = hw->wiphy->bands[status->band]; +- if (!sband || status->rate_idx >= sband->n_bitrates) +- return 0; +- +- rate = &sband->bitrates[status->rate_idx]; +- cck = rate->flags & IEEE80211_RATE_MANDATORY_B; +- +- return ieee80211_calc_legacy_rate_duration(rate->bitrate, sp, +- cck, len); +- + case RX_ENC_VHT: + streams = status->nss; + idx = status->rate_idx; +@@ -477,13 +459,47 @@ u32 ieee80211_calc_rx_airtime(struct iee + + duration = airtime_mcs_groups[group].duration[idx]; + duration <<= airtime_mcs_groups[group].shift; ++ *overhead = 36 + (streams << 2); ++ ++ return duration; ++} ++ ++ ++u32 ieee80211_calc_rx_airtime(struct ieee80211_hw *hw, ++ struct ieee80211_rx_status *status, ++ int len) ++{ ++ struct ieee80211_supported_band *sband; ++ u32 duration, overhead = 0; ++ ++ if (status->encoding == RX_ENC_LEGACY) { ++ const struct ieee80211_rate *rate; ++ bool sp = status->enc_flags & RX_ENC_FLAG_SHORTPRE; ++ bool cck; ++ ++ if (WARN_ON_ONCE(status->band > NL80211_BAND_5GHZ)) ++ return 0; ++ ++ sband = hw->wiphy->bands[status->band]; ++ if (!sband || status->rate_idx >= sband->n_bitrates) ++ return 0; ++ ++ rate = &sband->bitrates[status->rate_idx]; ++ cck = rate->flags & IEEE80211_RATE_MANDATORY_B; ++ ++ return ieee80211_calc_legacy_rate_duration(rate->bitrate, sp, ++ cck, len); ++ } ++ ++ duration = ieee80211_get_rate_duration(hw, status, &overhead); ++ if (!duration) ++ return 0; ++ + duration *= len; + duration /= AVG_PKT_SIZE; + duration /= 1024; + +- duration += 36 + (streams << 2); +- +- return duration; ++ return duration + overhead; + } + EXPORT_SYMBOL_GPL(ieee80211_calc_rx_airtime); + +@@ -530,46 +546,57 @@ static bool ieee80211_fill_rate_info(str + return false; + } + +-static u32 ieee80211_calc_tx_airtime_rate(struct ieee80211_hw *hw, +- struct ieee80211_tx_rate *rate, +- struct rate_info *ri, +- u8 band, int len) ++static int ieee80211_fill_rx_status(struct ieee80211_rx_status *stat, ++ struct ieee80211_hw *hw, ++ struct ieee80211_tx_rate *rate, ++ struct rate_info *ri, u8 band, int len) + { +- struct ieee80211_rx_status stat = { +- .band = band, +- }; ++ memset(stat, 0, sizeof(*stat)); ++ stat->band = band; + +- if (ieee80211_fill_rate_info(hw, &stat, band, ri)) +- goto out; ++ if (ieee80211_fill_rate_info(hw, stat, band, ri)) ++ return 0; + + if (rate->idx < 0 || !rate->count) +- return 0; ++ return -1; + + if (rate->flags & IEEE80211_TX_RC_80_MHZ_WIDTH) +- stat.bw = RATE_INFO_BW_80; ++ stat->bw = RATE_INFO_BW_80; + else if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) +- stat.bw = RATE_INFO_BW_40; ++ stat->bw = RATE_INFO_BW_40; + else +- stat.bw = RATE_INFO_BW_20; ++ stat->bw = RATE_INFO_BW_20; + +- stat.enc_flags = 0; ++ stat->enc_flags = 0; + if (rate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) +- stat.enc_flags |= RX_ENC_FLAG_SHORTPRE; ++ stat->enc_flags |= RX_ENC_FLAG_SHORTPRE; + if (rate->flags & IEEE80211_TX_RC_SHORT_GI) +- stat.enc_flags |= RX_ENC_FLAG_SHORT_GI; ++ stat->enc_flags |= RX_ENC_FLAG_SHORT_GI; + +- stat.rate_idx = rate->idx; ++ stat->rate_idx = rate->idx; + if (rate->flags & IEEE80211_TX_RC_VHT_MCS) { +- stat.encoding = RX_ENC_VHT; +- stat.rate_idx = ieee80211_rate_get_vht_mcs(rate); +- stat.nss = ieee80211_rate_get_vht_nss(rate); ++ stat->encoding = RX_ENC_VHT; ++ stat->rate_idx = ieee80211_rate_get_vht_mcs(rate); ++ stat->nss = ieee80211_rate_get_vht_nss(rate); + } else if (rate->flags & IEEE80211_TX_RC_MCS) { +- stat.encoding = RX_ENC_HT; ++ stat->encoding = RX_ENC_HT; + } else { +- stat.encoding = RX_ENC_LEGACY; ++ stat->encoding = RX_ENC_LEGACY; + } + +-out: ++ return 0; ++} ++ ++static u32 ieee80211_calc_tx_airtime_rate(struct ieee80211_hw *hw, ++ struct ieee80211_tx_rate *rate, ++ struct rate_info *ri, ++ u8 band, int len) ++{ ++ struct ieee80211_rx_status stat; ++ ++ if (ieee80211_fill_rx_status(&stat, hw, rate, ri, band, len)) ++ return 0; ++ + return ieee80211_calc_rx_airtime(hw, &stat, len); + } + diff --git a/feeds/ipq40xx/mac80211/patches/subsys/313-mac80211-improve-AQL-aggregation-estimation-for-low-.patch b/feeds/ipq40xx/mac80211/patches/subsys/313-mac80211-improve-AQL-aggregation-estimation-for-low-.patch new file mode 100644 index 000000000..7f7c75db5 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/subsys/313-mac80211-improve-AQL-aggregation-estimation-for-low-.patch @@ -0,0 +1,67 @@ +From: Felix Fietkau +Date: Wed, 12 Aug 2020 17:07:10 +0200 +Subject: [PATCH] mac80211: improve AQL aggregation estimation for low data + rates + +Links with low data rates use much smaller aggregates and are much more +sensitive to latency added by bufferbloat. +Tune the assumed aggregation length based on the tx rate duration. + +Signed-off-by: Felix Fietkau +--- + +--- a/net/mac80211/airtime.c ++++ b/net/mac80211/airtime.c +@@ -647,27 +647,41 @@ u32 ieee80211_calc_expected_tx_airtime(s + if (pubsta) { + struct sta_info *sta = container_of(pubsta, struct sta_info, + sta); ++ struct ieee80211_rx_status stat; + struct ieee80211_tx_rate *rate = &sta->tx_stats.last_rate; + struct rate_info *ri = &sta->tx_stats.last_rate_info; +- u32 airtime; ++ u32 duration, overhead; ++ u8 agg_shift; + +- if (!(rate->flags & (IEEE80211_TX_RC_VHT_MCS | +- IEEE80211_TX_RC_MCS))) +- ampdu = false; ++ if (ieee80211_fill_rx_status(&stat, hw, rate, ri, band, len)) ++ return 0; + ++ if (stat.encoding == RX_ENC_LEGACY || !ampdu) ++ return ieee80211_calc_rx_airtime(hw, &stat, len); ++ ++ duration = ieee80211_get_rate_duration(hw, &stat, &overhead); + /* + * Assume that HT/VHT transmission on any AC except VO will + * use aggregation. Since we don't have reliable reporting +- * of aggregation length, assume an average of 16. ++ * of aggregation length, assume an average size based on the ++ * tx rate. + * This will not be very accurate, but much better than simply +- * assuming un-aggregated tx. ++ * assuming un-aggregated tx in all cases. + */ +- airtime = ieee80211_calc_tx_airtime_rate(hw, rate, ri, band, +- ampdu ? len * 16 : len); +- if (ampdu) +- airtime /= 16; ++ if (duration > 400) /* <= VHT20 MCS2 1S */ ++ agg_shift = 1; ++ else if (duration > 250) /* <= VHT20 MCS3 1S or MCS1 2S */ ++ agg_shift = 2; ++ else if (duration > 150) /* <= VHT20 MCS5 1S or MCS3 2S */ ++ agg_shift = 3; ++ else ++ agg_shift = 4; + +- return airtime; ++ duration *= len; ++ duration /= AVG_PKT_SIZE; ++ duration /= 1024; ++ ++ return duration + (overhead >> agg_shift); + } + + if (!conf) diff --git a/feeds/ipq40xx/mac80211/patches/subsys/314-mac80211-add-missing-queue-hash-initialization-to-80.patch b/feeds/ipq40xx/mac80211/patches/subsys/314-mac80211-add-missing-queue-hash-initialization-to-80.patch new file mode 100644 index 000000000..eb56a2cac --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/subsys/314-mac80211-add-missing-queue-hash-initialization-to-80.patch @@ -0,0 +1,25 @@ +From: Felix Fietkau +Date: Mon, 17 Aug 2020 13:55:56 +0200 +Subject: [PATCH] mac80211: add missing queue/hash initialization to + 802.3 xmit + +Fixes AQL for encap-offloaded tx + +Signed-off-by: Felix Fietkau +--- + +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -4200,6 +4200,12 @@ static void ieee80211_8023_xmit(struct i + if (is_zero_ether_addr(ra)) + goto out_free; + ++ if (local->ops->wake_tx_queue) { ++ u16 queue = __ieee80211_select_queue(sdata, sta, skb); ++ skb_set_queue_mapping(skb, queue); ++ skb_get_hash(skb); ++ } ++ + multicast = is_multicast_ether_addr(ra); + + if (sta) diff --git a/feeds/ipq40xx/mac80211/patches/subsys/315-mac80211-check-and-refresh-aggregation-session-in-en.patch b/feeds/ipq40xx/mac80211/patches/subsys/315-mac80211-check-and-refresh-aggregation-session-in-en.patch new file mode 100644 index 000000000..e411d5972 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/subsys/315-mac80211-check-and-refresh-aggregation-session-in-en.patch @@ -0,0 +1,45 @@ +From: Felix Fietkau +Date: Mon, 17 Aug 2020 21:11:25 +0200 +Subject: [PATCH] mac80211: check and refresh aggregation session in + encap offload tx + +Update the last_tx timestamp to avoid tearing down the aggregation session +early. Fall back to the slow path if the session setup is still running + +Signed-off-by: Felix Fietkau +--- + +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -4189,6 +4189,8 @@ static void ieee80211_8023_xmit(struct i + bool authorized = false; + bool multicast; + unsigned char *ra = ehdr->h_dest; ++ struct tid_ampdu_tx *tid_tx; ++ u8 tid; + + if (IS_ERR(sta) || (sta && !sta->uploaded)) + sta = NULL; +@@ -4226,6 +4228,22 @@ static void ieee80211_8023_xmit(struct i + + memset(info, 0, sizeof(*info)); + ++ if (sta) { ++ 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)) { ++ /* fall back to non-offload slow path */ ++ __ieee80211_subif_start_xmit(skb, dev, 0, 0, NULL); ++ return; ++ } ++ ++ info->flags |= IEEE80211_TX_CTL_AMPDU; ++ if (tid_tx->timeout) ++ tid_tx->last_tx = jiffies; ++ } ++ } ++ + if (unlikely(!multicast && skb->sk && + skb_shinfo(skb)->tx_flags & SKBTX_WIFI_STATUS)) + info->ack_frame_id = ieee80211_store_ack_skb(local, skb, diff --git a/feeds/ipq40xx/mac80211/patches/subsys/316-mac80211-skip-encap-offload-for-tx-multicast-control.patch b/feeds/ipq40xx/mac80211/patches/subsys/316-mac80211-skip-encap-offload-for-tx-multicast-control.patch new file mode 100644 index 000000000..6dce21db1 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/subsys/316-mac80211-skip-encap-offload-for-tx-multicast-control.patch @@ -0,0 +1,136 @@ +From: Felix Fietkau +Date: Fri, 21 Aug 2020 05:54:10 +0200 +Subject: [PATCH] mac80211: skip encap offload for tx multicast/control + packets + +This simplifies the checks in the encap offload tx handler and allows using +it in cases where software crypto is used for multicast packets, e.g. when +using an AP_VLAN. + +Signed-off-by: Felix Fietkau +--- + +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -4184,88 +4184,47 @@ static void ieee80211_8023_xmit(struct i + struct sk_buff *skb) + { + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); +- struct ethhdr *ehdr = (struct ethhdr *)skb->data; + struct ieee80211_local *local = sdata->local; +- bool authorized = false; +- bool multicast; +- unsigned char *ra = ehdr->h_dest; + struct tid_ampdu_tx *tid_tx; + u8 tid; + +- if (IS_ERR(sta) || (sta && !sta->uploaded)) +- sta = NULL; +- +- if (sdata->vif.type == NL80211_IFTYPE_STATION && +- (!sta || !test_sta_flag(sta, WLAN_STA_TDLS_PEER))) +- ra = sdata->u.mgd.bssid; +- +- if (is_zero_ether_addr(ra)) +- goto out_free; +- + if (local->ops->wake_tx_queue) { + u16 queue = __ieee80211_select_queue(sdata, sta, skb); + skb_set_queue_mapping(skb, queue); + skb_get_hash(skb); + } + +- multicast = is_multicast_ether_addr(ra); +- +- if (sta) +- authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED); +- +- if (!multicast && !authorized && +- (ehdr->h_proto != sdata->control_port_protocol || +- !ether_addr_equal(sdata->vif.addr, ehdr->h_source))) +- goto out_free; +- +- if (multicast && sdata->vif.type == NL80211_IFTYPE_AP && +- !atomic_read(&sdata->u.ap.num_mcast_sta)) +- goto out_free; +- + if (unlikely(test_bit(SCAN_SW_SCANNING, &local->scanning)) && + test_bit(SDATA_STATE_OFFCHANNEL, &sdata->state)) + goto out_free; + + memset(info, 0, sizeof(*info)); + +- if (sta) { +- 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)) { +- /* fall back to non-offload slow path */ +- __ieee80211_subif_start_xmit(skb, dev, 0, 0, NULL); +- return; +- } +- +- info->flags |= IEEE80211_TX_CTL_AMPDU; +- if (tid_tx->timeout) +- tid_tx->last_tx = jiffies; ++ 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)) { ++ /* fall back to non-offload slow path */ ++ __ieee80211_subif_start_xmit(skb, dev, 0, 0, NULL); ++ return; + } ++ ++ info->flags |= IEEE80211_TX_CTL_AMPDU; ++ if (tid_tx->timeout) ++ tid_tx->last_tx = jiffies; + } + +- if (unlikely(!multicast && skb->sk && ++ 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); + +- if (unlikely(sdata->control_port_protocol == ehdr->h_proto)) { +- if (sdata->control_port_no_encrypt) +- info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; +- info->control.flags |= IEEE80211_TX_CTRL_PORT_CTRL_PROTO; +- } +- +- if (multicast) +- info->flags |= IEEE80211_TX_CTL_NO_ACK; +- + info->hw_queue = sdata->vif.hw_queue[skb_get_queue_mapping(skb)]; + + ieee80211_tx_stats(dev, skb->len); + +- if (sta) { +- sta->tx_stats.bytes[skb_get_queue_mapping(skb)] += skb->len; +- sta->tx_stats.packets[skb_get_queue_mapping(skb)]++; +- } ++ sta->tx_stats.bytes[skb_get_queue_mapping(skb)] += skb->len; ++ sta->tx_stats.packets[skb_get_queue_mapping(skb)]++; + + if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) + sdata = container_of(sdata->bss, +@@ -4286,6 +4245,7 @@ netdev_tx_t ieee80211_subif_start_xmit_8 + struct net_device *dev) + { + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); ++ struct ethhdr *ehdr = (struct ethhdr *)skb->data; + struct sta_info *sta; + + if (WARN_ON(!sdata->hw_80211_encap)) { +@@ -4302,6 +4262,10 @@ netdev_tx_t ieee80211_subif_start_xmit_8 + + if (ieee80211_lookup_ra_sta(sdata, skb, &sta)) + kfree_skb(skb); ++ else if (unlikely(IS_ERR_OR_NULL(sta) || !sta->uploaded || ++ !test_sta_flag(sta, WLAN_STA_AUTHORIZED) || ++ sdata->control_port_protocol == ehdr->h_proto)) ++ ieee80211_subif_start_xmit(skb, dev); + else + ieee80211_8023_xmit(sdata, dev, sta, skb); + diff --git a/feeds/ipq40xx/mac80211/patches/subsys/317-mac80211-set-info-control.hw_key-for-encap-offload-p.patch b/feeds/ipq40xx/mac80211/patches/subsys/317-mac80211-set-info-control.hw_key-for-encap-offload-p.patch new file mode 100644 index 000000000..cb5a98631 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/subsys/317-mac80211-set-info-control.hw_key-for-encap-offload-p.patch @@ -0,0 +1,31 @@ +From: Felix Fietkau +Date: Fri, 21 Aug 2020 06:03:45 +0200 +Subject: [PATCH] mac80211: set info->control.hw_key for encap offload + packets + +This is needed for drivers that don't do the key lookup themselves + +Signed-off-by: Felix Fietkau +--- + +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -4185,6 +4185,7 @@ static void ieee80211_8023_xmit(struct i + { + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ieee80211_local *local = sdata->local; ++ struct ieee80211_key *key; + struct tid_ampdu_tx *tid_tx; + u8 tid; + +@@ -4233,6 +4234,10 @@ static void ieee80211_8023_xmit(struct i + info->control.flags |= IEEE80211_TX_CTRL_HW_80211_ENCAP; + info->control.vif = &sdata->vif; + ++ key = rcu_dereference(sta->ptk[sta->ptk_idx]); ++ if (key) ++ info->control.hw_key = &key->conf; ++ + ieee80211_tx_8023(sdata, skb, skb->len, sta, false); + + return; diff --git a/feeds/ipq40xx/mac80211/patches/subsys/318-mac80211-rework-tx-encapsulation-offload-API.patch b/feeds/ipq40xx/mac80211/patches/subsys/318-mac80211-rework-tx-encapsulation-offload-API.patch new file mode 100644 index 000000000..7593c41da --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/subsys/318-mac80211-rework-tx-encapsulation-offload-API.patch @@ -0,0 +1,613 @@ +From: Felix Fietkau +Date: Thu, 13 Aug 2020 15:37:11 +0200 +Subject: [PATCH] mac80211: rework tx encapsulation offload API + +The current API (which lets the driver turn on/off per vif directly) has a +number of limitations: +- it does not deal with AP_VLAN +- conditions for enabling (no tkip, no monitor) are only checked at + add_interface time +- no way to indicate 4-addr support + +In order to address this, store offload flags in struct ieee80211_vif +(easy to extend for decap offload later). mac80211 initially sets the enable +flag, but gives the driver a chance to modify it before its settings are +applied. In addition to the .add_interface op, a .update_vif_offload op is +introduced, which can be used for runtime changes. + +If a driver can't disable encap offload at runtime, or if it has some extra +limitations, it can simply override the flags within those ops. + +Support for encap offload with 4-address mode interfaces can be enabled +by setting a flag from .add_interface or .update_vif_offload. + +Signed-off-by: Felix Fietkau +--- + +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -4150,6 +4150,35 @@ static int ath11k_set_he_mu_sounding_mod + return ret; + } + ++static void ath11k_mac_op_update_vif_offload(struct ieee80211_hw *hw, ++ struct ieee80211_vif *vif) ++{ ++ struct ath11k *ar = hw->priv; ++ struct ath11k_base *ab = ar->ab; ++ struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif); ++ u32 param_id, param_value; ++ int ret; ++ ++ param_id = WMI_VDEV_PARAM_TX_ENCAP_TYPE; ++ if (ath11k_frame_mode != ATH11K_HW_TXRX_ETHERNET || ++ (vif->type != NL80211_IFTYPE_STATION && ++ vif->type != NL80211_IFTYPE_AP)) ++ vif->offload_flags &= ~IEEE80211_OFFLOAD_ENCAP_ENABLED; ++ ++ if (vif->offload_flags & IEEE80211_OFFLOAD_ENCAP_ENABLED) ++ param_value = ATH11K_HW_TXRX_ETHERNET; ++ else ++ param_value = ATH11K_HW_TXRX_NATIVE_WIFI; ++ ++ 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 tx encap mode: %d\n", ++ arvif->vdev_id, ret); ++ vif->offload_flags &= ~IEEE80211_OFFLOAD_ENCAP_ENABLED; ++ } ++} ++ + static int ath11k_mac_op_add_interface(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) + { +@@ -4159,7 +4188,6 @@ static int ath11k_mac_op_add_interface(s + struct vdev_create_params vdev_param = {0}; + struct peer_create_params peer_param; + u32 param_id, param_value; +- int hw_encap = 0; + u16 nss; + int i; + int ret; +@@ -4253,30 +4281,7 @@ static int ath11k_mac_op_add_interface(s + list_add(&arvif->list, &ar->arvifs); + spin_unlock_bh(&ar->data_lock); + +- param_id = WMI_VDEV_PARAM_TX_ENCAP_TYPE; +- if (ath11k_frame_mode == ATH11K_HW_TXRX_ETHERNET) +- switch (vif->type) { +- case NL80211_IFTYPE_STATION: +- case NL80211_IFTYPE_AP_VLAN: +- case NL80211_IFTYPE_AP: +- hw_encap = 1; +- break; +- default: +- break; +- } +- +- if (ieee80211_set_hw_80211_encap(vif, hw_encap)) +- param_value = ATH11K_HW_TXRX_ETHERNET; +- else +- param_value = ATH11K_HW_TXRX_NATIVE_WIFI; +- +- 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 tx encap mode: %d\n", +- arvif->vdev_id, ret); +- goto err_vdev_del; +- } ++ ath11k_mac_op_update_vif_offload(hw, vif); + + nss = get_num_chains(ar->cfg_tx_chainmask) ? : 1; + ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, +@@ -5599,6 +5604,7 @@ static const struct ieee80211_ops ath11k + .reconfig_complete = ath11k_mac_op_reconfig_complete, + .add_interface = ath11k_mac_op_add_interface, + .remove_interface = ath11k_mac_op_remove_interface, ++ .update_vif_offload = ath11k_mac_op_update_vif_offload, + .config = ath11k_mac_op_config, + .bss_info_changed = ath11k_mac_op_bss_info_changed, + .configure_filter = ath11k_mac_op_configure_filter, +@@ -5852,6 +5858,7 @@ static int __ath11k_mac_register(struct + ieee80211_hw_set(ar->hw, QUEUE_CONTROL); + ieee80211_hw_set(ar->hw, SUPPORTS_TX_FRAG); + ieee80211_hw_set(ar->hw, REPORTS_LOW_ACK); ++ ieee80211_hw_set(ar->hw, SUPPORTS_TX_ENCAP_OFFLOAD); + if (ht_cap & WMI_HT_CAP_ENABLED) { + ieee80211_hw_set(ar->hw, AMPDU_AGGREGATION); + ieee80211_hw_set(ar->hw, TX_AMPDU_SETUP_IN_HW); +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -1603,6 +1603,21 @@ enum ieee80211_vif_flags { + IEEE80211_VIF_GET_NOA_UPDATE = BIT(3), + }; + ++ ++/** ++ * enum ieee80211_offload_flags - virtual interface offload flags ++ * ++ * @IEEE80211_OFFLOAD_ENCAP_ENABLED: tx encapsulation offload is enabled ++ * The driver supports sending frames passed as 802.3 frames by mac80211. ++ * It must also support sending 802.11 packets for the same interface. ++ * @IEEE80211_OFFLOAD_ENCAP_4ADDR: support 4-address mode encapsulation offload ++ */ ++ ++enum ieee80211_offload_flags { ++ IEEE80211_OFFLOAD_ENCAP_ENABLED = BIT(0), ++ IEEE80211_OFFLOAD_ENCAP_4ADDR = BIT(1), ++}; ++ + /** + * struct ieee80211_vif - per-interface data + * +@@ -1623,6 +1638,11 @@ enum ieee80211_vif_flags { + * these need to be set (or cleared) when the interface is added + * or, if supported by the driver, the interface type is changed + * at runtime, mac80211 will never touch this field ++ * @offloaad_flags: hardware offload capabilities/flags for this interface. ++ * These are initialized by mac80211 before calling .add_interface, ++ * .change_interface or .update_vif_offload and updated by the driver ++ * within these ops, based on supported features or runtime change ++ * restrictions. + * @hw_queue: hardware queue for each AC + * @cab_queue: content-after-beacon (DTIM beacon really) queue, AP mode only + * @chanctx_conf: The channel context this interface is assigned to, or %NULL +@@ -1659,6 +1679,7 @@ struct ieee80211_vif { + struct ieee80211_chanctx_conf __rcu *chanctx_conf; + + u32 driver_flags; ++ u32 offload_flags; + + #ifdef CPTCFG_MAC80211_DEBUGFS + struct dentry *debugfs_dir; +@@ -2325,6 +2346,9 @@ struct ieee80211_txq { + * aggregating MPDUs with the same keyid, allowing mac80211 to keep Tx + * A-MPDU sessions active while rekeying with Extended Key ID. + * ++ * @IEEE80211_HW_SUPPORTS_TX_ENCAP_OFFLOAD: Hardware supports tx encapsulation ++ * offload ++ * + * @NUM_IEEE80211_HW_FLAGS: number of hardware flags, used for sizing arrays + */ + enum ieee80211_hw_flags { +@@ -2377,6 +2401,7 @@ enum ieee80211_hw_flags { + IEEE80211_HW_SUPPORTS_MULTI_BSSID, + IEEE80211_HW_SUPPORTS_ONLY_HE_MULTI_BSSID, + IEEE80211_HW_AMPDU_KEYBORDER_SUPPORT, ++ IEEE80211_HW_SUPPORTS_TX_ENCAP_OFFLOAD, + + /* keep last, obviously */ + NUM_IEEE80211_HW_FLAGS +@@ -3811,6 +3836,8 @@ enum ieee80211_reconfig_type { + * @set_tid_config: Apply TID specific configurations. This callback may sleep. + * @reset_tid_config: Reset TID specific configuration for the peer. + * This callback may sleep. ++ * @update_vif_config: Update virtual interface offload flags ++ * This callback may sleep. + */ + struct ieee80211_ops { + void (*tx)(struct ieee80211_hw *hw, +@@ -4122,6 +4149,8 @@ struct ieee80211_ops { + int (*reset_tid_config)(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, u8 tids); ++ void (*update_vif_offload)(struct ieee80211_hw *hw, ++ struct ieee80211_vif *vif); + }; + + /** +--- a/net/mac80211/debugfs.c ++++ b/net/mac80211/debugfs.c +@@ -408,6 +408,7 @@ static const char *hw_flag_names[] = { + FLAG(SUPPORTS_MULTI_BSSID), + FLAG(SUPPORTS_ONLY_HE_MULTI_BSSID), + FLAG(AMPDU_KEYBORDER_SUPPORT), ++ FLAG(SUPPORTS_TX_ENCAP_OFFLOAD), + #undef FLAG + }; + +--- a/net/mac80211/driver-ops.h ++++ b/net/mac80211/driver-ops.h +@@ -1385,4 +1385,19 @@ static inline int drv_reset_tid_config(s + + return ret; + } ++ ++static inline void drv_update_vif_offload(struct ieee80211_local *local, ++ struct ieee80211_sub_if_data *sdata) ++{ ++ might_sleep(); ++ check_sdata_in_driver(sdata); ++ ++ if (!local->ops->update_vif_offload) ++ return; ++ ++ trace_drv_update_vif_offload(local, sdata); ++ local->ops->update_vif_offload(&local->hw, &sdata->vif); ++ trace_drv_return_void(local); ++} ++ + #endif /* __MAC80211_DRIVER_OPS */ +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -990,8 +990,6 @@ struct ieee80211_sub_if_data { + } debugfs; + #endif + +- bool hw_80211_encap; +- + /* must be last, dynamically sized area in this! */ + struct ieee80211_vif vif; + }; +@@ -1769,6 +1767,7 @@ void ieee80211_del_virtual_monitor(struc + bool __ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata); + void ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata, + bool update_bss); ++void ieee80211_recalc_offload(struct ieee80211_local *local); + + static inline bool ieee80211_sdata_running(struct ieee80211_sub_if_data *sdata) + { +--- a/net/mac80211/iface.c ++++ b/net/mac80211/iface.c +@@ -43,6 +43,7 @@ + */ + + static void ieee80211_iface_work(struct work_struct *work); ++static void ieee80211_set_vif_encap_ops(struct ieee80211_sub_if_data *sdata); + + bool __ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata) + { +@@ -348,6 +349,85 @@ static int ieee80211_check_queues(struct + return 0; + } + ++static bool ieee80211_iftype_supports_encap_offload(enum nl80211_iftype iftype) ++{ ++ switch (iftype) { ++ /* P2P GO and client are mapped to AP/STATION types */ ++ case NL80211_IFTYPE_AP: ++ case NL80211_IFTYPE_STATION: ++ return true; ++ default: ++ return false; ++ } ++} ++ ++static bool ieee80211_set_sdata_offload_flags(struct ieee80211_sub_if_data *sdata) ++{ ++ struct ieee80211_local *local = sdata->local; ++ u32 flags; ++ ++ flags = sdata->vif.offload_flags; ++ ++ if (ieee80211_hw_check(&local->hw, SUPPORTS_TX_ENCAP_OFFLOAD) && ++ ieee80211_iftype_supports_encap_offload(sdata->vif.type)) { ++ flags |= IEEE80211_OFFLOAD_ENCAP_ENABLED; ++ ++ if (!ieee80211_hw_check(&local->hw, SUPPORTS_TX_FRAG) && ++ local->hw.wiphy->frag_threshold != (u32)-1) ++ flags &= ~IEEE80211_OFFLOAD_ENCAP_ENABLED; ++ ++ if (local->monitors) ++ flags &= ~IEEE80211_OFFLOAD_ENCAP_ENABLED; ++ } else { ++ flags &= ~IEEE80211_OFFLOAD_ENCAP_ENABLED; ++ } ++ ++ if (sdata->vif.offload_flags == flags) ++ return false; ++ ++ sdata->vif.offload_flags = flags; ++ return true; ++} ++ ++ ++static void ieee80211_recalc_sdata_offload(struct ieee80211_sub_if_data *sdata) ++{ ++ struct ieee80211_local *local = sdata->local; ++ struct ieee80211_sub_if_data *vsdata; ++ ++ if (ieee80211_set_sdata_offload_flags(sdata)) { ++ drv_update_vif_offload(local, sdata); ++ ieee80211_set_vif_encap_ops(sdata); ++ } ++ ++ list_for_each_entry(vsdata, &local->interfaces, list) { ++ if (vsdata->vif.type != NL80211_IFTYPE_AP_VLAN || ++ vsdata->bss != &sdata->u.ap) ++ continue; ++ ++ ieee80211_set_vif_encap_ops(vsdata); ++ } ++} ++ ++void ieee80211_recalc_offload(struct ieee80211_local *local) ++{ ++ struct ieee80211_sub_if_data *sdata; ++ ++ if (!ieee80211_hw_check(&local->hw, SUPPORTS_TX_ENCAP_OFFLOAD)) ++ return; ++ ++ mutex_lock(&local->iflist_mtx); ++ ++ list_for_each_entry(sdata, &local->interfaces, list) { ++ if (!ieee80211_sdata_running(sdata)) ++ continue; ++ ++ ieee80211_recalc_sdata_offload(sdata); ++ } ++ ++ mutex_unlock(&local->iflist_mtx); ++} ++ + void ieee80211_adjust_monitor_flags(struct ieee80211_sub_if_data *sdata, + const int offset) + { +@@ -587,6 +667,7 @@ int ieee80211_do_open(struct wireless_de + if (rtnl_dereference(sdata->bss->beacon)) { + ieee80211_vif_vlan_copy_chanctx(sdata); + netif_carrier_on(dev); ++ ieee80211_set_vif_encap_ops(sdata); + } else { + netif_carrier_off(dev); + } +@@ -616,6 +697,7 @@ int ieee80211_do_open(struct wireless_de + + ieee80211_adjust_monitor_flags(sdata, 1); + ieee80211_configure_filter(local); ++ ieee80211_recalc_offload(local); + mutex_lock(&local->mtx); + ieee80211_recalc_idle(local); + mutex_unlock(&local->mtx); +@@ -625,10 +707,13 @@ int ieee80211_do_open(struct wireless_de + default: + if (coming_up) { + ieee80211_del_virtual_monitor(local); ++ ieee80211_set_sdata_offload_flags(sdata); + + res = drv_add_interface(local, sdata); + if (res) + goto err_stop; ++ ++ ieee80211_set_vif_encap_ops(sdata); + res = ieee80211_check_queues(sdata, + ieee80211_vif_type_p2p(&sdata->vif)); + if (res) +@@ -1286,61 +1371,6 @@ static const struct net_device_ops ieee8 + + }; + +-static void __ieee80211_set_hw_80211_encap(struct ieee80211_sub_if_data *sdata, +- bool enable) +-{ +- sdata->dev->netdev_ops = enable ? &ieee80211_dataif_8023_ops : +- &ieee80211_dataif_ops; +- sdata->hw_80211_encap = enable; +-} +- +-bool ieee80211_set_hw_80211_encap(struct ieee80211_vif *vif, bool enable) +-{ +- struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); +- struct ieee80211_local *local = sdata->local; +- struct ieee80211_sub_if_data *iter; +- struct ieee80211_key *key; +- +- mutex_lock(&local->iflist_mtx); +- list_for_each_entry(iter, &local->interfaces, list) { +- struct ieee80211_sub_if_data *disable = NULL; +- +- if (vif->type == NL80211_IFTYPE_MONITOR) { +- disable = iter; +- __ieee80211_set_hw_80211_encap(iter, false); +- } else if (iter->vif.type == NL80211_IFTYPE_MONITOR) { +- disable = sdata; +- enable = false; +- } +- if (disable) +- sdata_dbg(disable, +- "disable hw 80211 encap due to mon co-exist\n"); +- } +- mutex_unlock(&local->iflist_mtx); +- +- if (enable == sdata->hw_80211_encap) +- return enable; +- +- if (!sdata->dev) +- return false; +- +- if (!ieee80211_hw_check(&local->hw, SUPPORTS_TX_FRAG) && +- (local->hw.wiphy->frag_threshold != (u32)-1)) +- enable = false; +- +- mutex_lock(&sdata->local->key_mtx); +- list_for_each_entry(key, &sdata->key_list, list) { +- if (key->conf.cipher == WLAN_CIPHER_SUITE_TKIP) +- enable = false; +- } +- mutex_unlock(&sdata->local->key_mtx); +- +- __ieee80211_set_hw_80211_encap(sdata, enable); +- +- return enable; +-} +-EXPORT_SYMBOL(ieee80211_set_hw_80211_encap); +- + static void ieee80211_if_free(struct net_device *dev) + { + free_percpu(netdev_tstats(dev)); +@@ -1371,6 +1401,32 @@ static void ieee80211_if_setup_no_queue( + #endif + } + ++static void ieee80211_set_vif_encap_ops(struct ieee80211_sub_if_data *sdata) ++{ ++ struct ieee80211_local *local = sdata->local; ++ struct ieee80211_sub_if_data *bss = sdata; ++ bool enabled; ++ ++ if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) { ++ if (!sdata->bss) ++ return; ++ ++ bss = container_of(sdata->bss, struct ieee80211_sub_if_data, u.ap); ++ } ++ ++ if (!ieee80211_hw_check(&local->hw, SUPPORTS_TX_ENCAP_OFFLOAD) || ++ !ieee80211_iftype_supports_encap_offload(bss->vif.type)) ++ return; ++ ++ enabled = bss->vif.offload_flags & IEEE80211_OFFLOAD_ENCAP_ENABLED; ++ if (sdata->wdev.use_4addr && ++ !(bss->vif.offload_flags & IEEE80211_OFFLOAD_ENCAP_4ADDR)) ++ enabled = false; ++ ++ sdata->dev->netdev_ops = enabled ? &ieee80211_dataif_8023_ops : ++ &ieee80211_dataif_ops; ++} ++ + static void ieee80211_iface_work(struct work_struct *work) + { + struct ieee80211_sub_if_data *sdata = +@@ -1553,7 +1609,6 @@ static void ieee80211_setup_sdata(struct + sdata->vif.bss_conf.txpower = INT_MIN; /* unset */ + + sdata->noack_map = 0; +- sdata->hw_80211_encap = false; + + /* only monitor/p2p-device differ */ + if (sdata->dev) { +@@ -1688,6 +1743,7 @@ static int ieee80211_runtime_change_ifty + + ieee80211_teardown_sdata(sdata); + ++ ieee80211_set_sdata_offload_flags(sdata); + ret = drv_change_interface(local, sdata, internal_type, p2p); + if (ret) + type = ieee80211_vif_type_p2p(&sdata->vif); +@@ -1700,6 +1756,7 @@ static int ieee80211_runtime_change_ifty + ieee80211_check_queues(sdata, type); + + ieee80211_setup_sdata(sdata, type); ++ ieee80211_set_vif_encap_ops(sdata); + + err = ieee80211_do_open(&sdata->wdev, false); + WARN(err, "type change: do_open returned %d", err); +--- a/net/mac80211/key.c ++++ b/net/mac80211/key.c +@@ -177,13 +177,6 @@ static int ieee80211_key_enable_hw_accel + } + } + +- /* TKIP countermeasures don't work in encap offload mode */ +- if (key->conf.cipher == WLAN_CIPHER_SUITE_TKIP && +- sdata->hw_80211_encap) { +- sdata_dbg(sdata, "TKIP is not allowed in hw 80211 encap mode\n"); +- return -EINVAL; +- } +- + ret = drv_set_key(key->local, SET_KEY, sdata, + sta ? &sta->sta : NULL, &key->conf); + +@@ -219,14 +212,6 @@ static int ieee80211_key_enable_hw_accel + case WLAN_CIPHER_SUITE_CCMP_256: + case WLAN_CIPHER_SUITE_GCMP: + case WLAN_CIPHER_SUITE_GCMP_256: +- /* We cannot do software crypto of data frames with +- * encapsulation offload enabled. However for 802.11w to +- * function properly we need cmac/gmac keys. +- */ +- if (sdata->hw_80211_encap) +- return -EINVAL; +- /* Fall through */ +- + case WLAN_CIPHER_SUITE_AES_CMAC: + case WLAN_CIPHER_SUITE_BIP_CMAC_256: + case WLAN_CIPHER_SUITE_BIP_GMAC_128: +--- a/net/mac80211/trace.h ++++ b/net/mac80211/trace.h +@@ -2733,6 +2733,12 @@ TRACE_EVENT(drv_get_ftm_responder_stats, + ) + ); + ++DEFINE_EVENT(local_sdata_addr_evt, drv_update_vif_offload, ++ TP_PROTO(struct ieee80211_local *local, ++ struct ieee80211_sub_if_data *sdata), ++ TP_ARGS(local, sdata) ++); ++ + #endif /* !__MAC80211_DRIVER_TRACE || TRACE_HEADER_MULTI_READ */ + + #undef TRACE_INCLUDE_PATH +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -4181,11 +4181,10 @@ static bool ieee80211_tx_8023(struct iee + + static void ieee80211_8023_xmit(struct ieee80211_sub_if_data *sdata, + struct net_device *dev, struct sta_info *sta, +- struct sk_buff *skb) ++ struct ieee80211_key *key, struct sk_buff *skb) + { + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ieee80211_local *local = sdata->local; +- struct ieee80211_key *key; + struct tid_ampdu_tx *tid_tx; + u8 tid; + +@@ -4234,7 +4233,6 @@ static void ieee80211_8023_xmit(struct i + info->control.flags |= IEEE80211_TX_CTRL_HW_80211_ENCAP; + info->control.vif = &sdata->vif; + +- key = rcu_dereference(sta->ptk[sta->ptk_idx]); + if (key) + info->control.hw_key = &key->conf; + +@@ -4251,12 +4249,9 @@ netdev_tx_t ieee80211_subif_start_xmit_8 + { + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + struct ethhdr *ehdr = (struct ethhdr *)skb->data; ++ struct ieee80211_key *key; + struct sta_info *sta; +- +- if (WARN_ON(!sdata->hw_80211_encap)) { +- kfree_skb(skb); +- return NETDEV_TX_OK; +- } ++ bool offload = true; + + if (unlikely(skb->len < ETH_HLEN)) { + kfree_skb(skb); +@@ -4265,15 +4260,26 @@ netdev_tx_t ieee80211_subif_start_xmit_8 + + rcu_read_lock(); + +- if (ieee80211_lookup_ra_sta(sdata, skb, &sta)) ++ if (ieee80211_lookup_ra_sta(sdata, skb, &sta)) { + kfree_skb(skb); +- else if (unlikely(IS_ERR_OR_NULL(sta) || !sta->uploaded || +- !test_sta_flag(sta, WLAN_STA_AUTHORIZED) || +- sdata->control_port_protocol == ehdr->h_proto)) +- ieee80211_subif_start_xmit(skb, dev); ++ goto out; ++ } ++ ++ if (unlikely(IS_ERR_OR_NULL(sta) || !sta->uploaded || ++ !test_sta_flag(sta, WLAN_STA_AUTHORIZED) || ++ sdata->control_port_protocol == ehdr->h_proto)) ++ offload = false; ++ else if ((key = rcu_dereference(sta->ptk[sta->ptk_idx])) && ++ (!(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) || ++ key->conf.cipher == WLAN_CIPHER_SUITE_TKIP)) ++ offload = false; ++ ++ if (offload) ++ ieee80211_8023_xmit(sdata, dev, sta, key, skb); + else +- ieee80211_8023_xmit(sdata, dev, sta, skb); ++ ieee80211_subif_start_xmit(skb, dev); + ++out: + rcu_read_unlock(); + + return NETDEV_TX_OK; diff --git a/feeds/ipq40xx/mac80211/patches/subsys/319-mac80211-reduce-duplication-in-tx-status-functions.patch b/feeds/ipq40xx/mac80211/patches/subsys/319-mac80211-reduce-duplication-in-tx-status-functions.patch new file mode 100644 index 000000000..8b664d689 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/subsys/319-mac80211-reduce-duplication-in-tx-status-functions.patch @@ -0,0 +1,197 @@ +From: Felix Fietkau +Date: Mon, 17 Aug 2020 13:16:59 +0200 +Subject: [PATCH] mac80211: reduce duplication in tx status functions + +Move redundant functionality from __ieee80211_tx_status into +ieee80211_tx_status_ext. Preparation for unifying with the 802.3 tx status +codepath. + +Signed-off-by: Felix Fietkau +--- + +--- a/net/mac80211/status.c ++++ b/net/mac80211/status.c +@@ -184,18 +184,6 @@ static void ieee80211_frame_acked(struct + struct ieee80211_mgmt *mgmt = (void *) skb->data; + struct ieee80211_local *local = sta->local; + struct ieee80211_sub_if_data *sdata = sta->sdata; +- struct ieee80211_tx_info *txinfo = IEEE80211_SKB_CB(skb); +- +- if (ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS)) { +- sta->status_stats.last_ack = jiffies; +- if (txinfo->status.is_valid_ack_signal) { +- sta->status_stats.last_ack_signal = +- (s8)txinfo->status.ack_signal; +- sta->status_stats.ack_signal_filled = true; +- ewma_avg_signal_add(&sta->status_stats.avg_ack_signal, +- -txinfo->status.ack_signal); +- } +- } + + if (ieee80211_is_data_qos(mgmt->frame_control)) { + struct ieee80211_hdr *hdr = (void *) skb->data; +@@ -899,7 +887,8 @@ void ieee80211_tx_monitor(struct ieee802 + } + + static void __ieee80211_tx_status(struct ieee80211_hw *hw, +- struct ieee80211_tx_status *status) ++ struct ieee80211_tx_status *status, ++ int rates_idx, int retry_count) + { + struct sk_buff *skb = status->skb; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; +@@ -908,8 +897,6 @@ static void __ieee80211_tx_status(struct + struct sta_info *sta; + __le16 fc; + struct ieee80211_supported_band *sband; +- int retry_count; +- int rates_idx; + bool send_to_cooked; + bool acked; + bool noack_success; +@@ -918,8 +905,6 @@ static void __ieee80211_tx_status(struct + int tid = IEEE80211_NUM_TIDS; + u16 tx_time_est; + +- rates_idx = ieee80211_tx_get_rates(hw, info, &retry_count); +- + sband = local->hw.wiphy->bands[info->band]; + fc = hdr->frame_control; + +@@ -996,24 +981,14 @@ static void __ieee80211_tx_status(struct + if (info->flags & IEEE80211_TX_STAT_TX_FILTERED) { + ieee80211_handle_filtered_frame(local, sta, skb); + return; +- } else { ++ } else if (ieee80211_is_data_present(fc)) { + if (!acked && !noack_success) +- sta->status_stats.retry_failed++; +- sta->status_stats.retry_count += retry_count; +- +- if (ieee80211_is_data_present(fc)) { +- if (!acked && !noack_success) +- sta->status_stats.msdu_failed[tid]++; ++ sta->status_stats.msdu_failed[tid]++; + +- sta->status_stats.msdu_retries[tid] += +- retry_count; +- } ++ sta->status_stats.msdu_retries[tid] += ++ retry_count; + } + +- rate_control_tx_status(local, sband, status); +- if (ieee80211_vif_is_mesh(&sta->sdata->vif)) +- ieee80211s_update_metric(local, sta, status); +- + if (!(info->flags & IEEE80211_TX_CTL_INJECTED) && acked) + ieee80211_frame_acked(sta, skb); + +@@ -1038,20 +1013,6 @@ static void __ieee80211_tx_status(struct + true); + ieee80211_info_set_tx_time_est(info, 0); + } +- +- if (ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS)) { +- if (acked) { +- if (sta->status_stats.lost_packets) +- sta->status_stats.lost_packets = 0; +- +- /* Track when last TDLS packet was ACKed */ +- sta->status_stats.last_pkt_time = jiffies; +- } else if (noack_success) { +- /* nothing to do here, do not account as lost */ +- } else { +- ieee80211_lost_packet(sta, info); +- } +- } + } + + /* SNMP counters +@@ -1135,7 +1096,7 @@ void ieee80211_tx_status(struct ieee8021 + if (sta) + status.sta = &sta->sta; + +- __ieee80211_tx_status(hw, &status); ++ ieee80211_tx_status_ext(hw, &status); + rcu_read_unlock(); + } + EXPORT_SYMBOL(ieee80211_tx_status); +@@ -1148,7 +1109,7 @@ void ieee80211_tx_status_ext(struct ieee + struct ieee80211_sta *pubsta = status->sta; + struct ieee80211_supported_band *sband; + struct sta_info *sta; +- int retry_count; ++ int rates_idx, retry_count; + bool acked, noack_success; + + if (pubsta) { +@@ -1158,13 +1119,7 @@ void ieee80211_tx_status_ext(struct ieee + sta->tx_stats.last_rate_info = *status->rate; + } + +- if (status->skb) +- return __ieee80211_tx_status(hw, status); +- +- if (!status->sta) +- return; +- +- ieee80211_tx_get_rates(hw, info, &retry_count); ++ rates_idx = ieee80211_tx_get_rates(hw, info, &retry_count); + + sband = hw->wiphy->bands[info->band]; + +@@ -1176,20 +1131,30 @@ void ieee80211_tx_status_ext(struct ieee + sta->status_stats.retry_failed++; + sta->status_stats.retry_count += retry_count; + +- if (acked) { +- sta->status_stats.last_ack = jiffies; ++ if (ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS)) { ++ if (acked) { ++ sta->status_stats.last_ack = jiffies; + +- if (sta->status_stats.lost_packets) +- sta->status_stats.lost_packets = 0; ++ if (sta->status_stats.lost_packets) ++ sta->status_stats.lost_packets = 0; + +- /* Track when last packet was ACKed */ +- sta->status_stats.last_pkt_time = jiffies; +- } else if (test_sta_flag(sta, WLAN_STA_PS_STA)) { +- return; +- } else if (noack_success) { +- /* nothing to do here, do not account as lost */ +- } else { +- ieee80211_lost_packet(sta, info); ++ /* Track when last packet was ACKed */ ++ sta->status_stats.last_pkt_time = jiffies; ++ ++ if (info->status.is_valid_ack_signal) { ++ sta->status_stats.last_ack_signal = ++ (s8)info->status.ack_signal; ++ sta->status_stats.ack_signal_filled = true; ++ ewma_avg_signal_add(&sta->status_stats.avg_ack_signal, ++ -info->status.ack_signal); ++ } ++ } else if (test_sta_flag(sta, WLAN_STA_PS_STA)) { ++ return; ++ } else if (noack_success) { ++ /* nothing to do here, do not account as lost */ ++ } else { ++ ieee80211_lost_packet(sta, info); ++ } + } + + rate_control_tx_status(local, sband, status); +@@ -1197,6 +1162,10 @@ void ieee80211_tx_status_ext(struct ieee + ieee80211s_update_metric(local, sta, status); + } + ++ if (status->skb) ++ return __ieee80211_tx_status(hw, status, rates_idx, ++ retry_count); ++ + if (acked || noack_success) { + I802_DEBUG_INC(local->dot11TransmittedFrameCount); + if (!pubsta) diff --git a/feeds/ipq40xx/mac80211/patches/subsys/320-mac80211-remove-tx-status-call-to-ieee80211_sta_regi.patch b/feeds/ipq40xx/mac80211/patches/subsys/320-mac80211-remove-tx-status-call-to-ieee80211_sta_regi.patch new file mode 100644 index 000000000..168d6458a --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/subsys/320-mac80211-remove-tx-status-call-to-ieee80211_sta_regi.patch @@ -0,0 +1,26 @@ +From: Felix Fietkau +Date: Mon, 17 Aug 2020 13:29:12 +0200 +Subject: [PATCH] mac80211: remove tx status call to + ieee80211_sta_register_airtime + +All drivers using airtime fairness are calling ieee80211_sta_register_airtime +directly + +Signed-off-by: Felix Fietkau +--- + +--- a/net/mac80211/status.c ++++ b/net/mac80211/status.c +@@ -997,12 +997,6 @@ static void __ieee80211_tx_status(struct + ieee80211_sta_tx_notify(sta->sdata, (void *) skb->data, + acked, info->status.tx_time); + +- if (info->status.tx_time && +- wiphy_ext_feature_isset(local->hw.wiphy, +- NL80211_EXT_FEATURE_AIRTIME_FAIRNESS)) +- ieee80211_sta_register_airtime(&sta->sta, tid, +- info->status.tx_time, 0); +- + if ((tx_time_est = ieee80211_info_get_tx_time_est(info)) > 0) { + /* Do this here to avoid the expensive lookup of the sta + * in ieee80211_report_used_skb(). diff --git a/feeds/ipq40xx/mac80211/patches/subsys/321-mac80211-optimize-station-connection-monitor.patch b/feeds/ipq40xx/mac80211/patches/subsys/321-mac80211-optimize-station-connection-monitor.patch new file mode 100644 index 000000000..ed9efb2b0 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/subsys/321-mac80211-optimize-station-connection-monitor.patch @@ -0,0 +1,174 @@ +From: Felix Fietkau +Date: Mon, 17 Aug 2020 13:29:56 +0200 +Subject: [PATCH] mac80211: optimize station connection monitor + +Calling mod_timer for every rx/tx packet can be quite expensive. +Instead of constantly updating the timer, we can simply let it run out +and check the timestamp of the last ACK or rx packet to re-arm it. + +Signed-off-by: Felix Fietkau +--- + +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -2045,8 +2045,6 @@ void ieee80211_dynamic_ps_timer(struct t + void ieee80211_send_nullfunc(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata, + bool powersave); +-void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, +- struct ieee80211_hdr *hdr); + void ieee80211_sta_tx_notify(struct ieee80211_sub_if_data *sdata, + struct ieee80211_hdr *hdr, bool ack, u16 tx_time); + +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -2432,23 +2432,6 @@ static void ieee80211_set_disassoc(struc + sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM; + } + +-void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, +- struct ieee80211_hdr *hdr) +-{ +- /* +- * We can postpone the mgd.timer whenever receiving unicast frames +- * from AP because we know that the connection is working both ways +- * at that time. But multicast frames (and hence also beacons) must +- * be ignored here, because we need to trigger the timer during +- * data idle periods for sending the periodic probe request to the +- * AP we're connected to. +- */ +- if (is_multicast_ether_addr(hdr->addr1)) +- return; +- +- ieee80211_sta_reset_conn_monitor(sdata); +-} +- + static void ieee80211_reset_ap_probe(struct ieee80211_sub_if_data *sdata) + { + struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; +@@ -2521,21 +2504,13 @@ void ieee80211_sta_tx_notify(struct ieee + { + ieee80211_sta_tx_wmm_ac_notify(sdata, hdr, tx_time); + +- if (!ieee80211_is_data(hdr->frame_control)) +- return; +- +- if (ieee80211_is_any_nullfunc(hdr->frame_control) && +- sdata->u.mgd.probe_send_count > 0) { +- if (ack) +- ieee80211_sta_reset_conn_monitor(sdata); +- else +- sdata->u.mgd.nullfunc_failed = true; +- ieee80211_queue_work(&sdata->local->hw, &sdata->work); ++ if (!ieee80211_is_any_nullfunc(hdr->frame_control) || ++ !sdata->u.mgd.probe_send_count) + return; +- } + +- if (ack) +- ieee80211_sta_reset_conn_monitor(sdata); ++ if (!ack) ++ sdata->u.mgd.nullfunc_failed = true; ++ ieee80211_queue_work(&sdata->local->hw, &sdata->work); + } + + static void ieee80211_mlme_send_probe_req(struct ieee80211_sub_if_data *sdata, +@@ -3600,8 +3575,8 @@ static bool ieee80211_assoc_success(stru + * Start timer to probe the connection to the AP now. + * Also start the timer that will detect beacon loss. + */ +- ieee80211_sta_rx_notify(sdata, (struct ieee80211_hdr *)mgmt); + ieee80211_sta_reset_beacon_monitor(sdata); ++ ieee80211_sta_reset_conn_monitor(sdata); + + ret = true; + out: +@@ -4569,10 +4544,26 @@ static void ieee80211_sta_conn_mon_timer + from_timer(sdata, t, u.mgd.conn_mon_timer); + struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; + struct ieee80211_local *local = sdata->local; ++ struct sta_info *sta; ++ unsigned long timeout; + + if (sdata->vif.csa_active && !ifmgd->csa_waiting_bcn) + return; + ++ sta = sta_info_get(sdata, ifmgd->bssid); ++ if (!sta) ++ return; ++ ++ timeout = sta->status_stats.last_ack; ++ if (time_before(sta->status_stats.last_ack, sta->rx_stats.last_rx)) ++ timeout = sta->rx_stats.last_rx; ++ timeout += IEEE80211_CONNECTION_IDLE_TIME; ++ ++ if (time_is_before_jiffies(timeout)) { ++ mod_timer(&ifmgd->conn_mon_timer, round_jiffies_up(timeout)); ++ return; ++ } ++ + ieee80211_queue_work(&local->hw, &ifmgd->monitor_work); + } + +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -1811,9 +1811,6 @@ ieee80211_rx_h_sta_process(struct ieee80 + sta->rx_stats.last_rate = sta_stats_encode_rate(status); + } + +- if (rx->sdata->vif.type == NL80211_IFTYPE_STATION) +- ieee80211_sta_rx_notify(rx->sdata, hdr); +- + sta->rx_stats.fragments++; + + u64_stats_update_begin(&rx->sta->rx_stats.syncp); +@@ -4148,7 +4145,6 @@ void ieee80211_check_fast_rx(struct sta_ + fastrx.sa_offs = offsetof(struct ieee80211_hdr, addr2); + fastrx.expected_ds_bits = 0; + } else { +- fastrx.sta_notify = sdata->u.mgd.probe_send_count > 0; + fastrx.da_offs = offsetof(struct ieee80211_hdr, addr1); + fastrx.sa_offs = offsetof(struct ieee80211_hdr, addr3); + fastrx.expected_ds_bits = +@@ -4378,11 +4374,6 @@ static bool ieee80211_invoke_fast_rx(str + pskb_trim(skb, skb->len - fast_rx->icv_len)) + goto drop; + +- if (unlikely(fast_rx->sta_notify)) { +- ieee80211_sta_rx_notify(rx->sdata, hdr); +- fast_rx->sta_notify = false; +- } +- + /* statistics part of ieee80211_rx_h_sta_process() */ + if (!(status->flag & RX_FLAG_NO_SIGNAL_VAL)) { + stats->last_signal = status->signal; +--- a/net/mac80211/sta_info.h ++++ b/net/mac80211/sta_info.h +@@ -336,7 +336,6 @@ struct ieee80211_fast_tx { + * @expected_ds_bits: from/to DS bits expected + * @icv_len: length of the MIC if present + * @key: bool indicating encryption is expected (key is set) +- * @sta_notify: notify the MLME code (once) + * @internal_forward: forward froms internally on AP/VLAN type interfaces + * @uses_rss: copy of USES_RSS hw flag + * @da_offs: offset of the DA in the header (for header conversion) +@@ -352,7 +351,6 @@ struct ieee80211_fast_rx { + __le16 expected_ds_bits; + u8 icv_len; + u8 key:1, +- sta_notify:1, + internal_forward:1, + uses_rss:1; + u8 da_offs, sa_offs; +--- a/net/mac80211/status.c ++++ b/net/mac80211/status.c +@@ -1227,9 +1227,6 @@ void ieee80211_tx_status_8023(struct iee + sta->status_stats.retry_count += retry_count; + + if (ieee80211_hw_check(hw, REPORTS_TX_ACK_STATUS)) { +- if (acked && vif->type == NL80211_IFTYPE_STATION) +- ieee80211_sta_reset_conn_monitor(sdata); +- + sta->status_stats.last_ack = jiffies; + if (info->flags & IEEE80211_TX_STAT_ACK) { + if (sta->status_stats.lost_packets) diff --git a/feeds/ipq40xx/mac80211/patches/subsys/322-mac80211-swap-NEED_TXPROCESSING-and-HW_80211_ENCAP-t.patch b/feeds/ipq40xx/mac80211/patches/subsys/322-mac80211-swap-NEED_TXPROCESSING-and-HW_80211_ENCAP-t.patch new file mode 100644 index 000000000..b9069ef9b --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/subsys/322-mac80211-swap-NEED_TXPROCESSING-and-HW_80211_ENCAP-t.patch @@ -0,0 +1,227 @@ +From: Felix Fietkau +Date: Mon, 17 Aug 2020 13:35:32 +0200 +Subject: [PATCH] mac80211: swap NEED_TXPROCESSING and HW_80211_ENCAP tx + flags + +In order to unify the tx status path, the hw 802.11 encapsulation flag +needs to survive the trip to the tx status call. +Since we don't have any free bits in info->flags, we need to move one. +IEEE80211_TX_INTFL_NEED_TXPROCESSING is only used internally in mac80211, +and only before the call into the driver. + +Signed-off-by: Felix Fietkau +--- + +--- a/drivers/net/wireless/ath/ath11k/dp_tx.c ++++ b/drivers/net/wireless/ath/ath11k/dp_tx.c +@@ -14,7 +14,7 @@ ath11k_dp_tx_get_encap_type(struct ath11 + { + struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); + +- if (tx_info->control.flags & IEEE80211_TX_CTRL_HW_80211_ENCAP) ++ if (tx_info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) + return HAL_TCL_ENCAP_TYPE_ETHERNET; + + return HAL_TCL_ENCAP_TYPE_NATIVE_WIFI; +@@ -93,7 +93,7 @@ int ath11k_dp_tx(struct ath11k *ar, stru + if (test_bit(ATH11K_FLAG_CRASH_FLUSH, &ar->ab->dev_flags)) + return -ESHUTDOWN; + +- if (!(info->control.flags & IEEE80211_TX_CTRL_HW_80211_ENCAP) && ++ if (!(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) && + !ieee80211_is_data(hdr->frame_control)) + return -ENOTSUPP; + +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -3749,7 +3749,7 @@ static int ath11k_mac_mgmt_tx_wmi(struct + return -ENOSPC; + + info = IEEE80211_SKB_CB(skb); +- if (!(info->control.flags & IEEE80211_TX_CTRL_HW_80211_ENCAP)) { ++ if (!(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP)) { + if ((ieee80211_is_action(hdr->frame_control) || + ieee80211_is_deauth(hdr->frame_control) || + ieee80211_is_disassoc(hdr->frame_control)) && +@@ -3876,7 +3876,7 @@ static void ath11k_mac_op_tx(struct ieee + bool is_prb_rsp; + int ret; + +- if (info->control.flags & IEEE80211_TX_CTRL_HW_80211_ENCAP) { ++ if (info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) { + skb_cb->flags |= ATH11K_SKB_HW_80211_ENCAP; + } else if (ieee80211_is_mgmt(hdr->frame_control)) { + is_prb_rsp = ieee80211_is_probe_resp(hdr->frame_control); +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -720,9 +720,8 @@ struct ieee80211_bss_conf { + * @IEEE80211_TX_INTFL_OFFCHAN_TX_OK: Internal to mac80211. Used to indicate + * that a frame can be transmitted while the queues are stopped for + * off-channel operation. +- * @IEEE80211_TX_INTFL_NEED_TXPROCESSING: completely internal to mac80211, +- * used to indicate that a pending frame requires TX processing before +- * it can be sent out. ++ * @IEEE80211_TX_CTL_HW_80211_ENCAP: This frame uses hardware encapsulation ++ * (header conversion) + * @IEEE80211_TX_INTFL_RETRIED: completely internal to mac80211, + * used to indicate that a frame was already retried due to PS + * @IEEE80211_TX_INTFL_DONT_ENCRYPT: completely internal to mac80211, +@@ -791,7 +790,7 @@ enum mac80211_tx_info_flags { + IEEE80211_TX_STAT_AMPDU_NO_BACK = BIT(11), + IEEE80211_TX_CTL_RATE_CTRL_PROBE = BIT(12), + IEEE80211_TX_INTFL_OFFCHAN_TX_OK = BIT(13), +- IEEE80211_TX_INTFL_NEED_TXPROCESSING = BIT(14), ++ IEEE80211_TX_CTL_HW_80211_ENCAP = BIT(14), + IEEE80211_TX_INTFL_RETRIED = BIT(15), + IEEE80211_TX_INTFL_DONT_ENCRYPT = BIT(16), + IEEE80211_TX_CTL_NO_PS_BUFFER = BIT(17), +@@ -823,8 +822,9 @@ enum mac80211_tx_info_flags { + * @IEEE80211_TX_CTRL_AMSDU: This frame is an A-MSDU frame + * @IEEE80211_TX_CTRL_FAST_XMIT: This frame is going through the fast_xmit path + * @IEEE80211_TX_CTRL_SKIP_MPATH_LOOKUP: This frame skips mesh path lookup +- * @IEEE80211_TX_CTRL_HW_80211_ENCAP: This frame uses hardware encapsulation +- * (header conversion) ++ * @IEEE80211_TX_INTCFL_NEED_TXPROCESSING: completely internal to mac80211, ++ * used to indicate that a pending frame requires TX processing before ++ * it can be sent out. + * + * These flags are used in tx_info->control.flags. + */ +@@ -835,7 +835,7 @@ enum mac80211_tx_control_flags { + IEEE80211_TX_CTRL_AMSDU = BIT(3), + IEEE80211_TX_CTRL_FAST_XMIT = BIT(4), + IEEE80211_TX_CTRL_SKIP_MPATH_LOOKUP = BIT(5), +- IEEE80211_TX_CTRL_HW_80211_ENCAP = BIT(6), ++ IEEE80211_TX_INTCFL_NEED_TXPROCESSING = BIT(6), + }; + + /* +--- a/net/mac80211/mesh_hwmp.c ++++ b/net/mac80211/mesh_hwmp.c +@@ -212,7 +212,7 @@ static void prepare_frame_for_deferred_t + skb->priority = 7; + + info->control.vif = &sdata->vif; +- info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; ++ info->control.flags |= IEEE80211_TX_INTCFL_NEED_TXPROCESSING; + ieee80211_set_qos_hdr(sdata, skb); + ieee80211_mps_set_frame_flags(sdata, NULL, hdr); + } +@@ -1163,7 +1163,7 @@ int mesh_nexthop_resolve(struct ieee8021 + if (skb_queue_len(&mpath->frame_queue) >= MESH_FRAME_QUEUE_LEN) + skb_to_free = skb_dequeue(&mpath->frame_queue); + +- info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; ++ info->control.flags |= IEEE80211_TX_INTCFL_NEED_TXPROCESSING; + ieee80211_set_qos_hdr(sdata, skb); + skb_queue_tail(&mpath->frame_queue, skb); + if (skb_to_free) +--- a/net/mac80211/mesh_ps.c ++++ b/net/mac80211/mesh_ps.c +@@ -432,7 +432,7 @@ static void mpsp_qos_null_append(struct + + info = IEEE80211_SKB_CB(new_skb); + info->control.vif = &sdata->vif; +- info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; ++ info->control.flags |= IEEE80211_TX_INTCFL_NEED_TXPROCESSING; + + __skb_queue_tail(frames, new_skb); + } +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -2896,7 +2896,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80 + fwd_hdr->frame_control &= ~cpu_to_le16(IEEE80211_FCTL_RETRY); + info = IEEE80211_SKB_CB(fwd_skb); + memset(info, 0, sizeof(*info)); +- info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; ++ 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)) { +--- a/net/mac80211/status.c ++++ b/net/mac80211/status.c +@@ -66,8 +66,8 @@ static void ieee80211_handle_filtered_fr + + info->control.jiffies = jiffies; + info->control.vif = &sta->sdata->vif; +- info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING | +- IEEE80211_TX_INTFL_RETRANSMISSION; ++ info->control.flags |= IEEE80211_TX_INTCFL_NEED_TXPROCESSING; ++ info->flags |= IEEE80211_TX_INTFL_RETRANSMISSION; + info->flags &= ~IEEE80211_TX_TEMPORARY_FLAGS; + + sta->status_stats.filtered++; +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -530,7 +530,7 @@ ieee80211_tx_h_unicast_ps_buf(struct iee + + info->control.jiffies = jiffies; + info->control.vif = &tx->sdata->vif; +- info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; ++ info->control.flags |= IEEE80211_TX_INTCFL_NEED_TXPROCESSING; + info->flags &= ~IEEE80211_TX_TEMPORARY_FLAGS; + skb_queue_tail(&sta->ps_tx_buf[ac], tx->skb); + spin_unlock(&sta->ps_lock); +@@ -1132,7 +1132,7 @@ static bool ieee80211_tx_prep_agg(struct + tx->sta->sta.addr, tx->sta->sta.aid); + } + info->control.vif = &tx->sdata->vif; +- info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; ++ info->control.flags |= IEEE80211_TX_INTCFL_NEED_TXPROCESSING; + info->flags &= ~IEEE80211_TX_TEMPORARY_FLAGS; + __skb_queue_tail(&tid_tx->pending, skb); + if (skb_queue_len(&tid_tx->pending) > STA_MAX_TX_BUFFER) +@@ -1177,7 +1177,7 @@ ieee80211_tx_prepare(struct ieee80211_su + * we are doing the needed processing, so remove the flag + * now. + */ +- info->flags &= ~IEEE80211_TX_INTFL_NEED_TXPROCESSING; ++ info->control.flags &= ~IEEE80211_TX_INTCFL_NEED_TXPROCESSING; + + hdr = (struct ieee80211_hdr *) skb->data; + +@@ -1256,7 +1256,7 @@ static struct txq_info *ieee80211_get_tx + (info->control.flags & IEEE80211_TX_CTRL_PS_RESPONSE)) + return NULL; + +- if (!(info->control.flags & IEEE80211_TX_CTRL_HW_80211_ENCAP) && ++ 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) || +@@ -3640,7 +3640,7 @@ begin: + else + info->flags &= ~IEEE80211_TX_CTL_AMPDU; + +- if (info->control.flags & IEEE80211_TX_CTRL_HW_80211_ENCAP) ++ if (info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) + goto encap_out; + + if (info->control.flags & IEEE80211_TX_CTRL_FAST_XMIT) { +@@ -4230,7 +4230,7 @@ static void ieee80211_8023_xmit(struct i + sdata = container_of(sdata->bss, + struct ieee80211_sub_if_data, u.ap); + +- info->control.flags |= IEEE80211_TX_CTRL_HW_80211_ENCAP; ++ info->flags |= IEEE80211_TX_CTL_HW_80211_ENCAP; + info->control.vif = &sdata->vif; + + if (key) +@@ -4355,7 +4355,7 @@ static bool ieee80211_tx_pending_skb(str + + sdata = vif_to_sdata(info->control.vif); + +- if (info->flags & IEEE80211_TX_INTFL_NEED_TXPROCESSING) { ++ if (info->control.flags & IEEE80211_TX_INTCFL_NEED_TXPROCESSING) { + chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); + if (unlikely(!chanctx_conf)) { + dev_kfree_skb(skb); +@@ -4363,7 +4363,7 @@ static bool ieee80211_tx_pending_skb(str + } + info->band = chanctx_conf->def.chan->band; + result = ieee80211_tx(sdata, NULL, skb, true, 0); +- } else if (info->control.flags & IEEE80211_TX_CTRL_HW_80211_ENCAP) { ++ } else if (info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) { + if (ieee80211_lookup_ra_sta(sdata, skb, &sta)) { + dev_kfree_skb(skb); + return true; diff --git a/feeds/ipq40xx/mac80211/patches/subsys/323-mac80211-unify-802.3-offload-and-802.11-tx-status-co.patch b/feeds/ipq40xx/mac80211/patches/subsys/323-mac80211-unify-802.3-offload-and-802.11-tx-status-co.patch new file mode 100644 index 000000000..7bb54f499 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/subsys/323-mac80211-unify-802.3-offload-and-802.11-tx-status-co.patch @@ -0,0 +1,159 @@ +From: Felix Fietkau +Date: Mon, 17 Aug 2020 13:54:19 +0200 +Subject: [PATCH] mac80211: unify 802.3 (offload) and 802.11 tx status + codepath + +Make ieee80211_tx_status_8023 call ieee80211_tx_status_ext, similar to +ieee80211_tx_status. + +Signed-off-by: Felix Fietkau +--- + +--- a/net/mac80211/status.c ++++ b/net/mac80211/status.c +@@ -903,7 +903,6 @@ static void __ieee80211_tx_status(struct + struct ieee80211_bar *bar; + int shift = 0; + int tid = IEEE80211_NUM_TIDS; +- u16 tx_time_est; + + sband = local->hw.wiphy->bands[info->band]; + fc = hdr->frame_control; +@@ -996,17 +995,6 @@ static void __ieee80211_tx_status(struct + ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS)) + ieee80211_sta_tx_notify(sta->sdata, (void *) skb->data, + acked, info->status.tx_time); +- +- if ((tx_time_est = ieee80211_info_get_tx_time_est(info)) > 0) { +- /* Do this here to avoid the expensive lookup of the sta +- * in ieee80211_report_used_skb(). +- */ +- ieee80211_sta_update_pending_airtime(local, sta, +- skb_get_queue_mapping(skb), +- tx_time_est, +- true); +- ieee80211_info_set_tx_time_est(info, 0); +- } + } + + /* SNMP counters +@@ -1102,9 +1090,11 @@ void ieee80211_tx_status_ext(struct ieee + struct ieee80211_tx_info *info = status->info; + struct ieee80211_sta *pubsta = status->sta; + struct ieee80211_supported_band *sband; +- struct sta_info *sta; ++ struct sk_buff *skb = status->skb; ++ struct sta_info *sta = NULL; + int rates_idx, retry_count; + bool acked, noack_success; ++ u16 tx_time_est; + + if (pubsta) { + sta = container_of(pubsta, struct sta_info, sta); +@@ -1156,7 +1146,18 @@ void ieee80211_tx_status_ext(struct ieee + ieee80211s_update_metric(local, sta, status); + } + +- if (status->skb) ++ if (skb && (tx_time_est = ieee80211_info_get_tx_time_est(info)) > 0) { ++ /* Do this here to avoid the expensive lookup of the sta ++ * in ieee80211_report_used_skb(). ++ */ ++ ieee80211_sta_update_pending_airtime(local, sta, ++ skb_get_queue_mapping(skb), ++ tx_time_est, ++ true); ++ ieee80211_info_set_tx_time_est(info, 0); ++ } ++ ++ if (skb && !(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP)) + return __ieee80211_tx_status(hw, status, rates_idx, + retry_count); + +@@ -1171,6 +1172,12 @@ void ieee80211_tx_status_ext(struct ieee + } else { + I802_DEBUG_INC(local->dot11FailedCount); + } ++ ++ if (!skb) ++ return; ++ ++ ieee80211_report_used_skb(local, skb, false); ++ dev_kfree_skb(skb); + } + EXPORT_SYMBOL(ieee80211_tx_status_ext); + +@@ -1197,66 +1204,23 @@ void ieee80211_tx_status_8023(struct iee + struct ieee80211_vif *vif, + struct sk_buff *skb) + { +- struct ieee80211_local *local = hw_to_local(hw); + struct ieee80211_sub_if_data *sdata; +- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); ++ struct ieee80211_tx_status status = { ++ .skb = skb, ++ .info = IEEE80211_SKB_CB(skb), ++ }; + struct sta_info *sta; +- int retry_count; +- int rates_idx; +- bool acked; + + sdata = vif_to_sdata(vif); + +- acked = info->flags & IEEE80211_TX_STAT_ACK; +- rates_idx = ieee80211_tx_get_rates(hw, info, &retry_count); +- + rcu_read_lock(); + +- if (ieee80211_lookup_ra_sta(sdata, skb, &sta)) +- goto counters_update; +- +- if (IS_ERR(sta)) +- goto counters_update; +- +- if (!acked) +- sta->status_stats.retry_failed++; +- +- if (rates_idx != -1) +- sta->tx_stats.last_rate = info->status.rates[rates_idx]; +- +- sta->status_stats.retry_count += retry_count; +- +- if (ieee80211_hw_check(hw, REPORTS_TX_ACK_STATUS)) { +- sta->status_stats.last_ack = jiffies; +- if (info->flags & IEEE80211_TX_STAT_ACK) { +- if (sta->status_stats.lost_packets) +- sta->status_stats.lost_packets = 0; ++ if (!ieee80211_lookup_ra_sta(sdata, skb, &sta) && !IS_ERR(sta)) ++ status.sta = &sta->sta; + +- sta->status_stats.last_pkt_time = jiffies; +- } else { +- ieee80211_lost_packet(sta, info); +- } +- } ++ ieee80211_tx_status_ext(hw, &status); + +-counters_update: + rcu_read_unlock(); +- ieee80211_led_tx(local); +- +- if (!(info->flags & IEEE80211_TX_STAT_ACK) && +- !(info->flags & IEEE80211_TX_STAT_NOACK_TRANSMITTED)) +- goto skip_stats_update; +- +- I802_DEBUG_INC(local->dot11TransmittedFrameCount); +- if (is_multicast_ether_addr(skb->data)) +- I802_DEBUG_INC(local->dot11MulticastTransmittedFrameCount); +- if (retry_count > 0) +- I802_DEBUG_INC(local->dot11RetryCount); +- if (retry_count > 1) +- I802_DEBUG_INC(local->dot11MultipleRetryCount); +- +-skip_stats_update: +- ieee80211_report_used_skb(local, skb, false); +- dev_kfree_skb(skb); + } + EXPORT_SYMBOL(ieee80211_tx_status_8023); + diff --git a/feeds/ipq40xx/mac80211/patches/subsys/324-mac80211-support-using-ieee80211_tx_status_ext-to-fr.patch b/feeds/ipq40xx/mac80211/patches/subsys/324-mac80211-support-using-ieee80211_tx_status_ext-to-fr.patch new file mode 100644 index 000000000..5469a419b --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/subsys/324-mac80211-support-using-ieee80211_tx_status_ext-to-fr.patch @@ -0,0 +1,63 @@ +From: Felix Fietkau +Date: Thu, 20 Aug 2020 17:27:00 +0200 +Subject: [PATCH] mac80211: support using ieee80211_tx_status_ext to free + skbs without status info + +For encap-offloaded packets, ieee80211_free_txskb cannot be used, since it +does not have the vif pointer. +Using ieee80211_tx_status_ext for this purpose has the advantage of being able +avoid an extra station lookup for AQL + +Signed-off-by: Felix Fietkau +--- + +--- a/net/mac80211/status.c ++++ b/net/mac80211/status.c +@@ -1103,6 +1103,21 @@ void ieee80211_tx_status_ext(struct ieee + sta->tx_stats.last_rate_info = *status->rate; + } + ++ if (skb && (tx_time_est = ++ ieee80211_info_get_tx_time_est(IEEE80211_SKB_CB(skb))) > 0) { ++ /* Do this here to avoid the expensive lookup of the sta ++ * in ieee80211_report_used_skb(). ++ */ ++ ieee80211_sta_update_pending_airtime(local, sta, ++ skb_get_queue_mapping(skb), ++ tx_time_est, ++ true); ++ ieee80211_info_set_tx_time_est(IEEE80211_SKB_CB(skb), 0); ++ } ++ ++ if (!status->info) ++ goto free; ++ + rates_idx = ieee80211_tx_get_rates(hw, info, &retry_count); + + sband = hw->wiphy->bands[info->band]; +@@ -1146,17 +1161,6 @@ void ieee80211_tx_status_ext(struct ieee + ieee80211s_update_metric(local, sta, status); + } + +- if (skb && (tx_time_est = ieee80211_info_get_tx_time_est(info)) > 0) { +- /* Do this here to avoid the expensive lookup of the sta +- * in ieee80211_report_used_skb(). +- */ +- ieee80211_sta_update_pending_airtime(local, sta, +- skb_get_queue_mapping(skb), +- tx_time_est, +- true); +- ieee80211_info_set_tx_time_est(info, 0); +- } +- + if (skb && !(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP)) + return __ieee80211_tx_status(hw, status, rates_idx, + retry_count); +@@ -1173,6 +1177,7 @@ void ieee80211_tx_status_ext(struct ieee + I802_DEBUG_INC(local->dot11FailedCount); + } + ++free: + if (!skb) + return; + diff --git a/feeds/ipq40xx/mac80211/patches/subsys/325-mac80211-extend-ieee80211_tx_status_ext-to-support-b.patch b/feeds/ipq40xx/mac80211/patches/subsys/325-mac80211-extend-ieee80211_tx_status_ext-to-support-b.patch new file mode 100644 index 000000000..e8b29bb4c --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/subsys/325-mac80211-extend-ieee80211_tx_status_ext-to-support-b.patch @@ -0,0 +1,53 @@ +From: Felix Fietkau +Date: Fri, 21 Aug 2020 05:49:07 +0200 +Subject: [PATCH] mac80211: extend ieee80211_tx_status_ext to support + bulk free + +Store processed skbs ready to be freed in a list so the driver bulk free them + +Signed-off-by: Felix Fietkau +--- + +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -1092,12 +1092,14 @@ ieee80211_info_get_tx_time_est(struct ie + * @info: Basic tx status information + * @skb: Packet skb (can be NULL if not provided by the driver) + * @rate: The TX rate that was used when sending the packet ++ * @free_list: list where processed skbs are stored to be free'd by the driver + */ + struct ieee80211_tx_status { + struct ieee80211_sta *sta; + struct ieee80211_tx_info *info; + struct sk_buff *skb; + struct rate_info *rate; ++ struct list_head *free_list; + }; + + /** +--- a/net/mac80211/status.c ++++ b/net/mac80211/status.c +@@ -1053,7 +1053,10 @@ static void __ieee80211_tx_status(struct + * with this test... + */ + if (!local->monitors && (!send_to_cooked || !local->cooked_mntrs)) { +- dev_kfree_skb(skb); ++ if (status->free_list) ++ list_add_tail(&skb->list, status->free_list); ++ else ++ dev_kfree_skb(skb); + return; + } + +@@ -1182,7 +1185,10 @@ free: + return; + + ieee80211_report_used_skb(local, skb, false); +- dev_kfree_skb(skb); ++ if (status->free_list) ++ list_add_tail(&skb->list, status->free_list); ++ else ++ dev_kfree_skb(skb); + } + EXPORT_SYMBOL(ieee80211_tx_status_ext); + diff --git a/feeds/ipq40xx/mac80211/patches/subsys/326-mac80211-notify-the-driver-when-a-sta-uses-4-address.patch b/feeds/ipq40xx/mac80211/patches/subsys/326-mac80211-notify-the-driver-when-a-sta-uses-4-address.patch new file mode 100644 index 000000000..5ad5ac6a7 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/subsys/326-mac80211-notify-the-driver-when-a-sta-uses-4-address.patch @@ -0,0 +1,109 @@ +From: Felix Fietkau +Date: Fri, 21 Aug 2020 05:51:58 +0200 +Subject: [PATCH] mac80211: notify the driver when a sta uses 4-address + mode + +This is needed for encapsulation offload of 4-address mode packets + +Signed-off-by: Felix Fietkau +--- + +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -3840,6 +3840,8 @@ enum ieee80211_reconfig_type { + * This callback may sleep. + * @update_vif_config: Update virtual interface offload flags + * This callback may sleep. ++ * @sta_set_4addr: Called to notify the driver when a station starts/stops using ++ * 4-address mode + */ + struct ieee80211_ops { + void (*tx)(struct ieee80211_hw *hw, +@@ -4153,6 +4155,8 @@ struct ieee80211_ops { + struct ieee80211_sta *sta, u8 tids); + void (*update_vif_offload)(struct ieee80211_hw *hw, + struct ieee80211_vif *vif); ++ void (*sta_set_4addr)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, ++ struct ieee80211_sta *sta, bool enabled); + }; + + /** +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -1693,6 +1693,7 @@ static int ieee80211_change_station(stru + + rcu_assign_pointer(vlansdata->u.vlan.sta, sta); + __ieee80211_check_fast_rx_iface(vlansdata); ++ drv_sta_set_4addr(local, sta->sdata, &sta->sta, true); + } + + if (sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN && +--- a/net/mac80211/driver-ops.h ++++ b/net/mac80211/driver-ops.h +@@ -1400,4 +1400,18 @@ static inline void drv_update_vif_offloa + trace_drv_return_void(local); + } + ++static inline void drv_sta_set_4addr(struct ieee80211_local *local, ++ struct ieee80211_sub_if_data *sdata, ++ struct ieee80211_sta *sta, bool enabled) ++{ ++ sdata = get_bss_sdata(sdata); ++ if (!check_sdata_in_driver(sdata)) ++ return; ++ ++ trace_drv_sta_set_4addr(local, sdata, sta, enabled); ++ if (local->ops->sta_set_4addr) ++ local->ops->sta_set_4addr(&local->hw, &sdata->vif, sta, enabled); ++ trace_drv_return_void(local); ++} ++ + #endif /* __MAC80211_DRIVER_OPS */ +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -3518,6 +3518,9 @@ static bool ieee80211_assoc_success(stru + goto out; + } + ++ if (sdata->wdev.use_4addr) ++ drv_sta_set_4addr(local, sdata, &sta->sta, true); ++ + mutex_unlock(&sdata->local->sta_mtx); + + /* +--- a/net/mac80211/trace.h ++++ b/net/mac80211/trace.h +@@ -2739,6 +2739,33 @@ DEFINE_EVENT(local_sdata_addr_evt, drv_u + TP_ARGS(local, sdata) + ); + ++TRACE_EVENT(drv_sta_set_4addr, ++ TP_PROTO(struct ieee80211_local *local, ++ struct ieee80211_sub_if_data *sdata, ++ struct ieee80211_sta *sta, bool enabled), ++ ++ TP_ARGS(local, sdata, sta, enabled), ++ ++ TP_STRUCT__entry( ++ LOCAL_ENTRY ++ VIF_ENTRY ++ STA_ENTRY ++ __field(bool, enabled) ++ ), ++ ++ TP_fast_assign( ++ LOCAL_ASSIGN; ++ VIF_ASSIGN; ++ STA_ASSIGN; ++ __entry->enabled = enabled; ++ ), ++ ++ TP_printk( ++ LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT " enabled:%d", ++ LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG, __entry->enabled ++ ) ++); ++ + #endif /* !__MAC80211_DRIVER_TRACE || TRACE_HEADER_MULTI_READ */ + + #undef TRACE_INCLUDE_PATH diff --git a/feeds/ipq40xx/mac80211/patches/subsys/327-mac80211-reorganize-code-to-remove-a-forward-declara.patch b/feeds/ipq40xx/mac80211/patches/subsys/327-mac80211-reorganize-code-to-remove-a-forward-declara.patch new file mode 100644 index 000000000..a3d600152 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/subsys/327-mac80211-reorganize-code-to-remove-a-forward-declara.patch @@ -0,0 +1,1110 @@ +From: Felix Fietkau +Date: Tue, 8 Sep 2020 12:16:26 +0200 +Subject: [PATCH] mac80211: reorganize code to remove a forward + declaration + +Remove the newly added ieee80211_set_vif_encap_ops declaration. +No further code changes + +Signed-off-by: Felix Fietkau +--- + +--- a/net/mac80211/iface.c ++++ b/net/mac80211/iface.c +@@ -43,7 +43,6 @@ + */ + + static void ieee80211_iface_work(struct work_struct *work); +-static void ieee80211_set_vif_encap_ops(struct ieee80211_sub_if_data *sdata); + + bool __ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata) + { +@@ -349,6 +348,511 @@ static int ieee80211_check_queues(struct + return 0; + } + ++static int ieee80211_open(struct net_device *dev) ++{ ++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); ++ int err; ++ ++ /* fail early if user set an invalid address */ ++ if (!is_valid_ether_addr(dev->dev_addr)) ++ return -EADDRNOTAVAIL; ++ ++ err = ieee80211_check_concurrent_iface(sdata, sdata->vif.type); ++ if (err) ++ return err; ++ ++ return ieee80211_do_open(&sdata->wdev, true); ++} ++ ++static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, ++ bool going_down) ++{ ++ struct ieee80211_local *local = sdata->local; ++ unsigned long flags; ++ struct sk_buff *skb, *tmp; ++ u32 hw_reconf_flags = 0; ++ int i, flushed; ++ struct ps_data *ps; ++ struct cfg80211_chan_def chandef; ++ bool cancel_scan; ++ struct cfg80211_nan_func *func; ++ ++ clear_bit(SDATA_STATE_RUNNING, &sdata->state); ++ ++ cancel_scan = rcu_access_pointer(local->scan_sdata) == sdata; ++ if (cancel_scan) ++ ieee80211_scan_cancel(local); ++ ++ /* ++ * Stop TX on this interface first. ++ */ ++ if (sdata->dev) ++ netif_tx_stop_all_queues(sdata->dev); ++ ++ ieee80211_roc_purge(local, sdata); ++ ++ switch (sdata->vif.type) { ++ case NL80211_IFTYPE_STATION: ++ ieee80211_mgd_stop(sdata); ++ break; ++ case NL80211_IFTYPE_ADHOC: ++ ieee80211_ibss_stop(sdata); ++ break; ++ case NL80211_IFTYPE_MONITOR: ++ if (sdata->u.mntr.flags & MONITOR_FLAG_COOK_FRAMES) ++ break; ++ list_del_rcu(&sdata->u.mntr.list); ++ break; ++ default: ++ break; ++ } ++ ++ /* ++ * Remove all stations associated with this interface. ++ * ++ * This must be done before calling ops->remove_interface() ++ * because otherwise we can later invoke ops->sta_notify() ++ * whenever the STAs are removed, and that invalidates driver ++ * assumptions about always getting a vif pointer that is valid ++ * (because if we remove a STA after ops->remove_interface() ++ * the driver will have removed the vif info already!) ++ * ++ * In WDS mode a station must exist here and be flushed, for ++ * AP_VLANs stations may exist since there's nothing else that ++ * would have removed them, but in other modes there shouldn't ++ * be any stations. ++ */ ++ flushed = sta_info_flush(sdata); ++ WARN_ON_ONCE(sdata->vif.type != NL80211_IFTYPE_AP_VLAN && ++ ((sdata->vif.type != NL80211_IFTYPE_WDS && flushed > 0) || ++ (sdata->vif.type == NL80211_IFTYPE_WDS && flushed != 1))); ++ ++ /* don't count this interface for allmulti while it is down */ ++ if (sdata->flags & IEEE80211_SDATA_ALLMULTI) ++ atomic_dec(&local->iff_allmultis); ++ ++ if (sdata->vif.type == NL80211_IFTYPE_AP) { ++ local->fif_pspoll--; ++ local->fif_probe_req--; ++ } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { ++ local->fif_probe_req--; ++ } ++ ++ if (sdata->dev) { ++ netif_addr_lock_bh(sdata->dev); ++ spin_lock_bh(&local->filter_lock); ++ __hw_addr_unsync(&local->mc_list, &sdata->dev->mc, ++ sdata->dev->addr_len); ++ spin_unlock_bh(&local->filter_lock); ++ netif_addr_unlock_bh(sdata->dev); ++ } ++ ++ del_timer_sync(&local->dynamic_ps_timer); ++ cancel_work_sync(&local->dynamic_ps_enable_work); ++ ++ cancel_work_sync(&sdata->recalc_smps); ++ sdata_lock(sdata); ++ mutex_lock(&local->mtx); ++ sdata->vif.csa_active = false; ++ if (sdata->vif.type == NL80211_IFTYPE_STATION) ++ sdata->u.mgd.csa_waiting_bcn = false; ++ if (sdata->csa_block_tx) { ++ ieee80211_wake_vif_queues(local, sdata, ++ IEEE80211_QUEUE_STOP_REASON_CSA); ++ sdata->csa_block_tx = false; ++ } ++ mutex_unlock(&local->mtx); ++ sdata_unlock(sdata); ++ ++ cancel_work_sync(&sdata->csa_finalize_work); ++ ++ cancel_delayed_work_sync(&sdata->dfs_cac_timer_work); ++ ++ if (sdata->wdev.cac_started) { ++ chandef = sdata->vif.bss_conf.chandef; ++ WARN_ON(local->suspended); ++ mutex_lock(&local->mtx); ++ ieee80211_vif_release_channel(sdata); ++ mutex_unlock(&local->mtx); ++ cfg80211_cac_event(sdata->dev, &chandef, ++ NL80211_RADAR_CAC_ABORTED, ++ GFP_KERNEL); ++ } ++ ++ /* APs need special treatment */ ++ if (sdata->vif.type == NL80211_IFTYPE_AP) { ++ struct ieee80211_sub_if_data *vlan, *tmpsdata; ++ ++ /* down all dependent devices, that is VLANs */ ++ list_for_each_entry_safe(vlan, tmpsdata, &sdata->u.ap.vlans, ++ u.vlan.list) ++ dev_close(vlan->dev); ++ WARN_ON(!list_empty(&sdata->u.ap.vlans)); ++ } else if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) { ++ /* remove all packets in parent bc_buf pointing to this dev */ ++ ps = &sdata->bss->ps; ++ ++ spin_lock_irqsave(&ps->bc_buf.lock, flags); ++ skb_queue_walk_safe(&ps->bc_buf, skb, tmp) { ++ if (skb->dev == sdata->dev) { ++ __skb_unlink(skb, &ps->bc_buf); ++ local->total_ps_buffered--; ++ ieee80211_free_txskb(&local->hw, skb); ++ } ++ } ++ spin_unlock_irqrestore(&ps->bc_buf.lock, flags); ++ } ++ ++ if (going_down) ++ local->open_count--; ++ ++ switch (sdata->vif.type) { ++ case NL80211_IFTYPE_AP_VLAN: ++ mutex_lock(&local->mtx); ++ list_del(&sdata->u.vlan.list); ++ mutex_unlock(&local->mtx); ++ RCU_INIT_POINTER(sdata->vif.chanctx_conf, NULL); ++ /* see comment in the default case below */ ++ ieee80211_free_keys(sdata, true); ++ /* no need to tell driver */ ++ break; ++ case NL80211_IFTYPE_MONITOR: ++ if (sdata->u.mntr.flags & MONITOR_FLAG_COOK_FRAMES) { ++ local->cooked_mntrs--; ++ break; ++ } ++ ++ local->monitors--; ++ if (local->monitors == 0) { ++ local->hw.conf.flags &= ~IEEE80211_CONF_MONITOR; ++ hw_reconf_flags |= IEEE80211_CONF_CHANGE_MONITOR; ++ } ++ ++ ieee80211_adjust_monitor_flags(sdata, -1); ++ break; ++ case NL80211_IFTYPE_NAN: ++ /* clean all the functions */ ++ spin_lock_bh(&sdata->u.nan.func_lock); ++ ++ idr_for_each_entry(&sdata->u.nan.function_inst_ids, func, i) { ++ idr_remove(&sdata->u.nan.function_inst_ids, i); ++ cfg80211_free_nan_func(func); ++ } ++ idr_destroy(&sdata->u.nan.function_inst_ids); ++ ++ spin_unlock_bh(&sdata->u.nan.func_lock); ++ break; ++ case NL80211_IFTYPE_P2P_DEVICE: ++ /* relies on synchronize_rcu() below */ ++ RCU_INIT_POINTER(local->p2p_sdata, NULL); ++ /* fall through */ ++ default: ++ cancel_work_sync(&sdata->work); ++ /* ++ * When we get here, the interface is marked down. ++ * Free the remaining keys, if there are any ++ * (which can happen in AP mode if userspace sets ++ * keys before the interface is operating, and maybe ++ * also in WDS mode) ++ * ++ * Force the key freeing to always synchronize_net() ++ * to wait for the RX path in case it is using this ++ * interface enqueuing frames at this very time on ++ * another CPU. ++ */ ++ ieee80211_free_keys(sdata, true); ++ skb_queue_purge(&sdata->skb_queue); ++ } ++ ++ spin_lock_irqsave(&local->queue_stop_reason_lock, flags); ++ for (i = 0; i < IEEE80211_MAX_QUEUES; i++) { ++ skb_queue_walk_safe(&local->pending[i], skb, tmp) { ++ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); ++ if (info->control.vif == &sdata->vif) { ++ __skb_unlink(skb, &local->pending[i]); ++ ieee80211_free_txskb(&local->hw, skb); ++ } ++ } ++ } ++ spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); ++ ++ if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) ++ ieee80211_txq_remove_vlan(local, sdata); ++ ++ sdata->bss = NULL; ++ ++ if (local->open_count == 0) ++ ieee80211_clear_tx_pending(local); ++ ++ sdata->vif.bss_conf.beacon_int = 0; ++ ++ /* ++ * If the interface goes down while suspended, presumably because ++ * the device was unplugged and that happens before our resume, ++ * then the driver is already unconfigured and the remainder of ++ * this function isn't needed. ++ * XXX: what about WoWLAN? If the device has software state, e.g. ++ * memory allocated, it might expect teardown commands from ++ * mac80211 here? ++ */ ++ if (local->suspended) { ++ WARN_ON(local->wowlan); ++ WARN_ON(rtnl_dereference(local->monitor_sdata)); ++ return; ++ } ++ ++ switch (sdata->vif.type) { ++ case NL80211_IFTYPE_AP_VLAN: ++ break; ++ case NL80211_IFTYPE_MONITOR: ++ if (local->monitors == 0) ++ ieee80211_del_virtual_monitor(local); ++ ++ mutex_lock(&local->mtx); ++ ieee80211_recalc_idle(local); ++ mutex_unlock(&local->mtx); ++ ++ if (!(sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE)) ++ break; ++ ++ /* fall through */ ++ default: ++ if (going_down) ++ drv_remove_interface(local, sdata); ++ } ++ ++ ieee80211_recalc_ps(local); ++ ++ if (cancel_scan) ++ flush_delayed_work(&local->scan_work); ++ ++ if (local->open_count == 0) { ++ ieee80211_stop_device(local); ++ ++ /* no reconfiguring after stop! */ ++ return; ++ } ++ ++ /* do after stop to avoid reconfiguring when we stop anyway */ ++ ieee80211_configure_filter(local); ++ ieee80211_hw_config(local, hw_reconf_flags); ++ ++ if (local->monitors == local->open_count) ++ ieee80211_add_virtual_monitor(local); ++} ++ ++static int ieee80211_stop(struct net_device *dev) ++{ ++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); ++ ++ ieee80211_do_stop(sdata, true); ++ ++ return 0; ++} ++ ++static void ieee80211_set_multicast_list(struct net_device *dev) ++{ ++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); ++ struct ieee80211_local *local = sdata->local; ++ int allmulti, sdata_allmulti; ++ ++ allmulti = !!(dev->flags & IFF_ALLMULTI); ++ sdata_allmulti = !!(sdata->flags & IEEE80211_SDATA_ALLMULTI); ++ ++ if (allmulti != sdata_allmulti) { ++ if (dev->flags & IFF_ALLMULTI) ++ atomic_inc(&local->iff_allmultis); ++ else ++ atomic_dec(&local->iff_allmultis); ++ sdata->flags ^= IEEE80211_SDATA_ALLMULTI; ++ } ++ ++ spin_lock_bh(&local->filter_lock); ++ __hw_addr_sync(&local->mc_list, &dev->mc, dev->addr_len); ++ spin_unlock_bh(&local->filter_lock); ++ ieee80211_queue_work(&local->hw, &local->reconfig_filter); ++} ++ ++/* ++ * Called when the netdev is removed or, by the code below, before ++ * the interface type changes. ++ */ ++static void ieee80211_teardown_sdata(struct ieee80211_sub_if_data *sdata) ++{ ++ int i; ++ ++ /* free extra data */ ++ ieee80211_free_keys(sdata, false); ++ ++ ieee80211_debugfs_remove_netdev(sdata); ++ ++ for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++) ++ __skb_queue_purge(&sdata->fragments[i].skb_list); ++ sdata->fragment_next = 0; ++ ++ if (ieee80211_vif_is_mesh(&sdata->vif)) ++ ieee80211_mesh_teardown_sdata(sdata); ++} ++ ++static void ieee80211_uninit(struct net_device *dev) ++{ ++ ieee80211_teardown_sdata(IEEE80211_DEV_TO_SUB_IF(dev)); ++} ++ ++#if LINUX_VERSION_IS_GEQ(5,2,0) ++static u16 ieee80211_netdev_select_queue(struct net_device *dev, ++ struct sk_buff *skb, ++ struct net_device *sb_dev) ++#elif LINUX_VERSION_IS_GEQ(4,19,0) ++static u16 ieee80211_netdev_select_queue(struct net_device *dev, ++ struct sk_buff *skb, ++ struct net_device *sb_dev, ++ select_queue_fallback_t fallback) ++#elif LINUX_VERSION_IS_GEQ(3,14,0) || \ ++ (LINUX_VERSION_CODE == KERNEL_VERSION(3,13,11) && UTS_UBUNTU_RELEASE_ABI > 30) ++static u16 ieee80211_netdev_select_queue(struct net_device *dev, ++ struct sk_buff *skb, ++ void *accel_priv, ++ select_queue_fallback_t fallback) ++#elif LINUX_VERSION_IS_GEQ(3,13,0) ++static u16 ieee80211_netdev_select_queue(struct net_device *dev, ++ struct sk_buff *skb, ++ void *accel_priv) ++#else ++static u16 ieee80211_netdev_select_queue(struct net_device *dev, ++ struct sk_buff *skb) ++#endif ++{ ++ 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) ++{ ++ int i; ++ ++ for_each_possible_cpu(i) { ++ const struct pcpu_sw_netstats *tstats; ++ u64 rx_packets, rx_bytes, tx_packets, tx_bytes; ++ unsigned int start; ++ ++ tstats = per_cpu_ptr(netdev_tstats(dev), i); ++ ++ do { ++ start = u64_stats_fetch_begin_irq(&tstats->syncp); ++ rx_packets = tstats->rx_packets; ++ tx_packets = tstats->tx_packets; ++ rx_bytes = tstats->rx_bytes; ++ tx_bytes = tstats->tx_bytes; ++ } while (u64_stats_fetch_retry_irq(&tstats->syncp, start)); ++ ++ stats->rx_packets += rx_packets; ++ stats->tx_packets += tx_packets; ++ stats->rx_bytes += rx_bytes; ++ stats->tx_bytes += tx_bytes; ++ } ++} ++#if LINUX_VERSION_IS_LESS(4,11,0) ++/* Just declare it here to keep sparse happy */ ++struct rtnl_link_stats64 *bp_ieee80211_get_stats64(struct net_device *dev, ++ struct rtnl_link_stats64 *stats); ++struct rtnl_link_stats64 * ++bp_ieee80211_get_stats64(struct net_device *dev, ++ struct rtnl_link_stats64 *stats){ ++ ieee80211_get_stats64(dev, stats); ++ return stats; ++} ++#endif ++ ++static const struct net_device_ops ieee80211_dataif_ops = { ++ .ndo_open = ieee80211_open, ++ .ndo_stop = ieee80211_stop, ++ .ndo_uninit = ieee80211_uninit, ++ .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, ++#if LINUX_VERSION_IS_GEQ(4,11,0) ++ .ndo_get_stats64 = ieee80211_get_stats64, ++#else ++ .ndo_get_stats64 = bp_ieee80211_get_stats64, ++#endif ++ ++}; ++ ++#if LINUX_VERSION_IS_GEQ(5,2,0) ++static u16 ieee80211_monitor_select_queue(struct net_device *dev, ++ struct sk_buff *skb, ++ struct net_device *sb_dev) ++#elif LINUX_VERSION_IS_GEQ(4,19,0) ++static u16 ieee80211_monitor_select_queue(struct net_device *dev, ++ struct sk_buff *skb, ++ struct net_device *sb_dev, ++ select_queue_fallback_t fallback) ++#elif LINUX_VERSION_IS_GEQ(3,14,0) || \ ++ (LINUX_VERSION_CODE == KERNEL_VERSION(3,13,11) && UTS_UBUNTU_RELEASE_ABI > 30) ++static u16 ieee80211_monitor_select_queue(struct net_device *dev, ++ struct sk_buff *skb, ++ void *accel_priv, ++ select_queue_fallback_t fallback) ++#elif LINUX_VERSION_IS_GEQ(3,13,0) ++static u16 ieee80211_monitor_select_queue(struct net_device *dev, ++ struct sk_buff *skb, ++ void *accel_priv) ++#else ++static u16 ieee80211_monitor_select_queue(struct net_device *dev, ++ struct sk_buff *skb) ++#endif ++{ ++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); ++ struct ieee80211_local *local = sdata->local; ++ struct ieee80211_hdr *hdr; ++ struct ieee80211_radiotap_header *rtap = (void *)skb->data; ++ ++ if (local->hw.queues < IEEE80211_NUM_ACS) ++ return 0; ++ ++ if (skb->len < 4 || ++ skb->len < le16_to_cpu(rtap->it_len) + 2 /* frame control */) ++ return 0; /* doesn't matter, frame will be dropped */ ++ ++ hdr = (void *)((u8 *)skb->data + le16_to_cpu(rtap->it_len)); ++ ++ return ieee80211_select_queue_80211(sdata, skb, hdr); ++} ++ ++static const struct net_device_ops ieee80211_monitorif_ops = { ++ .ndo_open = ieee80211_open, ++ .ndo_stop = ieee80211_stop, ++ .ndo_uninit = ieee80211_uninit, ++ .ndo_start_xmit = ieee80211_monitor_start_xmit, ++ .ndo_set_rx_mode = ieee80211_set_multicast_list, ++ .ndo_set_mac_address = ieee80211_change_mac, ++ .ndo_select_queue = ieee80211_monitor_select_queue, ++#if LINUX_VERSION_IS_GEQ(4,11,0) ++ .ndo_get_stats64 = ieee80211_get_stats64, ++#else ++ .ndo_get_stats64 = bp_ieee80211_get_stats64, ++#endif ++ ++}; ++ ++static const struct net_device_ops ieee80211_dataif_8023_ops = { ++ .ndo_open = ieee80211_open, ++ .ndo_stop = ieee80211_stop, ++ .ndo_uninit = ieee80211_uninit, ++ .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, ++#if LINUX_VERSION_IS_GEQ(4,11,0) ++ .ndo_get_stats64 = ieee80211_get_stats64, ++#else ++ .ndo_get_stats64 = bp_ieee80211_get_stats64, ++#endif ++ ++}; ++ + static bool ieee80211_iftype_supports_encap_offload(enum nl80211_iftype iftype) + { + switch (iftype) { +@@ -389,6 +893,31 @@ static bool ieee80211_set_sdata_offload_ + return true; + } + ++static void ieee80211_set_vif_encap_ops(struct ieee80211_sub_if_data *sdata) ++{ ++ struct ieee80211_local *local = sdata->local; ++ struct ieee80211_sub_if_data *bss = sdata; ++ bool enabled; ++ ++ if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) { ++ if (!sdata->bss) ++ return; ++ ++ bss = container_of(sdata->bss, struct ieee80211_sub_if_data, u.ap); ++ } ++ ++ if (!ieee80211_hw_check(&local->hw, SUPPORTS_TX_ENCAP_OFFLOAD) || ++ !ieee80211_iftype_supports_encap_offload(bss->vif.type)) ++ return; ++ ++ enabled = bss->vif.offload_flags & IEEE80211_OFFLOAD_ENCAP_ENABLED; ++ if (sdata->wdev.use_4addr && ++ !(bss->vif.offload_flags & IEEE80211_OFFLOAD_ENCAP_4ADDR)) ++ enabled = false; ++ ++ sdata->dev->netdev_ops = enabled ? &ieee80211_dataif_8023_ops : ++ &ieee80211_dataif_ops; ++} + + static void ieee80211_recalc_sdata_offload(struct ieee80211_sub_if_data *sdata) + { +@@ -866,511 +1395,6 @@ int ieee80211_do_open(struct wireless_de + return res; + } + +-static int ieee80211_open(struct net_device *dev) +-{ +- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); +- int err; +- +- /* fail early if user set an invalid address */ +- if (!is_valid_ether_addr(dev->dev_addr)) +- return -EADDRNOTAVAIL; +- +- err = ieee80211_check_concurrent_iface(sdata, sdata->vif.type); +- if (err) +- return err; +- +- return ieee80211_do_open(&sdata->wdev, true); +-} +- +-static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, +- bool going_down) +-{ +- struct ieee80211_local *local = sdata->local; +- unsigned long flags; +- struct sk_buff *skb, *tmp; +- u32 hw_reconf_flags = 0; +- int i, flushed; +- struct ps_data *ps; +- struct cfg80211_chan_def chandef; +- bool cancel_scan; +- struct cfg80211_nan_func *func; +- +- clear_bit(SDATA_STATE_RUNNING, &sdata->state); +- +- cancel_scan = rcu_access_pointer(local->scan_sdata) == sdata; +- if (cancel_scan) +- ieee80211_scan_cancel(local); +- +- /* +- * Stop TX on this interface first. +- */ +- if (sdata->dev) +- netif_tx_stop_all_queues(sdata->dev); +- +- ieee80211_roc_purge(local, sdata); +- +- switch (sdata->vif.type) { +- case NL80211_IFTYPE_STATION: +- ieee80211_mgd_stop(sdata); +- break; +- case NL80211_IFTYPE_ADHOC: +- ieee80211_ibss_stop(sdata); +- break; +- case NL80211_IFTYPE_MONITOR: +- if (sdata->u.mntr.flags & MONITOR_FLAG_COOK_FRAMES) +- break; +- list_del_rcu(&sdata->u.mntr.list); +- break; +- default: +- break; +- } +- +- /* +- * Remove all stations associated with this interface. +- * +- * This must be done before calling ops->remove_interface() +- * because otherwise we can later invoke ops->sta_notify() +- * whenever the STAs are removed, and that invalidates driver +- * assumptions about always getting a vif pointer that is valid +- * (because if we remove a STA after ops->remove_interface() +- * the driver will have removed the vif info already!) +- * +- * In WDS mode a station must exist here and be flushed, for +- * AP_VLANs stations may exist since there's nothing else that +- * would have removed them, but in other modes there shouldn't +- * be any stations. +- */ +- flushed = sta_info_flush(sdata); +- WARN_ON_ONCE(sdata->vif.type != NL80211_IFTYPE_AP_VLAN && +- ((sdata->vif.type != NL80211_IFTYPE_WDS && flushed > 0) || +- (sdata->vif.type == NL80211_IFTYPE_WDS && flushed != 1))); +- +- /* don't count this interface for allmulti while it is down */ +- if (sdata->flags & IEEE80211_SDATA_ALLMULTI) +- atomic_dec(&local->iff_allmultis); +- +- if (sdata->vif.type == NL80211_IFTYPE_AP) { +- local->fif_pspoll--; +- local->fif_probe_req--; +- } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { +- local->fif_probe_req--; +- } +- +- if (sdata->dev) { +- netif_addr_lock_bh(sdata->dev); +- spin_lock_bh(&local->filter_lock); +- __hw_addr_unsync(&local->mc_list, &sdata->dev->mc, +- sdata->dev->addr_len); +- spin_unlock_bh(&local->filter_lock); +- netif_addr_unlock_bh(sdata->dev); +- } +- +- del_timer_sync(&local->dynamic_ps_timer); +- cancel_work_sync(&local->dynamic_ps_enable_work); +- +- cancel_work_sync(&sdata->recalc_smps); +- sdata_lock(sdata); +- mutex_lock(&local->mtx); +- sdata->vif.csa_active = false; +- if (sdata->vif.type == NL80211_IFTYPE_STATION) +- sdata->u.mgd.csa_waiting_bcn = false; +- if (sdata->csa_block_tx) { +- ieee80211_wake_vif_queues(local, sdata, +- IEEE80211_QUEUE_STOP_REASON_CSA); +- sdata->csa_block_tx = false; +- } +- mutex_unlock(&local->mtx); +- sdata_unlock(sdata); +- +- cancel_work_sync(&sdata->csa_finalize_work); +- +- cancel_delayed_work_sync(&sdata->dfs_cac_timer_work); +- +- if (sdata->wdev.cac_started) { +- chandef = sdata->vif.bss_conf.chandef; +- WARN_ON(local->suspended); +- mutex_lock(&local->mtx); +- ieee80211_vif_release_channel(sdata); +- mutex_unlock(&local->mtx); +- cfg80211_cac_event(sdata->dev, &chandef, +- NL80211_RADAR_CAC_ABORTED, +- GFP_KERNEL); +- } +- +- /* APs need special treatment */ +- if (sdata->vif.type == NL80211_IFTYPE_AP) { +- struct ieee80211_sub_if_data *vlan, *tmpsdata; +- +- /* down all dependent devices, that is VLANs */ +- list_for_each_entry_safe(vlan, tmpsdata, &sdata->u.ap.vlans, +- u.vlan.list) +- dev_close(vlan->dev); +- WARN_ON(!list_empty(&sdata->u.ap.vlans)); +- } else if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) { +- /* remove all packets in parent bc_buf pointing to this dev */ +- ps = &sdata->bss->ps; +- +- spin_lock_irqsave(&ps->bc_buf.lock, flags); +- skb_queue_walk_safe(&ps->bc_buf, skb, tmp) { +- if (skb->dev == sdata->dev) { +- __skb_unlink(skb, &ps->bc_buf); +- local->total_ps_buffered--; +- ieee80211_free_txskb(&local->hw, skb); +- } +- } +- spin_unlock_irqrestore(&ps->bc_buf.lock, flags); +- } +- +- if (going_down) +- local->open_count--; +- +- switch (sdata->vif.type) { +- case NL80211_IFTYPE_AP_VLAN: +- mutex_lock(&local->mtx); +- list_del(&sdata->u.vlan.list); +- mutex_unlock(&local->mtx); +- RCU_INIT_POINTER(sdata->vif.chanctx_conf, NULL); +- /* see comment in the default case below */ +- ieee80211_free_keys(sdata, true); +- /* no need to tell driver */ +- break; +- case NL80211_IFTYPE_MONITOR: +- if (sdata->u.mntr.flags & MONITOR_FLAG_COOK_FRAMES) { +- local->cooked_mntrs--; +- break; +- } +- +- local->monitors--; +- if (local->monitors == 0) { +- local->hw.conf.flags &= ~IEEE80211_CONF_MONITOR; +- hw_reconf_flags |= IEEE80211_CONF_CHANGE_MONITOR; +- } +- +- ieee80211_adjust_monitor_flags(sdata, -1); +- break; +- case NL80211_IFTYPE_NAN: +- /* clean all the functions */ +- spin_lock_bh(&sdata->u.nan.func_lock); +- +- idr_for_each_entry(&sdata->u.nan.function_inst_ids, func, i) { +- idr_remove(&sdata->u.nan.function_inst_ids, i); +- cfg80211_free_nan_func(func); +- } +- idr_destroy(&sdata->u.nan.function_inst_ids); +- +- spin_unlock_bh(&sdata->u.nan.func_lock); +- break; +- case NL80211_IFTYPE_P2P_DEVICE: +- /* relies on synchronize_rcu() below */ +- RCU_INIT_POINTER(local->p2p_sdata, NULL); +- /* fall through */ +- default: +- cancel_work_sync(&sdata->work); +- /* +- * When we get here, the interface is marked down. +- * Free the remaining keys, if there are any +- * (which can happen in AP mode if userspace sets +- * keys before the interface is operating, and maybe +- * also in WDS mode) +- * +- * Force the key freeing to always synchronize_net() +- * to wait for the RX path in case it is using this +- * interface enqueuing frames at this very time on +- * another CPU. +- */ +- ieee80211_free_keys(sdata, true); +- skb_queue_purge(&sdata->skb_queue); +- } +- +- spin_lock_irqsave(&local->queue_stop_reason_lock, flags); +- for (i = 0; i < IEEE80211_MAX_QUEUES; i++) { +- skb_queue_walk_safe(&local->pending[i], skb, tmp) { +- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); +- if (info->control.vif == &sdata->vif) { +- __skb_unlink(skb, &local->pending[i]); +- ieee80211_free_txskb(&local->hw, skb); +- } +- } +- } +- spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); +- +- if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) +- ieee80211_txq_remove_vlan(local, sdata); +- +- sdata->bss = NULL; +- +- if (local->open_count == 0) +- ieee80211_clear_tx_pending(local); +- +- sdata->vif.bss_conf.beacon_int = 0; +- +- /* +- * If the interface goes down while suspended, presumably because +- * the device was unplugged and that happens before our resume, +- * then the driver is already unconfigured and the remainder of +- * this function isn't needed. +- * XXX: what about WoWLAN? If the device has software state, e.g. +- * memory allocated, it might expect teardown commands from +- * mac80211 here? +- */ +- if (local->suspended) { +- WARN_ON(local->wowlan); +- WARN_ON(rtnl_dereference(local->monitor_sdata)); +- return; +- } +- +- switch (sdata->vif.type) { +- case NL80211_IFTYPE_AP_VLAN: +- break; +- case NL80211_IFTYPE_MONITOR: +- if (local->monitors == 0) +- ieee80211_del_virtual_monitor(local); +- +- mutex_lock(&local->mtx); +- ieee80211_recalc_idle(local); +- mutex_unlock(&local->mtx); +- +- if (!(sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE)) +- break; +- +- /* fall through */ +- default: +- if (going_down) +- drv_remove_interface(local, sdata); +- } +- +- ieee80211_recalc_ps(local); +- +- if (cancel_scan) +- flush_delayed_work(&local->scan_work); +- +- if (local->open_count == 0) { +- ieee80211_stop_device(local); +- +- /* no reconfiguring after stop! */ +- return; +- } +- +- /* do after stop to avoid reconfiguring when we stop anyway */ +- ieee80211_configure_filter(local); +- ieee80211_hw_config(local, hw_reconf_flags); +- +- if (local->monitors == local->open_count) +- ieee80211_add_virtual_monitor(local); +-} +- +-static int ieee80211_stop(struct net_device *dev) +-{ +- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); +- +- ieee80211_do_stop(sdata, true); +- +- return 0; +-} +- +-static void ieee80211_set_multicast_list(struct net_device *dev) +-{ +- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); +- struct ieee80211_local *local = sdata->local; +- int allmulti, sdata_allmulti; +- +- allmulti = !!(dev->flags & IFF_ALLMULTI); +- sdata_allmulti = !!(sdata->flags & IEEE80211_SDATA_ALLMULTI); +- +- if (allmulti != sdata_allmulti) { +- if (dev->flags & IFF_ALLMULTI) +- atomic_inc(&local->iff_allmultis); +- else +- atomic_dec(&local->iff_allmultis); +- sdata->flags ^= IEEE80211_SDATA_ALLMULTI; +- } +- +- spin_lock_bh(&local->filter_lock); +- __hw_addr_sync(&local->mc_list, &dev->mc, dev->addr_len); +- spin_unlock_bh(&local->filter_lock); +- ieee80211_queue_work(&local->hw, &local->reconfig_filter); +-} +- +-/* +- * Called when the netdev is removed or, by the code below, before +- * the interface type changes. +- */ +-static void ieee80211_teardown_sdata(struct ieee80211_sub_if_data *sdata) +-{ +- int i; +- +- /* free extra data */ +- ieee80211_free_keys(sdata, false); +- +- ieee80211_debugfs_remove_netdev(sdata); +- +- for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++) +- __skb_queue_purge(&sdata->fragments[i].skb_list); +- sdata->fragment_next = 0; +- +- if (ieee80211_vif_is_mesh(&sdata->vif)) +- ieee80211_mesh_teardown_sdata(sdata); +-} +- +-static void ieee80211_uninit(struct net_device *dev) +-{ +- ieee80211_teardown_sdata(IEEE80211_DEV_TO_SUB_IF(dev)); +-} +- +-#if LINUX_VERSION_IS_GEQ(5,2,0) +-static u16 ieee80211_netdev_select_queue(struct net_device *dev, +- struct sk_buff *skb, +- struct net_device *sb_dev) +-#elif LINUX_VERSION_IS_GEQ(4,19,0) +-static u16 ieee80211_netdev_select_queue(struct net_device *dev, +- struct sk_buff *skb, +- struct net_device *sb_dev, +- select_queue_fallback_t fallback) +-#elif LINUX_VERSION_IS_GEQ(3,14,0) || \ +- (LINUX_VERSION_CODE == KERNEL_VERSION(3,13,11) && UTS_UBUNTU_RELEASE_ABI > 30) +-static u16 ieee80211_netdev_select_queue(struct net_device *dev, +- struct sk_buff *skb, +- void *accel_priv, +- select_queue_fallback_t fallback) +-#elif LINUX_VERSION_IS_GEQ(3,13,0) +-static u16 ieee80211_netdev_select_queue(struct net_device *dev, +- struct sk_buff *skb, +- void *accel_priv) +-#else +-static u16 ieee80211_netdev_select_queue(struct net_device *dev, +- struct sk_buff *skb) +-#endif +-{ +- 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) +-{ +- int i; +- +- for_each_possible_cpu(i) { +- const struct pcpu_sw_netstats *tstats; +- u64 rx_packets, rx_bytes, tx_packets, tx_bytes; +- unsigned int start; +- +- tstats = per_cpu_ptr(netdev_tstats(dev), i); +- +- do { +- start = u64_stats_fetch_begin_irq(&tstats->syncp); +- rx_packets = tstats->rx_packets; +- tx_packets = tstats->tx_packets; +- rx_bytes = tstats->rx_bytes; +- tx_bytes = tstats->tx_bytes; +- } while (u64_stats_fetch_retry_irq(&tstats->syncp, start)); +- +- stats->rx_packets += rx_packets; +- stats->tx_packets += tx_packets; +- stats->rx_bytes += rx_bytes; +- stats->tx_bytes += tx_bytes; +- } +-} +-#if LINUX_VERSION_IS_LESS(4,11,0) +-/* Just declare it here to keep sparse happy */ +-struct rtnl_link_stats64 *bp_ieee80211_get_stats64(struct net_device *dev, +- struct rtnl_link_stats64 *stats); +-struct rtnl_link_stats64 * +-bp_ieee80211_get_stats64(struct net_device *dev, +- struct rtnl_link_stats64 *stats){ +- ieee80211_get_stats64(dev, stats); +- return stats; +-} +-#endif +- +-static const struct net_device_ops ieee80211_dataif_ops = { +- .ndo_open = ieee80211_open, +- .ndo_stop = ieee80211_stop, +- .ndo_uninit = ieee80211_uninit, +- .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, +-#if LINUX_VERSION_IS_GEQ(4,11,0) +- .ndo_get_stats64 = ieee80211_get_stats64, +-#else +- .ndo_get_stats64 = bp_ieee80211_get_stats64, +-#endif +- +-}; +- +-#if LINUX_VERSION_IS_GEQ(5,2,0) +-static u16 ieee80211_monitor_select_queue(struct net_device *dev, +- struct sk_buff *skb, +- struct net_device *sb_dev) +-#elif LINUX_VERSION_IS_GEQ(4,19,0) +-static u16 ieee80211_monitor_select_queue(struct net_device *dev, +- struct sk_buff *skb, +- struct net_device *sb_dev, +- select_queue_fallback_t fallback) +-#elif LINUX_VERSION_IS_GEQ(3,14,0) || \ +- (LINUX_VERSION_CODE == KERNEL_VERSION(3,13,11) && UTS_UBUNTU_RELEASE_ABI > 30) +-static u16 ieee80211_monitor_select_queue(struct net_device *dev, +- struct sk_buff *skb, +- void *accel_priv, +- select_queue_fallback_t fallback) +-#elif LINUX_VERSION_IS_GEQ(3,13,0) +-static u16 ieee80211_monitor_select_queue(struct net_device *dev, +- struct sk_buff *skb, +- void *accel_priv) +-#else +-static u16 ieee80211_monitor_select_queue(struct net_device *dev, +- struct sk_buff *skb) +-#endif +-{ +- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); +- struct ieee80211_local *local = sdata->local; +- struct ieee80211_hdr *hdr; +- struct ieee80211_radiotap_header *rtap = (void *)skb->data; +- +- if (local->hw.queues < IEEE80211_NUM_ACS) +- return 0; +- +- if (skb->len < 4 || +- skb->len < le16_to_cpu(rtap->it_len) + 2 /* frame control */) +- return 0; /* doesn't matter, frame will be dropped */ +- +- hdr = (void *)((u8 *)skb->data + le16_to_cpu(rtap->it_len)); +- +- return ieee80211_select_queue_80211(sdata, skb, hdr); +-} +- +-static const struct net_device_ops ieee80211_monitorif_ops = { +- .ndo_open = ieee80211_open, +- .ndo_stop = ieee80211_stop, +- .ndo_uninit = ieee80211_uninit, +- .ndo_start_xmit = ieee80211_monitor_start_xmit, +- .ndo_set_rx_mode = ieee80211_set_multicast_list, +- .ndo_set_mac_address = ieee80211_change_mac, +- .ndo_select_queue = ieee80211_monitor_select_queue, +-#if LINUX_VERSION_IS_GEQ(4,11,0) +- .ndo_get_stats64 = ieee80211_get_stats64, +-#else +- .ndo_get_stats64 = bp_ieee80211_get_stats64, +-#endif +- +-}; +- +-static const struct net_device_ops ieee80211_dataif_8023_ops = { +- .ndo_open = ieee80211_open, +- .ndo_stop = ieee80211_stop, +- .ndo_uninit = ieee80211_uninit, +- .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, +-#if LINUX_VERSION_IS_GEQ(4,11,0) +- .ndo_get_stats64 = ieee80211_get_stats64, +-#else +- .ndo_get_stats64 = bp_ieee80211_get_stats64, +-#endif +- +-}; +- + static void ieee80211_if_free(struct net_device *dev) + { + free_percpu(netdev_tstats(dev)); +@@ -1401,32 +1425,6 @@ static void ieee80211_if_setup_no_queue( + #endif + } + +-static void ieee80211_set_vif_encap_ops(struct ieee80211_sub_if_data *sdata) +-{ +- struct ieee80211_local *local = sdata->local; +- struct ieee80211_sub_if_data *bss = sdata; +- bool enabled; +- +- if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) { +- if (!sdata->bss) +- return; +- +- bss = container_of(sdata->bss, struct ieee80211_sub_if_data, u.ap); +- } +- +- if (!ieee80211_hw_check(&local->hw, SUPPORTS_TX_ENCAP_OFFLOAD) || +- !ieee80211_iftype_supports_encap_offload(bss->vif.type)) +- return; +- +- enabled = bss->vif.offload_flags & IEEE80211_OFFLOAD_ENCAP_ENABLED; +- if (sdata->wdev.use_4addr && +- !(bss->vif.offload_flags & IEEE80211_OFFLOAD_ENCAP_4ADDR)) +- enabled = false; +- +- sdata->dev->netdev_ops = enabled ? &ieee80211_dataif_8023_ops : +- &ieee80211_dataif_ops; +-} +- + static void ieee80211_iface_work(struct work_struct *work) + { + struct ieee80211_sub_if_data *sdata = diff --git a/feeds/ipq40xx/mac80211/patches/subsys/328-mac80211-extend-AQL-aggregation-estimation-to-HE-and.patch b/feeds/ipq40xx/mac80211/patches/subsys/328-mac80211-extend-AQL-aggregation-estimation-to-HE-and.patch new file mode 100644 index 000000000..3d687f834 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/subsys/328-mac80211-extend-AQL-aggregation-estimation-to-HE-and.patch @@ -0,0 +1,49 @@ +From: Felix Fietkau +Date: Thu, 27 Aug 2020 12:44:36 +0200 +Subject: [PATCH] mac80211: extend AQL aggregation estimation to HE and fix + unit mismatch + +The unit of the return value of ieee80211_get_rate_duration is nanoseconds, not +milliseconds. Adjust the duration checks to account for that. +For higher data rates, allow larger estimated aggregation sizes, and add some +values for HE as well, which can use much larger aggregates. +Since small packets with high data rates can now lead to duration values too +small for info->tx_time_est, return a minimum of 4us. + +Signed-off-by: Felix Fietkau +--- + +--- a/net/mac80211/airtime.c ++++ b/net/mac80211/airtime.c +@@ -668,20 +668,26 @@ u32 ieee80211_calc_expected_tx_airtime(s + * This will not be very accurate, but much better than simply + * assuming un-aggregated tx in all cases. + */ +- if (duration > 400) /* <= VHT20 MCS2 1S */ ++ if (duration > 400 * 1024) /* <= VHT20 MCS2 1S */ + agg_shift = 1; +- else if (duration > 250) /* <= VHT20 MCS3 1S or MCS1 2S */ ++ else if (duration > 250 * 1024) /* <= VHT20 MCS3 1S or MCS1 2S */ + agg_shift = 2; +- else if (duration > 150) /* <= VHT20 MCS5 1S or MCS3 2S */ ++ else if (duration > 150 * 1024) /* <= VHT20 MCS5 1S or MCS2 2S */ + agg_shift = 3; +- else ++ else if (duration > 70 * 1024) /* <= VHT20 MCS5 2S */ + agg_shift = 4; ++ else if (stat.encoding != RX_ENC_HE || ++ duration > 20 * 1024) /* <= HE40 MCS6 2S */ ++ agg_shift = 5; ++ else ++ agg_shift = 6; + + duration *= len; + duration /= AVG_PKT_SIZE; + duration /= 1024; ++ duration += (overhead >> agg_shift); + +- return duration + (overhead >> agg_shift); ++ return max_t(u32, duration, 4); + } + + if (!conf) diff --git a/feeds/ipq40xx/mac80211/patches/subsys/329-mac80211-add-AQL-support-for-VHT160-tx-rates.patch b/feeds/ipq40xx/mac80211/patches/subsys/329-mac80211-add-AQL-support-for-VHT160-tx-rates.patch new file mode 100644 index 000000000..e22a09e71 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/subsys/329-mac80211-add-AQL-support-for-VHT160-tx-rates.patch @@ -0,0 +1,23 @@ +From: Felix Fietkau +Date: Thu, 27 Aug 2020 12:47:48 +0200 +Subject: [PATCH] mac80211: add AQL support for VHT160 tx rates + +When converting from struct ieee80211_tx_rate to ieee80211_rx_status, +there was one check missing to fill in the bandwidth for 160 MHz + +Signed-off-by: Felix Fietkau +--- + +--- a/net/mac80211/airtime.c ++++ b/net/mac80211/airtime.c +@@ -560,7 +560,9 @@ static int ieee80211_fill_rx_status(stru + if (rate->idx < 0 || !rate->count) + return -1; + +- if (rate->flags & IEEE80211_TX_RC_80_MHZ_WIDTH) ++ if (rate->flags & IEEE80211_TX_RC_160_MHZ_WIDTH) ++ stat->bw = RATE_INFO_BW_160; ++ else if (rate->flags & IEEE80211_TX_RC_80_MHZ_WIDTH) + stat->bw = RATE_INFO_BW_80; + else if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) + stat->bw = RATE_INFO_BW_40; diff --git a/feeds/ipq40xx/mac80211/patches/subsys/370-mac80211-fix-misplaced-while-instead-of-if.patch b/feeds/ipq40xx/mac80211/patches/subsys/370-mac80211-fix-misplaced-while-instead-of-if.patch new file mode 100644 index 000000000..38144013f --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/subsys/370-mac80211-fix-misplaced-while-instead-of-if.patch @@ -0,0 +1,31 @@ +From 5981fe5b0529ba25d95f37d7faa434183ad618c5 Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Mon, 3 Aug 2020 11:02:10 +0200 +Subject: [PATCH] mac80211: fix misplaced while instead of if + +This never was intended to be a 'while' loop, it should've +just been an 'if' instead of 'while'. Fix this. + +I noticed this while applying another patch from Ben that +intended to fix a busy loop at this spot. + +Cc: stable@vger.kernel.org +Fixes: b16798f5b907 ("mac80211: mark station unauthorized before key removal") +Reported-by: Ben Greear +Link: https://lore.kernel.org/r/20200803110209.253009ae41ff.I3522aad099392b31d5cf2dcca34cbac7e5832dde@changeid +Signed-off-by: Johannes Berg +--- + net/mac80211/sta_info.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/net/mac80211/sta_info.c ++++ b/net/mac80211/sta_info.c +@@ -1051,7 +1051,7 @@ static void __sta_info_destroy_part2(str + might_sleep(); + lockdep_assert_held(&local->sta_mtx); + +- while (sta->sta_state == IEEE80211_STA_AUTHORIZED) { ++ if (sta->sta_state == IEEE80211_STA_AUTHORIZED) { + ret = sta_info_move_state(sta, IEEE80211_STA_ASSOC); + WARN_ON_ONCE(ret); + } diff --git a/feeds/ipq40xx/mac80211/patches/subsys/400-allow-ibss-mixed.patch b/feeds/ipq40xx/mac80211/patches/subsys/400-allow-ibss-mixed.patch new file mode 100644 index 000000000..feb6b5b11 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/subsys/400-allow-ibss-mixed.patch @@ -0,0 +1,29 @@ +ath10k-ct starting with version 5.2 allows the combination of +NL80211_IFTYPE_ADHOC and beacon_int_min_gcd in ath10k_10x_ct_if_comb +which triggers this warning. Ben told me that this is not a big problem +and we should ignore this. + +--- a/net/wireless/core.c ++++ b/net/wireless/core.c +@@ -612,21 +612,6 @@ static int wiphy_verify_combinations(str + c->limits[j].max > 1)) + return -EINVAL; + +- /* +- * This isn't well-defined right now. If you have an +- * IBSS interface, then its beacon interval may change +- * by joining other networks, and nothing prevents it +- * from doing that. +- * So technically we probably shouldn't even allow AP +- * and IBSS in the same interface, but it seems that +- * some drivers support that, possibly only with fixed +- * beacon intervals for IBSS. +- */ +- if (WARN_ON(types & BIT(NL80211_IFTYPE_ADHOC) && +- c->beacon_int_min_gcd)) { +- return -EINVAL; +- } +- + cnt += c->limits[j].max; + /* + * Don't advertise an unsupported type diff --git a/feeds/ipq40xx/mac80211/patches/subsys/500-mac80211_configure_antenna_gain.patch b/feeds/ipq40xx/mac80211/patches/subsys/500-mac80211_configure_antenna_gain.patch new file mode 100644 index 000000000..8db3a758a --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/subsys/500-mac80211_configure_antenna_gain.patch @@ -0,0 +1,160 @@ +--- a/include/net/cfg80211.h ++++ b/include/net/cfg80211.h +@@ -3610,6 +3610,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 + * + * @set_wds_peer: set the WDS peer for a WDS interface + * +@@ -3932,6 +3933,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); + + int (*set_wds_peer)(struct wiphy *wiphy, struct net_device *dev, + const u8 *addr); +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -1521,6 +1521,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 +@@ -1541,6 +1542,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 +@@ -2505,6 +2505,9 @@ enum nl80211_commands { + * @NL80211_ATTR_HE_6GHZ_CAPABILITY: HE 6 GHz Band Capability element (from + * association request when used with NL80211_CMD_NEW_STATION). + * ++ * @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 +@@ -2987,6 +2990,8 @@ enum nl80211_attrs { + + NL80211_ATTR_HE_6GHZ_CAPABILITY, + ++ 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 +@@ -2611,6 +2611,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 int ieee80211_set_wds_peer(struct wiphy *wiphy, struct net_device *dev, + const u8 *addr) + { +@@ -4041,6 +4054,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, + .set_wds_peer = ieee80211_set_wds_peer, + .rfkill_poll = ieee80211_rfkill_poll, + CFG80211_TESTMODE_CMD(ieee80211_testmode_cmd) +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -1383,6 +1383,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; +@@ -665,6 +671,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 +@@ -658,6 +658,7 @@ static const struct nla_policy nl80211_p + .type = NLA_EXACT_LEN, + .len = sizeof(struct ieee80211_he_6ghz_capa), + }, ++ [NL80211_ATTR_WIPHY_ANTENNA_GAIN] = { .type = NLA_U32 }, + }; + + /* policy for the key attributes */ +@@ -3136,6 +3137,20 @@ static int nl80211_set_wiphy(struct sk_b + if (result) + return result; + } ++ ++ if (info->attrs[NL80211_ATTR_WIPHY_ANTENNA_GAIN]) { ++ int idx, dbi = 0; ++ ++ if (!rdev->ops->set_antenna_gain) ++ return -EOPNOTSUPP; ++ ++ idx = NL80211_ATTR_WIPHY_ANTENNA_GAIN; ++ dbi = nla_get_u32(info->attrs[idx]); ++ ++ result = rdev->ops->set_antenna_gain(&rdev->wiphy, dbi); ++ if (result) ++ return result; ++ } + + if (info->attrs[NL80211_ATTR_WIPHY_ANTENNA_TX] && + info->attrs[NL80211_ATTR_WIPHY_ANTENNA_RX]) { diff --git a/feeds/ipq40xx/mac80211/patches/subsys/800-oom.patch b/feeds/ipq40xx/mac80211/patches/subsys/800-oom.patch new file mode 100644 index 000000000..401a8bf32 --- /dev/null +++ b/feeds/ipq40xx/mac80211/patches/subsys/800-oom.patch @@ -0,0 +1,71 @@ +From a8295e2c06e1aa313b4624df9dedf599df382eef Mon Sep 17 00:00:00 2001 +From: Ben Greear +Date: Thu, 9 May 2013 11:56:22 -0700 +Subject: mac80211: Limit number of pending skbs. + +Current code will allow any number of pending skbs, and +this can OOM the system when used with something like +the pktgen tool (which may not back off properly if +queue is stopped). + +Possibly this is just a bug in our version of pktgen, +but either way, it seems reasonable to add a limit +so that it is not possible to go OOM in this manner. + +Signed-off-by: Ben Greear + +diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c +index 3529d1368068..5eb60a50641e 100644 +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -35,6 +35,17 @@ + #include "wpa.h" + #include "wme.h" + #include "rate.h" ++#include ++ ++/* ++ * Maximum number of skbs that may be queued in a pending ++ * queue. After that, packets will just be dropped. ++ */ ++static int max_pending_qsize = 1000; ++module_param(max_pending_qsize, int, 0644); ++MODULE_PARM_DESC(max_pending_qsize, ++ "Maximum number of skbs that may be queued in a pending queue."); ++ + + /* misc utils */ + +@@ -1671,15 +1682,28 @@ static bool ieee80211_tx_frags(struct ieee80211_local *local, + * later transmission from the tx-pending + * tasklet when the queue is woken again. + */ +- if (txpending) ++ bool do_free = false; ++ if (txpending) { + skb_queue_splice_init(skbs, + &local->pending[q]); +- else +- skb_queue_splice_tail_init(skbs, +- &local->pending[q]); ++ } else { ++ u32 len = skb_queue_len(&local->pending[q]); ++ if (len >= max_pending_qsize) { ++ __skb_unlink(skb, skbs); ++ do_free = true; ++ } else { ++ skb_queue_splice_tail_init(skbs, ++ &local->pending[q]); ++ } ++ } + + spin_unlock_irqrestore(&local->queue_stop_reason_lock, + flags); ++ if (do_free) { ++ dev_kfree_skb_any(skb); ++ /* TODO: Add counter for this */ ++ } ++ + return false; + } + } diff --git a/feeds/ipq40xx/mac80211/ralink.mk b/feeds/ipq40xx/mac80211/ralink.mk new file mode 100644 index 000000000..6aca17077 --- /dev/null +++ b/feeds/ipq40xx/mac80211/ralink.mk @@ -0,0 +1,172 @@ +PKG_DRIVERS += \ + rt2x00-lib rt2x00-pci rt2x00-usb rt2x00-mmio \ + rt2400-pci rt2500-pci rt2500-usb \ + rt2800-lib rt2800-mmio rt2800-pci rt2800-soc rt2800-usb \ + rt61-pci rt73-usb + +PKG_CONFIG_DEPENDS += \ + CONFIG_PACKAGE_RT2X00_LIB_DEBUGFS \ + CONFIG_PACKAGE_RT2X00_DEBUG + +config-$(call config_package,rt2x00-lib) += RT2X00 RT2X00_LIB +config-$(call config_package,rt2x00-pci) += RT2X00_LIB_PCI +config-$(call config_package,rt2x00-mmio) += RT2X00_LIB_MMIO +config-$(call config_package,rt2x00-usb) += RT2X00_LIB_USB +config-$(CONFIG_PACKAGE_RT2X00_LIB_DEBUGFS) += RT2X00_LIB_DEBUGFS +config-$(CONFIG_PACKAGE_RT2X00_DEBUG) += RT2X00_DEBUG + +config-$(call config_package,rt2400-pci) += RT2400PCI +config-$(call config_package,rt2500-pci) += RT2500PCI +config-$(call config_package,rt2500-usb) += RT2500USB +config-$(call config_package,rt61-pci) += RT61PCI +config-$(call config_package,rt73-usb) += RT73USB + +config-$(call config_package,rt2800-lib) += RT2800_LIB + +config-$(call config_package,rt2800-soc) += RT2800SOC +config-$(call config_package,rt2800-pci) += RT2800PCI +config-y += RT2800PCI_RT33XX RT2800PCI_RT35XX RT2800PCI_RT53XX RT2800PCI_RT3290 + +config-$(call config_package,rt2800-usb) += RT2800USB +config-y += RT2800USB_RT33XX RT2800USB_RT35XX RT2800USB_RT3573 RT2800USB_RT53XX RT2800USB_RT55XX RT2800USB_UNKNOWN + +define KernelPackage/rt2x00/Default + $(call KernelPackage/mac80211/Default) + TITLE:=Ralink Drivers for RT2x00 cards +endef + +define KernelPackage/rt2x00-lib +$(call KernelPackage/rt2x00/Default) + DEPENDS+= @(PCI_SUPPORT||USB_SUPPORT||TARGET_ramips) +kmod-mac80211 + TITLE+= (LIB) + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ralink/rt2x00/rt2x00lib.ko + MENU:=1 +endef + +define KernelPackage/rt2x00-lib/config + if PACKAGE_kmod-rt2x00-lib + + config PACKAGE_RT2X00_LIB_DEBUGFS + bool "Enable rt2x00 debugfs support" + depends on PACKAGE_MAC80211_DEBUGFS + help + Enable creation of debugfs files for the rt2x00 drivers. + These debugfs files support both reading and writing of the + most important register types of the rt2x00 hardware. + + config PACKAGE_RT2X00_DEBUG + bool "Enable rt2x00 debug output" + help + Enable debugging output for all rt2x00 modules + + endif +endef + +define KernelPackage/rt2x00-mmio +$(call KernelPackage/rt2x00/Default) + DEPENDS+= @(PCI_SUPPORT||TARGET_ramips) +kmod-rt2x00-lib + HIDDEN:=1 + TITLE+= (MMIO) + FILES:= $(PKG_BUILD_DIR)/drivers/net/wireless/ralink/rt2x00/rt2x00mmio.ko +endef + +define KernelPackage/rt2x00-pci +$(call KernelPackage/rt2x00/Default) + DEPENDS+= @PCI_SUPPORT +kmod-rt2x00-mmio +kmod-rt2x00-lib + HIDDEN:=1 + TITLE+= (PCI) + FILES:= $(PKG_BUILD_DIR)/drivers/net/wireless/ralink/rt2x00/rt2x00pci.ko + AUTOLOAD:=$(call AutoProbe,rt2x00pci) +endef + +define KernelPackage/rt2x00-usb +$(call KernelPackage/rt2x00/Default) + DEPENDS+= @USB_SUPPORT +kmod-rt2x00-lib +kmod-usb-core + HIDDEN:=1 + TITLE+= (USB) + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ralink/rt2x00/rt2x00usb.ko + AUTOLOAD:=$(call AutoProbe,rt2x00usb) +endef + +define KernelPackage/rt2800-lib +$(call KernelPackage/rt2x00/Default) + DEPENDS+= @(PCI_SUPPORT||USB_SUPPORT||TARGET_ramips) +kmod-rt2x00-lib +kmod-lib-crc-ccitt +@DRIVER_11N_SUPPORT +@DRIVER_11W_SUPPORT + HIDDEN:=1 + TITLE+= (rt2800 LIB) + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ralink/rt2x00/rt2800lib.ko +endef + +define KernelPackage/rt2400-pci +$(call KernelPackage/rt2x00/Default) + DEPENDS+= @PCI_SUPPORT +kmod-rt2x00-pci +kmod-eeprom-93cx6 + TITLE+= (RT2400 PCI) + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ralink/rt2x00/rt2400pci.ko + AUTOLOAD:=$(call AutoProbe,rt2400pci) +endef + +define KernelPackage/rt2500-pci +$(call KernelPackage/rt2x00/Default) + DEPENDS+= @PCI_SUPPORT +kmod-rt2x00-pci +kmod-eeprom-93cx6 + TITLE+= (RT2500 PCI) + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ralink/rt2x00/rt2500pci.ko + AUTOLOAD:=$(call AutoProbe,rt2500pci) +endef + +define KernelPackage/rt2500-usb +$(call KernelPackage/rt2x00/Default) + DEPENDS+= @USB_SUPPORT +kmod-rt2x00-usb + TITLE+= (RT2500 USB) + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ralink/rt2x00/rt2500usb.ko + AUTOLOAD:=$(call AutoProbe,rt2500usb) +endef + +define KernelPackage/rt2800-mmio +$(call KernelPackage/rt2x00/Default) + TITLE += (RT28xx/RT3xxx MMIO) + DEPENDS += +kmod-rt2800-lib +kmod-rt2x00-mmio + HIDDEN:=1 + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ralink/rt2x00/rt2800mmio.ko +endef + +define KernelPackage/rt2800-soc +$(call KernelPackage/rt2x00/Default) + DEPENDS += @(TARGET_ramips_rt288x||TARGET_ramips_rt305x||TARGET_ramips_rt3883||TARGET_ramips_mt7620) +kmod-rt2800-mmio +kmod-rt2800-lib + TITLE += (RT28xx/RT3xxx SoC) + FILES := \ + $(PKG_BUILD_DIR)/drivers/net/wireless/ralink/rt2x00/rt2x00soc.ko \ + $(PKG_BUILD_DIR)/drivers/net/wireless/ralink/rt2x00/rt2800soc.ko + AUTOLOAD:=$(call AutoProbe,rt2800soc) +endef + +define KernelPackage/rt2800-pci +$(call KernelPackage/rt2x00/Default) + DEPENDS+= @PCI_SUPPORT +kmod-rt2x00-pci +kmod-rt2800-lib +kmod-rt2800-mmio +kmod-eeprom-93cx6 +rt2800-pci-firmware + TITLE+= (RT2860 PCI) + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ralink/rt2x00/rt2800pci.ko + AUTOLOAD:=$(call AutoProbe,rt2800pci) +endef + +define KernelPackage/rt2800-usb +$(call KernelPackage/rt2x00/Default) + DEPENDS+= @USB_SUPPORT +kmod-rt2x00-usb +kmod-rt2800-lib +kmod-lib-crc-ccitt +rt2800-usb-firmware + TITLE+= (RT2870 USB) + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ralink/rt2x00/rt2800usb.ko + AUTOLOAD:=$(call AutoProbe,rt2800usb) +endef + + +define KernelPackage/rt61-pci +$(call KernelPackage/rt2x00/Default) + DEPENDS+= @PCI_SUPPORT +kmod-rt2x00-pci +kmod-eeprom-93cx6 +kmod-lib-crc-itu-t +rt61-pci-firmware + TITLE+= (RT2x61 PCI) + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ralink/rt2x00/rt61pci.ko + AUTOLOAD:=$(call AutoProbe,rt61pci) +endef + +define KernelPackage/rt73-usb + $(call KernelPackage/rt2x00/Default) + DEPENDS+= @USB_SUPPORT +kmod-rt2x00-usb +kmod-lib-crc-itu-t +rt73-usb-firmware + TITLE+= (RT73 USB) + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ralink/rt2x00/rt73usb.ko + AUTOLOAD:=$(call AutoProbe,rt73usb) +endef diff --git a/feeds/ipq40xx/mac80211/realtek.mk b/feeds/ipq40xx/mac80211/realtek.mk new file mode 100644 index 000000000..bcf35e35c --- /dev/null +++ b/feeds/ipq40xx/mac80211/realtek.mk @@ -0,0 +1,206 @@ +PKG_DRIVERS += \ + rtl8180 rtl8187 \ + rtlwifi rtlwifi-pci rtlwifi-btcoexist rtlwifi-usb rtl8192c-common \ + rtl8192ce rtl8192se rtl8192de rtl8192cu rtl8723bs rtl8821ae \ + rtl8xxxu rtw88 + +config-$(call config_package,rtl8180) += RTL8180 +config-$(call config_package,rtl8187) += RTL8187 + +config-$(call config_package,rtlwifi) += RTL_CARDS RTLWIFI +config-$(call config_package,rtlwifi-pci) += RTLWIFI_PCI +config-$(call config_package,rtlwifi-btcoexist) += RTLBTCOEXIST +config-$(call config_package,rtlwifi-usb) += RTLWIFI_USB +config-$(call config_package,rtl8192c-common) += RTL8192C_COMMON +config-$(call config_package,rtl8192ce) += RTL8192CE +config-$(call config_package,rtl8192se) += RTL8192SE +config-$(call config_package,rtl8192de) += RTL8192DE +config-$(call config_package,rtl8192cu) += RTL8192CU +config-$(call config_package,rtl8821ae) += RTL8821AE +config-$(CONFIG_PACKAGE_RTLWIFI_DEBUG) += RTLWIFI_DEBUG + +config-$(call config_package,rtl8xxxu) += RTL8XXXU +config-y += RTL8XXXU_UNTESTED + +config-$(call config_package,rtl8723bs) += RTL8723BS +config-y += STAGING + +config-$(call config_package,rtw88) += RTW88 RTW88_CORE RTW88_PCI +config-y += RTW88_8822BE RTW88_8822CE RTW88_8723DE + +define KernelPackage/rtl818x/Default + $(call KernelPackage/mac80211/Default) + TITLE:=Realtek Drivers for RTL818x devices + URL:=https://wireless.wiki.kernel.org/en/users/drivers/rtl8187 + DEPENDS+= +kmod-eeprom-93cx6 +kmod-mac80211 +endef + +define KernelPackage/rtl8180 + $(call KernelPackage/rtl818x/Default) + DEPENDS+= @PCI_SUPPORT + TITLE+= (RTL8180 PCI) + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtl818x/rtl8180/rtl818x_pci.ko + AUTOLOAD:=$(call AutoProbe,rtl818x_pci) +endef + +define KernelPackage/rtl8187 +$(call KernelPackage/rtl818x/Default) + DEPENDS+= @USB_SUPPORT +kmod-usb-core + TITLE+= (RTL8187 USB) + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtl818x/rtl8187/rtl8187.ko + AUTOLOAD:=$(call AutoProbe,rtl8187) +endef + +define KernelPackage/rtlwifi/config + config PACKAGE_RTLWIFI_DEBUG + bool "Realtek wireless debugging" + depends on PACKAGE_kmod-rtlwifi + help + Say Y, if you want to debug realtek wireless drivers. + +endef + +define KernelPackage/rtlwifi + $(call KernelPackage/mac80211/Default) + TITLE:=Realtek common driver part + DEPENDS+= @(PCI_SUPPORT||USB_SUPPORT) +kmod-mac80211 +@DRIVER_11N_SUPPORT +@DRIVER_11W_SUPPORT + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtlwifi/rtlwifi.ko + HIDDEN:=1 +endef + +define KernelPackage/rtlwifi-pci + $(call KernelPackage/mac80211/Default) + TITLE:=Realtek common driver part (PCI support) + DEPENDS+= @PCI_SUPPORT +kmod-rtlwifi + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtlwifi/rtl_pci.ko + AUTOLOAD:=$(call AutoProbe,rtl_pci) + HIDDEN:=1 +endef + +define KernelPackage/rtlwifi-btcoexist + $(call KernelPackage/mac80211/Default) + TITLE:=Realtek BT coexist support + DEPENDS+= +kmod-rtlwifi + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtlwifi/btcoexist/btcoexist.ko + AUTOLOAD:=$(call AutoProbe,btcoexist) + HIDDEN:=1 +endef + +define KernelPackage/rtlwifi-usb + $(call KernelPackage/mac80211/Default) + TITLE:=Realtek common driver part (USB support) + DEPENDS+= @USB_SUPPORT +kmod-usb-core +kmod-rtlwifi + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtlwifi/rtl_usb.ko + AUTOLOAD:=$(call AutoProbe,rtl_usb) + HIDDEN:=1 +endef + +define KernelPackage/rtl8192c-common + $(call KernelPackage/mac80211/Default) + TITLE:=Realtek RTL8192CE/RTL8192CU common support module + DEPENDS+= +kmod-rtlwifi + FILES:= $(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtlwifi/rtl8192c/rtl8192c-common.ko + HIDDEN:=1 +endef + +define KernelPackage/rtl8192ce + $(call KernelPackage/mac80211/Default) + TITLE:=Realtek RTL8192CE/RTL8188CE support + DEPENDS+= +kmod-rtlwifi-pci +kmod-rtl8192c-common +rtl8192ce-firmware + FILES:= $(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/rtl8192ce.ko + AUTOLOAD:=$(call AutoProbe,rtl8192ce) +endef + +define KernelPackage/rtl8192se + $(call KernelPackage/mac80211/Default) + TITLE:=Realtek RTL8192SE/RTL8191SE support + DEPENDS+= +kmod-rtlwifi-pci +rtl8192se-firmware + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtlwifi/rtl8192se/rtl8192se.ko + AUTOLOAD:=$(call AutoProbe,rtl8192se) +endef + +define KernelPackage/rtl8192de + $(call KernelPackage/mac80211/Default) + TITLE:=Realtek RTL8192DE/RTL8188DE support + DEPENDS+= +kmod-rtlwifi-pci +rtl8192de-firmware + FILES:= $(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtlwifi/rtl8192de/rtl8192de.ko + AUTOLOAD:=$(call AutoProbe,rtl8192de) +endef + +define KernelPackage/rtl8192cu + $(call KernelPackage/mac80211/Default) + TITLE:=Realtek RTL8192CU/RTL8188CU support + DEPENDS+= +kmod-rtlwifi-usb +kmod-rtl8192c-common +rtl8192cu-firmware + FILES:= $(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/rtl8192cu.ko + AUTOLOAD:=$(call AutoProbe,rtl8192cu) +endef + +define KernelPackage/rtl8821ae + $(call KernelPackage/mac80211/Default) + TITLE:=Realtek RTL8821AE support + DEPENDS+= +kmod-rtlwifi-btcoexist +kmod-rtlwifi-pci +rtl8821ae-firmware + FILES:= $(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/rtl8821ae.ko + AUTOLOAD:=$(call AutoProbe,rtl8821ae) +endef + +define KernelPackage/rtl8xxxu + $(call KernelPackage/mac80211/Default) + TITLE:=alternative Realtek RTL8XXXU support + DEPENDS+= @USB_SUPPORT +kmod-usb-core +kmod-mac80211 + FILES:= $(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.ko + AUTOLOAD:=$(call AutoProbe,rtl8xxxu) +endef + +define KernelPackage/rtl8xxxu/description + This is an alternative driver for various Realtek RTL8XXX + parts written to utilize the Linux mac80211 stack. + The driver is known to work with a number of RTL8723AU, + RL8188CU, RTL8188RU, RTL8191CU, and RTL8192CU devices + + This driver is under development and has a limited feature + set. In particular it does not yet support 40MHz channels + and power management. However it should have a smaller + memory footprint than the vendor drivers and benetifs + from the in kernel mac80211 stack. + + It can coexist with drivers from drivers/staging/rtl8723au, + drivers/staging/rtl8192u, and drivers/net/wireless/rtlwifi, + but you will need to control which module you wish to load. + + RTL8XXXU_UNTESTED is enabled + This option enables detection of Realtek 8723/8188/8191/8192 WiFi + USB devices which have not been tested directly by the driver + author or reported to be working by third parties. + + Please report your results! +endef + +define KernelPackage/rtw88 + $(call KernelPackage/mac80211/Default) + TITLE:=Realtek RTL8822BE/RTL8822CE/RTL8723DE + DEPENDS+= @(PCI_SUPPORT) +kmod-mac80211 +@DRIVER_11AC_SUPPORT +@DRIVER_11N_SUPPORT +@DRIVER_11W_SUPPORT + FILES:=\ + $(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_8822be rtw88_8822ce rtw88_8723de) +endef + +define KernelPackage/rtl8723bs + $(call KernelPackage/mac80211/Default) + TITLE:=Realtek RTL8723BS SDIO Wireless LAN NIC driver (staging) + DEPENDS+=+kmod-mmc +kmod-mac80211 + FILES:=$(PKG_BUILD_DIR)/drivers/staging/rtl8723bs/r8723bs.ko + AUTOLOAD:=$(call AutoProbe,r8723bs) +endef + +define KernelPackage/rtl8723bs/description + This option enables support for RTL8723BS SDIO drivers, such as the wifi found + on the 1st gen Intel Compute Stick, the CHIP and many other Intel Atom and ARM + based devices. +endef diff --git a/feeds/ipq40xx/mac80211/scripts/import-backports.sh b/feeds/ipq40xx/mac80211/scripts/import-backports.sh new file mode 100755 index 000000000..35aa411e6 --- /dev/null +++ b/feeds/ipq40xx/mac80211/scripts/import-backports.sh @@ -0,0 +1,109 @@ +#!/usr/bin/env bash +BASE=$1; shift + +usage() { + echo "Usage: $0 NNN ..." + exit 1 +} + +check_number() { + case "$1" in + [0-9][0-9][0-9]) return 0;; + esac + return 1; +} + +patch_header() +{ + awk ' + /^(---|\*\*\*|Index:)[ \t][^ \t]|^diff -/ \ + { exit } + { print } + ' +} + +strip_diffstat() +{ + awk ' + /#? .* \| / \ + { eat = eat $0 "\n" + next } + /^#? .* files? changed(, .* insertions?\(\+\))?(, .* deletions?\(-\))?/ \ + { eat = "" + next } + { print eat $0 + eat = "" } + ' +} + +strip_trailing_whitespace() { + sed -e 's:[ '$'\t'']*$::' +} + +fixup_header() { + awk ' + /^From / { next } + /^Subject: / { + sub("Subject: \\[[^\]]*\\]", "Subject: [PATCH]") + } + { print } + ' +} + +check_number "$BASE" || usage + +quilt series > /dev/null || { + echo "Not in quilt directory" + exit 2 +} + +get_next() { + NEW=$BASE + quilt series | while read CUR; do + [ -n "$CUR" ] || break + CUR=${CUR%%-*} + check_number "$CUR" || continue + [ "$CUR" -lt "$NEW" ] && continue + [ "$CUR" -ge "$(($BASE + 100))" ] && continue + NEW="$(($CUR + 1))" + echo $NEW + done | tail -n1 +} + +CUR=$(get_next) +CUR="${CUR:-$BASE}" + +while [ -n "$1" ]; do + FILE="$1"; shift + NAME="$(basename $FILE)" + NAME="${NAME#[0-9]*-}" + echo -n "Processing patch $NAME: " + + [ -e "$FILE" ] || { + echo "file $FILE not found" + exit 1 + } + + grep -qE "$NAME$" patches/series && { + echo "already applied" + continue + } + + quilt new "$CUR-$NAME" || exit 1 + patch_header < "$FILE" | + strip_diffstat | + strip_trailing_whitespace | + fixup_header > "patches/$CUR-$NAME" + + quilt fold < "$FILE" || { + cp "$FILE" ./cur_patch + echo "patch $FILE failed to apply, copied to ./cur_patch" + exit 1 + } + + quilt refresh -p ab --no-index --no-timestamps + + CUR="$(($CUR + 1))" +done + +exit 0 diff --git a/feeds/ipq40xx/wireguard/Makefile b/feeds/ipq40xx/wireguard/Makefile new file mode 100644 index 000000000..394483ddb --- /dev/null +++ b/feeds/ipq40xx/wireguard/Makefile @@ -0,0 +1,55 @@ +# +# Copyright (C) 2016-2019 Jason A. Donenfeld +# Copyright (C) 2016 Baptiste Jonglez +# Copyright (C) 2016-2017 Dan Luedtke +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. + +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/kernel.mk + +PKG_NAME:=wireguard-backport + +PKG_VERSION:=1.0.20211208 +PKG_RELEASE:=1 + +PKG_SOURCE:=wireguard-linux-compat-$(PKG_VERSION).tar.xz +PKG_SOURCE_URL:=https://git.zx2c4.com/wireguard-linux-compat/snapshot/ +PKG_HASH:=c0e607138a17daac656f508d8e63ea3737b5221fa5d9288191ddeb099f5a3b92 + +PKG_LICENSE:=GPL-2.0 +PKG_LICENSE_FILES:=COPYING + +PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/wireguard-linux-compat-$(PKG_VERSION) +PKG_BUILD_PARALLEL:=1 +PKG_USE_MIPS16:=0 + +# WireGuard's makefile needs this to know where to build the kernel module +export KERNELDIR:=$(LINUX_DIR) + +include $(INCLUDE_DIR)/package.mk +include $(INCLUDE_DIR)/kernel-defaults.mk +include $(INCLUDE_DIR)/package-defaults.mk + +define Build/Compile + $(MAKE) $(KERNEL_MAKEOPTS) M="$(PKG_BUILD_DIR)/src" modules EXTRA_CFLAGS="-Wno-stringop-overread" +endef + +define KernelPackage/wireguard-backport + SECTION:=kernel + CATEGORY:=Kernel modules + SUBMENU:=Network Support + TITLE:=WireGuard kernel module + DEPENDS:=+IPV6:kmod-udptunnel6 +kmod-udptunnel4 + FILES:= $(PKG_BUILD_DIR)/src/wireguard.$(LINUX_KMOD_SUFFIX) + AUTOLOAD:=$(call AutoProbe,wireguard) +endef + +define KernelPackage/wireguard-backport/description + $(call Package/wireguard/Default/description) + + This package provides the kernel module for WireGuard. +endef + +$(eval $(call KernelPackage,wireguard-backport)) diff --git a/feeds/ipq40xx/wireguard/patches/100-compat.patch b/feeds/ipq40xx/wireguard/patches/100-compat.patch new file mode 100644 index 000000000..4318c8d1a --- /dev/null +++ b/feeds/ipq40xx/wireguard/patches/100-compat.patch @@ -0,0 +1,20 @@ +Index: wireguard-linux-compat-1.0.20211208/src/compat/compat.h +=================================================================== +--- wireguard-linux-compat-1.0.20211208.orig/src/compat/compat.h ++++ wireguard-linux-compat-1.0.20211208/src/compat/compat.h +@@ -686,15 +688,6 @@ struct __compat_dummy_container { char d + #define genl_dump_check_consistent(a, b) genl_dump_check_consistent(a, b, &genl_family) + #endif + +-#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0) && !defined(ISRHEL7) +-static inline void *skb_put_data(struct sk_buff *skb, const void *data, unsigned int len) +-{ +- void *tmp = skb_put(skb, len); +- memcpy(tmp, data, len); +- return tmp; +-} +-#endif +- + #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0) && !defined(ISRHEL7) + #define napi_complete_done(n, work_done) napi_complete(n) + #endif diff --git a/patches/0057-ipq40xx-add-v5.4-backport.patch b/patches/0057-ipq40xx-add-v5.4-backport.patch index 98ffe0251..a006e4e91 100644 --- a/patches/0057-ipq40xx-add-v5.4-backport.patch +++ b/patches/0057-ipq40xx-add-v5.4-backport.patch @@ -1,10 +1,11 @@ -From a704d32f181200a1d395c8205aa6d95774dfc64a Mon Sep 17 00:00:00 2001 +From ee9c999b3218a1bf51cdfb66e6c24cff46229b15 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Mon, 4 Sep 2023 12:30:52 +0200 -Subject: [PATCH 57/58] ipq40xx: add v5.4 backport +Subject: [PATCH 1/2] ipq40xx: add v5.4 backport Signed-off-by: John Crispin --- + package/kernel/linux/modules/crypto.mk | 2 +- ...dcode-path-to-awk-in-scripts-ld-vers.patch | 30 + .../011-kbuild-export-SUBARCH.patch | 21 + ...lper-to-get-data-pointed-by-a-symbol.patch | 53 + @@ -253,7 +254,7 @@ Signed-off-by: John Crispin ..._nvram-inline-code-checking-NVRAM-si.patch | 70 + .../999-bpf-off-by-one-backport.patch | 13 + ...r-bridge-s-private-skb-space-on-xmit.patch | 36 + - target/linux/generic/config-5.4 | 6572 ++++++++++++++ + target/linux/generic/config-5.4 | 6573 ++++++++++++++ .../mtd/partitions/openwrt,uimage.yaml | 91 + .../Documentation/networking/adm6996.txt | 110 + .../files-5.4/arch/mips/fw/myloader/Makefile | 5 + @@ -332,7 +333,6 @@ Signed-off-by: John Crispin .../211-darwin-uuid-typedef-clash.patch | 22 + .../hack-5.4/212-tools_portability.patch | 110 + .../hack-5.4/214-spidev_h_portability.patch | 24 + - .../generic/hack-5.4/220-gc_sections.patch | 144 + .../generic/hack-5.4/221-module_exports.patch | 109 + .../hack-5.4/230-openwrt_lzma_options.patch | 71 + .../hack-5.4/249-udp-tunnel-selection.patch | 11 + @@ -511,7 +511,7 @@ Signed-off-by: John Crispin .../pending-5.4/834-ledtrig-libata.patch | 149 + ...40-hwrng-bcm2835-set-quality-to-1000.patch | 26 + .../pending-5.4/920-mangle_bootargs.patch | 71 + - 506 files changed, 142580 insertions(+) + 506 files changed, 142438 insertions(+), 1 deletion(-) create mode 100644 target/linux/generic/backport-5.4/010-Kbuild-don-t-hardcode-path-to-awk-in-scripts-ld-vers.patch create mode 100644 target/linux/generic/backport-5.4/011-kbuild-export-SUBARCH.patch create mode 100644 target/linux/generic/backport-5.4/030-modpost-add-a-helper-to-get-data-pointed-by-a-symbol.patch @@ -839,7 +839,6 @@ Signed-off-by: John Crispin create mode 100644 target/linux/generic/hack-5.4/211-darwin-uuid-typedef-clash.patch create mode 100644 target/linux/generic/hack-5.4/212-tools_portability.patch create mode 100644 target/linux/generic/hack-5.4/214-spidev_h_portability.patch - create mode 100644 target/linux/generic/hack-5.4/220-gc_sections.patch create mode 100644 target/linux/generic/hack-5.4/221-module_exports.patch create mode 100644 target/linux/generic/hack-5.4/230-openwrt_lzma_options.patch create mode 100644 target/linux/generic/hack-5.4/249-udp-tunnel-selection.patch @@ -1019,6 +1018,19 @@ Signed-off-by: John Crispin create mode 100644 target/linux/generic/pending-5.4/840-hwrng-bcm2835-set-quality-to-1000.patch create mode 100644 target/linux/generic/pending-5.4/920-mangle_bootargs.patch +diff --git a/package/kernel/linux/modules/crypto.mk b/package/kernel/linux/modules/crypto.mk +index 53dcd24444..66c8e23343 100644 +--- a/package/kernel/linux/modules/crypto.mk ++++ b/package/kernel/linux/modules/crypto.mk +@@ -42,7 +42,7 @@ define KernelPackage/crypto-aead + CONFIG_CRYPTO_AEAD2 + FILES:= \ + $(LINUX_DIR)/crypto/aead.ko \ +- $(LINUX_DIR)/crypto/geniv.ko ++ $(LINUX_DIR)/crypto/geniv.ko@ge5.5 + AUTOLOAD:=$(call AutoLoad,09,aead,1) + $(call AddDepends/crypto, +kmod-crypto-null) + endef diff --git a/target/linux/generic/backport-5.4/010-Kbuild-don-t-hardcode-path-to-awk-in-scripts-ld-vers.patch b/target/linux/generic/backport-5.4/010-Kbuild-don-t-hardcode-path-to-awk-in-scripts-ld-vers.patch new file mode 100644 index 0000000000..7ac4f9d240 @@ -80260,10 +80272,10 @@ index 0000000000..20f71569da + diff --git a/target/linux/generic/config-5.4 b/target/linux/generic/config-5.4 new file mode 100644 -index 0000000000..a821a1de5f +index 0000000000..5f91923aba --- /dev/null +++ b/target/linux/generic/config-5.4 -@@ -0,0 +1,6572 @@ +@@ -0,0 +1,6573 @@ +# CONFIG_104_QUAD_8 is not set +CONFIG_32BIT=y +CONFIG_64BIT_TIME=y @@ -82539,6 +82551,7 @@ index 0000000000..a821a1de5f +# CONFIG_INIT_ON_ALLOC_DEFAULT_ON is not set +# CONFIG_INIT_ON_FREE_DEFAULT_ON is not set +CONFIG_INIT_STACK_NONE=y ++# CONFIG_INIT_STACK_ALL is not set +# CONFIG_INLINE_READ_LOCK is not set +# CONFIG_INLINE_READ_LOCK_BH is not set +# CONFIG_INLINE_READ_LOCK_IRQ is not set @@ -122167,156 +122180,6 @@ index 0000000000..415e9a423c + ? ((N)*(sizeof (struct spi_ioc_transfer))) : 0) + #define SPI_IOC_MESSAGE(N) _IOW(SPI_IOC_MAGIC, 0, char[SPI_MSGSIZE(N)]) + -diff --git a/target/linux/generic/hack-5.4/220-gc_sections.patch b/target/linux/generic/hack-5.4/220-gc_sections.patch -new file mode 100644 -index 0000000000..9b665f644a ---- /dev/null -+++ b/target/linux/generic/hack-5.4/220-gc_sections.patch -@@ -0,0 +1,144 @@ -+From e3d8676f5722b7622685581e06e8f53e6138e3ab Mon Sep 17 00:00:00 2001 -+From: Felix Fietkau -+Date: Sat, 15 Jul 2017 23:42:36 +0200 -+Subject: use -ffunction-sections, -fdata-sections and --gc-sections -+ -+In combination with kernel symbol export stripping this significantly reduces -+the kernel image size. Used on both ARM and MIPS architectures. -+ -+Signed-off-by: Felix Fietkau -+Signed-off-by: Jonas Gorski -+Signed-off-by: Gabor Juhos -+--- -+ Makefile | 10 +++---- -+ arch/arm/Kconfig | 1 + -+ arch/arm/boot/compressed/Makefile | 1 + -+ arch/arm/kernel/vmlinux.lds.S | 26 ++++++++-------- -+ arch/mips/Kconfig | 1 + -+ arch/mips/kernel/vmlinux.lds.S | 4 +-- -+ include/asm-generic/vmlinux.lds.h | 63 ++++++++++++++++++++------------------- -+ 7 files changed, 55 insertions(+), 51 deletions(-) -+ -+--- a/arch/arm/Kconfig -++++ b/arch/arm/Kconfig -+@@ -112,6 +112,7 @@ config ARM -+ select HAVE_UID16 -+ select HAVE_VIRT_CPU_ACCOUNTING_GEN -+ select IRQ_FORCED_THREADING -++ select HAVE_LD_DEAD_CODE_DATA_ELIMINATION -+ select MODULES_USE_ELF_REL -+ select NEED_DMA_MAP_STATE -+ select OF_EARLY_FLATTREE if OF -+--- a/arch/arm/boot/compressed/Makefile -++++ b/arch/arm/boot/compressed/Makefile -+@@ -108,6 +108,7 @@ ifeq ($(CONFIG_FUNCTION_TRACER),y) -+ ORIG_CFLAGS := $(KBUILD_CFLAGS) -+ KBUILD_CFLAGS = $(subst -pg, , $(ORIG_CFLAGS)) -+ endif -++KBUILD_CFLAGS_KERNEL := $(patsubst -f%-sections,,$(KBUILD_CFLAGS_KERNEL)) -+ -+ # -fstack-protector-strong triggers protection checks in this code, -+ # but it is being used too early to link to meaningful stack_chk logic. -+--- a/arch/arm/kernel/vmlinux.lds.S -++++ b/arch/arm/kernel/vmlinux.lds.S -+@@ -75,7 +75,7 @@ SECTIONS -+ . = ALIGN(4); -+ __ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) { -+ __start___ex_table = .; -+- ARM_MMU_KEEP(*(__ex_table)) -++ KEEP(*(__ex_table)) -+ __stop___ex_table = .; -+ } -+ @@ -100,24 +100,24 @@ SECTIONS -+ } -+ .init.arch.info : { -+ __arch_info_begin = .; -+- *(.arch.info.init) -++ KEEP(*(.arch.info.init)) -+ __arch_info_end = .; -+ } -+ .init.tagtable : { -+ __tagtable_begin = .; -+- *(.taglist.init) -++ KEEP(*(.taglist.init)) -+ __tagtable_end = .; -+ } -+ #ifdef CONFIG_SMP_ON_UP -+ .init.smpalt : { -+ __smpalt_begin = .; -+- *(.alt.smp.init) -++ KEEP(*(.alt.smp.init)) -+ __smpalt_end = .; -+ } -+ #endif -+ .init.pv_table : { -+ __pv_table_begin = .; -+- *(.pv_table) -++ KEEP(*(.pv_table)) -+ __pv_table_end = .; -+ } -+ -+--- a/arch/arm/kernel/vmlinux.lds.h -++++ b/arch/arm/kernel/vmlinux.lds.h -+@@ -22,13 +22,13 @@ -+ #define ARM_MMU_DISCARD(x) -+ #else -+ #define ARM_MMU_KEEP(x) -+-#define ARM_MMU_DISCARD(x) x -++#define ARM_MMU_DISCARD(x) KEEP(x) -+ #endif -+ -+ #define PROC_INFO \ -+ . = ALIGN(4); \ -+ __proc_info_begin = .; \ -+- *(.proc.info.init) \ -++ KEEP(*(.proc.info.init)) \ -+ __proc_info_end = .; -+ -+ #define HYPERVISOR_TEXT \ -+@@ -39,11 +39,11 @@ -+ #define IDMAP_TEXT \ -+ ALIGN_FUNCTION(); \ -+ __idmap_text_start = .; \ -+- *(.idmap.text) \ -++ KEEP(*(.idmap.text)) \ -+ __idmap_text_end = .; \ -+ . = ALIGN(PAGE_SIZE); \ -+ __hyp_idmap_text_start = .; \ -+- *(.hyp.idmap.text) \ -++ KEEP(*(.hyp.idmap.text)) \ -+ __hyp_idmap_text_end = .; -+ -+ #define ARM_DISCARD \ -+@@ -86,12 +86,12 @@ -+ . = ALIGN(8); \ -+ .ARM.unwind_idx : { \ -+ __start_unwind_idx = .; \ -+- *(.ARM.exidx*) \ -++ KEEP(*(.ARM.exidx*)) \ -+ __stop_unwind_idx = .; \ -+ } \ -+ .ARM.unwind_tab : { \ -+ __start_unwind_tab = .; \ -+- *(.ARM.extab*) \ -++ KEEP(*(.ARM.extab*)) \ -+ __stop_unwind_tab = .; \ -+ } -+ -+@@ -102,14 +102,14 @@ -+ #define ARM_VECTORS \ -+ __vectors_start = .; \ -+ .vectors 0xffff0000 : AT(__vectors_start) { \ -+- *(.vectors) \ -++ KEEP(*(.vectors)) \ -+ } \ -+ . = __vectors_start + SIZEOF(.vectors); \ -+ __vectors_end = .; \ -+ \ -+ __stubs_start = .; \ -+ .stubs ADDR(.vectors) + 0x1000 : AT(__stubs_start) { \ -+- *(.stubs) \ -++ KEEP(*(.stubs)) \ -+ } \ -+ . = __stubs_start + SIZEOF(.stubs); \ -+ __stubs_end = .; \ diff --git a/target/linux/generic/hack-5.4/221-module_exports.patch b/target/linux/generic/hack-5.4/221-module_exports.patch new file mode 100644 index 0000000000..47f40ac5e1